# sᴛᴜᴅɪᴏ87 | DɪsᴄᴏʀᴅMᴀɴᴀɢᴇʀ

Ein Discord-Bot für ein Support-Ticket-System, plus ein Web-Admin-Panel (Tailwind),
das **live** mit dem Bot verbunden ist: Tickets ansehen, übernehmen, direkt aus dem
Panel heraus in Discord antworten, und schließen – ohne Discord öffnen zu müssen.

## Funktionsumfang

- `/panel` – postet eine Nachricht mit "🎫 Ticket erstellen"-Button
- Nutzer klickt Button → falls Kategorien angelegt sind, wählt er zuerst eine per Auswahlmenü → Modal für ein kurzes Anliegen → privater Ticket-Kanal wird erstellt (mit der Support-Rolle der gewählten Kategorie, sonst der Standard-Rolle)
- `/setup` – legt die Standard-Support-Rolle, Ticket-Kategorie (Kanal-Ordner) und optionalen Log-Kanal fest
- `/ticket claim | close | add` – Ticket-Verwaltung direkt per Slash-Command
- Buttons "Übernehmen" / "Schließen" direkt im Ticket-Kanal
- Beim Schließen wird automatisch ein **HTML-Transcript** der gesamten Unterhaltung gespeichert
  (unter `transcripts/`) und, falls ein Log-Kanal konfiguriert ist, dort als Anhang gepostet
- **Automatisches Datenbank-Backup**: einmal täglich wird `data.sqlite` sicher kopiert
  (unter `backups/`), ältere als 14 Tage werden automatisch gelöscht
- **Moderation**: `/warn`, `/warnings`, `/kick`, `/ban`, `/unban` – jeweils mit eigener Discord-
  Berechtigung (Timeout-/Kick-/Bann-Mitglieder), automatischer DM an die betroffene Person (best effort),
  Eintrag im Log-Kanal (falls konfiguriert) und im Panel unter **Moderation** einsehbar
- **Ticket-Vorlagen**: Kategorien können bis zu 5 eigene Formularfelder haben (statt nur einem
  Freitext) – Nutzer sehen beim Erstellen ein passendes Discord-Modal
- **Sternebewertung**: Nach dem Schließen fragt der Bot per 5-Sterne-Buttons nach Zufriedenheit
  (nur der Ersteller kann bewerten), ausgewertet im Panel unter Mitarbeiter-Leistung
- **Auto-Antworten per Keyword**: Textbausteine können Schlüsselwörter haben; passt der Ticket-
  Betreff dazu, schlägt das Panel im Ticket-Chat automatisch den passenden Baustein vor
- **Anhänge/Screenshots**: Bilder aus dem Ticket-Kanal werden inline im Panel-Chat und im
  Transcript angezeigt
- **Ticket-Verknüpfung**: Zusammenhängende Tickets lassen sich im Panel als "verwandt" markieren
- **Mitarbeiter-Leistungsübersicht, CSV-Export, Wochenreport**: siehe Panel-Funktionen unten
- **E-Mail-Alarme** (optional, per SMTP): bei Bot-Ausfall und bei Hoch-Priorität-Tickets, die
  seit über einer Stunde unbearbeitet sind
- **Tastenkürzel**: `C` übernimmt das gerade geöffnete Ticket, `Strg+Enter` sendet die Antwort
- **Browser-Benachrichtigungen**: solange das Panel-Tab offen ist, meldet der Browser neue Tickets
- **Passwort-Reset per E-Mail-Link**, **Login-Verlauf** und **"Überall abmelden"** (siehe Panel-Konto)
- **Support-Zeiten**: außerhalb konfigurierter Zeiten postet der Bot automatisch einen Hinweistext
  im neuen Ticket
- **SLA-Eskalation**: unbeantwortete offene Tickets pingen nach konfigurierbarer Zeit eine
  Eskalations-Rolle im Kanal
- **Abwesenheits-Modus**: als abwesend markierte (verknüpfte) Mitarbeiter werden bei der
  Panel-Zuweisung automatisch übersprungen
- **Volltextsuche**: durchsucht nicht nur Betreff/Name, sondern den kompletten gespeicherten
  Chat-Verlauf eines Tickets
- **Gespeicherte Filter, Mehrfachauswahl (Massen-Schließen/-Zuweisen), interne @-Erwähnungen**
  mit Discord-DM-Hinweis: siehe Panel-Funktionen unten
