Skip to content

auto-create breakout voice channels on join #176

@karaktaka

Description

@karaktaka

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:
    1. Creates a new voice channel in the same category (or a configured category).
    2. Moves the user into the new breakout channel.
    3. Names the breakout channel based on a configurable pattern (e.g., General #2, General #3, or 🎮 Breakout 1).
    4. 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 asyncio task
  • 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 tracking

Store 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():

  1. Query all tracked breakout channels.
  2. For each, check if the Discord channel still exists and has members.
  3. If missing from Discord → remove from DB.
  4. If empty → schedule grace-period deletion.

Permissions

  • Bot needs Manage Channels and Move Members permissions.
  • Commands should require manage_channels permission 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions