{"id":15896217,"url":"https://github.com/numberoverzero/bottom","last_synced_at":"2025-10-23T07:34:03.752Z","repository":{"id":21744312,"uuid":"25066157","full_name":"numberoverzero/bottom","owner":"numberoverzero","description":"asyncio-based rfc2812-compliant IRC Client","archived":false,"fork":false,"pushed_at":"2024-06-21T04:04:47.000Z","size":309,"stargazers_count":78,"open_issues_count":7,"forks_count":23,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-02T11:59:10.843Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://bottom-docs.readthedocs.io","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/numberoverzero.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-10-11T06:28:17.000Z","updated_at":"2025-01-24T03:24:02.000Z","dependencies_parsed_at":"2024-10-28T04:03:49.347Z","dependency_job_id":null,"html_url":"https://github.com/numberoverzero/bottom","commit_stats":{"total_commits":263,"total_committers":14,"mean_commits":"18.785714285714285","dds":0.2053231939163498,"last_synced_commit":"a78ee27784ab03d3c4139cb6ad432452b7d2edc0"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/numberoverzero%2Fbottom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/numberoverzero%2Fbottom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/numberoverzero%2Fbottom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/numberoverzero%2Fbottom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/numberoverzero","download_url":"https://codeload.github.com/numberoverzero/bottom/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248076061,"owners_count":21043700,"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":[],"created_at":"2024-10-06T09:06:57.233Z","updated_at":"2025-10-23T07:33:58.485Z","avatar_url":"https://github.com/numberoverzero.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":".. image:: https://readthedocs.org/projects/bottom-docs/badge?style=flat-square\n    :target: http://bottom-docs.readthedocs.org/\n.. image:: https://img.shields.io/travis/numberoverzero/bottom/master.svg?style=flat-square\n    :target: https://travis-ci.org/numberoverzero/bottom\n.. image:: https://img.shields.io/pypi/v/bottom.svg?style=flat-square\n    :target: https://pypi.python.org/pypi/bottom\n.. image:: https://img.shields.io/github/issues-raw/numberoverzero/bottom.svg?style=flat-square\n    :target: https://github.com/numberoverzero/bottom/issues\n.. image:: https://img.shields.io/pypi/l/bottom.svg?style=flat-square\n    :target: https://github.com/numberoverzero/bottom/blob/master/LICENSE\n\nasyncio-based rfc2812-compliant IRC Client (3.8+)\n\nbottom isn't a kitchen-sink library.  Instead, it provides a consistent API\nwith a small surface area, tuned for performance and ease of extension.\nSimilar to the routing style of bottle.py, hooking into events is one line.\n\nInstallation\n============\n::\n\n    pip install bottom\n\nGetting Started\n===============\n\n(the full documentation is available here: http://bottom-docs.readthedocs.io/)\n\nCreate an instance:\n\n.. code-block:: python\n\n    import asyncio\n    import bottom\n\n    host = 'chat.freenode.net'\n    port = 6697\n    ssl = True\n\n    NICK = \"bottom-bot\"\n    CHANNEL = \"#bottom-dev\"\n\n    bot = bottom.Client(host=host, port=port, ssl=ssl)\n\n\nSend nick/user/join when connection is established:\n\n.. code-block:: python\n\n    @bot.on('CLIENT_CONNECT')\n    async def connect(**kwargs):\n        bot.send('NICK', nick=NICK)\n        bot.send('USER', user=NICK,\n                 realname='https://github.com/numberoverzero/bottom')\n\n        # Don't try to join channels until the server has\n        # sent the MOTD, or signaled that there's no MOTD.\n        done, pending = await asyncio.wait(\n            [bot.wait(\"RPL_ENDOFMOTD\"),\n             bot.wait(\"ERR_NOMOTD\")],\n            loop=bot.loop,\n            return_when=asyncio.FIRST_COMPLETED\n        )\n\n        # Cancel whichever waiter's event didn't come in.\n        for future in pending:\n            future.cancel()\n\n        bot.send('JOIN', channel=CHANNEL)\n\n\nRespond to ping:\n\n.. code-block:: python\n\n    @bot.on('PING')\n    def keepalive(message, **kwargs):\n        bot.send('PONG', message=message)\n\n\nEcho messages (channel and direct):\n\n.. code-block:: python\n\n    @bot.on('PRIVMSG')\n    def message(nick, target, message, **kwargs):\n        \"\"\" Echo all messages \"\"\"\n        # don't echo self\n        if nick == NICK: return\n        # respond directly\n        if target == NICK: target = nick\n        bot.send(\"PRIVMSG\", target=target, message=message)\n\n\nConnect and run the bot forever:\n\n.. code-block:: python\n\n    bot.loop.create_task(bot.connect())\n    bot.loop.run_forever()\n\nAPI\n===\n\nThe full API consists of 1 class, with 8 methods:\n\n.. code-block:: python\n\n    # manage connections\n\n    async Client.connect()\n    async Client.disconnect()\n\n    # send, receive, and wait for rfc-2812 messages\n\n    Client.send(command, **kwargs)\n    @Client.on(event)\n    Client.trigger(event, **kwargs)\n    async Client.wait(event)\n\n    # send and receive anything newline-terminated,\n    # provided for eg. IRCv3 extensions\n\n    Client.send_raw(message)\n    Client.handle_raw(message)\n\n\nContributors\n============\n\n* `fahhem \u003chttps://github.com/fahhem\u003e`_\n* `thebigmunch \u003chttps://github.com/thebigmunch\u003e`_\n* `tilal6991 \u003chttps://github.com/tilal6991\u003e`_\n* `AMorporkian \u003chttps://github.com/AMorporkian\u003e`_\n* `nedbat \u003chttps://github.com/nedbat\u003e`_\n* `Coinkite Inc \u003chttps://github.com/coinkite\u003e`_\n* `Johan Lorenzo \u003chttps://github.com/JohanLorenzo\u003e`_\n* `Dominik Miedziński \u003chttps://github.com/miedzinski\u003e`_\n* `Yay295 \u003chttps://github.com/Yay295\u003e`_\n* `Elijah Lazkani \u003chttps://github.com/elazkani\u003e`_\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnumberoverzero%2Fbottom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnumberoverzero%2Fbottom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnumberoverzero%2Fbottom/lists"}