Commit Graph
41 Commits
Author SHA1 Message Date
D4rkst3randClaude Fable 5 55e9ef57e2 Oeffentliche Statusseite nach Statuspage-Vorbild
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
Neue Seite /status auf dem Hub: Gesamtlage als Banner, darunter die
freigegebenen Dienste mit 90-Tage-Balken, die Game-Server, und die
Stoerungs-Historie der letzten 90 Tage.

Die Adressliste ist von einer kommagetrennten Einstellung in eine Tabelle
gewandert. Jeder Dienst hat jetzt Namen, Gruppe und einen Schalter
"oeffentlich" — sonst stuende auf einer oeffentlichen Seite die nackte URL,
auch von internen Diensten. Die alte Liste wird beim ersten Start uebernommen,
bewusst als nicht oeffentlich: was dort auftaucht, soll eine Entscheidung sein
und nicht durch eine Migration passieren.

/api/status liefert nur freigegebene Dienste und dabei keine Adressen, nur
Namen. Auch die Stoerungs-Historie ist gefiltert — sonst verriete sie, was es
sonst noch gibt. Im Browser gegengeprueft: auf der ganzen Seite steht kein
einziges https://.

Stoerungen werden jetzt aufgezeichnet, nicht nur gemeldet: pro Adresse ein
offener Eintrag, bis es wieder laeuft. Beim Wiederkommen wird er geschlossen,
bevor die DM rausgeht — sonst bliebe er bei einem Sendefehler ewig offen.

Aufbewahrung von 7 auf 90 Tage. Der Balken kann jetzt zwei Aufloesungen:
168 Stunden fuers Panel ("was war letzte Nacht?") und 90 Tage fuer die
Statusseite ("wie zuverlaessig?"). Stuendlich ueber 90 Tage waeren ueber 2000
Striche und unlesbar.

Im Panel sind aus der reinen Anzeige Verwaltung geworden: anlegen, bearbeiten,
entfernen, freigeben — dazu die Stoerungsliste.

Beim Bauen gefunden: die Uebernahme der alten Liste stand mitten in db.js und
rief getSetting(), dessen prepared statement erst 300 Zeilen weiter unten
entsteht. Der Bot starb beim Start mit "Cannot access getSettingStmt before
initialization" — nachgewiesen, dann ans Dateiende verschoben.

Geprueft: 182 SQL-Abfragen gegen das Schema, alle schreibenden Routen bewacht,
Stoerungs-Logik durchgespielt (doppeltes Eroeffnen wird abgelehnt, Schliessen
ohne offene gibt null), und beide Seiten im Browser mit drei Diensten in allen
drei Zustaenden.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-01 05:45:50 +02:00
D4rkst3randClaude Fable 5 fd2d31f07f Watchdog: Embeds statt Textzeilen, dazu eine Uebersicht im Panel
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
Die DM-Alarme waren als einzige Meldung noch reiner Text — direkt neben dem
Raid-Alarm, der ein Embed ist. Jetzt beide im selben Look, mit Ausfalldauer
bzw. Fehlergrund und Antwortzeit als Felder.

Uebersicht im Panel (System, unter den Watchdog-URLs): je Adresse ein
Erreichbarkeits-Balken ueber 7 Tage, gruen/rot/grau wie bei den Game-Servern,
dazu Status, Antwortzeit und seit wann etwas weg ist.

Dafuer schreibt der Waechter jetzt mit — vorher lebte sein Zustand nur im
Speicher und war nach jedem Neustart weg. Neue Tabelle watchdog_history,
gleiche Bauart und gleiche 7-Tage-Aufbewahrung wie player_history, stundenweise
zusammengefasst statt roh ausgeliefert.

Wichtig dabei: aufgezeichnet wird jeder Check, nicht nur die Wechsel. Sonst
saehen ruhige Stunden im Balken aus wie Messluecken.

Der Balken ist aus Server.jsx in components/UptimeTrack.jsx gewandert, damit
oeffentliche Seite und Panel denselben benutzen. Er zeigt die Antwortzeit im
Tooltip nur, wo sie erhoben wird — bei Game-Servern gibt es keine.

Der Endpunkt /api/watchdog liegt hinter der Rechtepruefung, nicht oeffentlich:
in der Adressliste koennen interne Dienste stehen.

Zwei fehlende Importe in api.js gefunden und ergaenzt (moduleEnabled, tuning) —
der erste Aufruf der Route waere sonst mit ReferenceError gestorben.

Geprueft: alle 171 SQL-Abfragen gegen das Schema, die drei neuen inklusive.
Im Browser mit drei Faellen — laeuft, ist weg, noch nie geprueft: Punktfarbe,
Quote, Ausfallstunden und Messluecken stimmen, die ungepruefte Adresse zeigt
korrekt gar keinen Balken. Oeffentliche Server-Seite nach dem Umbau
gegengeprueft.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-01 05:28:22 +02:00
D4rkst3randClaude Fable 5 2d4afad3cb Level-Embeds aufgewertet, Server-Footer korrigiert
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
Server-Monitor: Der Footer behauptete fest "alle 2 min", obwohl das Intervall
seit den einstellbaren Werten aus monitor_interval kommt. Wer im Panel etwas
anderes setzt, bekam eine falsche Angabe. Liest jetzt den echten Wert.

Level-Aufstieg: War als einziges im Community-Bereich reiner Text, waehrend
Geburtstage, Verlosungen und Bewerbungen laengst Embeds sind. Jetzt ueber
brandEmbed mit Avatar, Gesamt-XP und Rest bis zum naechsten Level. Der Text
bleibt die Vorlage aus dem Panel — nur der Rahmen ist neu.

Dazu zeigt das Embed die Belohnungs-Rolle: entweder die gerade vergebene oder
die naechste, auf die man hinspielt. grantRewards() gibt dafuer zurueck, was
wirklich dazukam.

Ist die Vorlage im Panel leer, wirft setDescription('') — der Aufstieg waere
still ausgefallen. Faellt jetzt auf eine schlichte Zeile zurueck.

/rank: Avatar als Thumbnail, Podest-Zeichen fuer die ersten drei, Rest-XP und
naechste Belohnung als eigene Felder. Das Feld erscheint nur, wenn es
Belohnungs-Rollen gibt — sonst stuende dort ein leeres Feld.