- **Eigenes Branding pro Server**: Name/Farbe/Logo fließen in die Bot-Embeds ein
- **DSGVO-Export/-Löschung**: alle gespeicherten Daten einer Discord-Person exportieren oder
  anonymisieren (nur Owner)
- **Kunden-Historie**: bei jedem Ticket sieht das Team sofort alle bisherigen Tickets derselben
  Person (auch als Hinweis direkt im Discord-Embed: "X frühere Ticket(s) dieser Person")
- **Öffentliche Status-Seite** (`status.html`, kein Login nötig, optional pro Server aktivierbar):
  zeigt Bot-Status, Ø Erstantwortzeit und Ticket-Zahlen – zum Teilen mit den eigenen Nutzern
- **Mobile-Web-Formular** als Alternative zum Discord-Modal: Button "📱 Web-Formular" neben
  "Ticket erstellen" schickt einen 15 Minuten gültigen, personalisierten Link zu einer eigenen
  Ticket-Erstellungsseite (`create-ticket.html`)
- **Serverübergreifende Suche** (nur Owner, im Multi-Server-Betrieb): Discord-User-ID eingeben,
  Panel zeigt auf welchen deiner Server (mit diesem Bot) die Person Mitglied ist – mit
  Mehrfachauswahl direkt gebündelt auf mehreren Servern gleichzeitig kicken/bannen
- **Ticket-Kanal-Präfix nach Priorität**: Kanäle mit Priorität "Hoch" bekommen automatisch ein 🔴
  vor den Namen, damit man's auch ohne Panel sofort sieht
- **Bot-Berechtigungs-Check**: prüft alle 5 Minuten, ob dem Bot auf einem Server plötzlich eine
  nötige Berechtigung fehlt (z. B. nach einem Rollen-Umbau) – Warnbanner im Panel + optional E-Mail
- **Schichtplan/Dienstplan**: im Panel hinterlegen, wer wann im Dienst ist – Sidebar zeigt live,
  wer gerade zuständig ist
- **Anhänge aus dem Panel senden**: Bild oder PDF direkt im Ticket-Chat hochladen (bis 8 MB),
  landet als echter Anhang im Discord-Kanal
- **Echte Web-Push-Benachrichtigungen** (optional, per VAPID-Schlüssel): neue Tickets werden
  gemeldet, auch wenn das Panel-Tab geschlossen ist
- **Zwei-Wege-Übersetzung** (optional, per DeepL-API-Key, pro Profil aktivierbar): eingehende
  Nachrichten werden automatisch in die eigene Sprache übersetzt (mit "Original anzeigen"),
  ausgehende Antworten lassen sich vor dem Senden in eine Zielsprache übersetzen
- **Admin-Panel** (`/public`, Tailwind, Dark- & **Light-Mode umschaltbar**):
  - Übersicht mit Live-Statistiken, **Diagrammen** (Tickets/Tag der letzten 14 Tage, Ø Bearbeitungszeit im Zeitverlauf)
  - Ticket-Liste mit Suche, Filtern und Sortierung nach Priorität (dringende zuerst)
  - Ticket-Detailansicht: zeigt die echten Discord-Nachrichten des Kanals live an,
    erlaubt Antworten direkt aus dem Panel, Priorität ändern, einer Person zuweisen,
    interne Notizen (nur Staff sichtbar, nicht im Discord-Kanal), Schnellantworten per Klick einfügen,
    Übernehmen/Schließen, sowie **Transcript herunterladen** bei geschlossenen Tickets
  - Mitglieder: alle Server-Mitglieder mit Suche, Rollen-Badges, Beitrittsdatum
  - **Moderation**: Mitglied wählen (oder per ID) und verwarnen/kicken/bannen, inkl. Warnungs-Zähler
    und durchsuchbarem Moderations-Log
  - **Konto** (für alle Rollen): Abwesenheits-Modus, Login-Verlauf, "Überall abmelden",
    ungelesene @-Erwähnungen aus internen Notizen
  - Einstellungen: **Bot starten/stoppen/neustarten** (unabhängig vom Panel), Standard-Support-Rolle,
    Kanal-Ordner für neue Tickets, Log-Kanal, Support-Zeiten, SLA-Eskalation, **Ticket-Kategorien**
    (je mit eigener Support-Rolle und optionalem Formular), **Textbausteine** (mit Schlüsselwörtern)
    verwalten, Panel-Nachricht posten, **Branding** (Name/Farbe/Logo), **Öffentliche Status-Seite**
    ein-/ausschalten, **Wartung** (Backups), **Datenschutz** (DSGVO-Export/-Löschung)
  - Team-Verwaltung: weitere Panel-Zugänge anlegen (**nur Owner**), optional mit E-Mail (für
    Passwort-Reset) und einem echten Discord-Konto verknüpft, damit "eigene Tickets" bot- und
    panel-übergreifend erkannt werden
  - **Aktivitäts-Log** (nur Owner): chronologische Übersicht, wer wann was im Panel gemacht hat
  - Ticket-Liste: Volltextsuche (auch im Chat-Verlauf), Prioritäts-Filter, "Nur meine", gespeicherte
    Filter, Mehrfachauswahl (Massen-Schließen/-Zuweisen), CSV-Export

