Backend (real implementations, no more stubs):
- Redis pub/sub bridge: subscribes to discord-gateway events (message/attachment/voice) and broadcasts to WS clients
- Redis command channel: backend publishes voice/media commands, discord-gateway executes and replies
- Voice service: connectVoice/disconnectVoice/getVoiceStatus via Redis commands with graceful fallback
- Media service: queue/skip/stop/volume via Redis commands, reads status from Redis cache
- Messages repository: ALL 7 methods now use real PostgreSQL queries (findMany, findById, findByChannel, create, update, delete, getAttachmentsByChannel)
- Analytics: period returns {start,end} epoch millis, overview includes hourly/topics/top_users, worst_flags as string[]
- Health check: actually queries SELECT 1 against database
- VoiceStatus type fixed: {connected, activeGuildId, activeChannelId, activeChannelName}
- Guild type: includes icon: string | null
- asyncHandler: accepts Promise<unknown> instead of Promise<void>
Discord Gateway:
- CommandHandler: subscribes to 'backend:command' Redis channel, executes voice/media commands, publishes replies
- Publishes voice:status and media:status to Redis for backend caching
- Shutdown handler updated to close command handler
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
46 lines
1.5 KiB
TypeScript
46 lines
1.5 KiB
TypeScript
/**
|
|
* Global broadcast functions for WebSocket events.
|
|
*
|
|
* These are assigned by ws/server.ts when the WebSocket server initializes.
|
|
* Other modules call them to push real-time events to connected frontend clients.
|
|
*
|
|
* Usage:
|
|
* import { broadcastMessageCreated } from "../ws/broadcast.js";
|
|
* broadcastMessageCreated(messageData);
|
|
*/
|
|
|
|
type BroadcastFn = (data: unknown) => void;
|
|
type BroadcastRawFn = (type: string, data: unknown) => void;
|
|
|
|
// Extend globalThis with broadcast function types
|
|
declare global {
|
|
// biome-ignore lint/suspicious/noAssignInExpressions: intentional global broadcast registry
|
|
var __broadcastFns:
|
|
| {
|
|
messageCreated: BroadcastFn;
|
|
messageUpdated: BroadcastFn;
|
|
messageDeleted: BroadcastFn;
|
|
attachmentUploaded: BroadcastFn;
|
|
raw: BroadcastRawFn;
|
|
}
|
|
| undefined;
|
|
}
|
|
|
|
const noop: BroadcastFn = () => {};
|
|
const noopRaw: BroadcastRawFn = () => {};
|
|
|
|
export const broadcastMessageCreated: BroadcastFn = (data) =>
|
|
(globalThis.__broadcastFns?.messageCreated ?? noop)(data);
|
|
|
|
export const broadcastMessageUpdated: BroadcastFn = (data) =>
|
|
(globalThis.__broadcastFns?.messageUpdated ?? noop)(data);
|
|
|
|
export const broadcastMessageDeleted: BroadcastFn = (data) =>
|
|
(globalThis.__broadcastFns?.messageDeleted ?? noop)(data);
|
|
|
|
export const broadcastAttachmentUploaded: BroadcastFn = (data) =>
|
|
(globalThis.__broadcastFns?.attachmentUploaded ?? noop)(data);
|
|
|
|
export const broadcastRaw: BroadcastRawFn = (type, data) =>
|
|
(globalThis.__broadcastFns?.raw ?? noopRaw)(type, data);
|