Nebenbei zwei veraltete ephemeral: true auf flags: MessageFlags.Ephemeral
umgestellt, wie es der Rest der Befehle schon macht.

Geprueft: alle vier Embeds wirklich gebaut und ausgegeben, discord.js
validiert dabei. Das Intervall im Footer zog den auf 7 gestellten Wert.
Die negative XP-Differenz im ersten Testlauf war ein inkonsistenter
Testdatensatz — mit 4200 XP ist man Level 9, nicht 7; ueber 0..60000 XP
durchgespielt wird die Differenz nie negativ.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-01 05:21:56 +02:00
D4rkst3randClaude Fable 5 8fa43a3e47 Code-Review: drei Fehler behoben
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
Session-Cookie ohne secure-Flag (src/web/auth.js)
    Das Anmelde-Cookie war httpOnly, sameSite und signiert — aber ohne secure.
    Beim ersten Aufruf ueber http, bevor der Proxy auf https umleitet, geht es
    damit im Klartext mit. Auf einem fremden WLAN ist das die Sitzung.

    Das Flag laesst sich nicht aus request.protocol ableiten: hinter dem
    Reverse-Proxy kommt jede Anfrage als http an, trustProxy ist nicht gesetzt.
    Stattdessen aus der konfigurierten Adresse des Hosts, mit derselben
    Zuordnung, die der OAuth-Redirect schon benutzt. Lokal ueber
    http://localhost bleibt es aus, sonst kaeme man beim Entwickeln nicht rein.

    Geprueft gegen sechs Hosts: hub und bot ergeben secure, localhost nicht.
    Gilt auch fuer das OAuth-State- und das SSO-Ruecksprung-Cookie.

Unbehandelte Rejection beim Start (src/bot/client.js)
    registerCommands() faengt nichts ab, der Aufrufer im ClientReady-Handler
    auch nicht. Seit Node 15 beendet eine unbehandelte Rejection den Prozess —
    ein Rate-Limit von Discord beim Start haette den Bot also abgeschossen und
    mit restart: unless-stopped in eine Neustart-Schleife geschickt. Dabei
    stehen die zuvor registrierten Befehle bei Discord weiter, und alles
    andere koennte laufen. Jetzt wird der Fehler geloggt und der Bot bleibt an.

Number('') ist 0 (src/bot/anti-raid.js)
    Beim Aufheben der Raid-Sperre wird die gemerkte Verifizierungsstufe
    zurueckgesetzt. Fehlt die Notiz, ergab Number('') die 0 — und 0 ist eine
    gueltige Stufe, naemlich "keine". Der Server waere also auf offen gestellt
    worden statt so gelassen, wie er war. Jetzt wird nur zurueckgesetzt, was
    auch wirklich als Zahl notiert ist.

Ohne Befund geprueft: alle 168 SQL-Abfragen gegen das echte Schema inklusive
Migrationen, alle 109 Routen auf Rechtepruefung (53 von 54 schreibenden haben
eine, die 54. haengt am timing-safe verglichenen Secret), Farbwerte vor dem
Einbetten in ausgeliefertes CSS, das Escaping der OG-Meta-Tags, Timer-Cleanup
im Frontend und die uebrigen async-Handler.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-01 04:48:52 +02:00
D4rkst3randClaude Fable 5 91397d8a44 Raid-Sperre von Hand setzen, aufheben oder nachsehen
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
Der fehlende Befehl zum Raid-Schutz. Drei Unterbefehle:

  status  ist gerade gesperrt, und wie lange noch
  an      jetzt sperren — fuer die Welle, die man kommen sieht
  aus     sofort aufheben — fuer den Fehlalarm um drei Uhr nachts

Rechte: ManageGuild, weil die Sperre genau das anfasst — Verifizierung und
Invites. Antworten sind ephemeral.

Die Sperr-Massnahmen sind in dichtmachen() herausgezogen, damit automatisch
und von Hand denselben Weg nehmen und sich nicht auseinanderentwickeln. Die
Meldung sagt jeweils dazu, wodurch sie ausgeloest wurde und wer es war.

Ist der Raid-Schutz ausgeschaltet, verweist der Befehl aufs Panel statt
stillschweigend nichts zu tun.

Dazu: der Befehl steht auf der oeffentlichen Befehls-Seite, in beiden
Sprachen, und die Zahl auf der Produktseite geht von 16 auf 17.

Geprueft: 17 Befehle laden, keine doppelten Namen, Rechte-Bitmaske 32
(ManageGuild), alle neuen Exporte vorhanden, kein Sprachschluessel fehlt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-01 04:32:39 +02:00
D4rkst3randClaude Fable 5 aef708c405 Raid-Schutz: erkennt Beitritts-Wellen und sperrt voruebergehend
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
Neues Modul anti_raid, standardmaessig AUS. Zaehlt Beitritte in einem
Zeitfenster; reisst es, geht der Server dicht: Verifizierung auf Hoch,
Einladungen gesperrt, DM an den Owner und Eintrag ins Protokoll.

Bewusst zurueckhaltend — es wird niemand gekickt oder gebannt. Bei einem
Fehlalarm, etwa nach einem Stream-Shoutout, waere ein Massenkick schlimmer
als der Raid. Beide Massnahmen sind reversibel und treffen niemanden, der
schon drin ist.

Der Sperrzustand liegt in den Einstellungen, nicht nur im Speicher: startet
der Bot mitten in einer Sperre neu, waere der Timer sonst weg und der Server
bliebe fuer immer dicht. Beim Start wird die Restzeit abgesessen oder, wenn
laengst abgelaufen, sofort aufgehoben.

Drei Werte im Panel: Schwelle (8), Fenster (20 s), Sperrdauer (15 min).

disableInvites() gibt es erst ab discord.js 14.4 und nur mit ManageGuild —
beides wird geprueft, statt im Ernstfall einen Fehler zu werfen.

Die Fenster-Logik ist als reine Funktion herausgezogen und mit neun Faellen
geprueft: langsame Beitritte loesen nicht aus, die Welle schon, der Rand des
Zeitfensters zaehlt nicht mehr mit, und nach Ruhe faengt das Fenster von vorn.