## Rollen im Panel

- **Owner**: voller Zugriff auf alles – alle Tickets, Einstellungen, Team, Aktivitäts-Log, Backups, Bot-Steuerung.
- **Staff**: sieht in der Ticket-Liste nur **offene (noch nicht übernommene) Tickets** sowie **eigene**
  (von ihnen übernommene oder ihnen zugewiesene) Tickets. Fremde, bereits von anderen übernommene
  Tickets sind weder sichtbar noch bearbeitbar (auch nicht per direktem Link/ID). Staff kann Textbausteine
  nutzen und Mitglieder einsehen, aber keine Einstellungen ändern, kein Team verwalten, den Bot nicht
  steuern und keine Backups einsehen.

Der allererste Account (aus `.env`) ist immer **Owner**. Weitere Zugänge legt ein Owner unter
**Team** an und wählt dort Rolle (Staff/Owner) sowie optional ein zu verknüpfendes Discord-Konto.

Bot und Panel laufen als **zwei unabhängige Prozesse**: Das Panel (Express-Server)
läuft dauerhaft, der Discord-Bot läuft als Kindprozess. Über **Einstellungen → Bot-
Steuerung** lässt sich der Bot jederzeit stoppen, starten oder neustarten – das
Panel selbst bleibt dabei immer erreichbar. Beide Prozesse teilen sich dieselbe
SQLite-Datenbank (`data.sqlite`), Ticket-Aktionen (Übernehmen/Schließen/Antworten),
die eine laufende Discord-Verbindung brauchen, schlagen fehl, solange der Bot
gestoppt ist, und funktionieren wieder, sobald er gestartet wurde.

## 1. Discord-Bot anlegen

