{"id":16132260,"url":"https://github.com/luk3yx/miniirc_extras","last_synced_at":"2025-04-06T14:43:14.408Z","repository":{"id":57441772,"uuid":"184181615","full_name":"luk3yx/miniirc_extras","owner":"luk3yx","description":"A WIP framework that adds more features to miniirc.","archived":false,"fork":false,"pushed_at":"2021-11-10T08:42:22.000Z","size":96,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-17T06:41:28.284Z","etag":null,"topics":["miniirc"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/luk3yx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-04-30T03:01:32.000Z","updated_at":"2023-10-01T06:26:44.000Z","dependencies_parsed_at":"2022-09-26T17:20:54.780Z","dependency_job_id":null,"html_url":"https://github.com/luk3yx/miniirc_extras","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luk3yx%2Fminiirc_extras","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luk3yx%2Fminiirc_extras/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luk3yx%2Fminiirc_extras/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luk3yx%2Fminiirc_extras/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/luk3yx","download_url":"https://codeload.github.com/luk3yx/miniirc_extras/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247500450,"owners_count":20948877,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["miniirc"],"created_at":"2024-10-09T22:29:34.061Z","updated_at":"2025-04-06T14:43:14.383Z","avatar_url":"https://github.com/luk3yx.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# miniirc_extras\n\n![Python 3.5+] [![Available on PyPI.]](https://pypi.org/project/miniirc_extras/) [![License: MIT]](https://github.com/luk3yx/miniirc_extras/blob/master/LICENSE.md)\n\n[Python 3.5+]: https://img.shields.io/badge/python-3.5+-blue.svg\n[Available on PyPI.]: https://img.shields.io/pypi/v/miniirc_extras.svg\n[License: MIT]: https://img.shields.io/pypi/l/miniirc.svg\n\nAn extension of miniirc ([GitHub](https://github.com/luk3yx/miniirc),\n[GitLab](https://gitlab.com/luk3yx/miniirc)) that adds more features.\n\nNote that miniirc_extras is still in beta and there can and will be breaking\nAPI changes before v1.0.0, and miniirc_extras may not work with older versions\nof miniirc.\n\n*Some features here may be merged into miniirc eventually.*\n\n## Loading features\n\nAfter importing miniirc_extras, features can be loaded with\n`irc.require('feature_name')`, and once loaded can be accessed with\n`irc.feature_name`.\n\n## Features\n\n - `chans`: Channel mode tracking, must be loaded while miniirc is disconnected.\n - `ensure_connection`: https://github.com/luk3yx/miniirc/issues/15\n - `mp`: *(WIP)* Multiprocessing handlers for miniirc.\n - `testfeature`: Debugging\n - `users`: User tracking, must be loaded while miniirc is disconnected.\n - `_json` *(Proof-of-concept)*: Parse JSON messages.\n\n### `irc.users`\n\n`irc.users` adds rudimentary user tracking to miniirc.\n\n#### `User` objects\n\nUser objects store the current user's information and user-defined data, and\ncan be accessed with `irc.users[Hostmask]` or `irc.users['nick']`.\n\nThe following items are available in `User` objects:\n\n| Variable      | Description                                               |\n| ------------- | --------------------------------------------------------  |\n| `nick`        | The user's current nickname.                              |\n| `ident`       | The user's current ident.                                 |\n| `host`        | The user's current hostname.                              |\n| `realname`    | The user's `realname`.                                    |\n| `hostmask`    | A `Hostmask` object containing the user's hostmask.       |\n| `raw_hostmask`| A string containing `nick!user@host`.                     |\n| `channels`    | A set containing `Channel` objects for channels the user is currently in. |\n| `account`     | A string containing the user's current NickServ account, or `None` if the user isn't logged in. |\n| `avatar_url`  | The avatar URL of the user. Currently only IRCCloud avatars work. |\n\nYou can also set and get items with strings as keys and JSON-compatible objects\nas values.\n\n`User` objects have the following helper functions:\n\n| Function          | Description                                             |\n| ----------------- | ------------------------------------------------------- |\n| `msg(*text)`      | Send a `PRIVMSG` to the user.                           |\n| `me(*text)`       | Send a `CTCP ACTION` (`/me`) to the user.               |\n| `notice(*text)`   | Send a `NOTICE` to the user.                            |\n| `kick(channel, reason='')` | Kicks the user from `channel` (a string or `Channel` object). |\n\n### `irc.chans`\n\n`irc.chans` adds channel mode tracking on top of `irc.users`. You can get\nchannels with `irc.chans['#channel-name']`\n\n#### `Channel` objects\n\n`Channel` objects have the following attributes:\n\n| Variable      | Description                                               |\n| ------------- | --------------------------------------------------------  |\n| `name`        | The name of the channel.                                  |\n| `modes`       | A `ModeList` object containing a list of modes.           |\n| `topic`       | The channel topic.                                        |\n| `users`       | A `set` containing `User` objects for members of this channel. |\n\n#### `ModeList` objects\n\nModeList objects store a list of modes, and have the following functions:\n\n| Function          | Description                                             |\n| ----------------- | ------------------------------------------------------- |\n| `getbool(mode)`   | Returns `True` if `mode` (a single-character string) is set on the corresponding channel. *Use this for `+i`, `+t`, etc* |\n| `getstr(mode, default=None)` | Return the parameter `mode` was set with, otherwise `default`. *Use this for `+k`, `+l`, etc* |\n| `getset(mode)` | Return a `frozenset` containing all the entries stored in `mode`. If you plan to use this for modes such as `+b`, you may want to run `MODE #channel +b` when the bot/client joins the channel to populate the list. *Use this for `+b`, `+e`, `+o`, `+v`, etc* |\n| `hasstr(mode)` | Returns `True` if `mode` is set with a single parameter, otherwise `False`. |\n| `hasset(mode)` | Equivalent to `len(getset(mode)) \u003e 0`. |\n\n*You can access `ModeList` objects like `dict`s, however this will require\nextra type checking code if you plan to use mypy or another type checker.*\n\n### `irc.mp`\n\nMultiprocessing handlers. You can create multiprocessing handlers with\n`irc.mp.Handler` and `irc.mp.CmdHandler`. These handlers are called with the\nlimited `RestrictedIRC` object (a subclass of `AbstractIRC`) instead of the\nnormal `IRC` object.\n\nThe following functions/variables work with `RestrictedIRC`:\n\n`active_caps`, `channels`, `connect_modes`, `ctcp`, `debug`, `ident`, `ip`,\n`ircv3_caps`, `isupport`, `me`, `msg`, `nick`, `notice`, `persist`,\n`ping_interval`, `port`, `quit_message`, `quote`, `realname`, `ssl`,\n`verify_ssl`\n\nTrying to modify these variables will result in an `AttributeError` or the set\noperation silently failing.\n\n## Misc classes\n\n### AbstractIRC\n\nThe `miniirc_extras.AbstractIRC` class provides an easy way to type check `IRC`\nobjects without stub files.\n\n### Hostmask\n\nminiirc_extras adds the abstract-ish class `miniirc_extras.Hostmask`:\n\n```py\nfrom miniirc_extras import Hostmask\n\nisinstance('test', Hostmask)                    # False\nisinstance(('nick', 123, 'host'), Hostmask)     # False\nisinstance(('nick', 'user', 'host'), Hostmask)  # True\n\nHostmask('nick', 'user', 'host') # ('nick', 'user', 'host')\nHostmask(123456, 'user', 'host') # TypeError\n```\n\n## Creating new features\n\n*This API will probably change in the future.*\n\nYou can create your own features with `miniirc_extras.Feature`:\n\n```py\n@miniirc_extras.Feature('feature_name')\nclass MyFeature:\n    def test_func(self):\n        print('test_func called with', self._irc)\n\n    def __call__(self):\n        print('MyFeature called with', self._irc)\n\n    def __init__(self, irc):\n        self._irc = irc\n```\n\nOnce registered, you can `require` and use it:\n\n```py\nirc.require('feature_name')\n\nirc.feature_name()           # MyFeature called with \u003cminiirc.IRC object\u003e\nirc.feature_name.test_func() # test_func called with \u003cminiirc.IRC object\u003e\n```\n\n## Miscellaneous functions\n\nSome miscellaneous functions and classes are located in `miniirc_extras.utils`.\n\n| Function          | Description                                             |\n| ----------------- | ------------------------------------------------------- |\n| `DummyIRC(...)`   | A subclass of `miniirc.IRC` that cannot connect to servers. `DummyIRC.__init__` has no required parameters. |\n| `dict_to_tags(tags)` | Converts a dict containing strings and booleans into an IRCv3 tags string. Example: `dict_to_tags({'tag1': True, 'tag2': 'tag-data'})` → `b'@tag1;tag2=tag-data '` |\n| `get_raw_socket(irc)` | Attempts to get the raw socket from an AbstractIRC object. This is not recommended, and under no circumstances should you attempt to receive data using this socket. **Only use this if there is no alternative.** Raises a miniirc_extras.error if no socket can be found. |\n| `tags_to_dict(tag_list, separator = ';')` | Converts a tags list (`tag1;tag2=tag-data`) joined by `separator` into a `dict` containing strings and booleans. |\n| `ircv3_message_parser(msg, *, colon=True)` | The same as `miniirc.ircv3_message_parser`, but also accepts `bytes` and `bytearray`s. The `colon` keyword argument works in the same way as the `colon` keyword argument on `miniirc.Handler`. |\n| `hostmask_to_str(hostmask)` | Converts a `Hostmask` object into a `nick!user@host` string. |\n| `ircv2_message_unparser(cmd, hostmask, tags, args, *, colon=True, encoding='utf-8')` | Converts miniirc-style message data into an IRCv2 message encoded with `encoding` (or `None` to return a `str`). When `colon` is `False`, `args[-1]` will have a colon prepended to it. |\n| `ircv3_message_unparser(cmd, hostmask, tags, args, *, colon=True, encoding='utf-8')` | The same as `ircv2_message_unparser`, but tags are added. |\n| `namedtuple(...)` | Alias for `collections.namedtuple` on Python 3.7+, otherwise a wrapper that adds `defaults` and `module` keyword arguments. |\n| `VersionInfo(major=0, minor=0, micro=0, releaselevel='final', serial=0)` | A `namedtuple` similar to `type(sys.version_info)`. |\n\n*Note that `dict_to_tags` and `tags_to_dict` are available in miniirc as\ninternal functions, however they can and will change.*\n\n### `miniirc_extras.utils.irc_from_url`\n\nAllows you to create `IRC` objects from URLs, for example\n`irc_from_url('irc://nick@ssl-server.example/#channel1,#channel2')` will create\nan `IRC` object with the nickname `nick`. Any keyword arguments passed to\n`irc_from_url` are sent to `IRC()`.\n\n### `miniirc_extras.utils.HandlerGroup`\n\nAllows you to create a group of handlers and apply them in bulk to `IRC`\nobjects.\n\n| Method            | Description                                             |\n| ----------------- | ------------------------------------------------------- |\n| `Handler(...)`    | Adds a `Handler` to the group, uses the same syntax as `irc.Handler`. |\n| `CmdHandler(...)`    | Adds a `CmdHandler` to the group, uses the same syntax as `irc.CmdHandler`. |\n| `add_to(irc_or_group)` | Adds all the handlers in this group to an IRC object or another handler group. |\n| `copy()`          | Returns another handler group with the same handlers as this one. |\n\n### `miniirc_extras.utils.numerics`\n\nAn `Enum` of most of the IRC numerics in [RFC 1459], [RFC 2812], and\n[modern.ircdocs.horse](https://modern.ircdocs.horse/#numerics). See\n`miniirc_extras/_numerics.py` for a list of\nnumerics and their names.\n\nExample:\n```py\nimport miniirc\nfrom miniirc_extras.utils import numerics\n\n@miniirc.Handler(numerics.RPL_WELCOME, colon=False)\ndef handler(irc, hostmask, args):\n    print('Connected to IRC!')\n```\n\nAnother example:\n```py\n\u003e\u003e\u003e from miniirc_extras.utils import numerics\n\u003e\u003e\u003e numerics.RPL_ISUPPORT\n\u003cnumerics.RPL_ISUPPORT: 0​0​5\u003e\n\u003e\u003e\u003e numerics['RPL_MOTD']\n\u003cnumerics.RPL_MOTD: 372\u003e\n\u003e\u003e\u003e numerics(465)\n\u003cnumerics.ERR_YOUREBANNEDCREEP: 465\u003e\n\u003e\u003e\u003e numerics('422')\n\u003cnumerics.ERR_NOMOTD: 422\u003e\n\u003e\u003e\u003e str(numerics.RPL_YOURHOST)\n'002'\n```\n\n### `miniirc_extras.aioirc`\n\nAn asyncio-oriented version of `miniirc.IRC`. Example:\n\n```py\nimport asyncio, time\nfrom miniirc_extras import aioirc\n\nirc = aioirc.AsyncIRC(ip, 6697, nickname, '#botwar', auto_connect=False)\n\n@irc.Handler('PRIVMSG', colon=False)\ndef handle_privmsg(irc, hostmask, args):\n    if args[0] == '#botwar' and args[1] == '\u003ethread_test':\n        irc.msg(args[0], '[Thread] Waiting 1 second...')\n        time.sleep(1)\n        irc.msg(args[0], '[Thread] Done!')\n\n@irc.Handler('PRIVMSG', colon=False)\nasync def handle_privmsg(irc, hostmask, args):\n    if args[0] == '#botwar' and args[1] == '\u003ecoro_test':\n        await irc.msg(args[0], '[Coroutine] Waiting 1 second...')\n        await asyncio.sleep(1)\n        await irc.msg(args[0], '[Coroutine] Done!')\n\nif __name__ == '__main__':\n    irc.connect()\n    asyncio.get_event_loop().run_forever()\n```\n\nThis probably doesn't need to be used unless asyncio-based libraries need to be\nused.\n\n### `miniirc_extras.formatting`\n\nText formatting. Inspired by [ircmessage](https://pypi.org/project/ircmessage/).\n\n#### `colours`/`colors` enum\n\nThe `colours` (or `colors`) enum contains colours and their corresponding code.\nDo not use these to format text, instead use the below `style` and `colorize`\nfunctions.\n\n#### `Styler` objects\n\nStyler objects are callables that apply IRC formatting to strings.\n\n```py\nminiirc_extras.formatting.Styler(fg=None, bg=None, *,\n        bold: bool = False, italics: bool = False, underline: bool = False,\n        reverse_colour: bool = False, strikethrough: bool = False,\n        spoiler: bool = False, monospace: bool = False, reset: bool = True)\n```\n\n*Note that `Styler` accepts both `reverse_colour` and `reverse_color`.*\n\n`fg` and `bg` can be strings or values from the aforementioned `Enum`.\n\nThe parameters passed to `__init__` are available as attributes on the object,\nfor example `styler.bold`.\n\nSetting `reset` to `False` is not recommended, as when enabled it only resets\nany changed formatting.\n\nFor cleaner code, you can also use\n`miniirc_extras.formatting.style(text, fg=None, ...)`.\n\n**Example:**\n\n```py\nfrom miniirc_extras import formatting\n\nstyler = formatting.Styler('red', bold=True, monospace=True)\nmsg = styler('Test message')\nprint(styler.fg)    # \u003ccolours.red: 04\u003e\nprint(styler.fg)    # None\nprint(styler.bold)  # True\nprint(repr(msg))    # '\\x11\\x02\\x0304Test message\\x0399\\x02\\x11'\n\nmsg2 = formatting.style('Test message', 'red', bold=True, monospace=True)\nassert msg == msg2 # No error\n\nprint(repr(formatting.unstyle(msg))) # 'Test message'\n```\n\n#### \"Lightweight\" stylers\n\nThere are a number of predefined `Styler`s that are more efficient (if you are\nonly adding one style):\n\n```py\nbold            = Styler(bold=True)\nitalics         = Styler(italics=True)\nitalic          = italics\nunderline       = Styler(underline=True)\nreverse_colour  = Styler(reverse_colour=True)\nreverse_color   = reverse_colour\nstrikethrough   = Styler(strikethrough=True)\nmonospace       = Styler(monospace=True)\nspoiler         = Styler(spoiler=True)\n```\n\nLightweight stylers are subclassed from `Styler` and will run slightly faster,\nprovided you are only changing one style.\n\nYou can also use `miniirc_extras.formatting.colorize(text, fg)` (or\n`miniirc_extras.formatting.colourise(text, fg)`) if you are only changing the\nforeground colour/color for a similarly small speed improvement.\n\n*Note that `formatting.style(text, 'red', bold=True)` is recommended over\n`formatting.bold(formatting.colorize(text, 'red'))`, as it is more readable\nand probably faster.*\n\n### Deprecated functions.\n\nThese functions still work for now but will probably be removed from\nminiirc_extras v1.0.0:\n\n#### `miniirc_extras.DummyIRC`\n\nNow called `miniirc_extras.utils.DummyIRC`.\n\n#### `miniirc_extras.VersionInfo`\n\nNow called `miniirc_extras.utils.VersionInfo`.\n\n#### Other planned breaking changes\n\n - To coincide with miniirc v2.0.0, all functions that take a `colon` keyword\n    argument here will default to `False` (instead of `True`). This may change\n    in miniirc_extras v1.0.0 instead.\n - If Python 3.5 is obsolete by the time miniirc_extras v1.0.0 is released,\n    support may be dropped.\n\n[RFC 1459]: https://tools.ietf.org/html/rfc1459\n[RFC 2812]: https://tools.ietf.org/html/rfc2812\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluk3yx%2Fminiirc_extras","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fluk3yx%2Fminiirc_extras","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluk3yx%2Fminiirc_extras/lists"}