-
Notifications
You must be signed in to change notification settings - Fork 0
Auto Voice Channels
One or more hub voice channels act as entry points. When a user joins a hub:
- The hub channel is renamed in place to the user's new channel name — the user stays in it, no move needed
- A replacement hub is created immediately in the same category
- An attached text channel is created below the voice channel — private, only visible to members in the voice channel
- A compact control panel is posted (silently) in the text channel with interactive buttons
- When the channel becomes empty, both voice + text channels are deleted after 30 seconds
Channel names track Discord rich presence (requires the Presence Intent enabled in Dev Portal) for every member in the voice channel, not just the owner. Any member's Playing X activity can drive the rename.
| Scenario | Channel name |
|---|---|
| 1 of 1 member playing Overwatch | Overwatch |
| 3 of 4 members playing Overwatch (the most-played game wins, count prefixed when more than one matches) | (3) Overwatch |
| Manually renamed via the panel, or Tryhard / Chill template | Whatever was set — also stored as the channel's fallback_name
|
| Nobody is playing anything | Reverts to the channel's fallback_name (the manual name, the initial random tech name on creation, or the last template choice) |
Pre-existing channel with no fallback_name (legacy row) |
Stays at its current name until the next manual rename or template pick |
The auto-rename is implemented in services/voice/autoNaming.ts and is shared between presenceUpdate (the live driver), the Auto / Counter template buttons, and the boot-time reconciler retry. presenceUpdate keys off the changed user's voice channel rather than the channel's owner — so a non-owner's game change can flip the channel name.
The panel is posted automatically in the private text channel as soon as the channel is created, with SuppressNotifications set so nobody is pinged. It stays the first/top message in the channel and is re-rendered on every voice-state change so the member list and timestamps stay current.
Layout (Components V2):
🔊 host @owner · created <t:N:R>
👥 In channel
• @member-a joined <t:N:R> · 🎮 Overwatch
• @member-b joined <t:N:R>
[Rename] [Hosts] [Templates]
[Locked / Unlocked] [Visible / Hidden] [Claim] [Delete]
A silent 📋 Open Panel sticky message lives at the bottom of the text channel so the panel is always one click away — the sticky is a single non-CV2 button (no header / warning text). Use /voice from any channel to get an ephemeral copy too.
Toggle buttons show the current state, not the pending action — same convention as the profile birthday-pings / year toggles and the /games view/pings buttons.
| Button | Current state ‑ green | Current state ‑ red |
|---|---|---|
| Lock |
Unlocked (anyone can join) |
Locked (@everyone Connect denied) |
| Hide | Visible |
Hidden |
Click to flip. The button label updates immediately because the panel re-renders on every state change.
| Button | Who can use | What it does |
|---|---|---|
| ✏️ Rename | Owner, hosts, sudo | Modal to set a custom name (also updates fallback_name) |
| 👑 Hosts | Owner, hosts, sudo | One panel listing every member with their current rank emoji (👑 host · 🛡️ sudo · 👤 member). Click toggles host status. |
| 📋 Templates | Owner, hosts, sudo | Auto / Counter ([x/y]) / Comp 5-stack / Tryhard / Chill — sets name + user limit in one click. Tryhard / Chill also overwrite fallback_name. |
| 🔒/🔓 Locked / Unlocked | Owner, hosts, sudo | Toggles @everyone Connect |
| 🙈/👁️ Hidden / Visible | Owner, hosts, sudo | Toggles channel visibility |
| 👤 Claim | Anyone in channel | Claim ownership when owner has left |
| 🗑️ Delete | Owner, hosts, sudo | Deletes both channels right away |
| Who | Access |
|---|---|
| @everyone | Denied (hidden) |
| Bot | Full access (send, manage) |
| Channel owner | View + send + read history |
| Hosts | View + send + read history |
| Members in voice channel | View + send + read history (added on join, removed on leave) |
| Sudo roles | View + send + manage messages |
When the owner leaves the voice channel and others remain, ownership automatically transfers to the longest-present remaining member. The control panel updates to reflect the new owner. The original owner can reclaim with the 👤 Claim button if they rejoin.
auto_channels holds the per-channel config (guild ID, voice channel ID, text channel ID, owner, hosts, allowed users/roles, lock state, hidden state, user limit, auto_name_enabled, name_template, fallback_name, control panel message ID, cleanup timestamp, source hub ID).
auto_channel_members(voice_channel_id, user_id, joined_at) backs the panel's "In channel" list. Written from voiceStateUpdate on join (upsert) and leave (delete). On boot, the reconciler:
- Backfills currently-occupying members at
now()(so old times pre-restart are lost but new joins are tracked accurately). - Re-runs the auto-rename for any tracked auto channel where the owner is currently in the channel and playing a game (and
auto_name_enabledis on) — closes the gap where presence updates between bot restarts were lost.
Set in .env (or override at runtime via /sudo → Settings → Voice / Hub Channels):
-
AUTO_VOICE_CATEGORY_ID— the Discord category that contains both hubs and auto channels -
HUB_CHANNEL_IDS— legacy comma-separated voice channel IDs that act as hubs (one-time seed; runtime list lives in thehub_channelstable) -
VOICE_CLEANUP_DELAY_MS— how long to wait before deleting empty channels (default: 30000)