D4rkst3randClaude Opus 5 0d7628f14e
Deploy / check (push) Canceled after 0s
Deploy / deploy (push) Canceled after 0s
Den Entwurf und das Logo-Original einsortieren
Drei Dateien lagen unversioniert im Wurzelverzeichnis herum. Alle drei
gehoeren ins Repo, nur nicht dorthin:

  logo.png                        -> docs/brand/logo.png
  ChatGPT Image 23. Juni 2025 ... -> docs/brand/studie-kopf-2025-06.png
  design_handoff_redesign/        -> docs/redesign/

logo.png ist NICHT irgendein Logo, sondern das Original, von dem
docs/brand/README.md die ganze Zeit spricht: "ein einziges Original, 2048x2048
mit Transparenz". Nachgerechnet statt geraten -- auf den Inhalt beschnitten
ergibt es 1986x1963, exakt die Masse von lockup.png. Es lag also die Quelle
der Marke unversioniert daneben.

Dabei aufgefallen und in der README vermerkt, nicht repariert: build.py liest
das Original ueber einen festen Pfad ausserhalb des Repos
(QUELLE = A:/Users/DAR/logo.png). Jetzt sind das zwei Kopien, die
auseinanderlaufen koennen. Umstellen kann nur, wer weiss, welche der beiden
gepflegt wird.

Das zweite Bild ist eine frueherere Kopf-Studie und nicht die Vorlage der
heutigen Marke -- andere Zeichnung, flacher, ohne Fell und Schulter. Sie wird
nirgends benutzt und liegt als Herkunft.

Vom Entwurfs-Paket ist der assets/-Ordner entfallen: er enthielt Kopien von
mark.png und lockup.png, die zwei Verzeichnisse weiter im Original liegen. Die
.dc.html-Referenzen zeigen jetzt auf ../brand/ und stellen das Logo weiter
dar, statt mit kaputten Bildern zurueckzubleiben. Der Kopf der README sagt
ausserdem, dass der Entwurf umgesetzt ist und wo bewusst abgewichen wurde --
sonst liest sich das Dokument in einem Jahr wie eine offene Aufgabe.

Dazu eine Zeile, die seit dem Redesign nicht mehr stimmte: build.py bezeichnet
(10, 10, 10) als "--bg der Marke". Das ist seit gestern #131316. Wirkt erst,
wenn jemand build.py laufen laesst -- die erzeugten Icons in frontend/public/
tragen bis dahin den alten Grund. Neu bauen konnte ich sie hier nicht, es gibt
weder Python noch Pillow auf dieser Maschine.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 15:19:49 +02:00
2026-08-01 04:19:51 +02:00

d4rkbot — D4RKST3R // COMMUNITY BOT

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.


Inhalt


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.

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

40 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 → 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
📢 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-setup postet den Ideen-Aufruf: Bereich wählen, Formular ausfüllen → Voting-Post mit 👍 und Thread zum Reden. Wünsche haben einen Stand (wird geprüft · geplant · in Arbeit · umgesetzt · nicht geplant) samt Begründung — auf der Roadmap und im Discord-Post. Wer gestimmt hat, bekommt eine DM, sobald es umgesetzt ist. Die Roadmap filtert nach Stand und Bereich, sortiert nach Top / Bewegung / Neu und zeigt die Zahl der Beiträge im Thread. Ein Klick öffnet die eigene Seite der Idee mit der Unterhaltung aus dem Discord-Thread — gespiegelt samt Screenshots, geschrieben wird weiter dort. Fehlende Forum-Tags legt das Panel auf Knopfdruck an. Ist der Voting-Kanal ein Forum, wird jeder Wunsch ein Forums-Beitrag mit Tags für Bereich und Stand — der Stand zieht beim Ändern automatisch mit. Eine Stimme je Person, egal ob 👍 oder Web-Knopf; Doppler lassen sich zusammenführen
🗳️ Umfragen /umfrage erzeugt eine native Discord-Poll — keine Reaktions-Bastelei, Discord zählt selbst
📻 Radio /radio holt den Bot in deinen Sprachkanal und öffnet eine Tafel mit Sender-Auswahl zum Durchschalten; der laufende Titel steht im Embed und aktualisiert sich selbst. 44 RauteMusik-Sender sind ab Werk eingetragen — dieselben, die im LS25 und ETS als Bordradio laufen —, eigene lassen sich im Panel ergänzen. Der Bot geht von selbst wieder raus, wenn der Kanal leer ist, und kommt nach einem Neustart zurück. Bewusst kein YouTube: daran sind Groovy und Rythm gestorben
🎉 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 Aufnahme läuft über ein Bewerbungs-Formular: ausfüllen, das Team nimmt an oder lehnt ab. Wer angenommen wird, bekommt Rolle und Listeneintrag. Eigener Panel-Bereich mit Liste, Rolle und Schlüssel-Vorrat — Playtester lassen sich dort auch wieder entfernen (die Rolle geht mit)
🎟️ Alpha-Keys Schlüssel-Vorrat im Panel: nachlegen, gezielt an eine Person schicken, an alle Wartenden verteilen, zurückziehen oder löschen. Zustellung per Direktnachricht — kommt sie nicht an, bleibt der Schlüssel frei
🎭 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. Ein Formular lässt sich als Playtester-Formular markieren; Angenommene landen dann auch im Playtester-Programm
🪪 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, Sammel-Löschungen, Joins/Leaves, Namens- und Rollen-Änderungen in einem privaten Kanal. Damit bei einer Löschung Verfasser und Wortlaut dastehen — auch bei alten Posts —, merkt sich der Bot Nachrichten kurz selbst; wie lange, steht unter Werte (0 = gar nicht). Wer eine fremde Nachricht gelöscht hat, kommt aus Discords Audit-Log
📬 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). Anliegen zur Auswahl — je eigener Name, Einstiegstext und Rolle, die benachrichtigt wird; bis fünf als Knöpfe, darüber als Menü. Das Team kann ein Ticket übernehmen, damit klar ist, wer sich kümmert. Schließen = Transcript per DM an den Ersteller + Kopie ins Mod-Log, inklusive Anliegen und Bearbeiter
👋 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