1. Gehe zum [Discord Developer Portal](https://discord.com/developers/applications) → **New Application**.
2. Unter **Bot** → **Add Bot**. Kopiere den **Token** (für `DISCORD_TOKEN`).
3. Aktiviere unter **Privileged Gateway Intents**:
   - `SERVER MEMBERS INTENT`
   - `MESSAGE CONTENT INTENT`
4. Unter **General Information** die **Application ID** kopieren (für `CLIENT_ID`).
5. Unter **OAuth2 → URL Generator**:
   - Scopes: `bot`, `applications.commands`
   - Bot-Permissions: `Manage Channels`, `Manage Roles`, `View Channels`,
     `Send Messages`, `Read Message History`, `Embed Links`,
     `Kick Members`, `Ban Members`, `Moderate Members` (für /warn, /kick, /ban, /unban)
   - Öffne die generierte URL und lade den Bot auf deinen Server ein.
6. Deine **Server-ID** (Rechtsklick auf den Servernamen → "Server-ID kopieren",
   Entwicklermodus muss in den Discord-Einstellungen aktiviert sein) → `GUILD_ID`.

## 2. Projekt einrichten

```bash
npm install
cp .env.example .env
```

Trage in `.env` ein:

```
DISCORD_TOKEN=...
CLIENT_ID=...
GUILD_ID=...
JWT_SECRET=ein-langer-zufaelliger-string
ADMIN_USERNAME=admin
ADMIN_PASSWORD=ein-sicheres-passwort
PORT=3000
```

Slash-Commands beim Discord-Server registrieren (einmalig, bei Änderungen erneut ausführen):

```bash
npm run deploy-commands
```

Bot & Panel starten:

```bash
npm start
```

Das Panel läuft dann unter `http://localhost:3000` (bzw. der Domain deines Hosts).
Der erste Admin-Zugang (`ADMIN_USERNAME` / `ADMIN_PASSWORD`) wird beim ersten Start
automatisch in der Datenbank angelegt. Weitere Zugänge lassen sich danach im Tab
**Team** im Panel selbst anlegen.

## 3. Ticket-System konfigurieren

1. Auf Discord: `/setup` ausführen → Support-Rolle und Ticket-Kategorie wählen
   (leg vorher eine Kategorie an, in der die privaten Ticket-Kanäle erstellt werden sollen).
2. Im Panel unter **Einstellungen** kannst du dieselbe Konfiguration auch bearbeiten
   und dort direkt das Ticket-Panel (den Button für Nutzer) in einen Kanal posten.

## 4. Hosting

Der Bot braucht einen dauerhaft laufenden Node-Prozess (kein reines Static-Hosting).
Optionen: eigener vServer/VPS mit [PM2](https://pm2.keymetrics.io/), Railway, Render,
Fly.io oder ein anderer Node-Host. Wichtig:

- Node.js ≥ 18
- Alle `.env`-Variablen als Umgebungsvariablen setzen
- `data.sqlite` liegt lokal neben dem Code – bei den meisten Plattformen brauchst du
  dafür ein **persistentes Volume** (sonst gehen Tickets bei jedem Deploy verloren)
- Port aus `PORT` muss öffentlich erreichbar sein (ggf. hinter einem Reverse Proxy
  wie nginx oder Caddy mit HTTPS)

Beispiel mit PM2 auf einem eigenen Server:

```bash
npm install -g pm2
pm2 start src/index.js --name ticket-bot
pm2 save
```

## Mehrere Server (Multi-Server-Unterstützung)

Ein Bot kann auf beliebig vielen Discord-Servern gleichzeitig laufen. Im Panel:

- Oben in der Sidebar ein **Server-Umschalter** – zeigt alle Server, auf denen der Bot
  aktuell Mitglied ist, per Dropdown zum Wechseln
- **"+ Server hinzufügen"** öffnet den normalen Discord-Einladungslink in einem neuen Tab;
  sobald der Server-Owner dort bestätigt, taucht der Server nach einem Klick auf ⟳ (oder
  automatisch nach spätestens 30 Sekunden) im Umschalter auf
- Slash-Commands werden auf neu hinzugekommenen Servern **automatisch** registriert
  (kein manuelles `deploy-commands` mehr nötig für neue Server)
- Alle Daten (Tickets, Einstellungen, Kategorien, Textbausteine, Aktivitäts-Log,
  Moderations-Log) sind pro Server sauber getrennt – ein Ticket von Server A taucht nie
  bei Server B auf, auch nicht per direktem Link

`GUILD_ID` in der `.env` dient nur noch als **Fallback**, falls das Panel aus irgendeinem
Grund noch keinen Server ausgewählt hat (z. B. beim allerersten Laden). Für den Normalbetrieb
mit mehreren Servern ist diese Variable nicht mehr entscheidend.

Panel-Zugänge (Team) sind aktuell **global** – ein Owner/Staff-Zugang funktioniert auf allen
Servern, die der Bot kennt. Eine Einschränkung "dieser Zugang darf nur Server X verwalten"
gibt es (noch) nicht; das wäre eine separate Erweiterung.

## E-Mail-Alarme einrichten (optional)

In der `.env`:

```
SMTP_HOST=smtp.deinanbieter.de
SMTP_PORT=587
SMTP_USER=bot@deinedomain.de
SMTP_PASS=dein-smtp-passwort
SMTP_FROM=bot@deinedomain.de
ALERT_EMAIL_TO=admin@deinedomain.de
```

Bleiben diese Felder leer, werden Alarme einfach übersprungen (kein Fehler, nur eine Log-Zeile).
Alarme werden ausgelöst bei: Bot-Ausfall (höchstens alle 30 Min. erneut), Tickets mit
Priorität "Hoch", die seit über einer Stunde offen sind (einmalig pro Ticket, bis die Priorität
geändert wird), sowie fehlenden Bot-Berechtigungen (höchstens alle 6 Std. erneut pro Server).

## Web-Push-Benachrichtigungen einrichten (optional)

Einmalig ein eigenes Schlüsselpaar erzeugen:

```bash
npx web-push generate-vapid-keys
```

Ausgabe in die `.env` eintragen:

```
VAPID_PUBLIC_KEY=...
VAPID_PRIVATE_KEY=...
VAPID_SUBJECT=mailto:admin@deinedomain.de
```

Ohne diese Variablen bleibt alles wie gewohnt nutzbar – nur eben ohne Push-Benachrichtigungen bei
geschlossenem Panel-Tab. Der Browser fragt beim ersten Öffnen des Panels nach der
Benachrichtigungs-Erlaubnis.

## Übersetzung einrichten (optional)

Ein kostenloser [DeepL-API-Key](https://www.deepl.com/pro-api) reicht:

```
DEEPL_API_KEY=dein-schluessel:fx
```

(Free-Keys enden per DeepL-Konvention auf `:fx` – Pro-Keys nicht; der Bot erkennt das automatisch
und nutzt den passenden API-Host.) Ohne Key bleibt die Funktion in den Panel-Einstellungen einfach
ausgegraut mit einem Hinweis.

## Projektstruktur

```
src/
  index.js                 Einstiegspunkt: startet Panel + Bot-Kindprozess
  botManager.js              Startet/stoppt/überwacht den Bot-Kindprozess, RPC-Bridge, Event-Weiterleitung
  backup.js                 Tägliches Datenbank-Backup
  reports.js                 Wöchentlicher Report per DM an Owner
  alerts.js                  E-Mail-Alarme (Bot-Ausfall, Hoch-Prio-Tickets, fehlende Berechtigungen)
  mailer.js                  SMTP-Versand (no-op wenn nicht konfiguriert)
  push.js                    Web-Push-Versand (no-op wenn nicht konfiguriert)
  translator.js               DeepL-Anbindung (no-op wenn nicht konfiguriert)
  db.js                     SQLite-Datenbank & Queries
  bot/
    botProcess.js              Bot-Kindprozess: Discord-Client + RPC-Handler fürs Panel, SLA-Check
    client.js               Discord-Client (Intents)
    deployCommands.js        Registriert Slash-Commands (für alle bekannten Server)
    ticketService.js          Kernlogik: Ticket erstellen/übernehmen/schließen/zuweisen, Events
    businessHours.js           Support-Zeiten-Prüfung, Wochentag/Uhrzeit-Hilfsfunktion
    moderation.js               Warn/Kick/Ban/Unban
    transcript.js                HTML-Transcript-Erstellung & -Löschung (DSGVO)
    commands/definitions.js    Slash-Command-Definitionen
    commands/handlers.js        Slash-Command-Ausführung
    interactions/buttons.js      Button-Handler (inkl. Sternebewertung, Web-Formular-Link)
    interactions/modals.js        Modal (Betreff/Formularfelder)
    events/ready.js, interactionCreate.js, messageCreate.js (Nachrichtenverlauf für Suche)
  api/
    server.js                Express-App
    auth.js                   JWT-Middleware (inkl. Token-Version für "Überall abmelden")
    guildContext.js            Liest den gerade im Panel gewählten Server (X-Guild-Id-Header)
    routes/auth.js, stats.js, tickets.js, discordMeta.js, botControl.js, topics.js,
           cannedResponses.js, auditLog.js, backups.js, moderation.js, savedFilters.js, gdpr.js,
           public.js (unauthentifiziert: Status-Seite & Web-Ticket-Formular), shifts.js, push.js
public/
  index.html                Login (mit "Passwort vergessen?")
  forgot-password.html         Passwort-Reset anfordern
  reset-password.html          Neues Passwort setzen
  status.html                  Öffentliche Status-Seite (kein Login)
  create-ticket.html            Mobile Web-Formular zur Ticket-Erstellung (kein Login, Token-basiert)
  sw.js                         Service Worker für Web-Push
  dashboard.html              Admin-Panel (Tailwind, dunkles Theme)
  assets/login.js, app.js
```

## Hinweis

Dieses Setup ist für **einen** Discord-Server (`GUILD_ID`) ausgelegt. Für mehrere
Server müsste die Konfiguration (`guild_config`) und Ticket-Auswahl im Panel
zusätzlich pro Server umschaltbar gemacht werden – die Datenbankstruktur ist dafür
mit `guild_id`-Spalten bereits vorbereitet.