Offen: ein Befehl zum sofortigen Aufheben. Bis dahin laeuft die Sperre aus
oder man setzt die Verifizierung in Discord selbst zurueck.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-01 04:25:25 +02:00
D4rkst3randClaude Fable 5 c0a56c1eb5 Logo auf der Willkommens-Karte und in geteilten Links
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
Zwei Stellen, an denen die Marke bisher fehlte.

Willkommens-Karte: Das Wasserzeichen war der Markenname als Text mit 5 %
Deckkraft — jetzt der Katzenkopf. Die Datei wird einmal beim Start gelesen
statt bei jedem Beitritt, und fehlt sie, rendert die Karte wie bisher ohne
Wasserzeichen. Der Schalter heisst entsprechend "Logo im Hintergrund".

Link-Vorschau: og:image war nur gesetzt, wenn ein Devlog einen Screenshot
hatte. Startseite, Roadmap, Funktionen und jedes Devlog ohne Bild kamen in
Discord als graue Textzeile. Jetzt faellt alles ohne eigenes Bild auf
og-default.png zurueck (1200x630, Lockup auf Schwarz mit Akzentstreifen),
und twitter:card ist durchgehend summary_large_image.

Die Laufzeit-Datei liegt unter src/bot/assets/, nicht in docs/ — das
Dockerfile kopiert nur src/ und frontend/dist/.

Geprueft: librsvg zeichnet das eingebettete <image> wirklich (42726 Pixel
unterscheiden sich gegen eine Fassung ohne), das OG-Bild landet im dist.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-01 03:55:28 +02:00
D4rkst3randClaude Fable 5 01fadadcd8 Grundgerüst-Assistent: alle fehlenden Kanäle auf einmal
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
Der Einzelknopf war der Anfang; wer frisch startet, klickt sich damit
sechzehnmal durch. Der Assistent macht das in einem Durchlauf.

Erst eine Vorschau, bevor irgendetwas passiert: was neu entsteht, was schon
existiert und nur verknüpft wird, welche Kanäle privat werden und in welche
Kategorie alles kommt. Die Kategorie heißt wie die Marke und wird
wiederverwendet, wenn es sie schon gibt.

Der Plan ist nach Einstellung entdoppelt — Devlogs und Wochen-Rückblick
brauchen denselben Kanal, der soll nicht zweimal auftauchen. Rollen kommen
ohne Kategorie, die gibt es dort nicht.

Zwischen zwei Anlagen liegen 350 ms. Discord verträgt ein Dutzend
Kanal-Erstellungen am Stück schlecht, und ein Rate-Limit mitten im Lauf
wäre die unangenehmste Art zu scheitern.

Scheitert ein Schritt, laufen die übrigen weiter und das Ergebnis zeigt pro
Zeile, was passiert ist. Vorher hätte ein einzelner Fehler den Rest
verschluckt.

Im Test: 19 offene Punkte, Vorschau zeigt 16, danach bleiben 2 — die beiden
ohne Vorlage (Gitea-Token und Watchdog-Adressen), die sich nicht anlegen
lassen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 21:17:36 +02:00
D4rkst3randClaude Fable 5 684573b88c Fehlende Kanäle und Rollen aus dem Panel anlegen
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
Die Status-Seite listet Module, denen ein Kanal oder eine Rolle fehlt.
Bisher hieß das: rüber zu Discord, Kanal anlegen, Rechte setzen, zurück ins
Panel, auswählen, speichern. Jetzt steht daneben ein Knopf, der genau das
in einem Schritt macht — inklusive Eintragen der Einstellung.

Die Vorlagen hängen bei den Modulen (modules.js): Name, Thema und ob der
Kanal privat sein soll. Private Kanäle bekommen @everyone entzogen und
Bot plus alle Rollen mit Moderationsrecht eingetragen — sonst legt man
einen Modmail-Kanal an, den das Team nicht sieht.

Gibt es Kanal oder Rolle schon (bei Rollen unabhängig von Groß- und
Kleinschreibung), werden sie verknüpft statt doppelt angelegt. Beim
Temp-Voice-Hub entsteht ein Sprachkanal statt eines Textkanals.