Gaming

Funktion Was sie macht
🎮 Game-Server-Monitor DiscordGSM-Stil: pro Server ein Live-Embed (🟢/🔴, Name im Spiel, 🔒 bei Passwort oder Whitelist, Spieler-Balken, Map, Version, Mod-Anzahl, Spieler-Liste, Knöpfe für Verbinden, Mod-Download und frei eintragbare Links wie Regeln oder TeamSpeak, Ping); alle Spiele, die gamedig kennt — die Auswahl im Panel kommt aus der Bibliothek selbst, inklusive Standard-Port und Hinweis auf nötige Zugangs-Codes (Farming Simulator, Terraria) — plus FiveM + HTTP-Check; Down/Up-Alerts mit Ausfalldauer
🖥️ Panel-Anbindung (optional) Trägt der Betreiber unter Config → Game-Server die Adresse des d4rk_gameserver-Panels und ein Lese-Zeichen ein, weiß der Monitor mehr als eine Abfrage hergibt. gamedig fragt einen Server — ein startendes Modpack antwortet nicht und sieht dadurch aus wie ein Ausfall (am ATM10 gemessen: 306 Sekunden bis zum ersten Spieler). Das Panel sieht den Container: 🟡 „Startet gerade" statt 🔴 „Offline", kein Fehlalarm während des Hochfahrens, kein Alarm für einen im Panel gestoppten Server — aber sehr wohl einer für Absturz, OOM-Kill oder fehlenden Container. Dazu RAM und CPU im Embed. Ohne Eintrag ändert sich nichts, und antwortet das Panel nicht, ebenfalls nicht. Umgekehrt gilt außerdem: im Panel hat jeder Server einen Schalter „Im Discord anzeigen" — wird er umgelegt, legt der Bot den Monitor-Eintrag binnen einer halben Minute selbst an und räumt ihn beim Ausschalten wieder weg. Das Panel schreibt dafür nichts hierher; das Häkchen reist im Statusbericht mit, den der Bot ohnehin abholt. Bild, Links und Zugangs-Code trägt man weiterhin hier ein — der Abgleich legt nur an und löscht, er überschreibt nie
🚜 LS — Höfe & Preise Für Farming-Simulator-Server: Besitzkarte auf dem Luftbild des Servers (Parzellen nach Hof eingefärbt, Fläche = Hektar, Fahrzeuge und Spieler live), die Preiskurven übers Jahr mit „jetzt verkaufen oder warten", dazu je Hof ein Embed, das sich selbst aktualisiert: Land, Fuhrpark mit Wert und Betriebsstunden, was in die Werkstatt muss, was gewaschen gehört und was geladen ist. Dazu die Modliste: der Bot meldet, was neu, aktualisiert oder entfernt wurde, und auf /mods/<server> steht jeder Mod einzeln zum Laden — durch den Bot hindurch, damit der Zugangs-Code des Spielservers nicht in einem Link landet. Nicht möglich: welche Frucht auf welchem Feld steht, und Tierställe — beides gibt der Feed nicht her (siehe docs/ls-feed.md)

Server & Technik

Funktion Beschreibung
🚨 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
🎨 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 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
🏓 Kleinkram /ping · /devlog-backfill und /galerie-backfill (Historie nacharchivieren, Admin)

Webinterface

