Ticket-System, Web-Composer und Nachrichten-Bearbeitung

- Tickets: /ticket-setup postet 🎫-Button; Klick erstellt privaten Thread
  (ein offenes Ticket pro User), Schließen-Button sperrt + archiviert
- Composer auf der Setup-Seite: Nachricht/Embed als Bot in beliebigen Kanal
  senden oder per Message-ID bearbeiten (nur eigene Bot-Posts)
- API v1: PATCH /api/v1/message — Skripte können ihre Bot-Posts aktualisieren
- Setting ticket_channel_id; README ergänzt

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-23 13:43:27 +02:00
co-authored by Claude Opus 4.8
parent f631c0e2ab
commit 4d1b0a956d
9 changed files with 310 additions and 4 deletions
+20
View File
@@ -252,6 +252,26 @@ export function commitHeatmap() {
.all();
}
// Ticket-System (Button → privater Thread)
db.exec(`
CREATE TABLE IF NOT EXISTS tickets (
thread_id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'open',
opened_at TEXT NOT NULL DEFAULT (datetime('now'))
);
`);
const insertTicket = db.prepare('INSERT INTO tickets (thread_id, user_id) VALUES (?, ?)');
const getTicketStmt = db.prepare('SELECT * FROM tickets WHERE thread_id = ?');
const closeTicketStmt = db.prepare(`UPDATE tickets SET status = 'closed' WHERE thread_id = ?`);
const openTicketByUserStmt = db.prepare(
`SELECT * FROM tickets WHERE user_id = ? AND status = 'open'`
);
export const saveTicket = (threadId, userId) => insertTicket.run(threadId, userId);
export const getTicket = (threadId) => getTicketStmt.get(threadId) ?? null;
export const closeTicket = (threadId) => closeTicketStmt.run(threadId);
export const openTicketOf = (userId) => openTicketByUserStmt.get(userId) ?? null;
// Modmail: DM-Konversationen ↔ Staff-Threads
db.exec(`
CREATE TABLE IF NOT EXISTS modmail (