Fehlen dem Bot die Rechte, steht das im Panel im Klartext („Dem Bot fehlt
das Recht Kanäle verwalten") statt einer Discord-Fehlernummer.

Bewusst nur Anlegen: kein Löschen, kein Umbenennen. Ein Fehlklick beim
Anlegen kostet einen überflüssigen Kanal, einer beim Löschen dessen
Verlauf. Umbenennen wäre zusätzlich eine Falle, weil Discord es auf zwei
Änderungen pro zehn Minuten und Kanal begrenzt.

moduleMissing liefert dafür Objekte statt Beschriftungen, damit das Panel
weiß, was sich anlegen lässt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 18:29:54 +02:00
D4rkst3randClaude Fable 5 3549b06cef /bug und /wunsch als Eingabefenster
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
Beide Befehle nahmen ihre Eingaben als Slash-Optionen entgegen. Das heißt:
eine Fehlerbeschreibung einzeilig in die Befehlszeile tippen, ohne
Umbrüche, ohne Absätze. Entsprechend dürftig fielen die Meldungen aus.

/bug öffnet jetzt ein Fenster mit vier Feldern: Titel, was ist passiert,
was war erwartet, wie kann man es nachstellen. Die letzten beiden sind
freiwillig und erzeugen im Issue nur dann eine Überschrift, wenn sie
ausgefüllt sind. /wunsch fragt die Idee und ein optionales „warum wäre das
gut?" ab — die Rückfrage macht aus einem Einzeiler einen Vorschlag, über
den man abstimmen kann.

Der Screenshot bleibt eine Option am Befehl, weil Discord in Fenstern
keine Dateien erlaubt. Er hängt damit an der Befehls-Interaktion, das
Formular kommt aber als eigene zurück — der Anhang wird deshalb kurz
zwischengeparkt und nach dem Absenden verwendet. Abgelaufene Einträge
räumt der nächste Aufruf mit weg, damit da nichts liegen bleibt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 16:53:04 +02:00
D4rkst3randClaude Fable 5 197c2a1ada Werte: 19 feste Zahlen im Panel einstellbar
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
XP-Beträge, Wartezeiten, Prüf-Intervalle, Obergrenzen und Postzeiten
standen als Konstanten im Code. Wer den Server-Monitor seltener prüfen
lassen wollte oder das Level-System anders austarieren, musste die
Quelldateien anfassen.

src/tuning.js hält sie jetzt an einer Stelle, mit Standard, erlaubtem
Bereich und Erklärung. Der neue Config-Bereich „Werte" zeigt sie nach
Themen gruppiert; neben jedem Feld steht der erlaubte Bereich und der
Standard, angepasste Werte lassen sich einzeln zurücksetzen.

Die Grenzen sind nicht Kosmetik: ein Vertipper beim Prüf-Intervall würde
sonst den Bot in eine Schleife im Sekundentakt schicken. Gespeichert wird
ganz oder gar nicht — ein ungültiger Wert im Formular lässt auch die
gültigen daneben unverändert, statt die Hälfte zu schreiben.

Intervalle laufen nicht mehr über setInterval mit festem Abstand, sondern
über everyTuned: der Wert wird vor jeder Runde neu gelesen. Ein geändertes
Intervall greift damit ab dem nächsten Durchlauf, ohne Neustart. Ein
Fehler in einer Runde beendet die Schleife nicht.

Beim Testen aufgefallen und behoben: Number('') ist 0 und nicht NaN — ein
nie gesetzter Wert wäre dadurch auf sein Minimum gefallen statt auf den
Standard. Das Level-System hätte also 1 XP pro Nachricht vergeben und der
Monitor jede Minute geprüft.

Der Fetch-Wrapper im Frontend hat die Fehlermeldung des Servers verworfen;
jetzt steht im Panel „XP pro Nachricht: 1–500 XP" statt „fehlgeschlagen".

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 16:49:34 +02:00
D4rkst3randClaude Fable 5 fb927d4399 Willkommens-Karte einstellbar: Farben, Bild, Texte, Live-Vorschau
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
Die Karte war komplett fest verdrahtet — Farben, der Schriftzug
„WILLKOMMEN", die Zeile „Member #N", das Hintergrund-Raster. Wer etwas
ändern wollte, musste das SVG im Code anfassen.

Jetzt steht das Aussehen unter Config → Support: vier Farben, die beiden
Textzeilen, ein optionales Hintergrundbild per Adresse, der Markenname im
Hintergrund an/aus, und die Karte selbst abschaltbar (dann bleibt das
Text-Embed mit Avatar als Vorschaubild).

Daneben eine Vorschau, die beim Tippen mitrendert — sie geht über
/api/welcome-preview.png und bekommt die Werte als Query, damit man sieht,
was man einstellt, bevor gespeichert wird. Gespeichert wird davon nichts.

Die Akzentfarben greifen auf die Markenfarben zurück, solange nichts
Eigenes gesetzt ist. Wer also die Marke umfärbt, hat die Karte gleich mit.

Beim Hintergrundbild ist Vorsicht eingebaut: nur http(s), Zeitlimit,
Größenbegrenzung, und ein nicht erreichbares Bild lässt die Karte ohne
Bild rendern statt sie ausfallen zu lassen. Über einem Bild liegt ein
Schleier, sonst säuft der Text ab.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 16:41:05 +02:00
D4rkst3randClaude Fable 5 2ce274707a Config statt Setup: Bereiche gruppiert, Suche, Status als Einstieg
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
Die Seite hieß Setup und listete 15 Bereiche flach untereinander. Wer
nicht wusste, dass Geburtstage unter „Community" stecken und Willkommens-
Texte unter „Support", hat geklickt bis er es fand.

Die Seitenleiste gruppiert jetzt nach Überblick, Auftritt, Inhalte,
Community, Technik und Zugang. Darüber steht ein Suchfeld, das nicht nur
Beschriftungen durchsucht, sondern auch Stichwörter je Bereich — „geburtstag"
führt zu Community, „ticket" zu Support. Enter springt zum ersten Treffer.

Der aktive Bereich steht in der Adresse (/settings#texte). Damit überlebt er
das Neuladen, und man kann jemandem einen Link auf genau die Stelle schicken.

Der Status-Bereich war die leerste Seite im ganzen Panel: sechs Zahlen. Er ist
jetzt der Einstieg und beantwortet die Frage, die man beim Öffnen wirklich hat
— was läuft noch nicht? Eingeschaltete Module, denen ein Kanal oder eine Rolle
fehlt, stehen dort mit einem Knopf, der direkt an die richtige Stelle springt.
Ist alles eingerichtet, sagt die Seite genau das.

Umbenannt in „Config", weil „Setup" nach einmaliger Einrichtung klingt — die
Seite ist aber der Ort, an dem man dauerhaft alles einstellt.

Schmale Bildschirme: die Leiste wird zur umbrechenden Zeile ohne
Gruppen-Überschriften, das Suchfeld nimmt die volle Breite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 16:13:33 +02:00
D4rkst3randClaude Fable 5 dadd75d452 Texte: 27 Bot-Nachrichten im Panel bearbeitbar
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
Bisher standen Begrüßung, Level-Ansage, Ticket-Texte und alle
Bestätigungs-Nachrichten fest im Code. Wer den Ton ändern wollte, musste
die Quelldateien anfassen und neu deployen — für alle außer mir also gar
nicht.

src/templates.js hält jetzt alle nach außen gehenden Texte an einer
Stelle: Standardtext, Platzhalter mit Erklärung und die Zuordnung zum
Modul. Der neue Setup-Tab „Texte" zeigt sie als Karten mit Textfeld;
die Bausteine darunter fügen sich per Klick an der Cursor-Position ein.

Der Standard bleibt im Code, die Datenbank speichert nur echte
Abweichungen. Ein leeres Feld heißt deshalb „wieder Standard" — und
angepasste Vorlagen sind an einer Marke erkennbar. Vorlagen zu
ausgeschalteten Modulen sind als solche gekennzeichnet, damit niemand
einen Text feilt, den gerade nichts sendet.

Unbekannte Platzhalter bleiben stehen statt still zu verschwinden, damit
ein Tippfehler in der Nachricht sichtbar wird.

Die Route heißt /api/texts, nicht /api/templates — letzteres sind seit je
die gespeicherten Composer-Nachrichten.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 16:06:27 +02:00
D4rkst3randClaude Fable 5 59aad27534 Modul-System: alle 35 Funktionen im Panel ein- und ausschaltbar
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
Bisher waren die Schalter über die Oberfläche verstreut: fünf Funktionen
hatten einen Haken, 22 weitere gingen nur über den Umweg „Kanal leeren".
Für jeden außer dem Owner war das nicht auffindbar.

Jetzt steht in src/modules.js ein zentrales Register aller Funktionen mit
Beschreibung, Standard-Zustand und den Einstellungen, die sie brauchen.
Daraus entsteht ein neuer Setup-Tab mit Karten: Schiebeschalter, kurze
Erklärung, Hinweis was noch fehlt ("Fehlt noch: Release-Kanal") und ein
Sprung zu den Einstellungen.

Damit die Schalter keine Attrappen sind, prüfen die Bot-Module jetzt an
18 Stellen zentral, ob sie laufen dürfen — Starboard, Galerie, Modmail,
Willkommen, Protokoll, Auto-Antworten, Sprachkanäle, Erinnerungen,
Events, Twitch/YouTube, Monitor, Wächter, Releases, Rückblick,
Geburtstage, Verlosungen und geplante Beiträge.

Funktionen mit vorhandenem Schalter (Level-System, Backups, Member-Gate …)
nutzen weiterhin dieselbe Einstellung, damit keine zweite Wahrheit
entsteht und bestehende Konfigurationen unverändert weiterlaufen.

Nebenbei gefunden und behoben: Beim Anlegen eines Modmail-Threads wurde
`member.client` benutzt, obwohl es an der Stelle kein `member` gibt — der
erste Modmail-Thread wäre mit einem Fehler abgebrochen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 15:53:44 +02:00
D4rkst3randClaude Fable 5 676fc45bb1 Willkommens-Karten, Geburtstage, Devlog-Permalinks mit OG-Vorschau, Auto-Publish
- Willkommens-Karten: gerendertes PNG (SVG → sharp) mit Avatar im
  Neon-Ring, Willkommens-Schriftzug und Member-Nummer; Fallback aufs
  bisherige Embed wenn das Rendering scheitert; Dockerfile installiert
  fonts-dejavu-core für die Text-Darstellung
- Geburtstags-System: /geburtstag setzen|entfernen (birthdays-Tabelle),
  tägliche Runde ab 09:00 Europe/Berlin (Doppel-Post-Schutz über
  last_birthday_run), Gratulations-Embed + Tages-Rolle (wird am
  nächsten Morgen wieder abgeräumt); Kanal + Rolle im Community-Tab
- Devlog-Permalinks: /devlogs/:id als eigene Seite (GET /api/devlogs/:id),
  Link-Symbol an jeder Karte, Link-kopieren-Button; der Server injiziert
  Open-Graph-Tags ins SPA-HTML — Devlog-Links zeigen Titel, Anriss und
  Bild, alle anderen Seiten bekommen Default-Tags (auch die Startseite)
- Auto-Publish: maybeCrosspost() veröffentlicht Devlog-, Release-,
  Composer- und geplante Posts automatisch in Ankündigungs-Kanälen
- brandEmbed: leere Avatar-URL crasht nicht mehr die Footer-Validierung

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 22:43:15 +02:00
D4rkst3randClaude Fable 5 ef0fb066f7 Startseite, Server-Seite v2 mit Logos, Lightbox-Fix, Navbar-Ausrichtung
- Startseite (/): Hero mit CTAs (Discord-Invite + Devlogs), Live-Zahlen
  (Member, Server online, Spieler), Bereichs-Kacheln, neuestes Devlog
  als Teaser — kein Redirect mehr auf /devlogs
- Server-Seite v2: Übersichtsleiste (X/Y online, Spieler gesamt),
  2-Spalten-Grid, Server-Logo (neues Feld image_url, https-only, auch
  als Embed-Thumbnail im Discord-Status), große Spielerzahl, Uptime %
  + Peak aus den 24h-Samples, Adresse als Copy-Button
- Lightbox: rendert jetzt per Portal in <body> (Header/Scanlines
  schienen durchs Overlay), Pfeile stehen neben dem Bild statt drauf,
  Info-Zeile unterm Bild
- Navbar: Community-Dropdown-Button auf Link-Höhe ausgerichtet
  (line-height + align-items)
- Setup Server-Tab: Logo-URL-Feld

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 22:25:30 +02:00
D4rkst3randClaude Fable 5 be11398f7c UX-Paket: Navbar aufgeräumt, /server-Seite, Lightbox, Skeletons, Audit-Log, Reroll
- Navbar entschlackt: nur noch Devlog · Roadmap · Server · Community ·
  Setup; Galerie/Level/Events/Changelog im Community-Dropdown,
  Profil/Commits/Logout im Avatar-Menü; Mobile-Burger mit Drawer
- Öffentliche /server-Seite: Live-Status-Karten mit Spieler-Balken,
  Map, Connect-Button und 24h-Spielerzahl-Chart (SVG); Monitor sampelt
  jede Abfrage in player_history (7 Tage Retention), GET /api/servers
  liefert nur öffentliche Felder (keine Query-URLs/Hosts)
- Lightbox: Galerie- und Devlog-Bilder öffnen im Overlay mit
  Pfeiltasten, Buttons, Wisch-Gesten und Zähler statt neuem Tab
- Skeleton-Loader: schimmernde Platzhalter auf Devlogs, Roadmap,
  Galerie, Level, Changelog und Server statt "Lade …"
- Team-Audit-Log: audit_log-Tabelle (max 500 Einträge), Logging bei
  Settings/Composer/Vorlagen/Rollen-Menüs/Gameservern/Team/API-Keys/
  Branding, GET /api/auditlog (Owner) + Liste im Team-Tab
- Giveaway: 🔁 Reroll-Button (Admin-only) + 👥 Teilnehmerliste am
  Gewinner-Post

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 22:15:58 +02:00
D4rkst3randClaude Fable 5 00249f9d8b Server-Monitor v3, Composer v2, Temp-Voice-Panel und Embed-Polish
- Server-Monitor v3: gamedig-Integration (300+ Spiele), GSM-Stil-Embeds
  (Spieler-Balken mit %, Map, Spieler-Liste, klickbarer Connect-Link,
  Ping im Footer), Down/Up-Alerts (2 Fails → 🚨, Recovery →  mit
  Downtime) in konfigurierbaren Alert-Kanal; Server-Tab mit 19
  Spiel-Presets, Host/Port bzw. Query-URL und Connect-URL
- Composer v2: visueller Embed-Builder mit Live-Discord-Preview
  (Autor, Felder, Bilder, Farbe, Footer, Timestamp), speicherbare
  Vorlagen (/api/templates), /api/compose versteht volle Embeds
- Temp-Voice: Control-Panel im erstellten Kanal (Umbenennen, Sperren,
  Limit, Löschen) — nur der Kanal-Besitzer darf bedienen
- Embed-Polish: brandEmbed-Factory (src/embeds.js), Footer überall
  mit Bot-Avatar-Icon

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 02:17:30 +02:00
D4rkst3randClaude Fable 5 332e89dcbd Server-Tab (DiscordGSM-Stil), Team-Rechte und Bot-Profil-Beschreibung
- Game-Server: eigene Tabelle statt CSV-Setting (automatische Migration), eigener
  Setup-Tab mit Server-Builder (Name, Typ fivem/http, Query-URL, Anzeige-Adresse);
  pro Server ein Live-Embed (gruen/rot, Spieler-Balken, Map, Adresse als Code-Block),
  edit in place; Embed wird beim Server-Loeschen mit entfernt
- Team-System: web_admins mit Bereichs-Scopes (content/community/rollen/bewerbungen/
  server/settings/devlogs); Owner behaelt Brand/System/API-Keys/Team exklusiv;
  32 Routen-Guards auf Scopes umgestellt, sensible PUT-Felder fuer Team gestrippt;
  Team-Tab (Owner) + Tab-Filterung im Frontend, /api/me liefert Scopes
- Bot-Karte: Profil-Beschreibung (Ueber mich) via application.edit
- Fix: settings-Tabelle wird vor der Gameserver-Migration angelegt (frische DBs
  crashten sonst beim Start)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 01:23:11 +02:00
D4rkst3randClaude Fable 5 19ec2802ac Tickets: Transcript beim Schließen + Thread-Löschung
- Schließen-Button erstellt jetzt ein Text-Transcript (chronologisch, inkl.
  Attachment-URLs, max 500 Nachrichten) und schickt es dem Ersteller per DM
- Kopie ins Mod-Log (Aufbewahrung fürs Team, mit Hinweis falls DM blockiert)
- Thread wird danach gelöscht statt nur archiviert (Fallback: sperren+archivieren,
  falls dem Bot Lösch-Rechte fehlen)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 01:11:16 +02:00
D4rkst3randClaude Fable 5 e72e6c8991 Community-Endgame: Alpha-Keys, Bewerbungen, Events, Stats, Triggers, /remind, Social, Temp-Voice + MEE6-Bot-Karte
- Alpha-Keys: Pool im Community-Tab, Ein-Klick-Verteilung per DM an alle Playtester
  (Key bleibt frei, wenn die DM geblockt wird)
- Bewerbungs-Formulare: Builder im neuen Bewerbungen-Tab (bis 5 Fragen),
  Button → Discord-Modal → Review-Embed mit /, Rolle + DM bei Entscheidung
- Events: GuildScheduledEventCreate → Announce-Embed; öffentliche /events-Seite
  aus den Discord-Events (5-min-Cache)
- Server-Stats: activity_daily (Nachrichten/Joins/Leaves) → Balken-Chart auf /level
- Triggers (Auto-Antworten, 30s-Cooldown), /remind (DM-Scheduler),
  Twitch-Live (Helix, App-Creds write-only) + YouTube-RSS-Announcements,
  Temp-Voice (Join to Create, Cleanup bei Leerstand + Start)
- Brand-Tab: MEE6-Style Bot-Identity-Karte (Avatar-Vorschau mit Status-Dot,
  Bot-Name via setUsername, Presence online/idle/dnd, Aktivität)
- Neue Intents: GuildVoiceStates, GuildScheduledEvents; alles smoke-getestet

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 01:02:47 +02:00
D4rkst3randClaude Fable 5 f7b261c648 Branding-Tab: Name/Farben/Bot-Status/Avatar/Banner + Button-Farben für Rollen-Menüs
- Alle Embeds nutzen jetzt brandName/brandColor/brandColor2/brandFooter aus den
  Settings (Codemod über 20 Module) — Farbe & Name serverweit per Klick änderbar
- Bot-Status (Presence): Typ (Spielt/Schaut/Hört/Status) + Text, sofort angewendet;
  Server-Monitor nutzt die Presence nur noch, wenn kein eigener Status gesetzt ist
- Avatar-/Banner-Upload direkt aufs Bot-Profil (Base64, 8-MB-Limit,
  Discord-Rate-Limit sauber gemeldet)
- Env-Verlagerung: GITEA_API_TOKEN (write-only Setting) und DISCORD_GUILD_ID
  jetzt auch über den Brand-Tab pflegbar — weniger Redeploys
- Rollen-Menüs: Button-Farbe pro Eintrag wählbar (Grau/Blau/Grün/Rot)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 00:40:08 +02:00
D4rkst3randClaude Fable 5 db9c7d07c9 Carl-Bot-Paket: Moderation, Auto-/Sticky-Roles, Level-System, Tags, geplante Posts
- Moderation: /warn (DM + Mod-Log), /warns (Historie + löschen), /timeout (max 28d),
  /purge (bulk, 14-Tage-Limit sauber gemeldet); Mod-Log erweitert um Join/Leave
  und Nick-/Rollen-Änderungen
- Auto-Rolle bei Join + Sticky-Roles (Rollen bei Leave gesichert, bei Rejoin
  wiederhergestellt; managed/@everyone ausgenommen) — Rollen-Tab
- Level-System (opt-in): 15-25 XP/Nachricht mit 60s-Cooldown, MEE6-Formel,
  Level-Up-Announce, Rollen-Belohnungen (Level=RolleID), /rank mit Fortschritt,
  öffentliche Bestenliste /level; Community-Tab
- Tags: /tag mit Autocomplete, Verwaltung im Composer-Tab (/api/tags)
- Geplante Posts: einmalig/täglich/wöchentlich, Minuten-Scheduler, DST-sicher
  über Neuberechnung aus Zeitfeldern; Composer-Tab (/api/scheduled)
- Autocomplete-Dispatch im InteractionCreate; alles smoke-getestet

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 00:30:23 +02:00
D4rkst3randClaude Fable 5 a27a594a07 Rollen-Menüs (Carl-Bot-Ersatz) + Setup-Redesign mit Tab-Sidebar
- Rollen-Menüs: Builder im Webinterface (Titel, Beschreibung, Kanal, Emoji/Label/Rolle,
  Exklusiv-Modus = max. 1 Rolle pro Menü), Bot postet Button-Embeds; Klick = Rolle
  nehmen/abgeben (ephemeres Feedback), Update editiert den Discord-Post in place,
  Löschen räumt ihn mit auf
- Bewusst Buttons statt klassischer Emoji-Reaktionen: kein Reaction-Spam am Post,
  kein Custom-Emoji-Parsing, exklusive Menüs möglich; halbfertige Reaction-Variante
  aus abgebrochener Session entfernt und konsolidiert
- Setup-Seite: komplett neu strukturiert in 8 Tabs mit sticky Sidebar
  (Status/Feeds/Community/Rollen/Support/Composer/System/API), Feedback als Toast
- Modern-Polish: weiche Radien auf Karten/Inputs/Buttons, ruhigere Input-Flächen
  mit Fokus-Glow, Sektions-Hover; JSON-Parser akzeptiert leere Bodies
- API: /api/rolemenus CRUD + publish (Admin), README aktualisiert

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 00:15:29 +02:00
D4rkst3randClaude Opus 4.8 4d1b0a956d Ticket-System, Web-Composer und Nachrichten-Bearbeitung
- Tickets: /ticket-setup postet 🎫-Button; Klick erstellt privaten Thread
  (ein offenes Ticket pro User), Schließen-Button sperrt + archiviert
- Composer auf der Setup-Seite: Nachricht/Embed als Bot in beliebigen Kanal
  senden oder per Message-ID bearbeiten (nur eigene Bot-Posts)
- API v1: PATCH /api/v1/message — Skripte können ihre Bot-Posts aktualisieren
- Setting ticket_channel_id; README ergänzt

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 13:43:27 +02:00
D4rkst3randClaude Opus 4.8 bc000aaa9f Feature-Voting, Giveaways und Contribution-Heatmap
- /wunsch: Voting-Embed mit 👍, Reaction-Tracking (add/remove) in SQLite,
  Top-20-Rangliste öffentlich auf der Roadmap-Seite
- /giveaway (Admin): Preis/Dauer/Gewinnerzahl, 🎉-Teilnahme-Button (toggle),
  Minuten-Scheduler zieht Gewinner, schließt das Embed ab und pingt sie
- Contribution-Heatmap: 52-Wochen-Grid in Brand-Gelb aus dem Commit-Archiv
  (/api/heatmap) auf der Roadmap-Seite
- Setting voting_channel_id auf der Setup-Seite

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 13:20:44 +02:00
D4rkst3randClaude Opus 4.8 075ea36bd2 Moderation & Kontakt + Game-Server-Monitor
- Modmail: DMs an den Bot landen als Threads im privaten Staff-Kanal,
  Thread-Antworten gehen als DM zurück (Zustell-Feedback per Reaktion)
- Willkommens-Embed für neue Member (GuildMemberAdd; Server-Members-Intent nötig)
- Mod-Log: gelöschte/bearbeitete User-Nachrichten in privaten Log-Kanal
- Server-Monitor: FiveM-kompatible Endpoints (/dynamic.json) alle 2 min,
  persistentes Status-Embed (edit in place) + Spielerzahl als Bot-Presence
- Neue Intents: DirectMessages, GuildMembers; Partials.Channel
- Setup-Seite: Sektionen // Moderation & Kontakt und // Game-Server

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 13:14:18 +02:00
D4rkst3randClaude Opus 4.8 a3c47656c5 Community-Paket: Playtester-Programm, Starboard, Screenshot-Galerie
- Playtester: /playtester-setup postet Bewerbungs-Embed mit 🧪-Button;
  Toggle vergibt Rolle + DB-Eintrag; Liste + Rollen-Auswahl auf der Setup-Seite
- Starboard: ab konfigurierbarem -Schwellwert Repost als Embed in den
  Best-of-Kanal (Dedupe, kein Selbst-Boarding); neue Intents/Partials für Reaktionen
- Galerie: Bilder aus dem Screenshot-Kanal lokal archiviert (live + /galerie-backfill,
  Delete-Sync, Bot reagiert mit ) → öffentliche /galerie-Seite mit Hover-Grid
- Setup-Seite: Sektion // Community (Rolle, Starboard-Kanal + Schwellwert, Screenshot-Kanal)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 12:34:34 +02:00
D4rkst3randClaude Opus 4.8 143288affa d4rkbot: API v1 mit Key-System, Env-Diät, Rebranding
- API-Keys (SHA-256-Hash, Scopes, last_used) — Verwaltung auf der Setup-Seite,
  Klartext-Key wird genau einmal angezeigt
- /api/v1: message, dm, roles (add/remove), member/:id, stats — Bearer-Auth
  mit Scope-Prüfung, Embed-Sanitizing, README-Doku mit Python-Beispiel
- Env-Diät: PUBLIC_URL + GITEA_URL jetzt Settings (Env nur Fallback),
  OAuth-Redirect dynamisch; Env enthält nur noch Secrets/Bootstrap
- Rebranding ecobot → d4rkbot (Packages, Container, Cookies, README);
  Volume-Name bleibt ecobot_data (Datenerhalt), Portainer-Stack-Name bleibt

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 11:56:48 +02:00
D4rkst3randClaude Opus 4.8 07c3bf47d0 Bug-Reports, Devlog-Threads und Watchdog
- /bug (alle Member): erstellt Gitea-Issue inkl. Screenshot-Upload als Asset;
  bug_reports-Tabelle für den Rückkanal — Issue geschlossen (issues-Webhook)
  → DM an den Reporter
- Auto-Thread '💬 Devlog <Datum>' unter jedem Devlog-Post (Setting, Default an)
- Watchdog: prüft Setting watchdog_urls alle 2 min, DM an Admin nach 2 Fails
  in Folge + Entwarnung mit Downtime-Dauer
- Setup-Seite: Bug-Repo, Threads-Toggle, Watchdog-URLs; Env GITEA_API_TOKEN/GITEA_URL

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 11:29:01 +02:00
D4rkst3randClaude Opus 4.8 3c8f442d6c Wochen-Rückblick: sonntags 20:00 automatisch in den Devlog-Kanal
- Scheduler (5-Minuten-Check, dedupe über last_weekly_recap-Setting)
- Embed: Commits pro Tag als Balken-Grafik, Commit-/Devlog-Zahlen, Top-Projekte
- Setting weekly_recap_enabled + 'Rückblick jetzt testen'-Button auf der Setup-Seite
- TZ Europe/Berlin im Compose (Scheduler + Datumsformate)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 10:41:17 +02:00
D4rkst3randClaude Opus 4.8 247e8c805c Rollen-Ping beim Devlog: Erwähnung + Abo-Button
- Setting devlog_ping_role_id (Rollen-Dropdown auf der Setup-Seite, leer = aus)
- Devlog-Post erwähnt die Rolle (allowedMentions gescoped) und trägt einen
  🔔-Button, über den Member die Rolle selbst an-/abmelden (ephemere Bestätigung)
- API liefert vergebbare Rollen (ohne @everyone/managed), PUT validiert

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 10:39:06 +02:00
D4rkst3randClaude Opus 4.8 be1fc227d0 Release-Ankündigungen + öffentliche Changelog-Seite
- Gitea-Release-Webhook: Releases werden archiviert (releases-Tabelle) und neue
  'published'-Releases als oranges 🚀-Embed mit Buttons angekündigt
- Release-Kanal auf der Setup-Seite wählbar (leer = Feature aus) + Test-Button
- /changelog: öffentliche Seite mit Tag-Chips, Pre-Release-Badge, Release-Notes
- /api/releases öffentlich; Updates/Redeliveries posten nicht doppelt

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 10:37:28 +02:00
D4rkst3randClaude Opus 4.8 ae5732a61b Setup-Seite: Kanal-Auswahl, Feed-Regeln und Status im Webinterface
- Settings-Tabelle in SQLite; Env-Variablen nur noch Fallback, Änderungen greifen sofort
- /settings (Admin): Devlog-/Commit-Kanal als Dropdown aus allen sichtbaren Textkanälen,
  je mit Test-senden-Button
- Commit-Feed-Regeln: an/aus, Branch-Filter, ignorierte Repos (archiviert wird immer,
  gefiltert wird nur das Posten; ignorierte Repos komplett übersprungen)
- Status-Panel: Bot-Tag, Uptime, Devlog-/Commit-Zahlen, DB-Größe
- API: GET/PUT /api/settings, POST /api/settings/test/:target (alles Admin-only)
- COMMIT_CHANNEL_ID/DEVLOG_CHANNEL_ID in config optional

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 10:21:05 +02:00
D4rkst3randClaude Opus 4.8 71d2bb07f1 Devlog-Löschung: Discord-Delete-Sync + Admin-Button im Webinterface
- MessageDelete-Listener (mit Partials): in Discord gelöschte Devlogs verschwinden
  automatisch aus dem Archiv, inkl. lokaler Bilder
- DELETE /api/devlogs/:id (nur Admin) + ✕-Button auf den Karten (nur für Admin sichtbar)
- Anlass: Test-Post mit Commit-Liste von vor der Prosa-Sperre stand noch im Archiv

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 01:16:44 +02:00
D4rkst3randClaude Opus 4.8 ed69d859ca Devlog-Seite: Bildergalerie, Projekt-Chips, Monats-Trenner
- Bild-Attachments werden beim Archivieren lokal gespeichert (Discord-CDN-URLs
  laufen ab) und unter /devlog-assets/ ausgeliefert; DB-Migration: images-Spalte
- Frontend: Bildergalerie im Grid (responsive nach Anzahl), Embed-Titel als
  Projekt-Chip, Commit-Fußzeile abgesetzt, Monats-Trenner in der Timeline
- Backfill lädt Bilder alter Devlogs nach (Dedupe verhindert Doppel-Downloads)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 00:56:53 +02:00
D4rkst3randClaude Opus 4.8 2f9d548bc8 Devlog-Archiv: Filter akzeptiert auch Bot-Posts, Backfill-Report mit Absender-Aufschlüsselung
- devlog.py kann per Webhook ODER Bot-Token posten — beides wird jetzt archiviert
  (nur User-Chatter und der EcoBot selbst bleiben ausgeschlossen)
- /devlog-backfill meldet jetzt Webhook/Bot/User-Zählung zur Diagnose

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 23:56:42 +02:00
D4rkst3randClaude Opus 4.8 2c63c62e14 Feature 3: Devlog-Archiv — Live-Listener + /devlog-backfill
- Webhook-Nachrichten im Devlog-Kanal werden automatisch in SQLite archiviert
  (devlog.py im EcoGame-Repo bleibt unverändert)
- /devlog-backfill (Admin): scannt die komplette Kanal-Historie in 100er-Blöcken
- Dedupe über Discord-Message-ID, Embeds werden mit Titel+Beschreibung erfasst
- Neue Intents: GuildMessages + MessageContent, neue Env-Var DEVLOG_CHANNEL_ID

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 23:51:16 +02:00
D4rkst3randClaude Opus 4.8 46d6a3f927 Feature 2: Commit-Feed — Gitea-Webhook, Discord-Embeds, SQLite-Archiv
- Fastify-Webserver mit /health und /webhooks/gitea (HMAC-SHA256-Signaturprüfung, timing-safe)
- Push-Commits werden in SQLite gespeichert (Dedupe per SHA) und als Embed gepostet
- Dockerfile auf node:22-slim (glibc-Prebuilds für better-sqlite3), Port 3080 published
- README: Anleitung für Cloudflare-DNS, Nginx Proxy Manager (bot.d4rkst3r.de) und Gitea-Webhook

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 23:27:33 +02:00
D4rkst3randClaude Opus 4.8 2b3fa3eb69 Initiales Setup: minimaler Discord-Bot mit /ping, Docker-Deployment und README
- discord.js v14 Bot mit Slash-Command-Registry (Guild oder global)
- Konfiguration über .env mit Validierung (config.js)
- Dockerfile + docker-compose.yml für Portainer-Deployment
- README mit Schritt-für-Schritt-Anleitung (Discord Developer Portal)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 23:10:19 +02:00