582d68580b0f3e553d5f6ddae4f03d5e75c56360
7
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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> |
||
|
|
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>
|
||
|
|
137452da11 |
Linked Roles: Rollen, die an geprueften Werten haengen
Neues Modul, standardmaessig aus. Ein Mitglied klickt in Discord auf "Rolle holen", landet auf /linked-roles, bestaetigt den OAuth-Dialog — und der Bot schiebt ihm drei Kennzahlen zu, die Discord dann gegen die Rollen-Einstellung prueft: level Zahl >= eingestelltem Wert dabei_seit Datum <= "vor X Tagen", also Mitglied seit mindestens X Tagen playtester Wahrheitswert Der Bot vergibt dabei keine Rollen. Er liefert nur die Zahlen; was daraus wird, entscheidet die Rollen-Einstellung im Server. Die Daten kommen aus dem, was ohnehin da ist: Level-Tabelle, Playtester-Liste, Discords Beitrittsdatum. Eigener OAuth-Weg statt /auth/login, weil die Berechtigungen andere sind — role_connections.write hat der normale Login nicht. Die Tokens werden gespeichert, und das ist keine Bequemlichkeit: ohne Refresh-Token bliebe jede Rolle auf dem Stand des Verknuepfungs-Tages stehen, ein Level-Up kaeme nie an. Discords eigene Anleitung sagt dasselbe. Der Umfang ist eng (nur identify + role_connections.write), beim Widerruf oder Entkoppeln fliegt der Datensatz sofort raus. Steht so auch als Kommentar an der Tabelle. Abgeglichen wird alle 6 Stunden, einstellbar. Dafuer kann everyTuned jetzt auch Stunden — und wirft bei einer unbekannten Einheit, statt den Abstand still um Faktor 60 oder 3600 danebenzulegen. Beim Bauen gefunden: moduleEnabled fehlte im Import von client.js. Der Bot waere beim ClientReady mit ReferenceError gestorben. Geprueft: alle drei Kennzahlen gegen Discords Formatgrenzen (Schluessel-Regex, Laengen, gueltige Typ-Codes), Modul- und Stellwert-Register, die Stunden-Umrechnung (6 h = 21600000 ms), Speichern und Loeschen einer Verknuepfung, dazu 186 SQL-Abfragen und alle Routen auf Rechtepruefung. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
aef708c405 |
Raid-Schutz: erkennt Beitritts-Wellen und sperrt voruebergehend
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> |
||
|
|
de4e812896 |
Werte für mehrere Funktionen, und Anlegen frischt die Auswahl auf
Zwei Nachzügler zu den Modul-Seiten. Die Thread-Archivdauer gilt für Tickets und Modmail, hing aber nur an Tickets — auf der Modmail-Seite fehlte sie also. `module` darf jetzt eine Liste sein; nach außen kommt immer eine, damit niemand zwischen einem und mehreren unterscheiden muss. Und beim Anlegen aus dem Panel wurde nur die Einstellung gesetzt, nicht die Kanalliste nachgeladen. Der frische Kanal stand damit zwar in der Einstellung, fehlte aber in der Auswahl — das Feld sah leer aus, obwohl es gesetzt war. Aufgefallen im Browser-Test: „Einsatzbereit" stand da, die Auswahl daneben war leer. Jetzt holt reloadSettings Kanäle, Rollen und Einstellungen frisch; das gilt für den Einzelknopf, den Assistenten und die Modul-Seiten gleichermaßen. Nachgeprüft: Kanal über die Status-Liste anlegen, dann ohne Neuladen nach Feeds wechseln — dort steht #dev-log. 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> |
||
|
|
197c2a1ada |
Werte: 19 feste Zahlen im Panel einstellbar
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>
|