README auf den heutigen Stand bringen und neu ordnen
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled

Die Funktionsliste war eine einzige Tabelle mit 46 Zeilen — in der Reihenfolge,
in der die Sachen entstanden sind, also in keiner. Jetzt ist sie nach denselben
Bereichen sortiert wie das Panel: Inhalte, Community, Moderation, Server, dazu
Plattform fuer alles, was keine Discord-Funktion ist. Wer im Panel etwas sucht,
findet den Abschnitt in der README am selben Platz.

Nachgetragen, was seither dazugekommen ist: AutoMod, Raid-Schutz, verknuepfte
Rollen, native Umfragen, Statusseite, Herzschlag, Seiten-Editor, Englisch fuer
die oeffentlichen Seiten. Und die Trennung in zwei Domains stand bisher gar
nicht drin, obwohl sie das Erste ist, was man verstehen muss — sie steht jetzt
ganz oben, mit einer Tabelle welche Seite was zeigt.

Korrigiert: 35 Module waren es mal, es sind 39. 15 Config-Bereiche waren es
mal, es sind 16. Die Seitentabelle fuehrte Hub-Seiten unter der Bot-Domain.
Die Projektstruktur kannte die Haelfte der Dateien nicht. In der
Ersteinrichtung fehlten die Rechte fuer AutoMod und Kanal-Anlegen sowie die
zusaetzlichen OAuth-Redirects.

Dazu ein Inhaltsverzeichnis, eine docs/README.md als Wegweiser, und in
konzept-zwei-seiten.md steht nicht mehr "muss noch aktiviert werden" — es
laeuft seit Ende Juli.

