68 lines
2.8 KiB
Markdown
68 lines
2.8 KiB
Markdown
# Voice
|
|
|
|
Voice state reads exist. Voice actions do not. This document records the plan and the decisions.
|
|
|
|
## Current
|
|
|
|
| Part | Status |
|
|
| --- | --- |
|
|
| `voice.get` | Implemented. One user's voice channel and its members. Without `guildId` it searches all guilds. |
|
|
| `voice.overview` | Implemented. Occupied voice channels and members for one guild. |
|
|
| `VOICE_STATE_UPDATE` events | Normalized and pushed. Mock-verified. Live check pending. |
|
|
| Join and leave | Not started. |
|
|
| Audio in and out | Not started. |
|
|
| Video | Not started. |
|
|
|
|
The core reads `VoiceStateStore` only. It never joins a call on its own.
|
|
|
|
## Planned actions
|
|
|
|
| Action | Parameters | Result |
|
|
| --- | --- | --- |
|
|
| `voice.join` | `channelId`, optional `mute` (default true) | `{ channelId, joined: true }` |
|
|
| `voice.leave` | none | `{ left: true }` |
|
|
| `voice.move` | `channelId` | `{ channelId, moved: true }` |
|
|
|
|
Rules:
|
|
|
|
- The channel must be a voice channel. The core validates the snowflake and the channel type.
|
|
- Join joins the call muted. The bot does not capture or send audio.
|
|
- Voice actions are state changes, not send floods. They stay out of the message pacing queue, but
|
|
the daemon rate limits them separately.
|
|
- The join implementation goes through Discord's internal channel action, located at runtime. The
|
|
lookup is unverified until the first live run. This is the same pattern as `reaction.add`.
|
|
|
|
The plan for later audio: the bot unmutes only while it plays an audio stream, then mutes again.
|
|
Audio playback is a later feature.
|
|
|
|
## Lifecycle
|
|
|
|
The bot leaves a call on its own in two cases.
|
|
|
|
1. **Owner leaves.** When the owner leaves the call, the bot waits `voiceLeaveDelaySeconds` and
|
|
then leaves. A rejoin inside the window cancels the leave.
|
|
2. **A stay target leaves.** The `stay @user` command pins the bot to a user. When that user
|
|
leaves, the bot waits the same delay and then leaves.
|
|
|
|
`stay @user` needs a chat command. Chat commands are paused at this time, so the command waits for
|
|
the voice backend. The default delay is proposed as 30 seconds and lives in the config.
|
|
|
|
The bot never leaves while the owner or the stay target is present. A manual `voice.leave` wins
|
|
over both rules.
|
|
|
|
## Collector account
|
|
|
|
The collector account is a stripped-down client with read-only voice membership. The daemon uses it
|
|
when the puppet cannot see a user's voice channel or the channel members. It stays deferred. See
|
|
[TODO.md](../TODO.md).
|
|
|
|
## Verification list
|
|
|
|
A live run must confirm these points.
|
|
|
|
1. The internal `selectVoiceChannel` lookup exists and joins the given channel.
|
|
2. The internal disconnect action leaves the call.
|
|
3. `VOICE_STATE_UPDATE` carries the fields that the core normalizes.
|
|
4. The join is muted and Discord shows the mute state.
|
|
5. The auto-leave timer works across a client restart. The timer is daemon state, not core state.
|