-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Summary
Add a module that lets server admins mark specific voice channels as multiplexable. When a user joins a multiplexable channel, the bot automatically creates a new breakout voice channel. When the last user leaves a breakout channel, it is deleted after a short grace period.
Motivation
Servers with active voice communities often run into the problem of either having too many permanent voice channels (cluttered) or too few (users have to manually create them). Auto-creating channels on demand keeps the channel list clean while always having capacity available.
Desired Behavior
Enabling a channel
- An admin command marks an existing voice channel as a source channel (multiplexable).
- The source channel acts as a "lobby" — joining it triggers the creation of a breakout channel.
Channel creation
- When a user joins a source channel, the bot:
- Creates a new voice channel in the same category (or a configured category).
- Moves the user into the new breakout channel.
- Names the breakout channel based on a configurable pattern (e.g.,
General #2,General #3, or🎮 Breakout 1). - Copies permission overwrites from the source channel (or a configured template).
- Joining an already-created breakout channel should not create another channel — only the source channel triggers creation.
Channel deletion
- When the last user leaves a breakout channel, start a grace period (e.g., 30–60 seconds, configurable per source channel).
- If the channel is still empty after the grace period, delete it.
- If someone rejoins during the grace period, cancel the deletion.
Tracking
- The bot must track which breakout channels belong to which source channel.
- On bot restart, the bot should reconcile state: check tracked breakout channels and clean up any that are empty (with grace period).
Proposed Commands
/autochannel enable <voice_channel> [naming_pattern] [user_limit] [grace_period]
Mark a voice channel as a source channel.
| Parameter | Type | Default | Description |
|---|---|---|---|
voice_channel |
VoiceChannel |
required | The source/lobby channel |
naming_pattern |
str |
{name} #{n} |
Pattern for breakout names. {name} = source name, {n} = incrementing number |
user_limit |
int |
0 (unlimited) |
User limit for created breakout channels |
grace_period |
int |
30 |
Seconds to wait before deleting an empty breakout |
/autochannel disable <voice_channel>
Remove a source channel. Optionally delete all existing breakout channels for it.
/autochannel list
Show all configured source channels and their active breakout channels.
Implementation Notes
Event-driven approach
Use @Cog.listener() on on_voice_state_update(member, before, after):
- Join source channel → create breakout + move member
- Leave breakout channel → if empty, schedule grace-period deletion via
asynciotask - Join breakout channel during grace period → cancel pending deletion
No polling loop required — Discord's voice state events cover all transitions.
Grace period handling
Use asyncio.create_task() with a sleep + recheck pattern:
async def _schedule_deletion(self, channel, grace_seconds):
await asyncio.sleep(grace_seconds)
if len(channel.members) == 0:
await channel.delete(reason="Autochannel: breakout empty after grace period")
# remove from trackingStore pending deletion tasks in a dict keyed by channel ID so they can be cancelled on rejoin.
Database model
AutoChannel — source channel configuration (new table, no migration needed):
| Column | Type | Purpose |
|---|---|---|
| Id | Integer (PK) | Auto-increment |
| GuildId | BigInteger | Discord guild ID |
| SourceChannelId | BigInteger | The multiplexable voice channel |
| NamingPattern | String | Template for breakout names |
| UserLimit | Integer | User limit for breakouts (0 = unlimited) |
| GracePeriod | Integer | Seconds before empty breakout deletion |
AutoChannelBreakout — tracks active breakout channels (new table):
| Column | Type | Purpose |
|---|---|---|
| Id | Integer (PK) | Auto-increment |
| GuildId | BigInteger | Discord guild ID |
| SourceChannelId | BigInteger | FK to source channel |
| BreakoutChannelId | BigInteger | The created breakout channel |
| CreatedAt | DateTime | When the breakout was created |
Startup reconciliation
On cog_load / setup, after wait_until_ready():
- Query all tracked breakout channels.
- For each, check if the Discord channel still exists and has members.
- If missing from Discord → remove from DB.
- If empty → schedule grace-period deletion.
Permissions
- Bot needs Manage Channels and Move Members permissions.
- Commands should require
manage_channelspermission from the invoking user.
Edge Cases to Handle
- Source channel is deleted while breakouts exist → clean up breakouts + DB entries
- Bot lacks permissions to create/delete channels → log error, notify channel
- Breakout channel is manually deleted → remove from tracking on next voice state event or audit log
- Rate limits on channel creation → queue creation requests if Discord rate-limits apply
- Multiple users join the source channel simultaneously → ensure only one breakout is created per join event (or one per user, depending on desired behavior)
Module Name Suggestion
autochannel — added to config.yaml modules list to enable.