89f6dfcd2971ac2b932b80a63a684b3d5ec75b4e
63
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
89f6dfcd29 |
Radio: Webradio im Sprachkanal, 44 Sender zum Durchschalten
/radio holt den Bot in den Sprachkanal und postet eine Tafel: Auswahlmenue mit allen Sendern, Stopp, und ein Embed mit dem laufenden Titel, das sich alle 30 Sekunden selbst nachfuehrt. Der Titel kommt aus dem Icecast-Strom selbst (Icy-MetaData). Bewusst so und nicht ueber eine Sender-API: das funktioniert bei jedem Strom, den jemand eintraegt, und nicht nur bei den drei, die ich kenne. Leere Titel-Bloecke heissen "unveraendert", deshalb werden bis zu drei gelesen. Die Tonkette braucht keine Opus-Bibliothek: ffmpeg holt das MP3 und gibt direkt Ogg/Opus aus, prism-media packt nur noch aus. Gemessen: 600 Pakete in fuenf Sekunden. Sonst muesste @discordjs/opus mit ins Image, und das will gebaut werden. Neu im Image ist nur ffmpeg. 44 RauteMusik-Sender sind ab Werk eingetragen — dieselben, die im LS25 und ETS als Bordradio laufen. Die Liste ist nicht abgeschrieben, sondern gemessen: jede Adresse einzeln angefragt, der Name kommt aus icy-name. Doppelgaenger sind raus (deutschrap-charts und wackenradio liefern denselben Strom wie deutschrap und metal). Eingetragen wird einmal, solange die Liste leer ist — wer loescht, behaelt es geloescht. Ein Auswahlmenue fasst nur 25 Eintraege. Bei 44 Sendern haette ein Deckel die letzten 19 stillschweigend verschluckt; stattdessen mehrere Menues, benannt nach ihrem ersten und letzten Sender. Der Bot geht raus, wenn der Kanal leer ist, und kommt nach einem Neustart in den Kanal zurueck — sonst beendet jeder Deploy die Musik endgueltig. Kein YouTube. Genau daran sind Groovy und Rythm gestorben, und was davon uebrig ist, ist ein Dauerlauf gegen kaputte Extraktoren. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
0982e8cd1b |
feat: Server aus dem Panel uebernehmen -- und nur die auch wieder loeschen
Im d4rk_gameserver-Panel bekommt jeder Server einen Schalter "Im Discord anzeigen". Das Panel schreibt dafuer NICHTS hierher: es setzt nur ein Haekchen, und das reist in dem Statusbericht mit, den der Monitor ohnehin alle 30 Sekunden abholt. Der Bot legt den Eintrag dann selbst an. Der umgekehrte Weg -- Panel ruft unsere API -- braeuchte dort ein Zeichen mit Schreibrecht. So bleibt es bei einem, das nur lesen kann. ZWEI FALLEN, beide beim Bauen aufgefallen: Der Abgleich lief zu spaet. In monitorTick stand `if (servers.length === 0) return` VOR dem Panel-Abruf; beim allerersten Server haette der Schalter also nichts getan, und zwar stillschweigend. Der Abruf steht jetzt davor. Loeschen braucht einen Besitzvermerk. Ohne den nimmt ein Haekchen im Panel den handgepflegten ATM10 mit -- die einzige verfuegbare Grundlage waere der Name, und beim ersten Server, der in beiden Werkzeugen gleich heisst, waere der Eintrag samt Bild, Links und Zugangs-Code weg. Neue Spalte `panel_name`, leer heisst "von Hand". Die UPDATE-Anweisung fasst sie nicht an, damit ein Bearbeiten im Webinterface die Herkunft behaelt. Und der Abgleich ueberschreibt nichts: angelegt und geloescht wird, mehr nicht. tools/panel-abgleich-pruefen.mjs prueft das auf einer EIGENEN Datenbank in /tmp und bricht ab, wenn sie es nicht ist -- eine Probe, die loeschen kann, darf nicht dort loeschen, wo es zaehlt. Alles gruen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
21eab627b9 |
fix: die Panel-Anbindung steht jetzt dort, wo man sie sucht
Der Betreiber hat sie nicht gefunden, und das zu Recht: die zwei Felder gab es nur auf der Modul-Detailseite unter Module -> Game-Server-Monitor. Der Reiter "Game-Server" hat aber einen eigenen, handgeschriebenen Block mit Status- und Alarm-Kanal -- und genau dort schaut nach, wer den Monitor einrichtet. Also stehen sie jetzt auch dort, direkt unter den Kanaelen, mit dem Absatz, der erklaert wofuer das gut ist. Die Modulseite behaelt sie; es sind dieselben Formularwerte, keine zweite Wahrheit -- genauso wie status_channel_id schon an beiden Stellen steht. Und ins Suchregister (setting-index.js), sonst findet die Suche in der Seitenleiste das Feld nicht und man sucht es mit den Augen. Das Register traegt selbst den Kommentar, dass ein vergessener Eintrag genau so endet. Geprueft, indem die Frontend-Stufe des Images gebaut und im Ergebnis nachgesehen wurde -- "Panel-Adresse", "Panel-Zeichen" und "Panel-Anbindung speichern" stehen im ausgelieferten Bundle. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
d6124fc2cd |
feat: der Monitor fragt das Panel, wenn eine Abfrage nicht ausreicht
gamedig FRAGT einen Server. Ein startendes Modpack antwortet nicht, und
nach zwei Fehlversuchen stand im Alarm-Kanal eine Ausfallmeldung, obwohl
niemand etwas kaputtgemacht hat -- am ATM10 des Betreibers gemessen jedes
Mal 306 Sekunden Fehlalarm.
Das d4rk_gameserver-Panel SIEHT den Container, statt ihn zu fragen. Neu
ist deshalb `src/panel.js`: Zustand, Fertig-Merkmal, RAM und CPU kommen
als Zusatzauskunft dazu, einmal je Durchlauf abgerufen und 20 Sekunden
zwischengespeichert.
Was das im Alarm-Kanal aendert:
startet gerade kein Alarm, aber nur innerhalb einer Gnadenfrist von
15 Minuten. Ohne diese Grenze fraesse die Anbindung
genau den Alarm, fuer den es sie gibt -- `bereit`
wird nie von allein wahr, ein haengender Start bliebe
sonst fuer immer stumm.
im Panel gestoppt kein Alarm (Code 0/143/137)
abgestuerzt ALARM, mit Code im Embed
OOM-Kill ALARM, und beim Namen genannt statt als Absturz
getarnt -- bei Modpacks die haeufigste Ursache
Container weg ALARM
Der Zaehler wird beim Unterdruecken NICHT zurueckgesetzt: ein bereits
gemeldeter Ausfall bleibt gemeldet, sonst verschluckt ein Stopp im Panel
die spaetere "wieder online"-Entwarnung und im Kanal bliebe ein Alarm
ohne Aufloesung stehen.
ES IST DURCHGEHEND OPTIONAL. Adresse und Zeichen stehen im Webinterface
unter "Server" und NICHT in der .env; ohne Eintrag -- und ebenso, wenn
das Panel nicht antwortet -- verhaelt sich der Monitor exakt wie vorher.
Das Zeichen darf nur lesen, damit auch ein verlorenes niemandem einen
Server stoppen kann.
`tools/panel-pruefen.mjs` prueft die Logik ohne Discord und ohne
Datenbank; deshalb laedt panel.js die Einstellungen erst beim Aufruf.
|
||
|
|
1ef06f747c |
Modliste: melden was sich geaendert hat, einzeln laden
Bisher gab es fuer Mods nur einen Link auf das Sammelpaket des Hosters — vier Gigabyte, auch wenn sich zwei Dateien geaendert haben. Jetzt liest der Bot die Modliste aus der Statusabfrage, die er ohnehin holt, und meldet im Kanal, was neu, aktualisiert oder entfernt wurde. Beim ersten Durchlauf bleibt es still, sonst kaeme eine Meldung ueber 110 "neue" Mods. Geaendert heisst: andere Version oder anderer Hash. Beides einzeln reicht nicht — manche Modder bessern nach, ohne die Version zu erhoehen. Dazu die Seite /mods/<server>: jeder Mod mit Version und Groesse, Suche ueber Titel, Dateiname und Autor, und ein Download je Zeile. Der laeuft durch den Bot, damit der Zugangs-Code des Spielservers nicht in einem Link landet — mit dem Code liesse sich auch der ganze Spielstand lesen. Angefragt wird nur, was wirklich in der Modliste steht; ueber den Dateinamen kommt man an nichts anderes heran. Groessen lernt der Bot beim Weiterleiten. Der Spielserver beantwortet kein HEAD (501) und ignoriert Range, es gibt also keinen billigen Weg, sie vorher zu erfahren — und 4 GB nur fuers Anzeigen zu holen waere keiner. Nebenbei gefunden und behoben: 'server.mods' und 'commands.tag' gab es je zweimal in den Sprachdateien. Der spaetere Eintrag gewinnt still, deshalb stand auf dem neuen Knopf woertlich "%s Mods (110)" und auf der Befehlsseite die Beschreibung von /tag statt der Kopfzeile. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
9b681754fa |
Ein Embed je Hof, das sich selbst aktualisiert
Der Fuhrpark stand bisher nur als Gesamtzahl im Karten-Embed. Jetzt bekommt jeder Hof eine eigene Nachricht im selben Kanal, die bei jedem Durchlauf bearbeitet statt neu gepostet wird: Land, Fahrzeuge mit Wert und Betriebsstunden, was in die Werkstatt muss, was gewaschen gehoert und was geladen ist. Die Fahrzeuge kommen aus vehicles.xml, blockweise gelesen — Verschleiss und Schmutz stehen in Kindelementen und gehoeren sonst dem falschen Fahrzeug. Gemietete Missionsfahrzeuge bleiben draussen, sie verfaelschen Anzahl und Wert. Faellt die Datei einmal aus, bleiben die Embeds stehen, statt dass ein Hof verschwindet und gleich darauf doppelt gepostet wird. Damit tauchen auch Hoefe auf, die noch kein Land gekauft haben: die Liste der Hoefe kommt aus Parzellen und Fuhrpark zusammen. Dazu raus, was nur den Kanal vollgeschrieben hat: die Meldung zum Monatswechsel und die zum Landkauf. Der Monat wird still weitergestellt — er steht ohnehin im Embed. Damit faellt der Ereignis-Kanal weg und mit ihm die gespeicherte Besitzliste. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
ea523b76b3 |
Servername aus dem Spiel und ein Schloss fuer Passwort oder Whitelist
Der Name im Panel ist der, den DU vergibst — wie der Server sich im Spiel nennt, stand nirgends. Steht jetzt darunter, aber nur wenn es etwas anderes ist als der eingetragene Name; sonst haette dieselbe Zeile zweimal dagestanden. Beim Schloss war die Frage, wie viel die Abfrage ueberhaupt hergibt. Nachgesehen statt geraten: 31 der 358 gamedig-Protokolle melden ein Passwort. valve gehoert dazu, deckt also CS2, Rust, ARK, Squad, 7DTD, Zomboid, Gmod und DayZ ab. Minecraft nicht, Farming Simulator auch nicht — im LS-XML kommt das Wort Passwort kein einziges Mal vor. Und eine Whitelist meldet grundsaetzlich kein Spiel, die steht in einer Datei auf dem Server. Also beides: automatisch, wo es geht, und eine Einstellung, die es schlaegt. Wer "Whitelist" eintraegt, bekommt sie angezeigt, auch wenn der Server schweigt. Wichtig dabei ist der dritte Zustand. "Sagt nichts" ist nicht "offen" — deshalb `null` und kein `false`. Ein Schloss, das bei jedem schweigenden Server fehlt, waere eine Aussage, die wir nicht belegen koennen; umgekehrt waere ein Schloss ohne Grundlage eine Luege. Bei unbekannt steht schlicht nichts da. Geprueft: Einstellung schlaegt Messung in allen vier Faellen, automatisch mit true/false/null, fehlender Server, unbekannter Wert faellt auf automatisch zurueck statt zu sperren, Schloss im Embed-Titel nur wenn belegt, Spielname nur bei echtem Unterschied (auch mit Leerzeichen drumherum). Panel und /server-Seite im laufenden Frontend angesehen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
b69cb6c5e4 |
Freie Links je Server statt fester Felder
connect_url und mods_url waren zwei Spalten fuer zwei Zwecke — und beim naechsten Zweck waere eine dritte dazugekommen. Jetzt gibt es eine Liste: Beschriftung plus Adresse, so viele wie noetig. Regeln, TeamSpeak, Shop, Bewerbung. Als JSON-Spalte, nicht als eigene Tabelle: es haengt an genau einem Server, wird immer komplett gelesen und immer komplett geschrieben. Gelesen wird es als Liste, geschrieben darf es als Liste hereinkommen — better-sqlite3 kann kein Array binden und wuerde sonst werfen. Kaputtes JSON ergibt eine leere Liste statt eines Absturzes im Monitor. Discord nimmt fuenf Knoepfe je Reihe; ab jetzt werden sie umgebrochen, bei zwei Reihen ist Schluss. Die Grenze steht im Code und nicht im Fehler beim Senden, den niemand sieht. Zu lange Beschriftungen werden auf 80 Zeichen gekuerzt, halbe Zeilen fliegen raus statt als leerer Knopf zu erscheinen. Was nicht http(s) ist — ts3server://, steam:// —, wird wie bisher ein Codeblock im Embed zum Kopieren. Dabei umbenannt: das Embed-Feld fuer einen nicht klickbaren Connect-Link hiess "Connect", der Knopf daneben "Verbinden". Jetzt heisst beides gleich. Geprueft: Umbruch bei zwoelf Links, Reihenfolge mit Connect und Mods vorn, halbe Zeilen, ueberlange Beschriftung, nicht klickbare Schemata, fehlendes und unbrauchbares links-Feld, dazu Speichern, Aendern und kaputtes JSON in der Datenbank. Panel und /server-Seite im laufenden Frontend angesehen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
9f929fe0e4 |
Eigene Kategorie Gaming fuer Game-Server und LS
Der Game-Server-Monitor stand unter "Server & Technik" zwischen DB-Sicherung, Repo-Sicherung und Member-Gate. Technisch nicht falsch — dort laeuft alles, was der Bot an Infrastruktur anfasst. Nur sucht niemand seinen LS-Server neben dem Datenbank-Backup. Mit dem LS-Modul waren es zwei Eintraege in der falschen Schublade, und das reicht fuer eine eigene. Getrennt wird nach dem, worum es geht: "Server & Technik" ist der Bot selbst, "Gaming" sind die Spiele-Server drumherum. Beide Ebenen ziehen mit — die Modul-Kacheln ueber MODULE_GROUPS, die Seitenleiste ueber TAB_SECTIONS —, und der Tab heisst jetzt "Game-Server" statt "Server", weil "Server" im selben Panel schon zweierlei bedeutete. Nebenbei: das Modul hiess "Server-Monitor" und ueberwacht Game-Server; jetzt steht das auch dran. Die Suche im Panel findet den Tab zusaetzlich ueber "ls", "landwirtschaft", "farming", "hof", "karte" und "preise". Geprueft: kein Modul ohne Gruppe, keine leere Gruppe, Seitenleiste und Modul-Kacheln im laufenden Panel angesehen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
e215cd4c7c |
LS-Modul: Besitzkarte auf dem Luftbild und Preiskurven
Der Feed eines LS-Servers gibt viel mehr her als die Spielerzahl, die der Monitor bisher davon benutzt hat: in denselben 49 KB stehen 163 Parzellen mit Besitzer und Hektar, 130 Felder, jedes Fahrzeug samt Ladung und die Position jedes Spielers. Und das Luftbild liefert der Server auch, in jeder Groesse bis 4096. Also eine Karte: gekaufte Parzellen nach Hof eingefaerbt, Kreisflaeche gleich Hektar, Fahrzeuge und Spieler live, dazu eine Hof-Uebersicht mit Flaeche und Wert. Wechselt Land den Besitzer, kommt eine Meldung — beim allerersten Durchlauf bewusst nicht, sonst haette der Botstart eine Meldung pro bereits gekaufter Parzelle abgesetzt. Dazu die Preiskurven aus der economy.xml: je Fruchtart, was sie in welcher der zwoelf Perioden bringt, als Balkenzeile mit "jetzt verkaufen" oder "+43 Prozent im Hochwinter". Was NICHT geht, und zwar grundsaetzlich: welche Frucht auf welchem Feld steht und wie weit sie ist. Das liegt in einer binaeren Density-Map, die kein Endpunkt herausgibt. Ich habe 18 Dateinamen durchprobiert, es gibt genau drei. Die Mods, die das anzeigen, sind reine HUD-Overlays ohne Ausgang. Und keiner der fuenf anderen LS-Bots kann es, obwohl einer davon Geld kostet. Das steht mit allen Belegen in docs/ls-feed.md, damit die Frage nicht dreimal kommt. Beim Bauen aufgefallen: - istLsServer() gab den Zugangs-Code zurueck statt true — die &&-Kette liefert den letzten wahren Wert. Beim ersten Log-Aufruf haette der Code im Klartext im Protokoll gestanden. - Die Karte als PNG war 2,5 MB, als JPEG 268 KB. Es ist ein Luftbild. - Nach Preisschwankung sortiert gewinnt Spargel: 26 bis 7540 Euro, und Weizen taucht gar nicht mehr auf. Die Liste arbeitet jetzt mit einer Auswahl. - Die Jahreszeit steht in keinem Endpunkt. Schaetzbar waere sie, aber nur solange niemand die Zeitskala aendert — also eine Einstellung. Geprueft gegen echte Serverdaten: Zerlegen der Statusabfrage inklusive Vollstaendigkeit aller 163 Parzellen, Ladung ohne Diesel und leere Slots, Hof-Uebersicht ohne verlorene Parzellen, Preiskurve mit vollem und leerem Balken an der richtigen Stelle, flache Kurve ohne Division durch Null, Besitzwechsel inklusive Erstlauf und neu hinzugekommener Parzelle, Hof-Namen aus der Einstellung, SVG ohne NaN und mit maskierten Namen, und der Merker in der Datenbank inklusive kaputtem JSON. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
eec170ff41 |
Connect-Links im Discord anklickbar, und Mods bekommen einen eigenen Knopf
Im Kanal stand woertlich das da:
[https://cfx.re/join/4odv68](https://cfx.re/join/4odv68)
Der Link war sein eigener Linktext. Discord macht aus der nackten URL zwischen
den eckigen Klammern zuerst selbst einen Link und kommt mit der
Masked-Link-Schreibweise dann nicht mehr durch — heraus kommen die Klammern im
Klartext. Der Kommentar an der Stelle behauptete ausserdem, so seien steam://
und Konsorten klickbar. Waren sie nie.
Jetzt sind es Link-Knoepfe unter dem Embed. Die Frage nach der Schreibweise
stellt sich damit gar nicht mehr, und ein Knopf sieht auch nach einem aus.
Discord nimmt dort nur http(s) an; fivem:// und steam:// stehen deshalb weiter
im Embed, aber als Codeblock zum Kopieren statt als toter Link.
Dazu ein eigenes Feld fuer den Mod-Download. Vorher landete der beim
Connect-Link, weil es kein anderes gab — und dann fuehrte "Verbinden" zu einer
ZIP-Datei. Farming Simulator liefert die Modliste ohnehin mit, also steht die
Anzahl jetzt auch im Embed und als Chip auf der Seite.
Beim Testen aufgefallen: eine neue Spalte hat jeden Aufrufer umgebracht, der
sie noch nicht kannte — better-sqlite3 wirft bei einem fehlenden benannten
Parameter. createGameserver und updateGameserver fuellen die Felder jetzt
einmal auf, statt das an jeder Aufrufstelle nachzuziehen.
Geprueft: was in einen Knopf darf und was nicht (https, http, fivem://,
steam://, leer, null, Leerzeichen, Satz mit Link drin), beide Knoepfe in einer
Reihe, nur einer, gar keiner — eine leere Reihe weist Discord ab —, https
landet im Knopf und nicht doppelt auch im Embed, fivem:// umgekehrt, Mods bei
47/0/null, und der Aufruf ohne die neue Spalte. Seite im laufenden Frontend
angesehen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
4e7fc99999 |
Server-Seite ueberarbeitet, und die Spielauswahl kommt jetzt aus gamedig
LS25 fehlte, aber nicht nur LS25: die Auswahl im Panel war eine von Hand gepflegte Liste mit neunzehn Eintraegen, und fuenf davon gab es bei gamedig gar nicht — "arkse", "ark", "sevendaystodie", "minecraftbe" und "terraria". Wer eines davon auswaehlte, bekam einen Server, der dauerhaft offline stand, ohne dass irgendwo ein Grund stand. Die echten IDs heissen ase, sdtd, mbe und terrariatshock. Also nicht LS25 nachtragen, sondern die Liste abschaffen: sie kommt jetzt aus gamedig selbst, 360 Eintraege, sortiert, mit Suche. Jedes Update bringt neue Spiele automatisch mit. Dazu der Standard-Query-Port als Vorschlag, sobald man ein Spiel waehlt. Bestehende Eintraege mit den toten IDs werden beim Start einmalig umgebogen. Farming Simulator hat noch eine zweite Huerde: der Server antwortet nur mit Zugangs-Code, und den hat queryServer nie durchgereicht. LS25 waere also auch mit richtiger ID offline geblieben. Jetzt gibt es eine Spalte dafuer, das Feld erscheint nur bei Spielen, die einen brauchen (Farming Simulator, Terraria — bei Satisfactory optional), und Speichern ohne Code wird abgelehnt statt stillschweigend hingenommen. Der Code steht nicht in der oeffentlichen API. Nebenbei aufgefallen: input[type=password] war im CSS nirgends erfasst. Das erste solche Feld kam voellig ungestylt daher. Die /server-Seite dazu: - Auslastungs-Balken mit eigener Farbe statt des XP-Balkens vom Level-System. Gruen frei, gelb ab 80 Prozent, rot voll — die Zahl steht rechtsbuendig, mittig laege sie bei 50 Prozent genau auf der Fuellkante. - Map, Version und Ping als Chips. Vorher standen sie mit Punkten getrennt in der Statuszeile und wurden auf dem Handy zu Brei. - Wer gerade drauf ist. Die Namen holt der Monitor ohnehin schon fuers Embed, auf der Seite standen sie nur nirgends. - Welches Spiel es ueberhaupt ist. Das stand nirgends ausser im Emoji. - Offline-Karten waren bisher leer bis auf das Wort. Jetzt steht dort, seit wann — soweit der Verlauf reicht, sonst gar nichts statt einer Schaetzung. - Zeitachse und Peak-Linie am Verlauf. Eine Flaeche ohne Bezugspunkt sagt nicht, wie hoch hoch ist. - Plaetze insgesamt in der Uebersicht oben. Geprueft: Token speichern und aendern, Spielnamen inklusive unbekannter ID, Token-Bedarf pro Protokoll, Liste ohne Doppler, alle Icon-Schluessel gegen gamedig, "zuletzt online" ignoriert Offline-Proben, und die Migration mit einer Datenbank im alten Stand. Beide Seiten am laufenden Frontend angesehen, auch auf Handybreite. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
22054c109e |
Mod-Log: eigenes Gedaechtnis, damit beim Loeschen nicht "unbekannt" dasteht
Dein Eintrag war der Normalfall, nicht die Ausnahme:
User: unbekannt
Inhalt: [kein Text / nicht im Cache]
Discord schickt beim Loeschen nur eine Huelle, sobald die Nachricht nicht mehr
im Cache des Bots liegt. Der reicht ein paar hundert Nachrichten weit und faengt
erst beim Start des Bots an — bei einem Post von gestern ist sie also nie drin.
Ein Protokoll, das genau dann nichts weiss, wenn es interessant wird, ist keins.
Also merkt sich der Bot Nachrichten jetzt kurz selbst: Verfasser, Wortlaut,
Namen der Anhaenge. Beim Loeschen steht das im Eintrag, danach wird der Merker
weggeworfen. Wie lange aufbewahrt wird, steht unter Werte — sieben Tage
voreingestellt, 0 heisst gar nicht mitschreiben. Bewusst knapp und einstellbar:
das ist ein Werkzeug zum Nachvollziehen von Loeschungen, kein Archiv.
Dazu drei Sachen, die vorher fehlten:
- Wer geloescht hat. Steht in Discords Audit-Log, aber nur wenn es jemand
anders war als der Verfasser. Gemeldet wird nur, was frisch ist und zu Kanal
und Verfasser passt — Discord zaehlt bei wiederholtem Loeschen denselben
Eintrag hoch statt neue anzulegen, da ist eine falsche Angabe schnell
gemacht. Lieber keine als eine falsche.
- Sammel-Loeschungen. /purge und Discords eigenes Aufraeumen standen gar nicht
im Log: eine geloeschte Nachricht fiel auf, hundert nicht. Jetzt mit Anzahl,
Kanal und den ersten fuenfzehn Zeilen.
- Anhaenge. Dass ein Bild dranhing, war vorher nirgends zu sehen — und das
Bild selbst ist nach dem Loeschen ohnehin weg.
Nebenbei: "[kein Text / nicht im Cache]" waren zwei Aussagen in einer und beide
unklar. Jetzt steht dort entweder der Wortlaut, oder dass die Nachricht keinen
hatte, oder dass sie aelter ist als die Aufbewahrung reicht.
Beim Testen gefunden: pruneMessageCache(0) hat nichts geloescht. "-0 days" ist
genau jetzt, und `created_at < jetzt` laesst die eben geschriebene Zeile stehen.
Bei 0 wird jetzt alles geleert, wie es gemeint war.
Geprueft: Merken, Wiederfinden, Anhaenge durch JSON, Bearbeiten zieht mit,
Vergessen nach dem Loggen, unbekannte ID, doppelte ID, Aufbewahrung mit einem
zu alten und einem frischen Eintrag, und der 0-Fall. Ereignisnamen und
AuditLogEvent gegen die installierte discord.js geprueft.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
b6b767acb7 |
Bis fuenf Eintraege Knoepfe statt Auswahlmenue
Du hattest recht. Bei vier Anliegen ist ein Auswahlmenue der schlechtere Weg: zwei Klicks statt einem, und die Moeglichkeiten sieht man erst nach dem Aufklappen. Ein Knopf ist beides — sichtbar und sofort. Umgekehrt gilt es nicht immer. Ab sechs wird die Knopfreihe zur Wand und Discord bricht sie um; dann ist das Menue das ruhigere Bild. Also nicht "Knoepfe statt Menue", sondern der Uebergang: bis fuenf Knoepfe, darueber Menue. Fuenf, weil genau so viele in eine Reihe passen. Betroffen waren nur zwei Stellen — Ticket-Anliegen und Wunsch-Bereiche. Alles andere im Bot waren ohnehin schon Knoepfe. Eine Sache verliert man dabei: die graue Beschreibungszeile, die ein Menue unter jedem Eintrag anzeigt. Die steht jetzt im Text des Aufruf-Posts, und da ist sie ehrlich gesagt besser aufgehoben — man liest sie, bevor man klickt, statt danach. Geprueft gegen discord.js selbst, weil Ueberlaengen und ungueltige Emojis sonst erst beim Posten auffallen: null Eintraege (der eine alte Knopf), eins bis fuenf (Knoepfe mit Emoji und der ID in der Kennung), sechs (zurueck zum Menue), Murks-Emoji (faellt weg, Knopf bleibt), 200 Zeichen langer Name (auf 80 gekuerzt), und die Beschreibungszeile in allen drei Faellen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
b3758f1f76 |
Screenshots zu Ideen, und der Bot legt die Forum-Tags selbst an
Zwei Fragen, zwei Antworten — eine davon ein Nein mit Umweg. ## Bilder im Eingabefenster: geht nicht Discord-Modals koennen nur Textfelder. Kein Datei-Anhang, keine Umgehung — das ist eine Grenze der Plattform, nicht unseres Codes. Der Umweg ist besser als er klingt: Wer nach dem Einreichen einen Screenshot in den Thread haengt, sieht ihn auf der Ideen-Seite. Die Bestaetigung nach dem Absenden sagt das jetzt auch. Damit kann man auch nachtraeglich noch Bilder dazulegen, was im Eingabefenster gar nicht ginge. ## Warum nicht einfach der Discord-Link Discord haengt seit einiger Zeit eine Signatur an die Anhang-Links (?ex=&is=&hm=), die nach etwa einem Tag ablaeuft. Ein gespeicherter Link zeigt morgen ein kaputtes Bild. Deshalb laden Devlogs und Galerie seit dem ersten Tag herunter — im Kopf von devlog-archive.js steht der Grund. Wuensche machen es jetzt genauso, ausgeliefert unter /wish-assets/. Beim Loeschen eines Beitrags oder eines ganzen Wunsches gehen die Dateien mit; sonst waechst der Ordner mit Bildern, auf die nichts mehr zeigt. Das Herunterladen stand vorher zweimal fast wortgleich im Code. Mit den Wuenschen waeren es drei Kopien geworden — also einmal nach bot/bilder.js, und Devlogs und Galerie ziehen mit um. Ein Fehler steckt jetzt an einer Stelle statt an dreien. ## Forum-Tags per Knopf Bisher musstest du sie von Hand anlegen. Jetzt macht es das Panel: die Bereiche von dort plus die fuenf Staende, mit ihren Emojis. Vorhandene bleiben, auch fremde — die Liste wird ergaenzt und nicht ersetzt. Discords Grenze von 20 Tags wird eingehalten, was nicht mehr reinpasst, wird gemeldet statt still verschluckt. Geprueft: forumTagsAnlegen gegen eine Kanal-Attrappe — leeres Forum, teilweise vorhandene, Gross/Kleinschreibung, fremde Tags, nichts zu tun (dann wird auch nicht geschrieben), volles Forum, kein Forum, kein Kanal. Im Browser die Ideen-Seite mit Bildern in einem Beitrag, einem Beitrag nur aus Bild ohne Text, und der Lightbox darueber. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
5073e7bcf4 |
Jede Idee bekommt ihre eigene Seite mit der Unterhaltung aus dem Thread
Vorbild windrose.support: Klick auf eine Idee, und man sieht sie ganz — Stand, Begruendung, wer sie eingereicht hat, und darunter, was dazu geschrieben wurde. Der Unterschied bleibt, wo geschrieben wird. Die Beitraege sind aus dem Discord-Thread gespiegelt, nicht hier getippt. Deshalb fuehrt der einzige Knopf am Ende in den Thread und nicht in ein Formular. Ein zweiter Ort fuer dieselbe Unterhaltung waere genau das, was ich beim Konzept als das Falsche bezeichnet habe. Bisher wurde nur mitgezaehlt. Jetzt landen die Beitraege in einer eigenen Tabelle — mit Bearbeiten und Loeschen, sonst stuende auf der Webseite fuer immer, was in Discord laengst zurueckgenommen wurde. Reine Bild-Posts ohne Text bleiben draussen, die haetten hier nichts zu sagen. Der Kommentar-Zaehler wird jetzt aus der Tabelle gezaehlt statt in einer Spalte mitgefuehrt. Eine Wahrheit statt zwei, die auseinanderlaufen koennen — dieselbe Ueberlegung wie beim Zuspruch. Nebenbei geprueft, weil es haette schiefgehen koennen: /api/wishes/suche und /api/wishes/:id liegen auf derselben Ebene. Der Router bevorzugt die feste Route vor der mit Platzhalter — nachgestellt mit find-my-way, nicht aus dem Gedaechtnis behauptet. Geprueft: im Browser die Seite mit drei Beitraegen und die ohne (kein Thread, keine Begruendung, Hinweis statt Liste), der Weg von der Roadmap dorthin ohne Neuladen, Migration erneut durchgespielt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
cc7a51f02e |
Emojis zum Anklicken, und Wuensche als Forums-Beitraege mit Tags
Ueberall, wo ein Emoji nach Discord geht — Rollen-Menues, Ticket-Anliegen,
Wunsch-Bereiche, Portal-Kacheln — stand ein leeres Textfeld, in das man mit
Win+. hineintippen musste. Jetzt sitzt daneben ein Knopf mit einer Tafel:
sieben Gruppen, deutsche Suchbegriffe ("auto", "geld", "warnung"), ein Klick
schreibt ins Feld. Das Feld bleibt daneben stehen, denn Server-Emojis
(<:name:123>) kennt nur Discord.
Bewusst eine eigene Liste statt einer Bibliothek: die vollstaendige
Unicode-Tabelle waere ein halbes Megabyte fuer eine Handvoll Symbole, und die
Suchbegriffe duerfen deutsch sein.
## Forum-Tags
Ist der Voting-Kanal ein Forum, wird jeder Wunsch jetzt ein Forums-Beitrag
statt Nachricht-plus-Thread — und bekommt Tags fuer Bereich und Stand. Damit
laesst sich auch in Discord filtern, wofuer Tags ja da sind. Beim Wechsel des
Stands zieht das Tag mit: der alte fliegt raus, der neue kommt rein, der
Bereich bleibt stehen.
Zugeordnet wird ueber den Namen. Wer im Forum ein Tag "Fahrzeuge" anlegt,
bekommt es automatisch gesetzt; wer keines anlegt, verliert nichts. Bewusst
keine ID-Zuordnung im Panel — das waere eine zweite Liste, die man pflegen
muss und die beim ersten Umbenennen auseinanderlaeuft.
Dabei aufgefallen und mitgefixt: im Forum liegt die Startnachricht im Beitrag
selbst und nicht im Kanal. Der Status-Aktualisierer hat sie vorher im Kanal
gesucht und nicht gefunden — die Begruendung waere im Forum also nie im Post
gelandet. Und der Titel wird jetzt nur um den Stand ergaenzt statt
ueberschrieben, damit "🚗 Fahrzeuge" stehen bleibt.
Geprueft: tagsFuer gegen 20 Faelle — kein Forum, Medien-Kanal, fehlende Tags,
Gross/Kleinschreibung, Deckel bei fuenf (mehr nimmt Discord nicht), und alle
fuenf Staende einzeln. Im Browser die Emoji-Tafel an allen vier Stellen:
Suche, Escape, Klick daneben, Leeren, Uebernehmen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
edf8fa14c5 |
Ideen bekommen Bereiche und einen Thread zum Reden
Nach dem Vorbild von windrose.support: Bereiche zum Einsortieren, Sortierung nach Top / Bewegung / Neu, und eine Zahl daneben, wie viel darueber geredet wird. Der Unterschied zu so einem Dienst ist, wo geredet wird. Zu jedem Wunsch macht der Bot jetzt einen Thread unter dem Post auf. Der Kommentar-Zaehler auf der Roadmap zaehlt die Beitraege darin und verlinkt hinein — es gibt also einen Zaehler wie bei einem Ideen-Board, aber ohne ein zweites Kommentarsystem neben Discord zu stellen. Genau das hatte ich beim letzten Mal als das Falsche bezeichnet, und dabei bleibt es. Eingereicht wird jetzt auch ueber einen Aufruf-Post: /wunsch-setup postet ihn, und mit Bereichen wird daraus ein Auswahlmenue — erst wohin, dann das Formular. Ohne Bereiche bleibt es beim einen Knopf. Derselbe Aufbau wie bei den Ticket-Anliegen, bis hin zur Emoji-Pruefung, die ich mir dort schon geschrieben hatte. Das Anlegen selbst ist nach bot/wishes.js gewandert. /wunsch, der Knopf und die Webseite gehen jetzt denselben Weg — vorher hatte die Webseite ihr eigenes Embed zusammengebaut, das dem aus dem Befehl nur aehnlich sah und keinen Thread bekam. "Bewegung" sind die Stimmen der letzten sieben Tage. Die Rangliste allein zementiert alte Wuensche: was einmal oben steht, bleibt oben, egal ob noch jemand hinschaut. Sortiert wird auf dem Server, weil die Zeitstempel der Stimmen im Browser gar nicht ankommen. Bewusst nicht uebernommen: Gegenstimmen. Windrose hat sie, aber bei einer Community dieser Groesse laden sie zum Nachtreten ein und schrecken vom Einreichen ab — und eine Zahl, die aus zwei Richtungen kommt, sagt am Ende weniger als eine, die nur zaehlt, wer etwas will. Geprueft: Migration erneut durchgespielt (das Schema hat drei Spalten dazubekommen), Routen, SQL gegen das Schema, und im Browser alle drei Filterreihen einzeln und kombiniert, der Sortierwechsel, die Thread-Links und die Bereichs-Pflege im Panel. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
fb61e7279d |
Wuensche bekommen einen Ausgang statt nur einer Punktzahl
Voting hatten wir. Was fehlte, war alles danach: ein Wunsch sammelte zwoelf Stimmen und dann passierte sichtbar nie wieder etwas damit. Genau das nennt der Artikel, der die Idee angestossen hat, "letting the board become a graveyard" — und das war der Zustand. Jeder Wunsch hat jetzt einen Stand: wird geprueft, geplant, in Arbeit, umgesetzt, nicht geplant — mit Begruendung. Die steht oeffentlich unter dem Wunsch auf der Roadmap und wird in den Discord-Post zurueckgeschrieben, wo abgestimmt wurde. Ein abgelehnter Wunsch mit einem Satz Begruendung ist mehr wert als einer, der ewig oben schwebt. Springt ein Wunsch auf "umgesetzt", bekommt jeder eine Direktnachricht, der dafuer gestimmt hat. Das ist der Punkt, an dem unser Aufbau einem fertigen Voting-Dienst ueberlegen ist: der Draht zu jedem Einzelnen ist ohnehin offen. ## Zwei Sachen, die kaputt waren Doppelt abstimmen ging. Der Zuspruch wurde von zwei Wegen hochgezaehlt — 👍 in Discord und der Web-Knopf — und nur der Web-Weg merkte sich, wer geklickt hat. Dieselbe Person zaehlte zweimal. Jetzt wird nicht mehr hochgezaehlt, sondern gezaehlt: eine Zeile je Person, egal woher der Klick kam. Der zusammengesetzte Schluessel schliesst den Fall aus, statt ihn nachtraeglich zu korrigieren. Die Discord-Nachrichten-ID war der Primaerschluessel. Damit konnte ein Wunsch nur existieren, solange seine Nachricht existiert, das Team konnte keinen von Hand eintragen, und zwei Doppler liessen sich nicht zusammenfuehren. Wuensche haben jetzt eine eigene ID; die Nachrichten-ID ist nur noch ein Verweis. Die Migration erhaelt den Zuspruch: was vom alten Punktestand nicht auf gespeicherte Web-Stimmen zurueckgeht, waren Reaktionen ohne Namen — die Zahl bleibt als Sockel stehen, weil rueckwirkend niemand mehr feststellen kann, wer das war. Durchgespielt gegen eine Datenbank im alten Aufbau: Punktestand erhalten, verwaiste Stimmen fallen raus, ein zweiter Start migriert nicht nochmal, und der Fall, in dem der alte Zaehler hinter den echten Stimmen zurueckhing, zaehlt jetzt richtig. ## Dazu Doppler zusammenfuehren: die Stimmen wandern zum Original, wer fuer beide gestimmt hat, zaehlt dort weiterhin einmal. Beim Tippen im Wunsch-Feld zeigt die Seite, was es schon gibt — ein Klick darauf stimmt mit, statt einen zweiten gleichen Wunsch anzulegen. Und die Liste laesst sich nach Stand filtern. Was ich bewusst nicht gebaut habe: Kommentare auf der Webseite. Jeder Wunsch ist schon eine Discord-Nachricht — die Diskussion gehoert in den Thread darunter und nicht in ein zweites System. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
1c5c7d2470 |
Playtester werden jetzt beworben, nicht angeklickt
Der Knopf unter dem Playtester-Aufruf hat jeden aufgenommen, der ihn gedrueckt hat — ohne Frage, ohne Pruefung. Fuer ein Programm, dessen Teilnehmer Zugang und Alpha-Keys bekommen, ist das die falsche Tuer. Statt einen zweiten Pruef-Ablauf danebenzustellen, laeuft die Aufnahme jetzt ueber die Bewerbungs-Formulare, die es laengst gibt: Modal ausfuellen, Review-Embed im Staff-Kanal, ✅ oder ❌, Rolle und Antwort-DM bei Zusage. Das ist dieselbe Maschinerie, nur ein anderer Aufhaenger — und damit auch nur eine Stelle, an der spaeter etwas kaputtgehen kann. Ein Formular laesst sich als Playtester-Formular markieren ("Annahme traegt als Playtester ein"). Wer dort angenommen wird, landet zusaetzlich in der Playtester-Liste, damit die Schluessel-Verteilung ihn kennt. Nur eines kann es sein — sonst wuesste /playtester-setup nicht, welches es posten soll. /playtester-setup postet jetzt den Knopf dieses Formulars. Fehlt das Formular, fehlen Fragen oder fehlt der Review-Kanal, sagt der Befehl das, statt einen Aufruf zu posten, der ins Leere fuehrt. Der alte Knopf in bereits geposteten Nachrichten nimmt niemanden mehr auf: er verweist auf den Aufruf. Austreten bleibt Selbstbedienung — dafuer braucht es keine Freigabe. Im Panel steht im Playtester-Bereich, ueber welches Formular die Aufnahme laeuft, ob es schon gepostet ist, und ein Weg dorthin. Ohne markiertes Formular steht dort, dass gerade niemand hereinkommt — das ist sonst der Grund, warum sich tagelang niemand bewirbt. Geprueft: Routen, SQL gegen das Schema, und im Browser beide Zustaende des Hinweises sowie der neue Schalter — beim Wechsel zwischen zwei Formularen folgt er dem richtigen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
ddd7610d6c |
Playtester bekommen einen eigenen Bereich, Module ziehen um
Playtester und Alpha-Keys standen als zwei Kaesten mitten im Community-Bereich zwischen Geburtstagen und Starboard. Die Liste war reine Anzeige: Namen und Datum, sonst nichts. Wer einem Einzelnen einen Schluessel geben wollte, konnte nur "an alle verteilen" druecken, und wer jemanden wieder rausnehmen wollte, musste an die Datenbank. Jetzt ist es ein eigener Bereich mit drei Zahlen oben und einer Liste, in der neben jedem Namen sein Schluessel steht. Daneben, je nach Zustand, "Schluessel geben" oder "Zurueckziehen", und ein ✕ zum Entfernen — die Rolle geht dabei mit, denn nur aus der Liste zu streichen und die Rolle stehen zu lassen waere eine Halbwahrheit. Der Vorrat ist jetzt sichtbar, nicht nur seine Groesse: einen vertippten Schluessel findet man sonst nie wieder. Nachlegen und "wer bekommt einen?" laufen ueber Dialoge, damit der Bereich nicht zumuellt — dafuer gibt es jetzt eine kleine Dialog-Komponente, gebaut wie die Lightbox (Portal, Escape, Hintergrund festhalten). Zurueckziehen legt den Schluessel zurueck in den Vorrat. Die Person hat ihn per DM natuerlich weiterhin — das ist eine Buchhaltung, keine Sperre. Loeschen geht absichtlich nur bei freien Schluesseln. ## Module dorthin, wo man sie sucht Ein paar Module standen im falschen Bereich, teils seit Langem: - Willkommens-Karte: Support → Brand. Sie ist Aussehen, kein Support-Fall, und im Brand-Bereich steht der Rest vom Auftritt. Der Block ist woertlich umgezogen, nur in eine eigene Konstante — so kann sich beim Umzug nichts am Inhalt geaendert haben. - Twitch & YouTube: System → Feeds. Es ist ein Feed. - Events: System → Community. - Auto-Rolle und Rollen merken: Ihre Felder standen laengst im Rollen-Bereich, nur das Register sagte "Community" — dadurch sprang "Einrichten" woanders hin als die Einstellung liegt. - Playtester und Alpha-Keys: Community → eigener Bereich. Damit ist System kein Sammelbecken mehr, sondern nur noch Technik: Waechter, Sprachkanaele, Erinnerungen, Sicherungen, Member-Gate. Geprueft: Routen (alle vier neuen bewacht), SQL gegen das Schema, und im Browser beide Dialoge (Escape schliesst, Hintergrund wird wieder freigegeben, Hinzufuegen bleibt bei leerem Feld aus), die Liste in allen drei Zustaenden, und die Suche — "willkommen" fuehrt jetzt nach Brand, "twitch" zu Feeds, "sticky" zu Rollen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
bb2aee7818 |
Tickets: Anliegen zur Auswahl, und das Team kann uebernehmen
Bisher sah jedes Ticket gleich aus: ein Knopf, ein Thread, und im Thread stand als Erstes die Frage, worum es ueberhaupt geht. Und wer sich darum kuemmert, stand nirgends — man sah hinterher nur, wer zufaellig auf "Schliessen" geklickt hat. Anliegen sind Kategorien, die man in der Config anlegt: Name, Emoji, eine Zeile Beschreibung, ein Einstiegstext und optional eine Rolle, die beim Oeffnen erfaehrt, dass etwas anliegt. Der Ticket-Post wird dadurch vom Knopf zum Auswahlmenue; das gewaehlte Anliegen steht im Thread-Namen und der Einstiegstext gleich im ersten Beitrag — gute Stelle fuer "was wir wissen muessen". Wer keine anlegt, merkt nichts: ohne Eintrag bleibt es beim einen Knopf. Wer nur eine Sorte Tickets hat, soll nichts einrichten muessen. Uebernehmen ist ein Knopf im Thread, sichtbar fuers Team (wer aufraeumen darf, darf auch uebernehmen). Danach steht im Thread, wer sich kuemmert, und der Knopf wird zu "Freigeben". Die Bedingung "nur wenn noch niemand dran ist" steckt im UPDATE und nicht davor — zwei gleichzeitige Klicks wuerden sonst beide gewinnen. Beim Schliessen landen Anliegen und Bearbeiter im Transcript und im Mod-Log-Eintrag. Die Erstellung ist dabei aus client.js nach tickets.js gewandert. Knopf und Menue gehen jetzt denselben Weg, und in client.js sind drei Importzeilen weggefallen, die nur noch dort standen. Geprueft: alsEmoji gegen 20 Eingaben (Unicode, Hautfarbe, ZWJ-Ketten, Server-Emoji, Murks) und das fertige Panel gegen discord.js selbst — ein ungueltiges Emoji oder ein zu langes Label laesst Discord sonst die ganze Nachricht fallen, und das faellt erst beim Senden auf. Im Browser: Liste, Bearbeiten-Formular und der leere Zustand. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
2292dedeaa |
README auf den heutigen Stand bringen und neu ordnen
Die Funktionsliste war eine einzige Tabelle mit 46 Zeilen — in der Reihenfolge, in der die Sachen entstanden sind, also in keiner. Jetzt ist sie nach denselben Bereichen sortiert wie das Panel: Inhalte, Community, Moderation, Server, dazu Plattform fuer alles, was keine Discord-Funktion ist. Wer im Panel etwas sucht, findet den Abschnitt in der README am selben Platz. Nachgetragen, was seither dazugekommen ist: AutoMod, Raid-Schutz, verknuepfte Rollen, native Umfragen, Statusseite, Herzschlag, Seiten-Editor, Englisch fuer die oeffentlichen Seiten. Und die Trennung in zwei Domains stand bisher gar nicht drin, obwohl sie das Erste ist, was man verstehen muss — sie steht jetzt ganz oben, mit einer Tabelle welche Seite was zeigt. Korrigiert: 35 Module waren es mal, es sind 39. 15 Config-Bereiche waren es mal, es sind 16. Die Seitentabelle fuehrte Hub-Seiten unter der Bot-Domain. Die Projektstruktur kannte die Haelfte der Dateien nicht. In der Ersteinrichtung fehlten die Rechte fuer AutoMod und Kanal-Anlegen sowie die zusaetzlichen OAuth-Redirects. Dazu ein Inhaltsverzeichnis, eine docs/README.md als Wegweiser, und in konzept-zwei-seiten.md steht nicht mehr "muss noch aktiviert werden" — es laeuft seit Ende Juli. Geprueft mit einem kleinen Skript: 11 Markdown-Dateien, keine toten Datei-Links, keine toten Anker, keine Tabelle mit falscher Spaltenzahl. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
c026b2a603 |
Wichtige Funktionen direkt in der Seitenleiste
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> |
||
|
|
c88926aba0 |
Modul-Seiten: alles zu einer Funktion an einem Ort
Bisher war eine Funktion über vier Bereiche verteilt: Schalter unter Module, Kanal unter Support, Texte unter Texte, Werte unter Werte. Wer die Begrüßung ändern wollte, brauchte drei Bereiche. Jetzt öffnet ein Klick auf die Karte die Seite dieser Funktion — mit Schalter, ihren Kanälen und Feldern, ihren Texten, ihren Werten und dem Weg zum passenden Werkzeug. Für „Willkommen" also Kanal, Karte, Farben, Vorschau und beide Texte untereinander. Bewusst keine 35 Einträge in der Seitenleiste: das Modul-Raster ist die Navigation, wie bei MEE6. Die Seitenleiste bleibt so lang wie vorher. Die Seite wird aus den Registern gebaut, nicht von Hand: modules.js kennt die Felder (neu: `fields` für alles jenseits der Pflichtkanäle, `tool` für den Verweis auf einen Editor), templates.js hatte die Zuordnung schon, tuning.js hat sie bekommen. Eine neue Funktion bekommt ihre Seite dadurch geschenkt — es gibt keinen Ort, an dem man sie vergessen könnte. Was ein eigenes Werkzeug hat — Rollen-Menüs, Bewerbungen, Composer, Server-Monitor —, bleibt in seinem Bereich; die Modul-Seite verlinkt nur dorthin. Dort ist mehr Platz, und die Editoren lassen sich nicht sinnvoll aus Registern erzeugen. Texte und Werte bleiben zusätzlich als flache Übersicht: wer alle Texte am Stück durchgehen will, soll dafür nicht 27 Seiten öffnen müssen. Beim Umbau ist mir ein Skript in die Quelldatei gelaufen — der Schreibvorgang scheiterte an einem Emoji und hinterließ modules.js leer. Wiederhergestellt aus dem letzten Commit; die Skripte schreiben jetzt erst in eine Zwischendatei und benennen danach um. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
01fadadcd8 |
Grundgerüst-Assistent: alle fehlenden Kanäle auf einmal
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> |
||
|
|
684573b88c |
Fehlende Kanäle und Rollen aus dem Panel anlegen
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> |
||
|
|
0240225165 |
Config-Suche findet einzelne Einstellungen
Die Seitenleisten-Suche kannte nur Bereiche: „starboard" führte zu Community, aber nicht zum Schwellwert-Feld. Bei rund 60 Einstellungen heißt das raten, in welchem Bereich etwas liegt. setting-index.js hält jetzt fest, wo jede Einstellung wohnt, mit Suchwörtern und Synonymen. Die Suche zeigt Treffer als eigene Gruppe unter den Bereichen; ein Klick wechselt den Bereich, scrollt zum Feld und hebt es kurz hervor. Enter nimmt den ersten Treffer, wobei Einstellungen Vorrang vor Bereichen haben — wer „schwellwert" tippt, will das Feld. Die Felder tragen dafür data-setting="<schlüssel>"; das Attribut wurde skriptgesteuert ergänzt, ohne die Struktur anzufassen. Fünf Einstellungen teilen sich ein Feld mit einer anderen (etwa die beiden Markenfarben) — die zeigen über `target` auf den Nachbarn. Textfelder werden beim Sprung fokussiert, Kanal-Auswahlen bewusst nicht: deren Fokus klappt die Liste auf und verdeckt alles darunter. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
3549b06cef |
/bug und /wunsch als Eingabefenster
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> |
||
|
|
2ce274707a |
Config statt Setup: Bereiche gruppiert, Suche, Status als Einstieg
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> |
||
|
|
dadd75d452 |
Texte: 27 Bot-Nachrichten im Panel bearbeitbar
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> |
||
|
|
59aad27534 |
Modul-System: alle 35 Funktionen im Panel ein- und ausschaltbar
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>
|
||
|
|
e8158ce90b |
Seiten-Editor: Inhalte pflegen ohne Code-Änderung
Antwort auf den CMS-Wunsch aus der Community — statt eines Forums, das neben aktivem Discord erfahrungsgemäß verwaist, ein schlanker Editor für eigene Seiten: Regeln, Über uns, Mitmachen, FAQ. - neuer Setup-Tab "Seiten" (Scope content): Titel, Adress-Kürzel wird aus dem Titel abgeleitet, Markdown-Editor mit Live-Vorschau daneben - pro Seite wählbar: veröffentlicht oder Entwurf, im Community-Menü oder nur per Direktlink, Reihenfolge - Anzeige unter /<kürzel>, gerendert mit dem vorhandenen Markdown-Parser - Entwürfe sind öffentlich nicht abrufbar — sie brauchen den content-Scope - reservierte Kürzel (devlogs, settings, api, impressum …) werden abgelehnt, damit nichts die festen Routen überschreibt Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
b5617a9d18 |
Repo-Backups, Gitea-Theme und Auto-Deploy
- Repo-Backups: nachts um 04:00 werden alle Gitea-Repos als git-Bundle gesichert — eine Datei pro Repo mit kompletter Historie, aus der sich direkt wieder klonen lässt. 14 Tage Rotation wie beim DB-Backup, Schalter und "Repos jetzt sichern" im System-Tab. Nutzt den bereits vorhandenen Gitea-Token; Dockerfile installiert dafür git mit. - Gitea-Theme im D4RKST3R-Look (docs/gitea-theme/): Neon-Gelb/Orange auf Schwarz, gebaut gegen die Variablen von Gitea 1.26, Diff-Farben bleiben lesbar. Einbau-Anleitung liegt daneben. - Auto-Deploy statt manuellem "Pull and redeploy": Workflow für Gitea Actions (prüft Server-Syntax und Frontend-Build, bevor deployed wird) plus dokumentierter Runner-loser Weg über den Portainer-Webhook. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
c73b4e1074 |
Portal-Dienste und geteiltes Design-System für die anderen Apps
- Dienste (Gitea, Kanban, Cloud …) werden im System-Tab gepflegt und erscheinen als Kacheln auf der Startseite; GET /api/services ist öffentlich, Pflege braucht den settings-Scope - /brand.css liefert die Design-Tokens (Farben live aus dem Brand-Tab, ändern sich damit überall mit) plus Basis-Klassen d4rk-card, d4rk-btn, d4rk-title, d4rk-tag - /brand-nav.js baut die D4RKST3R-Leiste in jede fremde App ein, mit Links zum Hub und zu allen gepflegten Diensten; die Links stecken fertig im Skript, dadurch kein zweiter Request und kein CORS nötig - Beide Dateien mit offenem CORS-Header und 5 Minuten Cache - Doku für Anbindung + Schriften in docs/sso.md ergänzt Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
70cae85064 |
Single Sign-On: der Bot als Identity-Provider für die anderen Dienste
Andere Apps (Kanban, Platform …) nutzen ab sofort den Discord-Login des Bots mit, statt jeweils eigenes OAuth zu bauen — und bekommen die Discord-Rollen des Users gleich mitgeliefert. Ablauf: App leitet auf /sso/authorize weiter, der Bot prüft die Session (ggf. erst Discord-Login) und schickt einen signierten Token zurück, den die App serverseitig per POST /sso/verify gegen die Nutzerdaten tauscht. Sicherheit: - Rücksprung-Ziele müssen einem registrierten Präfix entsprechen (kein Open Redirect, kein Token-Abgriff über fremde Hosts) - Token HMAC-signiert, 60 Sekunden gültig, nur einmal einlösbar - Verify braucht das App-Secret (timing-safe verglichen) - SSO bleibt Mitgliedern des Discord-Servers vorbehalten - App-Verwaltung ist Owner-only, Secret wird nur einmal angezeigt Dazu: sso_apps-Tabelle, Verwaltung im API-Tab, Rücksprung nach dem Login (return-Cookie, nur interne Pfade), Anleitung in docs/sso.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
8853bce2ec |
Impressum, Datenschutzerklärung und DSGVO-Löschfunktion
- /impressum (§ 5 DDG) und /datenschutz als öffentliche Seiten im Brand-Look; Betreiber-Angaben (Name, Anschrift, E-Mail, Zusatz) liegen als Settings und sind bewusst Owner-only — Team-Mitglieder mit settings-Scope kommen an die private Anschrift nicht heran - Die Datenschutzerklärung beschreibt die tatsächliche Verarbeitung dieser Instanz: Server-Logs, Session-Cookies (einwilligungsfrei nach § 25 Abs. 2 TDDDG, kein Tracking), Discord-Login, Level, Wünsche, Geburtstage, Playtester/Alpha-Keys, Bewerbungen, Tickets/Modmail, Erinnerungen, Moderation und Audit-Log - DSGVO Art. 17: DELETE /api/profile löscht XP, Geburtstag, Playtester-Eintrag, Abstimmungen, Erinnerungen, Rollen-Sicherung, Giveaway-Teilnahmen und gibt den Alpha-Key wieder frei; Button im Profil unter „Meine Daten", Löschung landet im Audit-Log - Footer verlinkt beide Rechtstexte, neues GET /api/legal (öffentlich) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
aa12dff7ab |
Member-Bereich: Profilseite, Rollen-Selfservice, Web-Voting, Member-Gate
Der Discord-Login ist jetzt für alle Member nützlich: - /profil: Rang + XP-Fortschritt, Discord-Rollen als Chips, Playtester- Badge, eigener Alpha-Key mit Kopier-Button - Rollen-Selfservice: veröffentlichte Rollen-Menüs direkt im Browser togglen (gleiche Exklusiv-Logik wie die Discord-Buttons; nur Rollen aus aktiven Menüs erlaubt) - Wunsch-Voting im Web: auf /roadmap Wünsche einreichen (postet wie /wunsch in den Voting-Kanal) und upvoten (wish_votes-Tabelle, ein Vote pro Member, unabhängig von Discord-👍) - Member-Gate: Login nur für Mitglieder der konfigurierten Guild; Abgewiesene sehen einen Banner mit Discord-Invite-Link (neue Settings member_gate_enabled + discord_invite_url im System-Tab) - Membership-Check mit 5-Minuten-Cache, Owner immer erlaubt Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
f631c0e2ab |
README aktualisiert (Setup-Sektionen, Endpoints, Struktur) + Community-Ankündigungspost
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |