feat: add voice recordings feature with database integration

- Implemented PostgreSQL and SQLite schemas for voice recordings.
- Created repository functions for inserting, updating, and listing voice recordings.
- Developed uploader logic to handle file uploads and database updates.
- Added routes for accessing voice recordings via API.
- Enhanced UI state to include recordings tab.
- Introduced moderation WebSocket event for uploaded recordings.
This commit is contained in:
MythEclipse
2026-05-18 20:15:38 +07:00
parent 9d5559a45b
commit 3b9e87ee6c
17 changed files with 1404 additions and 13 deletions
+1 -1
View File
@@ -1,7 +1,6 @@
import type { Router } from "express";
import express from "express";
import { AppError } from "../errors";
import type { MessageRecord } from "../moderation/types";
import {
getAnalysisQueueStatus,
queueMessageAnalysis,
@@ -11,6 +10,7 @@ import {
searchMessages,
updateMessageAIAnalysis,
} from "../moderation/messageStore";
import type { MessageRecord } from "../moderation/types";
export function createAnalysisRoutes(): Router {
const router = express.Router();
+39
View File
@@ -0,0 +1,39 @@
import {
Router,
type Request,
type Response,
type NextFunction,
} from "express";
import { listVoiceRecordings } from "../database/voiceRecordingRepo";
import { AppError } from "../errors";
import { createChildLogger } from "../logger";
const logger = createChildLogger("recordings-routes");
export function createRecordingsRoutes(): Router {
const router = Router();
router.get(
"/recordings",
async (_req: Request, res: Response, next: NextFunction) => {
try {
const recordings = await listVoiceRecordings(100);
res.json(recordings);
} catch (error) {
logger.error(
{ error: error instanceof Error ? error.message : String(error) },
"Failed to list recordings",
);
next(
new AppError(
"DATABASE_ERROR",
"Failed to retrieve voice recordings",
500,
),
);
}
},
);
return router;
}
+1 -1
View File
@@ -9,7 +9,7 @@ export interface SharedUIState {
selectedVoiceChannel: string;
selectedTextGuild: string;
selectedTextChannel: string;
activeTab: "voice" | "messages" | "media" | "review";
activeTab: "voice" | "messages" | "media" | "review" | "recordings";
isListening: boolean;
isStreaming: boolean;
}