Modul-Felder speichern wieder, und die Feed-Adresse ist einstellbar
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled

Die LS-Kanaele liessen sich im Panel waehlen und waren nach dem Speichern
wieder leer. Der Grund: PUT /api/settings fuehrt fuer jede Feldart eine von
Hand gepflegte Liste erlaubter Schluessel, und ein Schluessel, der nirgends
steht, faellt still durch. Keine Fehlermeldung, kein Log — das Feld sieht
funktionsfaehig aus und vergisst.

Das ist keine Einzelheit, sondern eine Falle fuer jedes kuenftige Modul: wer
eins ergaenzt und diese Listen nicht mitpflegt, baut denselben Fehler nach.
Die Modulliste weiss laengst, welche Felder es gibt und welcher Art sie sind —
also holt der Handler sie jetzt von dort, statt sie ein zweites Mal
aufzuzaehlen.

Beim Bauen des Helfers ware ich fast in die naechste Falle gelaufen: ich hatte
alle requires-Eintraege als Kanaele eingestuft. Dort stehen aber auch
gitea_api_token und watchdog_urls, und die haetten dann die Kanal-Pruefung
durchlaufen — Speichern waere mit "Kanal nicht gefunden" gescheitert, sobald
jemand seinen Gitea-Token aendert. Uebernommen wird jetzt nur, was der
Namenskonvention folgt.

Dazu die fest verdrahtete Feed-Adresse. http://host:port/feed war eine Wette
auf drei Annahmen gleichzeitig: dass jeder Hoster http nimmt, den Feed unter
/feed ablegt und keinen Pfad davorsetzt. Aendern konnte das niemand. Jetzt gibt
es ein Feld dafuer, und wer die ganze Abfrage-URL ins Host-Feld einfuegt,
bekommt es mitsamt Schema und Pfad automatisch ausgefuellt. Was dahinter kommt
(dedicated-server-stats.xml und Geschwister) gibt Giants vor und bleibt im
Code.

Geprueft: jedes Feld jedes Moduls landet in einem Eimer — der Test faellt
kuenftig aus, sobald jemand ein Feld ergaenzt, das nicht speicherbar waere.
Dazu, dass nichts faelschlich in die Kanal- oder Rollenpruefung geraet, keine
Dubletten, und die Feed-Basis mit eigenem Pfad, https, ueberzaehligen
Schraegstrichen sowie sechs Sorten Unbrauchbarem. Das Einfuegen einer
https-URL mit Pfad im laufenden Panel angesehen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-09 02:13:32 +02:00
co-authored by Claude Opus 5
parent 768fcda666
commit c5e13182c0
4 changed files with 86 additions and 8 deletions
+20 -5
View File
@@ -29,7 +29,7 @@ import {
savePage, getPage, listPages, listPublishedPages, deletePage,
} from '../db.js';
import crypto from 'node:crypto';
import { moduleStates, moduleDetail, setModuleEnabled, moduleEnabled, moduleFavorites, setModuleFavorites, MODULE_GROUPS, MODULES, MAX_FAVORITES } from '../modules.js';
import { moduleStates, moduleDetail, setModuleEnabled, moduleEnabled, moduleFavorites, setModuleFavorites, moduleSettingKeys, MODULE_GROUPS, MODULES, MAX_FAVORITES } from '../modules.js';
import { templateStates, setTemplate, TEMPLATE_GROUPS } from '../templates.js';
import { tuningStates, setTuning, tuning, TUNING_GROUPS } from '../tuning.js';
import { lastResults, GAME_ICONS, spielName, spielListe } from '../bot/server-monitor.js';
@@ -1005,14 +1005,20 @@ ${rssItems}
]) delete body[key];
}
// Was ein Modul an Feldern mitbringt, ist im Register beschrieben —
// von dort geholt statt hier nochmal aufgezählt. Ein Feld, das im
// Panel steht, aber nicht in dieser Datei, verfiel sonst stumm.
const ausRegister = moduleSettingKeys();
// Kanäle: müssen existierende Textkanäle sein (optionale dürfen leer sein = aus)
const OPTIONAL_CHANNELS = [
const OPTIONAL_CHANNELS = [...new Set([
'release_channel_id', 'backup_channel_id', 'starboard_channel_id',
'screenshot_channel_id', 'modmail_channel_id', 'welcome_channel_id',
'modlog_channel_id', 'status_channel_id', 'voting_channel_id', 'ticket_channel_id',
'events_announce_channel_id', 'social_announce_channel_id', 'server_alert_channel_id',
'birthday_channel_id',
];
...ausRegister.kanal,
])];
// Auch Devlog- und Commit-Kanal dürfen leer sein: leer heißt „noch nicht
// eingerichtet", und der Bot kommt damit klar. Vorher scheiterte das
// Speichern JEDER Einstellung, solange einer der beiden nicht gesetzt war
@@ -1038,7 +1044,10 @@ ${rssItems}
setSetting(key, value);
}
// Rollen: müssen existieren ('' = Feature aus)
for (const key of ['devlog_ping_role_id', 'playtester_role_id', 'autorole_id', 'birthday_role_id']) {
for (const key of [...new Set([
'devlog_ping_role_id', 'playtester_role_id', 'autorole_id', 'birthday_role_id',
...ausRegister.rolle,
])]) {
if (body[key] === undefined) continue;
const value = String(body[key] ?? ''); // null = keine Rolle, siehe oben
if (unchanged(key, value)) continue; // unverändert → nicht prüfen
@@ -1195,7 +1204,13 @@ ${rssItems}
setSetting(key, String(body[key]).trim());
}
}
for (const key of ['commit_branch_filter', 'ignored_repos', 'bug_report_repo', 'watchdog_urls', 'roadmap_repo']) {
// Freitext-Felder. Die Modul-Felder kommen aus dem Register dazu, sonst
// muss jedes neue Modul auch hier eingetragen werden — und wer das
// vergisst, merkt es erst, wenn das Feld beim Speichern verschwindet.
for (const key of [...new Set([
'commit_branch_filter', 'ignored_repos', 'bug_report_repo', 'watchdog_urls', 'roadmap_repo',
...ausRegister.text,
])]) {
if (body[key] !== undefined) {
setSetting(key, String(body[key]).trim());
}