{"id":28899192,"url":"https://github.com/s4w3d0ff/pool-guy","last_synced_at":"2026-03-02T17:33:39.119Z","repository":{"id":270538874,"uuid":"910633123","full_name":"s4w3d0ff/pool-guy","owner":"s4w3d0ff","description":"When you need someone to maintain and clean your kiddie pool during twitch live streams, but can't rely on streamelements to get it done.","archived":false,"fork":false,"pushed_at":"2025-09-04T03:57:10.000Z","size":354,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-01-25T11:44:54.809Z","etag":null,"topics":["api","async","chatbot","eventsub","twitch","websocket"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/s4w3d0ff.png","metadata":{"files":{"readme":"README.md","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-12-31T22:04:11.000Z","updated_at":"2025-09-04T03:57:14.000Z","dependencies_parsed_at":"2025-01-01T06:15:20.454Z","dependency_job_id":"43132bc6-9832-44cd-a8c5-010e2bbe18de","html_url":"https://github.com/s4w3d0ff/pool-guy","commit_stats":null,"previous_names":["s4w3d0ff/pool-guy"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/s4w3d0ff/pool-guy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s4w3d0ff%2Fpool-guy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s4w3d0ff%2Fpool-guy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s4w3d0ff%2Fpool-guy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s4w3d0ff%2Fpool-guy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/s4w3d0ff","download_url":"https://codeload.github.com/s4w3d0ff/pool-guy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s4w3d0ff%2Fpool-guy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30011965,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-02T17:00:27.440Z","status":"ssl_error","status_checked_at":"2026-03-02T17:00:03.402Z","response_time":60,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["api","async","chatbot","eventsub","twitch","websocket"],"created_at":"2025-06-21T08:08:06.761Z","updated_at":"2026-03-02T17:33:39.085Z","avatar_url":"https://github.com/s4w3d0ff.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pool Guy 🏊‍♂️\n\nA lightweight Twitch bot framework.\n\n[![Python Version](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/downloads/)\n[![License](https://img.shields.io/badge/license-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)\n\n## Features\n\n- EventSub websocket handling\n- Priority queue for EventSub notifications\n- Bot command and ratelimit decorators\n- Framework to support multiple storage backends\n\n## Limitations:\n- Conduit/shards are not implimented\n- Only uses \"[OIDC authorization code grant flow](https://dev.twitch.tv/docs/authentication/#authentication-flows)\" for oauth tokens\n\n\n## Quick Setup\n\n### Install from pypi:\n```bash\npip install poolguy\n```\n\n### Install directly from git:\n```bash\npip install git+https://github.com/s4w3d0ff/pool-guy.git\n```\n\n### Simple Command Bot:\n```python\nimport asyncio\nimport logging\nfrom poolguy import CommandBot, Alert, command, rate_limit\n\nlogger = logging.getLogger(__name__)\n\n\nclass ExampleBot(CommandBot):\n    @command(name=\"hi\", aliases=[\"hello\"])\n    @rate_limit(calls=1, period=10, warn_cooldown=5)\n    async def hi(self, user, channel, args):\n        await self.send_chat(f\"Hi, @{user['username']}\", channel[\"broadcaster_id\"])\n\n    async def my_loop(self):\n        logger.warning(f'my_loop started')\n        while self.ws._running:\n            await asyncio.sleep(10)\n            logger.info(f\"loop\")\n        logger.warning(f'my_loop stopped')\n\n    async def after_login(self):\n        await self.add_task(self.my_loop)\n\n\nclass ChannelChatMessageAlert(Alert):\n    \"\"\"channel.chat.message\"\"\"\n    queue_skip = True\n    store = False\n    priority = 3\n\n    async def process(self):\n        logger.debug(f'{self.data}')\n        await self.bot.command_check(self.data)\n        logger.info(f'[Chat] {self.data[\"chatter_user_name\"]}: {self.data[\"message\"][\"text\"]}')\n\n\nif __name__ == '__main__':\n    import os\n    from rich.logging import RichHandler\n    logging.basicConfig(\n        format=\"%(message)s\",\n        datefmt=\"%X\",\n        level=logging.INFO,\n        handlers=[RichHandler(rich_tracebacks=True)]\n    )\n    bot = ExampleBot(\n        client_id=os.getenv(\"CLIENT_ID\"),\n        client_secret=os.getenv(\"CLIENT_SECRET\"),\n        redirect_uri=\"http://localhost:5000/callback\",\n        scopes=[\n            \"user:read:chat\",\n            \"user:write:chat\"\n        ],\n        channels={\n            \"channel.chat.message\": None\n        },\n        browser={\n            \"chrome\": \"C:\\\\Program Files\\\\Google\\\\Chrome\\\\Application\\\\chrome.exe\"\n        },\n        alert_objs={\n            \"channel.chat.message\": ChannelChatMessageAlert\n        }\n    )\n    asyncio.run(bot.start())\n    \n```\nMore fleshed out example: https://github.com/s4w3d0ff/deezbot\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fs4w3d0ff%2Fpool-guy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fs4w3d0ff%2Fpool-guy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fs4w3d0ff%2Fpool-guy/lists"}