From 684573b88c7aece22b9130b280e0d006fe42ab8a Mon Sep 17 00:00:00 2001 From: D4rkst3r Date: Fri, 31 Jul 2026 18:29:54 +0200 Subject: [PATCH] =?UTF-8?q?Fehlende=20Kan=C3=A4le=20und=20Rollen=20aus=20d?= =?UTF-8?q?em=20Panel=20anlegen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- README.md | 13 ++++- frontend/src/pages/Settings.jsx | 39 +++++++++++++- frontend/src/style.css | 5 ++ src/bot/server-setup.js | 90 +++++++++++++++++++++++++++++++++ src/modules.js | 52 ++++++++++++------- src/web/api.js | 21 ++++++++ 6 files changed, 197 insertions(+), 23 deletions(-) create mode 100644 src/bot/server-setup.js diff --git a/README.md b/README.md index e51b81c..946d684 100644 --- a/README.md +++ b/README.md @@ -140,8 +140,17 @@ Der aktive Bereich steht in der Adresse (`/settings#texte`), Links und Neuladen landen also wieder dort. Der Status-Bereich ist der Einstieg: Kennzahlen plus **„Noch einzurichten"** — -alle eingeschalteten Module, denen noch ein Kanal oder eine Rolle fehlt, mit -Sprung direkt zur richtigen Stelle. +alle eingeschalteten Module, denen noch ein Kanal oder eine Rolle fehlt. Daneben +steht **„Kanal anlegen"** bzw. **„Rolle anlegen"**: der Bot legt sie in Discord +an, setzt bei privaten Kanälen die Rechte (nur Team sieht sie) und trägt die +Einstellung gleich ein. Gibt es Kanal oder Rolle schon, werden sie verknüpft +statt doppelt angelegt. + +Dafür braucht der Bot *Kanäle verwalten* bzw. *Rollen verwalten* — fehlt das +Recht, sagt das Panel genau das. Die Vorlagen (Name, Thema, privat/öffentlich) +stehen bei den Modulen in [`src/modules.js`](src/modules.js). Gelöscht oder +umbenannt wird bewusst nichts: ein Fehlklick beim Anlegen kostet einen +überflüssigen Kanal, einer beim Löschen dessen Verlauf. Team-Mitglieder sehen nur die Bereiche ihrer Rechte. Alles zur Laufzeit änderbar — gespeichert in SQLite, Env-Variablen sind nur Fallback, kein Redeploy nötig: diff --git a/frontend/src/pages/Settings.jsx b/frontend/src/pages/Settings.jsx index 18010c4..efa4545 100644 --- a/frontend/src/pages/Settings.jsx +++ b/frontend/src/pages/Settings.jsx @@ -304,6 +304,7 @@ export default function Settings({ me }) { const [modules, setModules] = useState([]); const [moduleGroups, setModuleGroups] = useState([]); const [modFilter, setModFilter] = useState('alle'); + const [creating, setCreating] = useState(null); // Einstellung, die gerade angelegt wird // Text-Vorlagen (was der Bot nach außen schreibt) const [templates, setTemplates] = useState([]); const [templateGroups, setTemplateGroups] = useState([]); @@ -501,6 +502,26 @@ export default function Settings({ me }) { } } + /** Fehlenden Kanal / fehlende Rolle vom Bot anlegen lassen */ + async function createMissing(entry) { + setCreating(entry.setting); + try { + const res = await apiPost('/api/setup/create', { setting: entry.setting }); + setModules(res.modules); + // Die neue Auswahl steht sofort im Formular — und zählt nicht als + // ungespeicherte Änderung, weil der Vergleichsstand mitwandert. + setForm(res.settings); + setData((d) => (d ? { ...d, settings: res.settings } : d)); + flash(res.wiederverwendet + ? `✓ Vorhandenen ${res.art === 'rolle' ? 'Rolle' : 'Kanal'} „${res.name}" verknüpft` + : `✓ ${res.art === 'rolle' ? 'Rolle' : 'Kanal'} „${res.name}" angelegt`); + } catch (error) { + flash(`✗ ${error.body?.error ?? 'Anlegen fehlgeschlagen'}`); + } finally { + setCreating(null); + } + } + /** Alle geänderten Stellwerte auf einmal speichern */ async function saveTuning() { const changed = Object.fromEntries( @@ -1023,8 +1044,22 @@ export default function Settings({ me }) {
{m.name} - {m.missing.join(', ')} + {m.missing.map((x) => x.label).join(', ')} + {/* Was der Bot selbst anlegen kann, bekommt einen Knopf dafür */} + {m.missing.filter((x) => x.create).map((x) => ( + + ))} {m.tab && (