Community-Hub (hub.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, Community-Wünsche, Contribution-Heatmap
/server öffentlich Live-Status aller Game-Server: Logo, Auslastungs-Balken, Map/Version/Ping, Wer gerade drauf ist, 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
/wunsch/:id öffentlich Eine Idee mit Stand, Begründung und der Unterhaltung aus dem Thread
/<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
/commits Admin Archivierte Commits aller Repos (SHA → Gitea-Link)
/settings Team Config-Seite — siehe unten

Produktseite (bot.d4rkst3r.de)

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

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)

17 Bereiche, in der Seitenleiste nach Themen gruppiert:

Gruppe Bereiche
Überblick Status · Module · Texte · Werte
Auftritt Brand (samt Willkommens-Karte) · Seiten
Inhalte Feeds · Composer
Community Community · Rollen · Support · Playtester · 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. 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 kennt die Felder, src/templates.js die Texte, src/tuning.js die Werte — jeweils über module verknüpft. Eine neue Funktion bekommt ihre Seite dadurch geschenkt.

Module, Werte, Texte

  • 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.

Suchen, Speichern, Einrichten

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.

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, 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.

„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. 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 ist zur Laufzeit änderbar und liegt in SQLite; Env-Variablen sind nur Fallback.


Ersteinrichtung

1. Discord-App (Developer Portal)

  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
    • 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; 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 URLhttps://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.

2. Environment-Variablen

Vorlage: .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 + 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 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
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'))"

3. Routing

Cloudflare: CNAME bot und hub → Zone, Proxied. Nginx Proxy Manager: beide Hosts → host.docker.internal:3080, Block Common Exploits, Force SSL. Test:

curl https://bot.d4rkst3r.de/health

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 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, 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). Automatisch geht es über docs/auto-deploy.md.

Daten liegen im Volume ecobot_data (/app/data): SQLite (ecobot.db, WAL)

  • Devlog- und Galerie-Bilder.

Manuell statt Portainer:

git clone git@gitea:D4rkst3r/d4rkbot.git && cd d4rkbot
cp .env.example .env   # Werte eintragen
docker compose up -d --build

Lokale Entwicklung

npm install
npm run dev

Bot + API laufen auf :3080 mit den Werten aus .env. Frontend mit Hot-Reload:

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):

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- und Berechtigungs-Checks
GET /api/v1/stats read Devlog-/Commit-Zahlen, Guilds, Uptime

Beispiel (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 /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/* · /wish-assets/* Lokal gespeicherte Bilder (Discord-Links laufen ab)
GET /brand.css · /brand-nav.js Design-Tokens + Navigation für andere Apps (CORS offen)
GET /api/legal · DELETE /api/profile — / Member Impressums-Angaben · DSGVO-Löschung
GET /api/profile · /api/myroles* · POST /api/wishes* Member Profil · Rollen-Selfservice · Wunsch einreichen/voten
PUT /api/wishes/:id/status · POST /api/wishes/:id/merge Team (community) Stand setzen (+ DM an Stimmen-Geber) · Doppler zusammenführen
GET /api/wishes/:id · /api/wishes/suche?q= Eine Idee mit Beiträgen aus dem Thread · Suche vor dem Einreichen
GET/POST/PUT/DELETE /api/wish-categories Team (community) Bereiche für Wünsche pflegen
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
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.


Projektstruktur

d4rkbot/
├── src/
│   ├── 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)
│   ├── repo-backup.js        # Gitea-Repos als git-Bundle sichern
│   ├── bot/
│   │   ├── 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
│   │   ├── 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 — Spielliste, Icons, Abfrage)
│   │   ├── watchdog.js       # URL-Checks, Störungen, DM-Alarm
│   │   ├── heartbeat.js      # Eigene Erreichbarkeit aufzeichnen
│   │   ├── wishes.js        # Ideen: einreichen, Thread, Forum-Tags
│   │   ├── bilder.js        # Bilder aus Discord lokal sichern
│   │   ├── 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, OG-Tags
│       ├── auth.js           # Discord-OAuth2 + Session-Cookies
│       ├── api.js            # REST-API + Settings + RSS
│       ├── 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           # 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
└── docker-compose.yml        # Portainer-ready, Volume ecobot_data, TZ

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 Single Sign-On: Ablauf, Endpoints, Anbindung eigener Dienste
docs/auto-deploy.md Push auf main → Portainer rollt neu aus
docs/konzept-zwei-seiten.md Warum und wie Produktseite und Hub getrennt sind
docs/brand/README.md Logo-Master, abgeleitete Symbole, Build-Skript
docs/gitea-theme/README.md D4RKST3R-Theme für Gitea
docs/nutzungsbedingungen.md Entwurf für die Nutzungsbedingungen-Seite
S
Description
No description provided
Readme
7.4 MiB
Languages
JavaScript 90.4%
CSS 8.7%
PowerShell 0.7%
Dockerfile 0.2%