Nach dem Umbau lagen alle Funktionen hinter dem Raster — für die vier, fünf, die man dauernd anfasst, ist das ein Umweg zu viel. Oben in der Seitenleiste steht jetzt „Meine Funktionen": ein Klick öffnet die Seite direkt. Welche dort stehen, entscheidet der Stern auf der Modul-Karte oder auf der Seite selbst. Bewusst nicht alle 35: Deckel bei acht, sonst ist der Gewinn gegenüber dem Raster wieder weg. Der Standard ist eine Vermutung (Devlogs, Willkommen, Tickets, Starboard, Galerie) und ausdrücklich zum Ändern gedacht. Die Auswahl liegt als Einstellung in der Datenbank, nicht im Browser — sie gilt damit auf jedem Gerät und fürs ganze Team. Eine geleerte Auswahl wird als solche gespeichert, sonst käme beim nächsten Laden der Standard zurück. Der Stern ist ungeheftet nur angedeutet und wird erst beim Überfahren deutlich — 35 Karten mit vollen Sternen sähen aus wie ein Sternenhimmel. Nebenbei: bei geöffneter Modul-Seite war sowohl „Module" als auch die Funktion in der Leiste hervorgehoben. Jetzt nur noch die Funktion. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
428 lines
26 KiB
Markdown
428 lines
26 KiB
Markdown
# 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.
|
|
|
|
**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
|
|
|
|
### Discord
|
|
| Feature | 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) |
|
|
| 🔗 **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 |
|
|
| 🔑 **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) |
|
|
| ⚡ **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) |
|
|
|
|
### Webinterface (`bot.d4rkst3r.de`)
|
|
| Seite | Zugriff | Inhalt |
|
|
|---|---|---|
|
|
| `/devlogs` | öffentlich | Devlog-Archiv: Timeline, Bildergalerien, Projekt-Chips, **Volltextsuche**; `/devlogs/:id` als teilbarer Permalink |
|
|
| `/roadmap` | öffentlich | Meilensteine aus Gitea mit Fortschrittsbalken |
|
|
| `/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 |
|
|
| `/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 |
|
|
|
|
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).
|
|
|
|
### Module
|
|
|
|
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.
|
|
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.
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
### 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 |
|
|
|
|
Das Suchfeld über der Leiste findet **Bereiche und einzelne Einstellungen**:
|
|
„geburtstag" führt zu Community, „schwellwert" direkt aufs Starboard-Feld, das
|
|
kurz hervorgehoben wird. Enter nimmt den ersten Treffer. Welche Einstellung wo
|
|
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.
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
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
|
|
|
|
---
|
|
|
|
## 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!)
|
|
und **Message Content Intent** + **Server Members Intent** aktivieren
|
|
(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)
|
|
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)
|
|
→ URL öffnen, Bot einladen
|
|
6. In Discord: Entwicklermodus an → Server-ID = `DISCORD_GUILD_ID`,
|
|
eigene User-ID = `ADMIN_DISCORD_ID`
|
|
|
|
⚠️ **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.
|
|
|
|
### 2. Environment-Variablen
|
|
Vorlage: [.env.example](.env.example) — lokal als `.env` (gitignored),
|
|
in Portainer als Stack-Environment-Variables.
|
|
|
|
| Variable | Pflicht | Zweck |
|
|
|---|---|---|
|
|
| `DISCORD_TOKEN` | ✅ | Bot-Token |
|
|
| `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) |
|
|
| `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 |
|
|
| `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) |
|
|
|
|
¹ Generieren: `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"}`
|
|
|
|
### 4. Gitea-Webhook (systemweit oder pro Repo)
|
|
- Typ **Gitea**, URL `https://bot.d4rkst3r.de/webhooks/gitea`,
|
|
Content Type `application/json`, Geheimnis = `GITEA_WEBHOOK_SECRET`
|
|
- 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) —
|
|
`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`,
|
|
Compose path `docker-compose.yml`
|
|
- 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).
|
|
|
|
Daten liegen im Volume `ecobot_data` (`/app/data`): SQLite (`ecobot.db`, WAL)
|
|
+ Devlog-Bilder (`devlog_images/` — lokal gespeichert, weil Discord-CDN-Links ablaufen).
|
|
|
|
Manuell statt Portainer:
|
|
```
|
|
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
|
|
|
|
```
|
|
npm install
|
|
npm run dev # Bot + API auf :3080 (Werte aus .env)
|
|
```
|
|
|
|
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).
|
|
|
|
Commit-Feed ohne Gitea testen (signierte Fake-Testzustellung):
|
|
```
|
|
node tools/test-webhook.mjs
|
|
```
|
|
|
|
---
|
|
|
|
## API v1 — für eigene Skripte & Dienste
|
|
|
|
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:
|
|
```
|
|
Authorization: Bearer d4rk_<key>
|
|
```
|
|
|
|
| Endpoint | Scope | Body / Antwort |
|
|
|---|---|---|
|
|
| `POST /api/v1/message` | `message` | `{ channel_id, content?, embed? }` → postet als Bot (Embed: title, description, color, url, image, thumbnail, footer, fields) |
|
|
| `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/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(),
|
|
headers={"Content-Type": "application/json",
|
|
"Authorization": "Bearer d4rk_...",
|
|
"User-Agent": "mein-script/1.0"})
|
|
urllib.request.urlopen(req)
|
|
```
|
|
|
|
---
|
|
|
|
## HTTP-Endpoints
|
|
|
|
| Route | Auth | Zweck |
|
|
|---|---|---|
|
|
| `GET /health` | — | Healthcheck |
|
|
| `POST /webhooks/gitea` | HMAC-Signatur | Push / Release / Issues von Gitea |
|
|
| `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 /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/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.
|
|
|
|
---
|
|
|
|
## Projektstruktur
|
|
|
|
```
|
|
d4rkbot/
|
|
├── src/
|
|
│ ├── index.js # Start: Bot, Webserver, Wochen-Rückblick, Watchdog
|
|
│ ├── config.js # Env-Konfiguration mit Validierung
|
|
│ ├── db.js # SQLite: Schema, Migrationen, FTS5, alle Queries
|
|
│ ├── runtime-settings.js # Effektive Settings (DB vor Env)
|
|
│ ├── 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)
|
|
│ ├── bot/
|
|
│ │ ├── client.js # Discord-Client, Commands, Listener, Button-Handler
|
|
│ │ ├── commit-feed.js # Push → Embed
|
|
│ │ ├── release-feed.js # Release → Ankündigungs-Embed
|
|
│ │ ├── devlog-archive.js # Nachricht → SQLite (+ Bild-Download)
|
|
│ │ ├── 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
|
|
│ └── web/
|
|
│ ├── server.js # Fastify: Webhooks, Static, SPA-Fallback
|
|
│ ├── auth.js # Discord-OAuth2 + Session-Cookies
|
|
│ ├── api.js # REST-API + Settings + RSS
|
|
│ └── devlog-endpoint.js# Devlog-Post: 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
|
|
├── 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
|
|
└── 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`.
|