refactor: replace Database type with SqliteDatabase in moderation modules

This commit is contained in:
MythEclipse
2026-05-13 19:47:44 +07:00
parent 471e3bac82
commit 9f09f5ef28
5 changed files with 78 additions and 20 deletions

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@ node_modules
recordings recordings
.env .env
dist/ dist/
.muxer-queue.db

View File

@@ -1,7 +1,7 @@
import { createChildLogger } from "../logger"; import { createChildLogger } from "../logger";
import { config } from "../config"; import { config } from "../config";
import { retryWithBackoff } from "../retry"; import { retryWithBackoff } from "../retry";
import type Database from "better-sqlite3"; import type { SqliteDatabase } from "../muxer-queue";
import { updateAttachmentAsUploaded, updateAttachmentAsFailedUpload } from "./messageStore"; import { updateAttachmentAsUploaded, updateAttachmentAsFailedUpload } from "./messageStore";
const logger = createChildLogger("attachment-uploader"); const logger = createChildLogger("attachment-uploader");
@@ -109,7 +109,7 @@ export async function downloadDiscordAttachment(url: string): Promise<Buffer> {
} }
export async function processAttachmentUpload( export async function processAttachmentUpload(
db: Database.Database, db: SqliteDatabase,
attachmentId: string, attachmentId: string,
discordUrl: string, discordUrl: string,
filename: string, filename: string,

View File

@@ -1,6 +1,6 @@
import type { Client, Message, TextChannel, ThreadChannel } from "discord.js-selfbot-v13"; import type { Client, Message, TextChannel, ThreadChannel } from "discord.js-selfbot-v13";
import type Database from "better-sqlite3";
import { createChildLogger } from "../logger"; import { createChildLogger } from "../logger";
import type { SqliteDatabase } from "../muxer-queue";
import { config } from "../config"; import { config } from "../config";
import { insertMessage, insertAttachment } from "./messageStore"; import { insertMessage, insertAttachment } from "./messageStore";
import { processAttachmentUpload } from "./attachmentUploader"; import { processAttachmentUpload } from "./attachmentUploader";
@@ -9,7 +9,7 @@ import type { MessageRecord, AttachmentRecord } from "./types";
const logger = createChildLogger("message-capture"); const logger = createChildLogger("message-capture");
async function captureMessage( async function captureMessage(
db: Database.Database, db: SqliteDatabase,
message: Message, message: Message,
type: "text" | "edited" | "deleted", type: "text" | "edited" | "deleted",
): Promise<void> { ): Promise<void> {
@@ -101,7 +101,7 @@ async function captureMessage(
); );
} }
export function registerMessageCapture(client: Client, db: Database.Database): void { export function registerMessageCapture(client: Client, db: SqliteDatabase): void {
client.on("messageCreate", async (message) => { client.on("messageCreate", async (message) => {
if (!message.guildId || message.guildId !== config.MONITOR_GUILD_ID) return; if (!message.guildId || message.guildId !== config.MONITOR_GUILD_ID) return;
if (message.author?.bot) return; if (message.author?.bot) return;

View File

@@ -1,10 +1,10 @@
import type Database from "better-sqlite3";
import { createChildLogger } from "../logger"; import { createChildLogger } from "../logger";
import type { SqliteDatabase } from "../muxer-queue";
import type { MessageRecord, AttachmentRecord } from "./types"; import type { MessageRecord, AttachmentRecord } from "./types";
const logger = createChildLogger("message-store"); const logger = createChildLogger("message-store");
export function insertMessage(db: Database.Database, message: MessageRecord): void { export function insertMessage(db: SqliteDatabase, message: MessageRecord): void {
try { try {
const stmt = db.prepare(` const stmt = db.prepare(`
INSERT INTO messages ( INSERT INTO messages (
@@ -41,7 +41,7 @@ export function insertMessage(db: Database.Database, message: MessageRecord): vo
} }
export function updateMessageAsEdited( export function updateMessageAsEdited(
db: Database.Database, db: SqliteDatabase,
messageId: string, messageId: string,
editedContent: string, editedContent: string,
editedAt: number, editedAt: number,
@@ -65,7 +65,7 @@ export function updateMessageAsEdited(
} }
export function updateMessageAsDeleted( export function updateMessageAsDeleted(
db: Database.Database, db: SqliteDatabase,
messageId: string, messageId: string,
deletedAt: number, deletedAt: number,
): void { ): void {
@@ -88,7 +88,7 @@ export function updateMessageAsDeleted(
} }
export function getMessagesByChannel( export function getMessagesByChannel(
db: Database.Database, db: SqliteDatabase,
channelId: string, channelId: string,
limit: number = 50, limit: number = 50,
offset: number = 0, offset: number = 0,
@@ -112,7 +112,7 @@ export function getMessagesByChannel(
} }
} }
export function insertAttachment(db: Database.Database, attachment: AttachmentRecord): void { export function insertAttachment(db: SqliteDatabase, attachment: AttachmentRecord): void {
try { try {
const stmt = db.prepare(` const stmt = db.prepare(`
INSERT INTO attachments ( INSERT INTO attachments (
@@ -149,7 +149,7 @@ export function insertAttachment(db: Database.Database, attachment: AttachmentRe
} }
export function getAttachmentsByChannel( export function getAttachmentsByChannel(
db: Database.Database, db: SqliteDatabase,
channelId: string, channelId: string,
limit: number = 50, limit: number = 50,
offset: number = 0, offset: number = 0,
@@ -174,7 +174,7 @@ export function getAttachmentsByChannel(
} }
export function updateAttachmentAsUploaded( export function updateAttachmentAsUploaded(
db: Database.Database, db: SqliteDatabase,
attachmentId: string, attachmentId: string,
uploadedUrl: string, uploadedUrl: string,
uploadedAt: number, uploadedAt: number,
@@ -198,7 +198,7 @@ export function updateAttachmentAsUploaded(
} }
export function updateAttachmentAsFailedUpload( export function updateAttachmentAsFailedUpload(
db: Database.Database, db: SqliteDatabase,
attachmentId: string, attachmentId: string,
error: string, error: string,
): void { ): void {

View File

@@ -1,9 +1,21 @@
import path from "node:path"; import path from "node:path";
import Database from "better-sqlite3"; import { Database } from "bun:sqlite";
import { createChildLogger } from "./logger"; import { createChildLogger } from "./logger";
const logger = createChildLogger("muxer-queue"); const logger = createChildLogger("muxer-queue");
export interface SqliteStatement {
run: (...params: unknown[]) => { changes: number };
all: (...params: unknown[]) => unknown[];
get: (...params: unknown[]) => unknown;
}
export interface SqliteDatabase {
prepare: (sql: string) => SqliteStatement;
exec: (sql: string) => void;
close: () => void;
}
export interface MuxerJobData { export interface MuxerJobData {
userId: string; userId: string;
sessionId: string; sessionId: string;
@@ -23,13 +35,14 @@ interface StoredJob {
} }
const dbPath = path.join(process.cwd(), ".muxer-queue.db"); const dbPath = path.join(process.cwd(), ".muxer-queue.db");
let db: Database.Database | null = null; let db: SqliteDatabase | null = null;
function initializeDatabase(): Database.Database { function initializeDatabase(): SqliteDatabase {
const database = new Database(dbPath); const database = new Database(dbPath) as SqliteDatabase;
database.pragma("journal_mode = WAL");
database.exec(` database.exec(`
PRAGMA journal_mode = WAL;
CREATE TABLE IF NOT EXISTS muxer_jobs ( CREATE TABLE IF NOT EXISTS muxer_jobs (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
data TEXT NOT NULL, data TEXT NOT NULL,
@@ -43,12 +56,56 @@ function initializeDatabase(): Database.Database {
CREATE INDEX IF NOT EXISTS idx_status ON muxer_jobs(status); CREATE INDEX IF NOT EXISTS idx_status ON muxer_jobs(status);
CREATE INDEX IF NOT EXISTS idx_createdAt ON muxer_jobs(createdAt); CREATE INDEX IF NOT EXISTS idx_createdAt ON muxer_jobs(createdAt);
CREATE TABLE IF NOT EXISTS messages (
id TEXT PRIMARY KEY,
guild_id TEXT NOT NULL,
channel_id TEXT NOT NULL,
thread_id TEXT,
user_id TEXT NOT NULL,
username TEXT NOT NULL,
avatar_url TEXT,
content TEXT NOT NULL,
edited_content TEXT,
created_at INTEGER NOT NULL,
edited_at INTEGER,
deleted_at INTEGER,
type TEXT NOT NULL DEFAULT 'text',
metadata TEXT
);
CREATE INDEX IF NOT EXISTS idx_messages_channel ON messages(channel_id);
CREATE INDEX IF NOT EXISTS idx_messages_user ON messages(user_id);
CREATE INDEX IF NOT EXISTS idx_messages_created ON messages(created_at DESC);
CREATE INDEX IF NOT EXISTS idx_messages_thread ON messages(thread_id);
CREATE TABLE IF NOT EXISTS attachments (
id TEXT PRIMARY KEY,
message_id TEXT NOT NULL,
guild_id TEXT NOT NULL,
channel_id TEXT NOT NULL,
user_id TEXT NOT NULL,
filename TEXT NOT NULL,
size INTEGER NOT NULL,
type TEXT NOT NULL,
discord_url TEXT NOT NULL,
uploaded_url TEXT,
upload_status TEXT NOT NULL DEFAULT 'pending',
upload_error TEXT,
created_at INTEGER NOT NULL,
uploaded_at INTEGER,
FOREIGN KEY (message_id) REFERENCES messages(id)
);
CREATE INDEX IF NOT EXISTS idx_attachments_channel ON attachments(channel_id);
CREATE INDEX IF NOT EXISTS idx_attachments_message ON attachments(message_id);
CREATE INDEX IF NOT EXISTS idx_attachments_status ON attachments(upload_status);
`); `);
return database; return database;
} }
function getDatabase(): Database.Database { function getDatabase(): SqliteDatabase {
if (!db) { if (!db) {
db = initializeDatabase(); db = initializeDatabase();
} }