refactor: atomic, DRY, and logging improvements

- Shared Redis channel constants as single source of truth (redis-channels.ts)
- commandHandler.ts split into VoiceHandler, MediaHandler, GuildHandler,
  ModerationHandler with handler-registry.ts dispatch
- messageStore.ts (1322 lines) split into domain-specific DB files:
  messages.db.ts, attachments.db.ts, reviews.db.ts,
  moderation-actions.db.ts, retention.db.ts
- recorder.ts startSpeaking callback extracted into speakingHandler.ts,
  streamSetup.ts, segmentFinalizer.ts
- autoDeleteManager.ts split into autoDeleteEligibility.ts,
  autoDeleteNotify.ts, autoDeleteLogger.ts
- Added createChildLogger() logging across 8 service files
- Backend messages.repository.ts migrated from raw SQL to Drizzle ORM
- Fixed biome.json to exclude packages/**/dist/* from lint
- Fixed config.ts GUILD_ID pre-existing type error

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
MythEclipse
2026-06-09 17:34:18 +07:00
co-authored by Claude Opus 4.8
parent 7108f6bb47
commit b68789fffc
37 changed files with 3620 additions and 2345 deletions
+1
View File
@@ -2,4 +2,5 @@ export * from "./config/index.js";
export * from "./errors/index.js";
export * from "./logger/index.js";
export * from "./moderation-types.js";
export * from "./redis-channels.js";
export * from "./utils/index.js";
+84
View File
@@ -0,0 +1,84 @@
// ---------------------------------------------------------------------------
// Redis Channel Constants — single source of truth
//
// All Redis channel names, status keys, and command types used for
// inter-service communication between discord-gateway and backend.
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// Event channels (discord-gateway -> backend via pub/sub)
// ---------------------------------------------------------------------------
export const DISCORD_MESSAGE_CREATED = "discord:message:created";
export const DISCORD_MESSAGE_UPDATED = "discord:message:updated";
export const DISCORD_MESSAGE_DELETED = "discord:message:deleted";
export const DISCORD_MESSAGE_ANALYZED = "discord:message:analyzed";
export const DISCORD_ATTACHMENT_CREATED = "discord:attachment:created";
export const DISCORD_ATTACHMENT_UPLOADED = "discord:attachment:uploaded";
export const DISCORD_VOICE_STARTED = "discord:voice:started";
export const DISCORD_VOICE_STOPPED = "discord:voice:stopped";
export const DISCORD_VOICE_UPLOADED = "discord:voice:uploaded";
export const DISCORD_VOICE_ACTIVE_USER = "discord:voice:active_user";
export const DISCORD_VOICE_PCM = "discord:voice:pcm";
export const DISCORD_ANALYSIS_QUEUE_STATUS = "discord:analysis:queue_status";
// ---------------------------------------------------------------------------
// Command channels (backend -> discord-gateway)
// ---------------------------------------------------------------------------
export const BACKEND_COMMAND = "backend:command";
export const BACKEND_VOICE_TRANSMIT = "backend:voice:transmit";
export const BACKEND_COMMAND_REPLY_PREFIX = "backend:command:reply:";
// ---------------------------------------------------------------------------
// Status keys (set by discord-gateway, read by backend via Redis GET)
// ---------------------------------------------------------------------------
export const VOICE_STATUS_KEY = "voice:status";
export const MEDIA_STATUS_KEY = "media:status";
// ---------------------------------------------------------------------------
// Command types (used as the `type` field in CommandMessage envelopes)
// ---------------------------------------------------------------------------
export const COMMAND_VOICE_CONNECT = "voice:connect";
export const COMMAND_VOICE_DISCONNECT = "voice:disconnect";
export const COMMAND_VOICE_CHANNELS = "voice:channels";
export const COMMAND_VOICE_TRANSMIT_START = "voice:transmit:start";
export const COMMAND_VOICE_TRANSMIT_STOP = "voice:transmit:stop";
export const COMMAND_GUILDS_LIST = "guilds:list";
export const COMMAND_GUILDS_TEXT_CHANNELS = "guilds:text-channels";
export const COMMAND_MEDIA_QUEUE = "media:queue";
export const COMMAND_MEDIA_SKIP = "media:skip";
export const COMMAND_MEDIA_STOP = "media:stop";
export const COMMAND_MEDIA_VOLUME = "media:volume";
export const COMMAND_MODERATION_ACTION = "moderation:action";
// ---------------------------------------------------------------------------
// Event envelope — used by discord-gateway when publishing to Redis
// ---------------------------------------------------------------------------
export interface DiscordGatewayEvent {
type: string;
data: unknown;
timestamp: number;
source: string;
}
// ---------------------------------------------------------------------------
// Command envelope — used by backend when publishing to backend:command
// ---------------------------------------------------------------------------
export interface CommandMessage {
id: string;
type: string;
payload: Record<string, unknown>;
replyChannel: string;
}
export interface CommandReply<T = unknown> {
id: string;
success: boolean;
data?: T;
error?: string;
}