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
+10 -5
View File
@@ -28,6 +28,7 @@ import { createMessageRoutes } from "./routes/messageRoutes";
import { createSyncRoutes } from "./routes/syncRoutes";
import { createUIStateRoutes } from "./routes/uiStateRoutes";
import { createVoiceRoutes } from "./routes/voiceRoutes";
import { createRecordingsRoutes } from "./routes/recordingsRoutes";
import { Streamer } from "./streaming";
import type { VoiceController } from "./voiceController";
@@ -56,7 +57,7 @@ interface SharedUIState {
selectedVoiceChannel: string;
selectedTextGuild: string;
selectedTextChannel: string;
activeTab: "voice" | "messages" | "media" | "review";
activeTab: "voice" | "messages" | "media" | "review" | "recordings";
isListening: boolean;
isStreaming: boolean;
}
@@ -94,11 +95,11 @@ export function normalizeSharedUIState(
selectedVoiceChannel: value.selectedVoiceChannel ?? "",
selectedTextGuild: value.selectedTextGuild ?? guild,
selectedTextChannel: value.selectedTextChannel ?? "",
activeTab: (["voice", "messages", "media", "review"].includes(
activeTab: (["voice", "messages", "media", "review", "recordings"].includes(
value.activeTab ?? "",
)
? value.activeTab
: "voice") as "voice" | "messages" | "media" | "review",
: "voice") as "voice" | "messages" | "media" | "review" | "recordings",
isListening: value.isListening ?? false,
isStreaming: value.isStreaming ?? false,
};
@@ -143,13 +144,16 @@ function patchSharedUIState(patch: SharedUIStatePatch) {
sharedUIState.selectedTextChannel = patch.selectedTextChannel;
}
if (
["voice", "messages", "media", "review"].includes(patch.activeTab ?? "")
["voice", "messages", "media", "review", "recordings"].includes(
patch.activeTab ?? "",
)
) {
sharedUIState.activeTab = patch.activeTab as
| "voice"
| "messages"
| "media"
| "review";
| "review"
| "recordings";
}
if (typeof patch.isListening === "boolean") {
sharedUIState.isListening = patch.isListening;
@@ -325,6 +329,7 @@ export async function startWebserver(
app.use("/api", createMessageRoutes());
app.use("/api", createAnalysisRoutes());
app.use("/api", createSyncRoutes(_client));
app.use("/api", createRecordingsRoutes());
app.use(
"/api",
createMediaRoutes(mediaController, {