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
@@ -210,24 +210,24 @@ export class DashboardRepository {
[...params, limit + 1],
);
const data = ((rows as Record<string, unknown>[]) || []).slice(0, limit).map((r) => ({
channel_id: String(r.channel_id),
channel_name: r.channel_name as string | null,
guild_id: r.guild_id as string | null,
total_messages: Number(r.total_messages),
flagged_count: Number(r.flagged_count),
last_message_at: r.last_message_at ? Number(r.last_message_at) : null,
culture_summary: r.culture_summary as string | null,
last_analyzed_at: r.last_analyzed_at
? Number(r.last_analyzed_at)
: null,
}));
const data = ((rows as Record<string, unknown>[]) || [])
.slice(0, limit)
.map((r) => ({
channel_id: String(r.channel_id),
channel_name: r.channel_name as string | null,
guild_id: r.guild_id as string | null,
total_messages: Number(r.total_messages),
flagged_count: Number(r.flagged_count),
last_message_at: r.last_message_at ? Number(r.last_message_at) : null,
culture_summary: r.culture_summary as string | null,
last_analyzed_at: r.last_analyzed_at
? Number(r.last_analyzed_at)
: null,
}));
const lastRow = rows[limit - 1] as Record<string, unknown> | undefined;
const nextCursor =
rows.length > limit
? String(lastRow?.total_messages ?? "")
: null;
rows.length > limit ? String(lastRow?.total_messages ?? "") : null;
return { data, nextCursor };
}
@@ -56,9 +56,7 @@ export function createDashboardRouter(): Router {
const search =
typeof req.query.search === "string" ? req.query.search : undefined;
const guildId =
typeof req.query.guild_id === "string"
? req.query.guild_id
: undefined;
typeof req.query.guild_id === "string" ? req.query.guild_id : undefined;
const result = await dashboardService.listChannels({
limit,
@@ -25,7 +25,11 @@ export class DashboardService {
return dashboardRepository.getUserDetail(userId);
}
async listChannels(query: { limit: number; search?: string; guildId?: string }) {
async listChannels(query: {
limit: number;
search?: string;
guildId?: string;
}) {
logger.debug({ query }, "Listing dashboard channels");
return dashboardRepository.listChannels(query);
}