Geprueft mit einem kleinen Skript: 11 Markdown-Dateien, keine toten
Datei-Links, keine toten Anker, keine Tabelle mit falscher Spaltenzahl.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-01 07:16:32 +02:00
co-authored by Claude Opus 5
parent e32152b5ac
commit 2292dedeaa
3 changed files with 396 additions and 224 deletions
+362 -222
View File
@@ -1,95 +1,192 @@
# d4rkbot — D4RKST3R // COMMUNITY BOT
Discord-Bot + Webinterface: Devlog-Tagebuch, Commit-Feed, Changelog und
Community-Tools für die EcoGame-Entwicklung — alles gebrandet, alles über
die Config-Seite steuerbar.
Discord-Bot mit Webinterface: Devlog-Tagebuch, Commit-Feed, Changelog,
Moderation und Community-Werkzeuge für die EcoGame-Entwicklung. Alles
gebrandet, alles zur Laufzeit über die Config-Seite steuerbar — kein Redeploy,
keine Paywall.
**Stack:** Node.js 20+ (ESM), discord.js v14, Fastify 5, React 19 + Vite,
SQLite (better-sqlite3, FTS5), Docker Multi-Stage deploybar als Portainer-Stack.
**Stack:** Node.js 20+ (ESM) · discord.js v14 · Fastify 5 · React 19 + Vite ·
SQLite (better-sqlite3, FTS5) · Docker Multi-Stage, deploybar als Portainer-Stack.
---
## Features
## Inhalt
### Discord
| Feature | Beschreibung |
* [Zwei Seiten, ein Bot](#zwei-seiten-ein-bot)
* [Funktionen](#funktionen) — [Inhalte](#inhalte--feeds) · [Community](#community) · [Moderation](#moderation--support) · [Server](#server--technik) · [Plattform](#plattform)
* [Webinterface](#webinterface)
* [Config-Seite](#config-seite-settings)
* [Ersteinrichtung](#ersteinrichtung)
* [Deployment](#deployment-portainer) · [Lokale Entwicklung](#lokale-entwicklung)
* [API v1](#api-v1--für-eigene-skripte--dienste) · [HTTP-Endpoints](#http-endpoints)
* [Projektstruktur](#projektstruktur)
* [Weitere Dokumentation](#weitere-dokumentation)
---
## Zwei Seiten, ein Bot
Ein Prozess bedient zwei Domains — welche Seite ausgeliefert wird, entscheidet
der Host:
| Domain | Rolle |
|---|---|
| **`bot.d4rkst3r.de`** | Produktseite des Bots: was er kann, welche Befehle es gibt, Dashboard fürs Team |
| **`hub.d4rkst3r.de`** | Community-Hub: Devlogs, Roadmap, Galerie, Level, Events, Status |
Beide teilen sich Anmeldung, Datenbank und Design. Solange die beiden Adressen
in der Config leer bleiben, verhält sich alles wie eine einzige Seite — das
Umschalten ist jederzeit reversibel. Details:
[docs/konzept-zwei-seiten.md](docs/konzept-zwei-seiten.md).
Die öffentlichen Seiten gibt es auf **Deutsch und Englisch**; die Sprache
kommt aus dem Browser und lässt sich oben rechts umschalten. Die Config-Seite
bleibt bewusst deutsch — sie sieht nur das Team.
---
## Funktionen
**39 Module**, einzeln an- und abschaltbar. Ein ausgeschaltetes Modul reagiert
auf nichts mehr: keine Posts, keine Hintergrund-Prüfungen.
### Inhalte & Feeds
| Funktion | Beschreibung |
|---|---|
| 📔 **Devlog-Posts** | `tools/devlog.py` (EcoGame-Repo) schickt Prosa + Bilder an den Bot-Endpoint → gebrandetes Embed (Datum-Titel, Author-Zeile, Commit-Zähler im Footer, Bilder-Grid, Link-Buttons) |
| 💬 **Auto-Threads** | Diskussions-Thread unter jedem Devlog-Post („💬 Devlog 23.07.") |
| 🔔 **Rollen-Ping** | Ping-Rolle beim Devlog-Post; Member abonnieren sie selbst über den 🔔-Button |
| 📦 **Commit-Feed** | Gitea-Push-Webhooks → Embeds in den (privaten) Commit-Kanal |
| 🚀 **Release-Ankündigungen** | Neues Gitea-Release → oranges Ankündigungs-Embed |
| 📊 **Wochen-Rückblick** | Sonntags 20:00 automatisch: Commits pro Tag als Balken, Devlogs, Top-Projekte |
| 🐛 **`/bug`** | Eingabefenster mit vier Feldern (was ist passiert, was war erwartet, wie nachstellen) → Gitea-Issue inkl. Screenshot-Upload; Issue geschlossen → DM an den Reporter |
| 🚨 **Watchdog** | Prüft eigene Dienste alle 2 min, DM-Alarm bei Ausfall + Entwarnung |
| 🧪 **Playtester-Programm** | `/playtester-setup` postet den Bewerbungs-Button; Rolle + Liste (Config-Seite); Alpha-Keys später per DM über die API |
| ⭐ **Starboard** | Nachrichten mit genug ⭐-Reaktionen landen automatisch im Best-of-Kanal |
| 📸 **Screenshot-Galerie** | Bilder aus dem Screenshot-Kanal → öffentliche `/galerie` (lokal gespeichert); Historie via `/galerie-backfill` |
| 📬 **Modmail** | DM an den Bot → Thread im privaten Staff-Kanal; Antworten im Thread gehen als DM zurück |
| 🎫 **Tickets** | `/ticket-setup` postet den Button; Klick öffnet einen privaten Thread (ein offenes Ticket pro User). Schließen = **Transcript per DM** an den Ersteller + Kopie ins Mod-Log, Thread wird gelöscht |
| 🎭 **Rollen-Menüs** | Carl-Bot-Ersatz: Menüs im Webinterface bauen (Emoji, Label, Rolle, optional exklusiv), Bot postet Button-Embeds; Klick = Rolle nehmen/abgeben, Posts jederzeit editierbar |
| 🛡️ **Moderation** | `/warn` (DM + Historie), `/warns`, `/timeout`, `/purge` — alles im Mod-Log; dazu Join/Leave- und Nick-/Rollen-Änderungs-Logging |
| 🪪 **Auto- & Sticky-Roles** | Start-Rolle für neue Member; Rollen werden bei Leave gesichert und bei Rejoin wiederhergestellt |
| 📈 **Level-System** | XP pro Nachricht (60s-Cooldown, MEE6-Formel), `/rank`, Level-Up-Announce, Rollen-Belohnungen, öffentliche Bestenliste auf `/level` |
| 🏷️ **Tags** | `/tag <name>` (mit Autocomplete) postet gespeicherte Text-Bausteine — verwaltet im Composer-Tab |
| ⏰ **Geplante Posts** | Einmalig, täglich oder wöchentlich — im Composer-Tab geplant, vom Bot gepostet (bei Carl Premium) |
| 🎨 **Branding** | Brand-Tab mit Bot-Identity-Karte (Avatar-Vorschau, Name, Status online/idle/dnd, Aktivität), Embed-Farben, Banner-Upload, Guild-ID & Gitea-Token ohne Env-Redeploy |
| 🎟️ **Alpha-Keys** | Key-Pool im Community-Tab; Ein-Klick-Verteilung an alle Playtester per DM |
| 📋 **Bewerbungen** | Formulare (bis 5 Fragen) als Discord-Modal, Review mit ✅/❌ im Staff-Kanal, Rolle + DM bei Annahme — z. B. FiveM-Whitelist |
| 📅 **Events** | Neue Discord-Events werden angekündigt + öffentliche `/events`-Seite |
| 💬 **Triggers** | Auto-Antworten auf Schlüsselwörter (30s-Cooldown), verwaltet im Composer-Tab |
| ⏰ **/remind** | Erinnerungen per DM (`/remind dauer:2h text:…`) |
| 📣 **Twitch/YouTube** | 🔴-Live- und ▶️-Neues-Video-Announcements (YouTube ohne Key via RSS, Twitch mit App-Credentials) |
| 🔊 **Temp-Voice** | „Join to Create": Hub-Kanal betreten → eigener Voice-Kanal mit Control-Panel (Umbenennen, Sperren, Limit, Löschen — nur für den Besitzer), löscht sich wenn leer |
| 📊 **Server-Stats** | Nachrichten/Joins/Leaves pro Tag → Aktivitäts-Chart auf der Level-Seite |
| 👋 **Willkommens-Karten** | Begrüßung neuer Member als gerendertes Bild (Avatar mit Neon-Ring, Member-Nummer, Brand-Look); Fallback aufs Text-Embed |
| 🎂 **Geburtstage** | `/geburtstag` zum Eintragen; morgens ab 09:00 Gratulation im Kanal + Tages-Rolle (Community-Tab) |
| 📢 **Auto-Publish** | Devlog-/Release-/Composer-Posts in Ankündigungs-Kanälen werden automatisch veröffentlicht (Follower bekommen sie) |
| 🚀 **Release-Ankündigungen** | Neues Gitea-Release → Ankündigungs-Embed + Eintrag im Changelog |
| 📊 **Wochen-Rückblick** | Sonntags automatisch: Commits pro Tag als Balken, Devlogs, Top-Projekte |
| 📣 **Twitch / YouTube** | 🔴 Live- und ▶️ Neues-Video-Meldungen (YouTube ohne Key via RSS, Twitch mit App-Credentials) |
| 🔗 **Link-Vorschau** | Jedes Devlog hat einen Permalink (`/devlogs/:id`); geteilte Links zeigen überall gebrandete Open-Graph-Vorschau mit Bild |
| 📋 **Mod-Log** | Gelöschte/bearbeitete Nachrichten in einen privaten Log-Kanal |
| 🎮 **Server-Monitor** | DiscordGSM-Stil: eigener Config-Tab, pro Server ein Live-Embed (🟢/🔴, Spieler-Balken mit %, Map, Spieler-Liste, klickbarer Connect-Link, Ping); **300+ Spiele via gamedig** (Minecraft, Rust, CS2, Valheim, ARK …) + FiveM + HTTP-Check; Down/Up-Alerts (🚨 nach 2 Fehlversuchen, ✅ mit Downtime bei Recovery) in eigenen Alert-Kanal; Spielerzahl in der Presence |
| 👥 **Team-Rechte** | Team-Mitglieder bekommen gezielten Web-Zugriff (Composer, Bewerbungen, Rollen, Server, …) — Brand, System, API-Keys bleiben Owner-only; **Audit-Log** im Team-Tab zeigt dem Owner die letzten Aktionen |
| 📢 **Auto-Publish** | Posts in Ankündigungs-Kanälen werden automatisch veröffentlicht (Follower bekommen sie) |
### Community
| Funktion | Beschreibung |
|---|---|
| 📈 **Level-System** | XP pro Nachricht (Cooldown, MEE6-Formel), `/rank`, Level-Up-Announce, Rollen-Belohnungen, öffentliche Bestenliste |
| ⭐ **Starboard** | Nachrichten mit genug ⭐-Reaktionen landen im Best-of-Kanal |
| 📸 **Screenshot-Galerie** | Bilder aus dem Screenshot-Kanal → öffentliche Galerie (lokal gespeichert, weil Discord-CDN-Links ablaufen) |
| 💡 **Feature-Voting** | `/wunsch` öffnet ein Eingabefenster (Idee + „warum wäre das gut?") → Voting-Post mit 👍; Top-Wünsche öffentlich auf der Roadmap |
| 🗳️ **Umfragen** | `/umfrage` erzeugt eine **native Discord-Poll** — keine Reaktions-Bastelei, Discord zählt selbst |
| 🎉 **Giveaways** | `/giveaway` (Admin): Teilnahme-Button, automatische Ziehung; am Gewinner-Post 🔁 Neu auslosen + 👥 Teilnehmerliste |
| 🎂 **Geburtstage** | `/geburtstag` zum Eintragen; morgens Gratulation im Kanal + Tages-Rolle |
| 📅 **Events** | Neue Discord-Events werden angekündigt + öffentliche Events-Seite |
| 🧪 **Playtester-Programm** | `/playtester-setup` postet den Bewerbungs-Button; Rolle + Liste im Panel |
| 🎟️ **Alpha-Keys** | Key-Pool im Panel; Ein-Klick-Verteilung an alle Playtester per DM |
| 🎭 **Rollen-Menüs** | Menüs im Webinterface bauen (Emoji, Label, Rolle, optional exklusiv), Bot postet Button-Embeds; Posts jederzeit editierbar |
| 📋 **Bewerbungen** | Formulare (bis 5 Fragen) als Discord-Modal, Review mit ✅/❌ im Staff-Kanal, Rolle + DM bei Annahme — z. B. FiveM-Whitelist |
| 🪪 **Verknüpfte Rollen** | Discords *Linked Roles*: Level, Playtester-Status und Dabei-seit werden als geprüfte Kennzahlen an Discord gemeldet — Rollen vergibt dann Discord selbst |
### Moderation & Support
| Funktion | Beschreibung |
|---|---|
| 🛡️ **Moderation** | `/warn` (DM + Historie), `/warns`, `/timeout`, `/purge` — alles im Mod-Log |
| 🤖 **AutoMod** | Treffer von Discords eigenem Filter landen als Embed im Protokoll (Nutzer, Regel, Auslöser, Maßnahme, getroffenes Wort); Regeln sind im Panel sichtbar und schaltbar. Wortlisten bleiben in Discord |
| 🚨 **Raid-Schutz** | Erkennt Beitritts-Wellen und sperrt den Server vorübergehend (Prüfstufe hoch, Einladungen aus). `/raid an\|aus\|status` auch von Hand |
| 📋 **Protokoll** | Gelöschte und bearbeitete Nachrichten, Joins/Leaves, Namens- und Rollen-Änderungen in einem privaten Kanal |
| 📬 **Modmail** | DM an den Bot → Thread im privaten Staff-Kanal; Antworten im Thread gehen als DM zurück |
| 🎫 **Tickets** | Button öffnet einen privaten Thread (ein offenes Ticket pro User). Schließen = **Transcript per DM** an den Ersteller + Kopie ins Mod-Log |
| 👋 **Willkommens-Karten** | Begrüßung als gerendertes Bild (Avatar mit Neon-Ring, Member-Nummer, Brand-Look), konfigurierbar; Fallback aufs Text-Embed |
| 🪪 **Auto- & Sticky-Roles** | Start-Rolle für neue Member; Rollen werden bei Leave gesichert und bei Rejoin wiederhergestellt |
| 🐛 **`/bug`** | Eingabefenster (was ist passiert, was war erwartet, wie nachstellen) → Gitea-Issue inkl. Screenshot-Upload; Issue geschlossen → DM an den Reporter |
### Server & Technik
| Funktion | Beschreibung |
|---|---|
| 🎮 **Game-Server-Monitor** | DiscordGSM-Stil: pro Server ein Live-Embed (🟢/🔴, Spieler-Balken, Map, Spieler-Liste, Connect-Link, Ping); **300+ Spiele via gamedig** (Minecraft, Rust, CS2, Valheim, ARK …) + FiveM + HTTP-Check; Down/Up-Alerts mit Ausfalldauer |
| 🚨 **Wächter** | Prüft eigene Dienste in einstellbarem Takt, DM-Alarm bei Ausfall + Entwarnung; speist die öffentliche Statusseite |
| 💓 **Herzschlag** | Der Bot zeichnet sich selbst auf — im Dashboard steht neben der Laufzeit ein Erreichbarkeits-Balken über 7 Tage. Fehlende Stunden sind rot: dass nichts dasteht, *ist* die Aussage |
| 🔊 **Temp-Voice** | „Join to Create": Hub-Kanal betreten → eigener Voice-Kanal mit Control-Panel (Umbenennen, Sperren, Limit, Löschen — nur für den Besitzer), löscht sich wenn leer |
| 💬 **Auto-Antworten** | Antworten auf Schlüsselwörter (mit Cooldown), verwaltet im Composer |
| ⏰ **`/remind`** | Erinnerungen per DM (`/remind dauer:2h text:…`) |
| 🗓️ **Geplante Posts** | Einmalig, täglich oder wöchentlich — im Composer geplant, vom Bot gepostet |
| 🏷️ **Textbausteine** | `/tag <name>` (mit Autocomplete) postet gespeicherte Bausteine |
| 💾 **DB-Backups** | Nächtlich, gzip, rotierend, optional als Upload in einen Discord-Kanal |
| 📦 **Repo-Backups** | Nachts alle Gitea-Repos als git-Bundle (komplette Historie, direkt wieder klonbar), 14 Tage Rotation |
| 🚪 **Member-Gate** | Login nur für Server-Mitglieder; wer draußen ist, bekommt den Invite-Link |
### Plattform
| Funktion | Beschreibung |
|---|---|
| 🎨 **Branding** | Bot-Identity-Karte (Avatar-Vorschau, Name, Status, Aktivität), Embed-Farben, Banner-Upload, Guild-ID und Gitea-Token ohne Env-Redeploy |
| 👥 **Team-Rechte** | Team-Mitglieder bekommen gezielten Web-Zugriff (Composer, Bewerbungen, Rollen, Server …) — Brand, System und API-Keys bleiben Owner-only; **Audit-Log** zeigt dem Owner die letzten Aktionen |
| 🔑 **Single Sign-On** | Andere Dienste (Kanban, Platform …) nutzen den Discord-Login des Bots mit und bekommen die Discord-Rollen gleich mitgeliefert — [Anleitung](docs/sso.md) |
| 🎨 **Geteiltes Design** | `/brand.css` + `/brand-nav.js` geben jeder anderen App den D4RKST3R-Look samt Navigation — Farben kommen live aus dem Brand-Tab; dazu ein [Gitea-Theme](docs/gitea-theme/) im selben Look |
| 💾 **Repo-Backups** | Nachts werden alle Gitea-Repos als git-Bundle gesichert (komplette Historie, direkt wieder klonbar) |
| 🎨 **Geteiltes Design** | `/brand.css` + `/brand-nav.js` geben jeder anderen App den D4RKST3R-Look samt Navigation — Farben live aus dem Brand-Tab; dazu ein [Gitea-Theme](docs/gitea-theme/) im selben Look |
| 🏠 **Portal** | Dienste (Gitea, Kanban, Cloud …) in der Config pflegen → Kacheln auf der Startseite und Links in der geteilten Navigation |
| 📄 **Seiten-Editor** | Frei anlegbare Markdown-Seiten (Regeln, Über uns, Nutzungsbedingungen …) — im Menü oder nur in der Fußzeile |
| ⚖️ **Rechtstexte** | Impressum + Datenschutz in der Config gepflegt; Member können ihre Daten selbst löschen (DSGVO Art. 17) |
| ⚡ **Auto-Deploy** | Push auf `main` → Portainer rollt neu aus; optional mit Code-Prüfung über Gitea Actions — [Anleitung](docs/auto-deploy.md) |
| 🏠 **Portal** | Dienste (Gitea, Kanban, Cloud …) in der Config pflegen → Kacheln auf der Startseite und Links in der geteilten Navigation |
| ⚖️ **Rechtstexte** | `/impressum` + `/datenschutz` in der Config gepflegt; Member können ihre Daten selbst löschen (DSGVO Art. 17) |
| 💡 **Feature-Voting** | `/wunsch` öffnet ein Eingabefenster (Idee + „warum wäre das gut?") → Voting-Post mit 👍; Top-Wünsche öffentlich auf der Roadmap-Seite |
| 🎉 **Giveaways** | `/giveaway` (Admin): Teilnahme-Button, automatische Ziehung nach Ablauf; am Gewinner-Post: 🔁 Neu auslosen (Admin) + 👥 Teilnehmerliste |
| 📈 **Contribution-Heatmap** | GitHub-Style-Jahreskalender aus dem Commit-Archiv auf der Roadmap-Seite |
| 👤 **Member-Bereich** | Discord-Login für alle Member: `/profil` (Rang + XP-Balken, Rollen, Playtester-Badge, eigener Alpha-Key), Rollen-Selfservice im Browser (nutzt die Rollen-Menüs), Wünsche einreichen + upvoten auf der Roadmap; **Member-Gate**: Login nur für Server-Mitglieder (abweisbare bekommen den Invite-Link) |
| 🏓 `/ping`, 🗄 `/devlog-backfill` | Lebenszeichen · Kanal-Historie nacharchivieren (Admin) |
| 🏓 **Kleinkram** | `/ping` · `/devlog-backfill` und `/galerie-backfill` (Historie nacharchivieren, Admin) |
---
## Webinterface
### Community-Hub (`hub.d4rkst3r.de`)
### Webinterface (`bot.d4rkst3r.de`)
| Seite | Zugriff | Inhalt |
|---|---|---|
| `/` | öffentlich | Startseite: Hero, Live-Zahlen (Member/Server/Spieler), Bereichs-Kacheln, neuestes Devlog |
| `/devlogs` | öffentlich | Devlog-Archiv: Timeline, Bildergalerien, Projekt-Chips, **Volltextsuche**; `/devlogs/:id` als teilbarer Permalink |
| `/roadmap` | öffentlich | Meilensteine aus Gitea mit Fortschrittsbalken |
| `/roadmap` | öffentlich | Meilensteine aus Gitea mit Fortschrittsbalken, Community-Wünsche, Contribution-Heatmap |
| `/server` | öffentlich | Live-Status aller Game-Server: Logo, Spieler-Balken, 24h-Verlauf, Uptime & Peak, Copy-Adresse |
| `/status` | öffentlich | Betriebsstatus: Lage-Banner, Dienste mit 90-Tage-Balken, Game-Server, Störungs-Historie |
| `/galerie` | öffentlich | Community-Screenshots aus dem Discord |
| `/level` | öffentlich | XP-Bestenliste + Server-Aktivitäts-Chart |
| `/events` | öffentlich | Discord-Events (Playtests, Streams …) |
| `/changelog` | öffentlich | Alle Releases mit Notes, Tag- und Pre-Release-Chips |
| `/feed.xml` | öffentlich | RSS-Feed der Devlogs |
| `/<kürzel>` | öffentlich | Frei angelegte Seiten aus dem Seiten-Editor |
| `/impressum` · `/datenschutz` | öffentlich | Rechtstexte — Angaben aus der Config (Owner-only) |
| `/profil` | Member | Eigenes Profil: Rang, XP, Rollen (togglebar), Alpha-Key, DSGVO-Löschung |
| `/impressum` · `/datenschutz` | öffentlich | Rechtstexte — Betreiber-Angaben aus der Config (Owner-only) |
| `/<kürzel>` | öffentlich | **Frei angelegte Seiten** (Regeln, Über uns, FAQ …) — im Seiten-Tab gepflegt |
| `/` | öffentlich | Startseite: Hero, Live-Zahlen (Member/Server/Spieler), Bereichs-Kacheln, neuestes Devlog |
| `/server` | öffentlich | Live-Status aller Game-Server: Logo, Spieler-Balken, 24h-Verlauf, Uptime & Peak, Copy-Adresse |
| `/commits` | nur Admin | Archivierte Commits aller Repos (SHA → Gitea-Link) |
| `/settings` | nur Admin | **Config-Seite** — siehe unten |
| `/commits` | Admin | Archivierte Commits aller Repos (SHA → Gitea-Link) |
| `/settings` | Team | **Config-Seite** — siehe unten |
Login via Discord-OAuth2 (identify-Scope, signierte Session-Cookies, keine Token-Speicherung).
Design: D4RKST3R-Brand (Neon-Gelb/Orange auf Schwarz, Bebas Neue + Barlow Condensed +
Share Tech Mono, selbst gehostet).
### Produktseite (`bot.d4rkst3r.de`)
### Module
| Seite | Zugriff | Inhalt |
|---|---|---|
| `/` | öffentlich | Was der Bot ist und kann |
| `/features` | öffentlich | Alle Funktionen nach Bereichen, mit Symbolen |
| `/commands` | öffentlich | Befehlsübersicht |
| `/dashboard` | Team | Dieselbe Config-Seite wie auf dem Hub |
| `/linked-roles` | Member | Discords Verknüpfungs-Ablauf für *Linked Roles* |
Jede Funktion hat **ihre eigene Seite**: ein Klick auf ihre Karte zeigt Schalter,
Kanäle und Rollen, ihre Texte, ihre Werte und den Weg zum passenden Werkzeug —
statt alles über vier Bereiche verteilt. Für „Willkommen" also Kanal, Karte,
Farben, Vorschau und Begrüßungstext an einem Ort. Die Adresse merkt sich die
Seite (`/settings#module/welcome`).
Login via Discord-OAuth2 (identify-Scope, signierte Session-Cookies, keine
Token-Speicherung außer für Linked Roles). Design: D4RKST3R-Brand
(Neon-Gelb/Orange auf Schwarz, Bebas Neue + Barlow Condensed + Share Tech Mono,
selbst gehostet).
---
## Config-Seite (`/settings`)
**16 Bereiche**, in der Seitenleiste nach Themen gruppiert:
| Gruppe | Bereiche |
|---|---|
| Überblick | Status · Module · Texte · Werte |
| Auftritt | Brand · Seiten |
| Inhalte | Feeds · Composer |
| Community | Community · Rollen · Support · Bewerbungen |
| Technik | Server · System |
| Zugang | API · Team |
### Modul-Seiten
Jede Funktion hat **ihre eigene Seite**: ein Klick auf ihre Karte zeigt
Schalter, Kanäle und Rollen, ihre Texte, ihre Werte und den Weg zum passenden
Werkzeug — statt alles über vier Bereiche verteilt. Für „Willkommen" also
Kanal, Karte, Farben, Vorschau und Begrüßungstext an einem Ort. Die Adresse
merkt sich die Seite (`/settings#module/welcome`).
Die Funktionen, die man dauernd anfasst, stehen zusätzlich **oben in der
Seitenleiste** unter *Meine Funktionen* — ein Klick statt Umweg übers Raster.
@@ -97,52 +194,29 @@ Welche das sind, entscheidet der Stern auf der Modul-Karte (höchstens acht,
damit die Leiste kurz bleibt).
Gebaut wird sie aus den Registern: [`src/modules.js`](src/modules.js) kennt die
Felder, [`src/templates.js`](src/templates.js) die Texte, [`src/tuning.js`](src/tuning.js)
die Werte — jeweils über `module` verknüpft. Eine neue Funktion bekommt ihre
Seite dadurch geschenkt.
Felder, [`src/templates.js`](src/templates.js) die Texte,
[`src/tuning.js`](src/tuning.js) die Werte — jeweils über `module` verknüpft.
Eine neue Funktion bekommt ihre Seite dadurch geschenkt.
Alle **35 Funktionen** lassen sich im Tab *Module* einzeln ein- und ausschalten —
gruppiert nach Inhalte, Community, Moderation und Server. Jede Karte zeigt, ob das
Modul einsatzbereit ist oder noch etwas fehlt (z. B. ein Kanal), und verlinkt direkt
zu seinen Einstellungen. Ein ausgeschaltetes Modul reagiert auf nichts mehr: keine
Posts, keine Hintergrund-Prüfungen.
### Module, Werte, Texte
Definiert sind sie zentral in [`src/modules.js`](src/modules.js). Funktionen mit
einem bereits vorhandenen Schalter (Level-System, Backups …) nutzen weiterhin
dieselbe Einstellung — es gibt also keine zweite Wahrheit.
* **Module** — alle 39 Funktionen einzeln schaltbar, gruppiert nach Inhalte,
Community, Moderation und Server. Jede Karte zeigt, ob das Modul
einsatzbereit ist oder noch etwas fehlt (z. B. ein Kanal). Funktionen mit
einem bereits vorhandenen Schalter nutzen weiterhin dieselbe Einstellung —
es gibt keine zweite Wahrheit.
* **Werte** — Zahlen, die das Verhalten steuern (XP, Wartezeiten,
Prüf-Intervalle, Postzeiten, Obergrenzen) mit erlaubtem Bereich und Standard.
Geänderte Intervalle greifen ab dem nächsten Durchlauf, ohne Neustart.
Gespeichert wird ganz oder gar nicht: ein ungültiger Wert lässt die anderen
im selben Formular unverändert.
* **Texte** — was der Bot nach außen schreibt, als Vorlage. Platzhalter wie
`{user}` oder `{count}` setzt der Bot beim Senden ein; ein Klick auf den
Baustein fügt ihn an der Cursor-Position ein. Ein leeres Feld stellt den
Standard wieder her — der lebt im Code, die Datenbank enthält nur echte
Abweichungen.
### Werte
Zahlen, die das Verhalten steuern — XP pro Nachricht, Wartezeiten,
Prüf-Intervalle, Postzeiten, Obergrenzen — stehen im Tab *Werte* mit erlaubtem
Bereich und Standard. Geänderte Intervalle greifen ab dem nächsten Durchlauf,
ohne Neustart.
Definiert sind sie in [`src/tuning.js`](src/tuning.js). Gespeichert wird ganz
oder gar nicht: ein ungültiger Wert lässt die anderen im selben Formular
unverändert.
### Texte
Was der Bot nach außen schreibt — Begrüßungen, Bestätigungen, Direktnachrichten —
steht als Vorlage im Tab *Texte*. Platzhalter wie `{user}` oder `{count}` setzt der
Bot beim Senden ein; ein Klick auf den Baustein fügt ihn an der Cursor-Position ein.
Ein leeres Feld stellt den Standardtext wieder her.
Die Vorlagen stehen in [`src/templates.js`](src/templates.js). Der Standard lebt im
Code, die Datenbank enthält nur echte Abweichungen.
### Config-Seite (`/settings`)
15 Bereiche, in der Seitenleiste nach Themen gruppiert:
| Gruppe | Bereiche |
|---|---|
| Überblick | Status · Module · Texte |
| Auftritt | Brand · Seiten |
| Inhalte | Feeds · Composer |
| Community | Community · Rollen · Support · Bewerbungen |
| Technik | Server · System |
| Zugang | API · Team |
### Suchen, Speichern, Einrichten
Das Suchfeld über der Leiste findet **Bereiche und einzelne Einstellungen**:
„geburtstag" führt zu Community, „schwellwert" direkt aufs Starboard-Feld, das
@@ -151,55 +225,35 @@ liegt, steht in [`frontend/src/setting-index.js`](frontend/src/setting-index.js)
Sobald sich etwas vom gespeicherten Stand unterscheidet, erscheint unten eine
Leiste mit Anzahl, *Verwerfen* und *Speichern*; beim Verlassen mit offenen
Änderungen fragt der Browser nach.
Der aktive Bereich steht in der Adresse (`/settings#texte`), Links und Neuladen
landen also wieder dort.
Änderungen fragt der Browser nach. Der aktive Bereich steht in der Adresse
(`/settings#texte`), Links und Neuladen landen also wieder dort.
Der Status-Bereich ist der Einstieg: Kennzahlen plus **„Noch einzurichten"** —
alle eingeschalteten Module, denen noch ein Kanal oder eine Rolle fehlt. Daneben
steht **„Kanal anlegen"** bzw. **„Rolle anlegen"**: der Bot legt sie in Discord
an, setzt bei privaten Kanälen die Rechte (nur Team sieht sie) und trägt die
Einstellung gleich ein. Gibt es Kanal oder Rolle schon, werden sie verknüpft
statt doppelt angelegt.
Der Status-Bereich ist der Einstieg: Kennzahlen, Erreichbarkeits-Balken und
**„Noch einzurichten"** — alle eingeschalteten Module, denen noch ein Kanal
oder eine Rolle fehlt. Daneben steht **„Kanal anlegen"** bzw. **„Rolle
anlegen"**: der Bot legt sie in Discord an, setzt bei privaten Kanälen die
Rechte und trägt die Einstellung gleich ein. Gibt es Kanal oder Rolle schon,
werden sie verknüpft statt doppelt angelegt.
Daneben legt **„Alles auf einmal anlegen"** das ganze Grundgerüst an: erst eine
Vorschau (was ist neu, was ist schon da, in welche Kategorie kommt es), dann ein
Durchlauf mit Ergebnis je Zeile. Neue Kanäle landen in einer eigenen Kategorie,
und ein Fehler bei einem Kanal bricht die restlichen nicht ab.
**„Alles auf einmal anlegen"** legt das ganze Grundgerüst an: erst eine
Vorschau (was ist neu, was ist schon da, in welche Kategorie kommt es), dann
ein Durchlauf mit Ergebnis je Zeile. Ein Fehler bei einem Kanal bricht die
restlichen nicht ab.
Dafür braucht der Bot *Kanäle verwalten* bzw. *Rollen verwalten* — fehlt das
Recht, sagt das Panel genau das. Die Vorlagen (Name, Thema, privat/öffentlich)
stehen bei den Modulen in [`src/modules.js`](src/modules.js). Gelöscht oder
umbenannt wird bewusst nichts: ein Fehlklick beim Anlegen kostet einen
überflüssigen Kanal, einer beim Löschen dessen Verlauf.
Recht, sagt das Panel genau das. Gelöscht oder umbenannt wird bewusst nichts:
ein Fehlklick beim Anlegen kostet einen überflüssigen Kanal, einer beim Löschen
dessen Verlauf.
Team-Mitglieder sehen nur die Bereiche ihrer Rechte. Alles zur Laufzeit änderbar —
gespeichert in SQLite, Env-Variablen sind nur Fallback, kein Redeploy nötig:
- **Allgemein:** Öffentliche URL, Gitea-URL
- **Kanäle** (Devlog / Commit / Release) als Dropdown + „Test senden"-Button je Kanal
- **Devlog:** Ping-Rolle, Auto-Threads, Wochen-Rückblick (+ Sofort-Test)
- **Commit-Feed:** an/aus, Branch-Filter, ignorierte Repos
(gefiltert wird nur das Posten — archiviert wird immer)
- **Community:** Playtester-Rolle (+ Liste), Starboard-Kanal + ⭐-Schwellwert,
Screenshot-Kanal, Voting-Kanal
- **Moderation & Kontakt:** Modmail-, Willkommens-, Mod-Log-Kanal
- **Game-Server:** eigener Tab — Spiel-Auswahl (19 Presets + freie gamedig-ID), Host/Port
oder Query-URL, Connect-URL, Status- & Alert-Kanal
- **Composer:** visueller **Embed-Builder mit Live-Discord-Preview** (Autor, Felder,
Bilder, Farbe, Footer), Nachrichten senden & nachträglich bearbeiten, speicherbare Vorlagen
- **Bug-Reports / Roadmap:** Ziel-Repos
- **Backups:** DB nächtlich (an/aus, Upload-Kanal, „Backup jetzt") + **Repo-Backups**
um 04:00 (alle Gitea-Repos als git-Bundle, 14 Tage Rotation, „Repos jetzt sichern")
- **Watchdog:** überwachte URLs
- **API-Keys:** erstellen (Name + Scopes), widerrufen, last-used
- **Status-Panel:** Bot-Account, Uptime, Devlog-/Commit-Zahlen, DB-Größe, letztes Backup
Team-Mitglieder sehen nur die Bereiche ihrer Rechte. Alles ist zur Laufzeit
änderbar und liegt in SQLite; Env-Variablen sind nur Fallback.
---
## Ersteinrichtung
### 1. Discord-App ([Developer Portal](https://discord.com/developers/applications))
1. **New Application** → Name vergeben
2. **General Information** → Application ID = `DISCORD_CLIENT_ID`
3. **Bot** → Reset Token = `DISCORD_TOKEN` (wird nur einmal angezeigt!)
@@ -207,20 +261,34 @@ gespeichert in SQLite, Env-Variablen sind nur Fallback, kein Redeploy nötig:
(Devlog-Listener bzw. Willkommens-Embeds)
4. **OAuth2** → Client Secret = `DISCORD_CLIENT_SECRET`;
unter **Redirects** eintragen:
- `https://bot.d4rkst3r.de/auth/callback`
- `http://localhost:3080/auth/callback` (lokale Entwicklung)
* `https://bot.d4rkst3r.de/auth/callback`
* `https://hub.d4rkst3r.de/auth/callback` (bei zwei Seiten)
* `https://bot.d4rkst3r.de/linked-roles/callback` (für Linked Roles)
* `http://localhost:3080/auth/callback` (lokale Entwicklung)
5. **OAuth2 → URL Generator:** Scopes `bot` + `applications.commands`;
Permissions: Send Messages, Embed Links, Attach Files, Read Message History,
**Create Public Threads**, **Manage Roles** (für den 🔔-Abo-Button)
Rechte: Send Messages, Embed Links, Attach Files, Read Message History,
**Create Public Threads**, **Manage Roles** (🔔-Abo-Button, Rollen-Menüs),
**Manage Server** (AutoMod-Regeln lesen und schalten),
**Manage Channels** (Kanäle anlegen, Raid-Sperre)
→ URL öffnen, Bot einladen
6. In Discord: Entwicklermodus an → Server-ID = `DISCORD_GUILD_ID`,
eigene User-ID = `ADMIN_DISCORD_ID`
> **Linked Roles** brauchen zusätzlich unter *General Information* die
> *Linked Roles Verification URL* → `https://bot.d4rkst3r.de/linked-roles`.
> Die Kennzahlen meldet der Bot beim Start selbst an.
> **AutoMod-Treffer** kommen nur bei Bots mit *Manage Server* an — der nötige
> Gateway-Intent (`AutoModerationExecution`) ist nicht privilegiert und muss im
> Portal nicht freigeschaltet werden.
⚠️ **Kanal-Overrides:** In Kanälen, in denen `@everyone` nicht schreiben darf,
braucht der Bot eigene Overrides (Kanal ansehen, Nachrichten senden, Links einbetten,
Dateien anhängen, Threads erstellen). Die Bot-Rolle muss **über** der Ping-Rolle stehen.
braucht der Bot eigene Overrides (Kanal ansehen, Nachrichten senden, Links
einbetten, Dateien anhängen, Threads erstellen). Die Bot-Rolle muss **über** der
Ping-Rolle stehen.
### 2. Environment-Variablen
Vorlage: [.env.example](.env.example) — lokal als `.env` (gitignored),
in Portainer als Stack-Environment-Variables.
@@ -230,86 +298,103 @@ in Portainer als Stack-Environment-Variables.
| `DISCORD_CLIENT_ID` | ✅ | Application ID |
| `DISCORD_CLIENT_SECRET` | ✅ | OAuth2-Login |
| `SESSION_SECRET` | ✅ | Session-Cookies signieren¹ |
| `ADMIN_DISCORD_ID` | ✅ | Deine User-ID (Admin-Zugriff + Watchdog-DMs) |
| `ADMIN_DISCORD_ID` | ✅ | Deine User-ID (Admin-Zugriff + Wächter-DMs) |
| `GITEA_WEBHOOK_SECRET` | ✅ | HMAC-Prüfung der Gitea-Webhooks¹ |
| `DEVLOG_POST_SECRET` | ✅ | Secret im Devlog-Endpoint-Pfad¹ |
| `DISCORD_GUILD_ID` | optional | Guild-Commands sofort statt global (bis 1h) |
| `GITEA_API_TOKEN` | optional | Für `/bug` → Issues (Scope `write:issue`); alternativ im Brand-Tab hinterlegen |
| `DISCORD_GUILD_ID` | optional | Guild-Commands sofort statt global (bis 1 h) |
| `GITEA_API_TOKEN` | optional | Für `/bug` → Issues (Scope `write:issue`); alternativ im Brand-Tab |
| `GITEA_URL` | optional | Default `https://git.d4rkst3r.de` |
| `PUBLIC_URL` | optional | Default `https://bot.d4rkst3r.de` |
| `COMMIT_CHANNEL_ID` / `DEVLOG_CHANNEL_ID` | optional | Fallbacks — Kanäle kommen normal von der Config-Seite |
| `TZ` | optional | Default `Europe/Berlin` (Wochen-Rückblick, Datumsformate) |
| `DB_PATH` | optional | Default `./data/ecobot.db` |
| `COMMIT_CHANNEL_ID` / `DEVLOG_CHANNEL_ID` | optional | Fallbacks — Kanäle kommen normal aus der Config |
| `TZ` | optional | Default `Europe/Berlin` (Postzeiten, Datumsformate) |
¹ Generieren: `node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"`
¹ Generieren:
```bash
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
```
### 3. Routing (einmalig eingerichtet)
Cloudflare: CNAME `bot` → Zone, Proxied. Nginx Proxy Manager: `bot.d4rkst3r.de`
`host.docker.internal:3080`, Block Common Exploits, Force SSL.
Test: `https://bot.d4rkst3r.de/health``{"status":"ok"}`
### 3. Routing
Cloudflare: CNAME `bot` und `hub` → Zone, Proxied. Nginx Proxy Manager:
beide Hosts → `host.docker.internal:3080`, Block Common Exploits, Force SSL.
Test:
```bash
curl https://bot.d4rkst3r.de/health
```
### 4. Gitea-Webhook (systemweit oder pro Repo)
- Typ **Gitea**, URL `https://bot.d4rkst3r.de/webhooks/gitea`,
* Typ **Gitea**, URL `https://bot.d4rkst3r.de/webhooks/gitea`,
Content Type `application/json`, Geheimnis = `GITEA_WEBHOOK_SECRET`
- Trigger-Events: **Push**, **Release**, **Issues**
* Trigger-Events: **Push**, **Release**, **Issues**
(Push = Commit-Feed · Release = Ankündigungen/Changelog · Issues = Bug-Rückkanal-DMs)
### 5. devlog.py (EcoGame-Repo)
In `tools/.devlog_webhook` steht die Bot-Endpoint-URL:
```
https://bot.d4rkst3r.de/webhooks/devlog/<DEVLOG_POST_SECRET>
```
Workflow: Prosa nach `tools/devlog_today.txt` (+ Bilder in `devlog_images/`, max 4)
`python tools/devlog.py` (oder Task täglich 21:00) → Bot postet + archiviert,
Prosa-Datei und Bilder werden danach gelöscht (gepostet = erledigt).
Ohne Prosa postet das Skript **nichts** (Schutz des öffentlichen Kanals).
Der Endpoint versteht das Discord-Webhook-Format (JSON + Multipart) —
Workflow: Prosa nach `tools/devlog_today.txt` (+ Bilder in `devlog_images/`,
max 4) → `python tools/devlog.py` (oder Task täglich 21:00) → Bot postet und
archiviert, Prosa-Datei und Bilder werden danach gelöscht (gepostet =
erledigt). Ohne Prosa postet das Skript **nichts** (Schutz des öffentlichen
Kanals). Der Endpoint versteht das Discord-Webhook-Format (JSON + Multipart) —
`devlog.py` kennt den Bot also gar nicht.
---
## Deployment (Portainer)
1. **Stacks → Add stack** → Name `ecobot` (Bestands-Stack behalten! Der Name steckt im Volume-Prefix) → Build method **Repository**
- URL `https://git.d4rkst3r.de/D4rkst3r/d4rkbot`, Reference `refs/heads/main`,
1. **Stacks → Add stack** → Name `ecobot` (Bestands-Stack behalten! Der Name
steckt im Volume-Prefix) → Build method **Repository**
* URL `https://git.d4rkst3r.de/D4rkst3r/d4rkbot`, Reference `refs/heads/main`,
Compose path `docker-compose.yml`
- Privates Repo: Authentication mit Gitea-Token (Scope `read:repository`)
* Privates Repo: Authentication mit Gitea-Token (Scope `read:repository`)
2. Environment-Variablen eintragen (Tabelle oben)
3. **Deploy the stack**
**Updates:** Stack öffnen → **Pull and redeploy**
(„Re-pull image" **aus** lassen — das Image wird lokal gebaut, nicht aus einer Registry gezogen).
**Updates:** Stack öffnen → **Pull and redeploy** („Re-pull image" **aus**
lassen — das Image wird lokal gebaut, nicht aus einer Registry gezogen).
Automatisch geht es über [docs/auto-deploy.md](docs/auto-deploy.md).
Daten liegen im Volume `ecobot_data` (`/app/data`): SQLite (`ecobot.db`, WAL)
+ Devlog-Bilder (`devlog_images/` — lokal gespeichert, weil Discord-CDN-Links ablaufen).
+ Devlog- und Galerie-Bilder.
Manuell statt Portainer:
```
```bash
git clone git@gitea:D4rkst3r/d4rkbot.git && cd d4rkbot
cp .env.example .env # Werte eintragen
docker compose up -d --build
docker logs -f d4rkbot
```
---
## Lokale Entwicklung
```
```bash
npm install
npm run dev # Bot + API auf :3080 (Werte aus .env)
npm run dev
```
Frontend mit Hot-Reload:
```
cd frontend
npm install
npm run dev # Vite auf :5173, proxied /api + /auth → :3080
```
Alternativ `npm run build` im frontend/ — der Bot liefert `frontend/dist`
dann selbst unter :3080 aus (so läuft es auch im Container, Multi-Stage-Build).
Bot + API laufen auf `:3080` mit den Werten aus `.env`. Frontend mit
Hot-Reload:
Commit-Feed ohne Gitea testen (signierte Fake-Testzustellung):
```bash
cd frontend && npm install && npm run dev
```
Vite läuft auf `:5173` und leitet `/api` + `/auth` an `:3080` weiter.
Alternativ `npm run build` im `frontend/` — der Bot liefert `frontend/dist`
dann selbst unter `:3080` aus (so läuft es auch im Container, Multi-Stage-Build).
Commit-Feed ohne Gitea testen (signierte Fake-Zustellung):
```bash
node tools/test-webhook.mjs
```
@@ -320,8 +405,9 @@ node tools/test-webhook.mjs
Der Bot ist die zentrale Discord-Brücke der Infrastruktur: devlog.py, Platform,
FiveM-Server, CI-Jobs … reden alle mit einer API statt mit zig Discord-Webhooks.
**Auth:** API-Keys auf der Config-Seite erstellen (Name + Scopes, Key wird einmalig
angezeigt, Widerruf jederzeit). Jeder Request:
**Auth:** API-Keys auf der Config-Seite erstellen (Name + Scopes, Key wird
einmalig angezeigt, Widerruf jederzeit). Jeder Request:
```
Authorization: Bearer d4rk_<key>
```
@@ -332,15 +418,17 @@ Authorization: Bearer d4rk_<key>
| `PATCH /api/v1/message` | `message` | `{ channel_id, message_id, content?, embed? }` → eigenen Bot-Post bearbeiten |
| `POST /api/v1/dm` | `dm` | `{ user_id, content }` → Direktnachricht |
| `POST /api/v1/roles` | `roles` | `{ user_id, role_id, action: "add"\|"remove" }` → Rolle vergeben (z. B. Shop-Kauf → Kunden-Rolle) |
| `GET /api/v1/member/:id` | `read` | Member-Info: Name, Rollen, Beitritt — für Login-/Berechtigungs-Checks |
| `GET /api/v1/member/:id` | `read` | Member-Info: Name, Rollen, Beitritt — für Login- und Berechtigungs-Checks |
| `GET /api/v1/stats` | `read` | Devlog-/Commit-Zahlen, Guilds, Uptime |
Beispiel (Python):
```python
import urllib.request, json
req = urllib.request.Request(
"https://bot.d4rkst3r.de/api/v1/message",
data=json.dumps({"channel_id": "123", "embed": {"title": "Build fertig ✅", "color": 0xF5C518}}).encode(),
data=json.dumps({"channel_id": "123",
"embed": {"title": "Build fertig ✅", "color": 0xF5C518}}).encode(),
headers={"Content-Type": "application/json",
"Authorization": "Bearer d4rk_...",
"User-Agent": "mein-script/1.0"})
@@ -358,24 +446,28 @@ urllib.request.urlopen(req)
| `POST /webhooks/devlog/:secret` | Secret im Pfad | Devlog von devlog.py (JSON/Multipart) |
| `GET /api/devlogs?page=&q=` | — | Archiv + FTS5-Volltextsuche |
| `GET /api/releases` · `/api/roadmap` · `/api/gallery` · `/api/wishes` · `/api/heatmap` | — | Changelog · Milestones · Galerie · Wunsch-Ranking · Commit-Heatmap |
| `GET /api/servers` · `/api/status` | — | Game-Server-Status · öffentlicher Betriebsstatus (Namen, nie Adressen) |
| `GET /api/pages` · `/api/features` | — | Veröffentlichte Seiten · Funktionsliste für die Produktseite |
| `GET /feed.xml` | — | RSS |
| `GET /devlog-assets/*` · `/gallery-assets/*` | — | Lokal gespeicherte Bilder |
| `GET /api/playtesters` | Admin | Playtester-Liste |
| `POST/GET /api/v1/*` | API-Key (Bearer) | Externe Skripte — siehe „API v1" oben |
| `GET/POST/DELETE /api/apikeys` | Admin | API-Key-Verwaltung |
| `GET/POST/PUT/DELETE /api/rolemenus`, `POST /api/rolemenus/:id/publish` | Admin | Rollen-Menüs |
| `POST /api/compose` · `GET/PUT/DELETE /api/templates` | Team (content) | Embed-Composer senden/bearbeiten · Vorlagen |
| `GET /api/profile` · `GET/POST /api/myroles*` · `POST /api/wishes*` | Member | Profil · Rollen-Selfservice · Wunsch einreichen/voten |
| `GET /sso/authorize` · `POST /sso/verify` | App-Secret | **Single Sign-On** für andere Dienste — siehe [docs/sso.md](docs/sso.md) |
| `GET /brand.css` · `/brand-nav.js` | — | Design-Tokens + Navigation für andere Apps (CORS offen) |
| `GET /api/services` | — | Dienste-Kacheln fürs Portal (Pflege: Scope `settings`) |
| `GET /api/legal` · `DELETE /api/profile` | — / Member | Impressums-Angaben · DSGVO-Löschung |
| `GET/PUT /api/settings`, `POST /api/settings/test/:target` | Admin | Config-Seite |
| `GET /api/profile` · `/api/myroles*` · `POST /api/wishes*` | Member | Profil · Rollen-Selfservice · Wunsch einreichen/voten |
| `GET /linked-roles` · `/linked-roles/callback` | Member | Discords Verknüpfungs-Ablauf für Linked Roles |
| `GET /sso/authorize` · `POST /sso/verify` | App-Secret | **Single Sign-On** für andere Dienste — siehe [docs/sso.md](docs/sso.md) |
| `POST/GET /api/v1/*` | API-Key (Bearer) | Externe Skripte — siehe „API v1" oben |
| `GET /api/watchdog` · `/api/automod` | Team | Wächter-Übersicht · AutoMod-Regeln |
| `PUT /api/automod/:id` · `/api/monitored*` | Team (settings) | Regel schalten · überwachte Dienste pflegen |
| `GET/PUT /api/settings`, `POST /api/settings/test/:target` | Team | Config-Seite |
| `GET/PUT /api/modules` · `/api/texts` · `/api/tuning` | Team (settings) | Module · Textvorlagen · Werte |
| `POST /api/compose` · `GET/PUT/DELETE /api/templates` | Team (content) | Composer senden/bearbeiten · Vorlagen |
| `GET/POST/PUT/DELETE /api/rolemenus`, `POST /api/rolemenus/:id/publish` | Team (rollen) | Rollen-Menüs |
| `GET/POST/DELETE /api/apikeys` | Owner | API-Key-Verwaltung |
| `GET /api/commits?page=` · `DELETE /api/devlogs/:id` | Admin | Commit-Archiv · Devlog löschen |
| `GET /auth/login` · `/auth/callback` · `/auth/logout` | — | Discord-OAuth2 |
Devlogs, die in Discord gelöscht werden, verschwinden automatisch auch aus dem
Archiv (MessageDelete-Sync) — zusätzlich gibt es den ✕-Button für Admins auf der Webseite.
Archiv (MessageDelete-Sync) — zusätzlich gibt es den ✕-Button für Admins.
---
@@ -384,44 +476,92 @@ Archiv (MessageDelete-Sync) — zusätzlich gibt es den ✕-Button für Admins a
```
d4rkbot/
├── src/
│ ├── index.js # Start: Bot, Webserver, Wochen-Rückblick, Watchdog
│ ├── index.js # Start: Bot, Webserver, Scheduler
│ ├── config.js # Env-Konfiguration mit Validierung
│ ├── db.js # SQLite: Schema, Migrationen, FTS5, alle Queries
│ ├── runtime-settings.js # Effektive Settings (DB vor Env)
│ ├── modules.js # Register: welche Funktionen es gibt
│ ├── templates.js # Register: was der Bot schreibt
│ ├── tuning.js # Register: welche Zahlen stellbar sind
│ ├── embeds.js # brandEmbed-Factory (Farbe, Footer, Bot-Icon)
│ ├── gitea-api.js # Gitea-REST (Issues + Assets für /bug)
│ ├── backup.js # Nächtliche DB-Backups (gzip, Rotation, Upload)
│ ├── embeds.js # brandEmbed-Factory (Farbe, Footer, Bot-Icon)
│ ├── repo-backup.js # Gitea-Repos als git-Bundle sichern
│ ├── bot/
│ │ ├── client.js # Discord-Client, Commands, Listener, Button-Handler
│ │ ├── client.js # Discord-Client, Commands, Listener, Buttons
│ │ ├── commit-feed.js # Push → Embed
│ │ ├── release-feed.js # Release → Ankündigungs-Embed
│ │ ├── devlog-archive.js # Nachricht → SQLite (+ Bild-Download)
│ │ ├── weekly-recap.js # Sonntags-Zusammenfassung
│ │ ├── community.js # Starboard + Screenshot-Galerie
│ │ ├── mod-tools.js # Modmail, Willkommens-Embed, Mod-Log
│ │ ├── server-monitor.js # Game-Server-Status (gamedig 300+ Spiele, Alerts)
│ │ ├── giveaways.js # Giveaway-Ziehung (Scheduler)
│ │ ├── weekly-recap.js # Sonntags-Zusammenfassung + Scheduler
│ │ ├── watchdog.js # URL-Checks + DM-Alarm
│ │ ── commands/ # ping, devlog-backfill, bug, playtester-setup,
│ │ # galerie-backfill, wunsch, giveaway
│ │ ├── levels.js # XP, Level-Up, Rollen-Belohnungen
│ │ ├── mod-tools.js # Modmail, Willkommen, Mod-Log
│ │ ├── automod.js # Discords Filter spiegeln + Regeln schalten
│ │ ├── anti-raid.js # Beitritts-Wellen erkennen, Server sperren
│ │ ├── tickets.js # Private Threads + Transcript
│ │ ── app-forms.js # Bewerbungs-Modals + Review
│ │ ├── role-menus.js # Button-Embeds für Rollen
│ │ ├── linked-roles.js # Kennzahlen an Discord melden
│ │ ├── giveaways.js # Ziehung + Reroll
│ │ ├── birthdays.js # Gratulation + Tages-Rolle
│ │ ├── server-monitor.js # Game-Server (gamedig, 300+ Spiele)
│ │ ├── watchdog.js # URL-Checks, Störungen, DM-Alarm
│ │ ├── heartbeat.js # Eigene Erreichbarkeit aufzeichnen
│ │ ├── server-setup.js # Kanäle und Rollen anlegen
│ │ ├── welcome-card.js # Willkommens-Bild rendern
│ │ ├── social-notify.js # Twitch + YouTube
│ │ ├── presence.js # Status des Bots
│ │ ├── extras.js # Temp-Voice, Trigger, Erinnerungen, Events
│ │ └── commands/ # 18 Slash-Commands
│ └── web/
│ ├── server.js # Fastify: Webhooks, Static, SPA-Fallback
│ ├── server.js # Fastify: Webhooks, Static, SPA-Fallback, OG-Tags
│ ├── auth.js # Discord-OAuth2 + Session-Cookies
│ ├── api.js # REST-API + Settings + RSS
── devlog-endpoint.js# Devlog-Post: Embed, Bilder, Ping, Thread, Archiv
── api-v1.js # Öffentliche API mit Bearer-Keys
│ ├── sso.js # Identity-Provider für andere Dienste
│ ├── brand.js # /brand.css + /brand-nav.js
│ ├── linked-roles.js # Verknüpfungs-Ablauf
│ ├── scheduled-posts.js# Geplante Beiträge
│ └── devlog-endpoint.js# Devlog: Embed, Bilder, Ping, Thread, Archiv
├── frontend/ # React + Vite (D4RKST3R-Design)
│ └── src/
│ ├── App.jsx # Layout, Router, Nav, Login-Status
│ ├── markdown.jsx # Mini-Markdown (fett/kursiv/Code/Links/Listen/---/##)
│ ├── components/ # EmbedComposer (Builder + Discord-Preview)
── pages/ # Devlogs, Roadmap, Galerie, Changelog, Commits, Settings
│ ├── App.jsx # Hub: Layout, Router, Navigation
│ ├── BotApp.jsx # Produktseite: eigene Navigation
│ ├── site.js # Welche der beiden Seiten gilt
── i18n.jsx # Sprachumschalter + Wörterbücher
│ ├── locales/ # de.js · en.js (öffentliche Seiten)
│ ├── markdown.jsx # Mini-Markdown
│ ├── icons.jsx # Lucide-Symbole
│ ├── components/ # Composer, Lightbox, UptimeTrack, ModulePage …
│ └── pages/ # Alle Seiten inkl. Settings
├── docs/ # Anleitungen und Konzepte
├── tools/test-webhook.mjs # Lokaler Commit-Feed-Test
├── .env.example # Vorlage für alle Env-Variablen
├── Dockerfile # Multi-Stage: Frontend-Build + node:22-slim Runtime
├── Dockerfile # Multi-Stage: Frontend-Build + node:22-slim
└── docker-compose.yml # Portainer-ready, Volume ecobot_data, TZ
```
**Neue Slash-Commands:** Datei in `src/bot/commands/` (exportiert `data` + `execute`)
und in `client.js` bei `commandModules` eintragen.
**Neue Settings:** Key in `db.js`-Settings nutzen, Zugriff über `runtime-settings.js`,
UI in `frontend/src/pages/Settings.jsx`, GET/PUT in `src/web/api.js`.
**Neuer Slash-Command:** Datei in `src/bot/commands/` (exportiert `data` +
`execute`) und in `client.js` bei `commandModules` eintragen.
**Neue Einstellung:** Key in `db.js` nutzen, Zugriff über
`runtime-settings.js`, UI in `frontend/src/pages/Settings.jsx`, GET/PUT in
`src/web/api.js` — und in `setting-index.js` eintragen, damit die Suche sie
findet.
**Neues Modul:** Eintrag in `src/modules.js` (Gruppe, Tab, Schalter,
Voraussetzungen), Symbol in `frontend/src/module-icons.jsx`, englischer Name
in `frontend/src/locales/en.js`. Die Modul-Seite entsteht daraus von selbst.
---
## Weitere Dokumentation
| Datei | Inhalt |
|---|---|
| [docs/sso.md](docs/sso.md) | Single Sign-On: Ablauf, Endpoints, Anbindung eigener Dienste |
| [docs/auto-deploy.md](docs/auto-deploy.md) | Push auf `main` → Portainer rollt neu aus |
| [docs/konzept-zwei-seiten.md](docs/konzept-zwei-seiten.md) | Warum und wie Produktseite und Hub getrennt sind |
| [docs/brand/README.md](docs/brand/README.md) | Logo-Master, abgeleitete Symbole, Build-Skript |
| [docs/gitea-theme/README.md](docs/gitea-theme/README.md) | D4RKST3R-Theme für Gitea |
| [docs/nutzungsbedingungen.md](docs/nutzungsbedingungen.md) | Entwurf für die Nutzungsbedingungen-Seite |