Services & Extensions¶
Services encapsulate long-lived Discord behaviour, while extensions expose the asynchronous setup hook that registers
those services and any associated cogs.
Service catalog¶
| Service | Module / Class | Responsibilities |
|---|---|---|
| API client | extensions/api_service.py → APIService |
Maintains an authenticated aiohttp session to the API and exposes helpers for maps, completions, playtests, and notifications. Stored on bot.api. |
| RabbitMQ | extensions/rabbit.py → RabbitHandler |
Connects to RabbitMQ using pooled channels, declares queues (and DLQs), wraps handlers registered through queue_consumer, and exposes helpers such as publish and wait_until_drained. Stored on bot.rabbit. |
| Notifications | extensions/notifications.py → NotificationHandler |
Determines whether a user has opted into specific notification bitmasks and sends DMs or channel pings accordingly. Stored on bot.notifications. |
| Newsfeed | extensions/newsfeed.py → NewsfeedHandler |
Registers builders for each newsfeed payload type, publishes events into the configured channel, and consumes api.newsfeed.create messages. Stored on bot.newsfeed. |
| Completions | extensions/completions.py → CompletionHandler |
Resolves verification channels, renders verification views, emits follow-up newsfeed events, and handles completion-related queues. Stored on bot.completions. |
| Playtest | extensions/playtest.py → PlaytestHandler |
Manages playtest threads, queue-driven state changes, and XP grants tied to votes. Stored on bot.playtest. |
| XP | extensions/xp.py → XPHandler |
Resolves XP channels, applies XP grants from the api.xp.grant queue, and exposes helpers for other services to award XP. Stored on bot.xp. |
| Map edits | extensions/moderator.py → MapEditHandler |
Manages map edit verification views and listens to map edit queues. Stored on bot.map_editor. |
| Thumbnails | extensions/video_thumbnail.py → VideoThumbnailHandler |
Generates video thumbnails for embeds and newsfeed entries. Stored on bot.thumbnail_service. |
Extend this table as new extensions ship so there is a single map of the long-lived services attached to the bot instance.
Extension anatomy¶
- Setup hook: Each extension defines
async def setup(bot)and attaches services, cogs, or background tasks. - Shared state: Handlers either use property setters on
Genji(for examplebot.api) or inherit fromutilities.base.BaseHandlerto gain guild/channel resolution helpers. - Queue registration: Background work is tied to RabbitMQ queues by decorating handler coroutines with
@queue_consumer("queue-name"). - Cross-extension collaboration: Handlers call into one another via the properties on
bot. For example, the completions flow callsbot.apito fetch payloads, usesbot.notificationsto determine DM preferences, and leveragesbot.xpto grant XP during verification updates.
BaseHandler¶
The utilities.base.BaseHandler class provides common functionality for services:
from utilities.base import BaseHandler
class MyService(BaseHandler):
async def _resolve_channels(self) -> None:
"""Called after bot is ready and guild is resolved."""
self.my_channel = await self.guild.fetch_channel(channel_id)
async def do_work(self) -> None:
"""Service methods can access self.guild and resolved channels."""
await self.my_channel.send("Hello!")
Features:
- Automatic guild resolution
- Channel resolution hook
- Access to bot instance
Creating a New Extension¶
To add a new feature to the bot:
-
Create the extension file:
-
Define the setup function:
-
Optionally create a service:
-
Register queue handlers (if needed):
-
Import in
extensions/__init__.py:
Document queues, commands, and presentation helpers in the relevant sections when adding new functionality so future contributors can follow the established patterns.
Next Steps¶
- Core Bot Lifecycle - Understand bot startup
- Messaging & Queues - Learn about queue handlers
- Newsfeed & Embeds - UI guidelines
- Configuration - Configure the bot