Moderation & Kontakt + Game-Server-Monitor
- Modmail: DMs an den Bot landen als Threads im privaten Staff-Kanal, Thread-Antworten gehen als DM zurück (Zustell-Feedback per Reaktion) - Willkommens-Embed für neue Member (GuildMemberAdd; Server-Members-Intent nötig) - Mod-Log: gelöschte/bearbeitete User-Nachrichten in privaten Log-Kanal - Server-Monitor: FiveM-kompatible Endpoints (/dynamic.json) alle 2 min, persistentes Status-Embed (edit in place) + Spielerzahl als Bot-Presence - Neue Intents: DirectMessages, GuildMembers; Partials.Channel - Setup-Seite: Sektionen // Moderation & Kontakt und // Game-Server Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -178,6 +178,25 @@ export const listGallery = (limit, offset) => ({
|
||||
total: countGalleryStmt.get().n,
|
||||
});
|
||||
|
||||
// Modmail: DM-Konversationen ↔ Staff-Threads
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS modmail (
|
||||
user_id TEXT PRIMARY KEY,
|
||||
thread_id TEXT NOT NULL UNIQUE,
|
||||
username TEXT,
|
||||
opened_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
`);
|
||||
const upsertModmail = db.prepare(`
|
||||
INSERT INTO modmail (user_id, thread_id, username) VALUES (?, ?, ?)
|
||||
ON CONFLICT(user_id) DO UPDATE SET thread_id = excluded.thread_id, username = excluded.username
|
||||
`);
|
||||
const modmailByUserStmt = db.prepare('SELECT * FROM modmail WHERE user_id = ?');
|
||||
const modmailByThreadStmt = db.prepare('SELECT * FROM modmail WHERE thread_id = ?');
|
||||
export const saveModmail = (userId, threadId, username) => upsertModmail.run(userId, threadId, username);
|
||||
export const modmailByUser = (userId) => modmailByUserStmt.get(userId) ?? null;
|
||||
export const modmailByThread = (threadId) => modmailByThreadStmt.get(threadId) ?? null;
|
||||
|
||||
// API-Keys für externe Skripte (/api/v1/*) — nur der SHA-256-Hash wird gespeichert
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS api_keys (
|
||||
|
||||
Reference in New Issue
Block a user