refactor: replace Database type with SqliteDatabase in moderation modules
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@ node_modules
|
|||||||
recordings
|
recordings
|
||||||
.env
|
.env
|
||||||
dist/
|
dist/
|
||||||
|
.muxer-queue.db
|
||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user