feat(discord-gateway): implement voice & push improvements

- Voice disconnect broadcast on stopRecording
- Multi-guild voice support (VoiceController Map<guildId>)
- Session finalization + auto-enqueue muxer job
- Recordings API: duration field, channelId/userId filters
- Transmitter Redis connection reuse (shared conn)
- FFmpeg stderr memory cap (4KB limit)
- 10 new Redis event channels + Redis bridge subscriptions
- New DB tables: message_reactions, message_edits
- Webhook notification module
- Gateway metrics / Prometheus endpoint
- Multi-guild message capture (MONITOR_GUILD_IDS array)
- Thread tracking, presence, channel topic, guild member events
- Edit history snapshot on message update
- Muxer audio post-processing worker

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
MythEclipse
2026-06-13 13:51:21 +07:00
co-authored by Claude
parent fd3b5c5ca5
commit 14c0081f01
17 changed files with 260 additions and 90 deletions
@@ -4,6 +4,7 @@ import {
COMMAND_VOICE_CHANNELS,
COMMAND_VOICE_CONNECT,
COMMAND_VOICE_DISCONNECT,
COMMAND_VOICE_DISCONNECT_GUILD,
CommandReply,
VOICE_STATUS_KEY,
} from "@bete/shared";
@@ -28,11 +29,19 @@ export interface Channel {
type: "voice" | "text";
}
export interface GuildVoiceEntry {
guildId: string;
channelId: string;
channelName: string;
connectedAt: number;
}
export interface VoiceStatus {
connected: boolean;
activeGuildId: string | null;
activeChannelId: string | null;
activeChannelName: string | null;
connections: GuildVoiceEntry[];
}
export const DEFAULT_VOICE_STATUS: VoiceStatus = {
@@ -40,6 +49,7 @@ export const DEFAULT_VOICE_STATUS: VoiceStatus = {
activeGuildId: null,
activeChannelId: null,
activeChannelName: null,
connections: [],
};
/**
@@ -157,3 +167,18 @@ export async function disconnectVoice(): Promise<VoiceStatus> {
"disconnectVoice",
);
}
/**
* Disconnect from a specific guild's voice channel.
*/
export async function disconnectVoiceGuild(
guildId: string,
): Promise<VoiceStatus> {
logger.info({ guildId }, "disconnectVoiceGuild called");
return withFallback(
() =>
publishCommand<VoiceStatus>(COMMAND_VOICE_DISCONNECT_GUILD, { guildId }),
() => readVoiceStatusFallback(),
"disconnectVoiceGuild",
);
}