Metadata-Version: 2.1
Name: miniirc
Version: 1.6.3
Summary: A lightweight IRC framework.
Home-page: https://github.com/luk3yx/miniirc
Author: luk3yx
License: MIT
Description: # miniirc
        
        [![Python 3.4+]](#python-version-support) [![Available on PyPI.]](https://pypi.org/project/miniirc/) [![License: MIT]](https://github.com/luk3yx/miniirc/blob/master/LICENSE.md)
        
        A relatively simple thread-safe(-ish) IRC client framework.
        
        To install miniirc, simply run `pip3 install miniirc` as root.
        
        If you have previously used miniirc, you may want to read the
        [deprecations list] (last updated 2020-04-28).
        
        *This repository is available on both [GitHub](https://github.com/luk3yx/miniirc) and [GitLab](https://gitlab.com/luk3yx/miniirc).*
        
        [Python 3.4+]: https://img.shields.io/badge/python-3.4/3.5+-blue.svg
        [Available on PyPI.]: https://img.shields.io/pypi/v/miniirc.svg
        [License: MIT]: https://img.shields.io/pypi/l/miniirc.svg
        [deprecations list]: #deprecations
        
        ## Parameters
        
        ```py
        irc = miniirc.IRC(ip, port, nick, channels=None, *, ssl=None, ident=None, realname=None, persist=True, debug=False, ns_identity=None, auto_connect=True, ircv3_caps=set(), quit_message='I grew sick and died.', ping_interval=60, ping_timeout=None, verify_ssl=True)
        ```
        
        *Note that everything before the \* is a positional argument.*
        
        ### Typical usage
        
        You don't need to add every argument, and the `ip`, `port`, `nick`, and
        `channels` arguments should be specified as positional arguments.
        
        ```py
        irc = miniirc.IRC('irc.example.com', 6697, 'my-bot', ['#my-channel'], ns_identity=('my-bot', 'hunter2'))
        ```
        
        ### Parameter descriptions
        
        | Parameter     | Description                                                |
        | ------------- | -------------------------------------------------------- |
        | `ip`          | The IP/hostname of the IRC server to connect to.          |
        | `port`        | The port to connect to.                                   |
        | `nick`        | The nickname of the bot.                                  |
        | `channels`    | The channels to join on connect. This can be an iterable containing strings (list, set, etc), or (since v1.5.0) a comma-delimited string. |
        | `ssl`         | Enable TLS/SSL. If `None`, TLS/SSL is disabled unless the port is `6697`. |
        | `ident`       | The ident to use, defaults to `nick`.                     |
        | `realname`    | The realname to use, defaults to `nick` as well.          |
        | `persist`     | Whether to automatically reconnect.                       |
        | `debug`       | Enables debug mode, prints all IRC messages. This can also be a file-like object (with write mode enabled) if you want debug messages to be written into a file instead of being printed to stdout, or a function (for example `logging.debug`). |
        | `ns_identity` | The NickServ account to use as a tuple/list of length 2 (`('<user>', '<password>')`). For compatibility, this can be a string (`'<user> <password>'`). |
        | `auto_connect`| Runs `.connect()` straight away.                          |
        | `ircv3_caps`  | A set() of additional IRCv3 capabilities to request. SASL is auto-added if `ns_identity` is specified. |
        | `connect_modes` | A mode string (for example `'+B'`) of UMODEs to set when connected. |
        | `quit_message`| Sets the default quit message. This can be modified per-quit with `irc.disconnect()`. |
        | `ping_interval` | If no packets are sent or received for this amount of seconds, miniirc will send a `PING`, and if no reply is sent, after the ping timeout, miniirc will attempt to reconnect. Set to `None` to disable. |
        | `ping_timeout` | The ping timeout used alongside the above `ping_interval` option, if unspecified will default to `ping_interval`. |
        | `verify_ssl`  | Verifies TLS/SSL certificates. Disabling this is not recommended as it opens the IRC connection up to MiTM attacks. If you have trouble with certificate verification, try running `pip3 install certifi` first. |
        
        *The only mandatory parameters are `ip`, `port`, and `nick`.*
        
        ## Functions
        
        | Function      | Description                                               |
        | ------------- | --------------------------------------------------------  |
        | `change_parser(parser=...)` | *See the message parser section for documentation.* |
        | `connect()`   | Connects to the IRC server if not already connected.      |
        | `ctcp(target, *msg, reply=False, tags=None)` | Sends a `CTCP` request or reply to `target`. |
        | `debug(...)`  | Debug, calls `print(...)` if debug mode is on.            |
        | `disconnect(msg=..., *, auto_reconnect=False)`| Disconnects from the IRC server. `auto_reconnect` will be overriden by `self.persist` if set to `True`. |
        | `Handler(...)` | An event handler, see [Handlers](#handlers) for more info. |
        | `me(target, *msg, tags=None)`        | Sends a `/me` (`CTCP ACTION`) to `target`.  |
        | `msg(target, *msg, tags=None)`       | Sends a `PRIVMSG` to `target`. `target` should not contain spaces or start with a colon. |
        | `notice(target, *msg, tags=None)`    | Sends a `NOTICE` to `target`. `target` should not contain spaces or start with a colon. |
        | `quote(*msg, force=False, tags=None)` | Sends a raw message to IRC, use `force=True` to send while disconnected. Do not send multiple commands in one `irc.quote()`, as the newlines will be stripped and it will be sent as one command. The `tags` parameter optionally allows you to add a `dict` with IRCv3 client tags (all starting in `+`), and will not be sent to IRC servers that do not support client tags. |
        | `send(*msg, force=False, tags=None)` | Sends a command to the IRC server, treating every positional argument as a parameter. The usage of this is recommended over `irc.quote()` unless you know what you are doing. |
        
        *Note that if `force=False` on `irc.quote` (or `irc.msg` etc is called) while
        miniirc is not connected, messages will be temporarily stored and then sent
        once miniirc is connected. Setting `force=True` will throw errors if miniirc is
        completely disconnected (`irc.connected` is `None`).*
        
        ### irc.quote and irc.send
        
        The two functions `irc.quote` and `irc.send` may sound similar, however are
        fundamentally different: `irc.quote()` joins all provided arguments with spaces
        and sends them as a raw message to IRC, while `irc.send()` treats each argument
        as a parameter. If arguments passed to `irc.send()` contain spaces, they are
        replaced with U+00A0 (a non-breaking space, visually similar to a regular
        space however not interpreted as one).
        
        #### Examples
        
         - `irc.quote('PRIVMSG', '#channel :Hello,', 'world!')` sends "Hello, world!"
            to #channel.
         - `irc.quote('PRIVMSG', '#channel', 'Hello, world!')` is invalid ("Hello," and
            "world!" are sent as separate parameters).
         - `irc.send('PRIVMSG', '#channel', 'Hello, world!')` will send "Hello, world!"
            to "#channel".
         - `irc.send('PRIVMSG', '#channel :Hello,', 'world!')` will send "world!" to
            `#channel\xa0:Hello,`, where `\xa0` is a non-breaking space.
        
        *If you are unsure and do not need compatibility with miniirc <1.5.0, use
        `irc.send()`. `PRIVMSG` is just used as an example, if you need to send
        `PRIVMSG`s use `irc.msg()` instead.*
        
        ## Variables
        
        *These variables should not be changed outside `miniirc.py`.*
        
        | Variable      | Description                                               |
        | ------------- | --------------------------------------------------------  |
        | `active_caps` | A `set` of IRCv3 capabilities that have been successfully negotiated with the IRC server. This is empty while disconnected. |
        | `connected`   | A boolean (or `None`), `True` when miniirc is connected, `False` when miniirc is connecting, and `None` when miniirc is not connected. |
        | `current_nick` | *New in v1.4.3.* The bot/client's current nickname, currently an alias for `irc.nick`. Do not modify this, and use this instead of `irc.nick` when getting the bot's current nickname for compatibility with miniirc v2.0.0. |
        | `isupport`    | A `dict` with values (not necessarily strings) from `ISUPPORT` messages sent to the client. |
        | `msglen`      | The maximum length (in bytes) of messages (including `\r\n`). This is automatically changed if the server supports the `oragono.io/maxline-2` capability. |
        | `nick`        | The nickname to use when connecting to IRC. Until miniirc v2.0.0, you should only modify this while disconnected, as it is currently automatically updated with nickname changes. |
        
        The following arguments passed to `miniirc.IRC` are also available: `ip`,
        `port`, `channels`, `ssl`, `ident`, `realname`, `persist`, `connect_modes`,
        `quit_message`, `ping_interval`, `verify_ssl`.
        
        ## Handlers
        
        `miniirc.Handler` and `miniirc.CmdHandler` are function decorators that add
        functions to an event handler list. Functions in this list are called in their
        own thread when their respective IRC event(s) is/are received. Handlers may
        work on every IRC object in existence (`miniirc.Handler`) or only on
        specific IRC objects (`irc.Handler`).
        
        The basic syntax for a handler is as followed, where `*events` is a list of events (`PRIVMSG`, `NOTICE`, etc) are called.
        
        ```py
        import miniirc
        @miniirc.Handler(*events, colon=False)
        def handler(irc, hostmask, args):
            # irc:      An 'IRC' object.
            # hostmask: A 'hostmask' object.
            # args:     A list containing the arguments sent to the command. Everything
            #             following the first `:` in the command is put into one item
            #             (args[-1]). If "colon" is "False", the leading ":" (if any)
            #             is automatically removed. To prevent your code from horribly
            #             breaking, always set it to False unless you know what you are
            #             doing.
            pass
        ```
        
        #### Recommendations when using handlers:
        
         - If you don't need support for miniirc <1.4.0 and are parsing the last
            parameter, setting `colon` to `False` is strongly recommended. If the
            `colon` parameter is omitted, it defaults to `True`, however this will
            change when miniirc v2.0.0 is released.
         - Although `Handler` and `CmdHandler` currently accept any object that can be
            converted to a string, every event is converted to a string internally.
         - Not specifying the [`ircv3`](#ircv3-tags) parameter when it is not required
            prevents a redundant `dict` from being created.
         - To add handlers to a specific `IRC` object and not every one in existence,
            use `irc.Handler` and `irc.CmdHandler` instead. If you want to create a
            `Bot` or `Client` class and automatically add handlers to `IRC` objects
            created inside it, see
            [making existing functions handlers](#making-existing-functions-handlers).
        
        ### Hostmask object
        
        Hostmasks are tuples with the format `('user', 'ident', 'hostname')`. If `ident`
        and `hostname` aren't sent from the server, they will be filled in with the
        previous value. If a command is received without a hostmask, all the `hostmask`
        elements will be set to the name of the command. This is deprecated, however,
        and when miniirc v2.0.0 is released the `hostmask` elements will be set to
        empty strings.
        
        ### Making existing functions handlers
        
        You can make existing functions handlers (for example class instance methods)
        with `irc.Handler(*events)(handler_function)`. You probably don't want to use
        `miniirc.Handler` for class instance methods, as this will create a handler
        that gets triggered for every `IRC` object.
        
        You can also add multiple handlers of the same type easily:
        
        ```py
        add_handler = irc.Handler('PRIVMSG', colon=False)
        add_handler(handler_1)
        add_handler(self.instance_handler)
        ```
        
        This is useful if you want to create a `Bot` (or `Client`) class and add
        class-specific handlers without creating global process-wide handlers or
        creating a wrapper function for every class instance.
        
        ### IRCv3 support
        
        #### IRCv3 tags
        
        If you want your handler to support IRCv3 message tags, you need to add
        `ircv3=True` to the `Handler` or `CmdHandler` decorator. You will need to add a
        `tags` parameter to your function after `hostmask`. IRCv3 tags are sent to the
        handlers as `dict`s, with values of either strings or `True`.
        
        *miniirc will automatically un-escape IRCv3 tag values.*
        
        ```py
        import miniirc
        @miniirc.Handler(*events, colon=False, ircv3=True)
        def handler(irc, hostmask, tags, args):
            pass
        ```
        
        #### IRCv3 capabilities
        
        You can handle IRCv3 capabilities before connecting using a handler.
        You must use `force=True` on any `irc.quote()` called here, as when this is
        called, miniirc may not yet be fully connected. Do not use the `colon` argument
        for `Handler` when creating these handlers to avoid unexpected side-effects.
        
        ```py
        import miniirc
        @miniirc.Handler('IRCv3 my-cap-name')
        def handler(irc, hostmask, args):
            # Process the capability here
        
            # IRCv3.2 capabilities:
            #   args = ['my-cap-name', 'IRCv3.2-parameters']
        
            # IRCv3.1 capabilities:
            #   args = ['my-cap-name']
        
            # Remove the capability from the processing list.
            irc.finish_negotiation(args[0]) # This can also be 'my-cap-name'.
        ```
        
        ### Custom message parsers
        
        If the IRC server you are connecting to supports a non-standard message syntax, you can
        create custom message parsers. These are called with the raw message (as a `str`) and
        can either return `None` to ignore the message or a 4-tuple (`cmd, hostmask, tags, args`)
        that will then be sent on to the handlers. The items in this 4-tuple should be the same
        type as the items expected by handlers (and `cmd` should be a string).
        
        #### Message parser example
        
        This message parser makes the normal parser allow `~` as an IRCv3 tag prefix character.
        
        ```py
        import miniirc
        
        def my_message_parser(msg):
            if msg.startswith('~'):
                msg = '@' + msg[1:]
            return miniirc.ircv3_message_parser(msg)
        ```
        
        #### Changing message parsers
        
        To change message parsers, you can use `irc.change_parser(func=...)`. If `func` is not
        specified, it will default to the built-in parser. You can only change message parsers
        on-the-fly (for example in an IRCv3 CAP handler). If you need to change message parsers
        before connecting, you can disable `auto_connect` and change it then.
        
        ```py
        irc = miniirc.IRC(..., auto_connect=False)
        irc.change_parser(my_message_parser)
        irc.connect()
        ```
        
        ### Handling multiple events
        
        If you want to handle multiple events and/or be able to get the name of the
        event being triggered, you can use `irc.CmdHandler`. This will pass an extra
        `command` argument to the handler function (between `irc` and `hostmask`),
        containing a string with the command name (such as `PRIVMSG`).
        
        #### Catch-all handlers
        
        **Please do not use these unless there is no other alternative.**
        
        If you want to handle *every* event, you can use catch-all handlers. To create
        these, you can call `irc.CmdHandler()` *without* any parameters. Note that this
        handler will be called many times while connecting (and once connected).
        
        *You cannot call `irc.Handler()` without parameters.*
        
        ### Example
        
        ```py
        import miniirc
        
        # Not required, however this makes sure miniirc isn't insanely outdated.
        assert miniirc.ver >= (1,4,3)
        
        @miniirc.Handler('PRIVMSG', 'NOTICE', colon=True)
        def handler(irc, hostmask, args):
            print(hostmask[0], 'sent a message to', args[0], 'with content', args[1])
            # nickname sent a message to #channel with content :Hello, world!
        
        @miniirc.CmdHandler('PRIVMSG', 'NOTICE', colon=False)
        def cmdhandler(irc, command, hostmask, args):
            print(hostmask[0], 'sent a', command, 'to', args[0], 'with content',
                args[1])
            # nickname sent a PRIVMSG to #channel with content Hello, world!
        ```
        
        This will print a line whenever the bot gets a `PRIVMSG` or `NOTICE`.
        
        ## Misc functions
        
        miniirc provides the following helper functions:
        
        | Name                          | Description                               |
        | ----------------------------- | ----------------------------------------- |
        | `miniirc.get_ca_certs()`      | Runs `certifi.where()` if `certifi` is installed, otherwise returns `None`. |
        | `miniirc.ircv3_message_parser(msg)` | The default IRCv2/IRCv3 message parser, returns `cmd, hostmask, tags, args`. |
        | `miniirc.ver`                 | A tuple containing version information.   |
        | `miniirc.version`             | The `CTCP VERSION` reply, can be changed. |
        
        The version numbering system should be similar to [SemVer](https://semver.org/),
        however backwards compatibility is preserved where possible when major releases
        change.
        
        ## Python version support
        
         - Python 2 does not work and will (probably) never work with miniirc. If you
            MUST use Python 2, you could try manually porting miniirc.
         - Python 3.3 and below probably won't work, and fixes will not be added unless
            they are very trivial.
         - Python 3.4 support will be dropped in miniirc v2.1.0 (miniirc v2.0.0 will
             have backported bugfixes for a few months).
         - Python 3.5, although not recommended, should work, however it is not tested
             as thoroughly as more recent versions.
         - Python 3.6 and above should work with the latest stable version of miniirc.
        
        If there is a bug/error in Python 3.4 or newer, please open an issue or pull
        request on [GitHub](https://github.com/luk3yx/miniirc/issues) or
        [GitLab](https://gitlab.com/luk3yx/miniirc/issues).
        
        *If you are using Python 3.5 or an older version of Python, I strongly
        recommend updating. Later versions of Python include features such as f-strings
        that make software development easier.*
        
        ## miniirc_extras
        
        If you want more advanced(-ish) features such as user tracking, you can use
        [miniirc_extras](https://pypi.org/project/miniirc-extras/)
        ([GitHub](https://github.com/luk3yx/miniirc_extras),
        [GitLab](https://gitlab.com/luk3yx/miniirc_extras)). Note that miniirc_extras
        is still in beta and there will be breaking API changes in the future.
        
        ## Deprecations
        
        When miniirc v2.0.0 is released, the following breaking changes will (probably)
        be made:
        
         - Internal-only attributes `irc.handlers`, `irc.sock`, and `irc.sendq`
            (please do not use these) will be renamed. Again, please do not use these.
         - `irc.nick` will be the nickname used when connecting to IRC rather than the
            current nickname, use `irc.current_nick` for the current nickname (since
            v1.4.3). This will stop lots of underscores being automatically appended to
            nicknames.
         - `irc.ns_identity` will be stored as a tuple instead of a string, for example
            `('username', 'password with spaces')` instead of
            `'username password with spaces'`. Both formats are currently accepted and
            will be accepted in the `ns_identity` keyword argument.
         - No exceptions will be raised in `irc.quote`/`irc.send` with `force=True`
            when the socket is closed. Instead of relying on these exceptions, use
            `irc.connected` which is set to `None` when completely disconnected.
         - As stated in the Python version support section, Python 3.4 support will be
            dropped in miniirc v2.1.0, however bugfixes will be backported for a few
            months.
         - The `colon` keyword argument to `Handler` and `CmdHandler` will default to
            `False` instead of `True`.
         - Unspecified hostmasks will be an empty string instead of the command. Don't
            rely on this "feature" if possible, simply ignore the hostmask if you do
            not need it.
         - The `extended-join` capability will be requested by default, use `args[0]`
            instead of `args[-1]` to get the channel from a `JOIN` event.
         - The `tags` keyword argument will be read-only.
        
        ## Working examples/implementations
        
        Here is a list of some (open-source) bots using miniirc, in alphabetical order:
        
         - [irc-rss-feed-bot] - Posts RSS entry titles and shortened URLs to IRC
            channels. *Python 3.8+*
         - [irc-url-title-bot] - Gets webpage titles from URLs posted in IRC channels.
            *Python 3.8+*
         - [lurklite] - A generic configurable IRC bot.
            *[GitHub](https://github.com/luk3yx/lurklite) link.*
         - [stdinbot] - A very simple bot that dumps stdin to an IRC channel.
            *[GitHub](https://github.com/luk3yx/stdinbot) link.*
        
        *Want to add your own bot/client to this list? Open an issue on
        [GitHub](https://github.com/luk3yx/miniirc/issues) or
        [GitLab](https://gitlab.com/luk3yx/miniirc/issues).*
        
        [irc-rss-feed-bot]:  https://github.com/impredicative/irc-rss-feed-bot
        [irc-url-title-bot]: https://github.com/impredicative/irc-url-title-bot
        [lurklite]:          https://gitlab.com/luk3yx/lurklite
        [stdinbot]:          https://gitlab.com/luk3yx/stdinbot
        
Platform: UNKNOWN
Classifier: Intended Audience :: Developers
Classifier: Development Status :: 5 - Production/Stable
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.0
Description-Content-Type: text/markdown
