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>
This commit is contained in:
2026-07-31 15:53:44 +02:00
co-authored by Claude Fable 5
parent bdbd35883c
commit 59aad27534
16 changed files with 451 additions and 1 deletions
+20
View File
@@ -20,6 +20,7 @@ import {
savePage, getPage, listPages, listPublishedPages, deletePage,
} from '../db.js';
import crypto from 'node:crypto';
import { moduleStates, setModuleEnabled, MODULE_GROUPS } from '../modules.js';
import { lastResults, GAME_ICONS } from '../bot/server-monitor.js';
import { publishAppForm, unpublishAppForm, MAX_QUESTIONS } from '../bot/app-forms.js';
import { sanitizeEmbed } from './api-v1.js';
@@ -164,6 +165,25 @@ export function registerApiRoutes(app, client) {
}),
}));
// --- Module: zentrale An/Aus-Schalter aller Funktionen ---
app.get('/api/modules', async (request, reply) => {
if (requireAnyScope(request, reply)) return;
return { modules: moduleStates(), groups: MODULE_GROUPS };
});
app.put('/api/modules/:id', async (request, reply) => {
if (requireScope(request, reply, 'settings')) return;
const id = String(request.params.id);
const on = Boolean(request.body?.enabled);
if (!setModuleEnabled(id, on)) {
return reply.code(404).send({ error: 'Modul unbekannt' });
}
logAudit(getSessionUser(request), on ? 'modul aktiviert' : 'modul deaktiviert', id);
request.log.info(`Modul ${id}${on ? 'an' : 'aus'}`);
return { ok: true, modules: moduleStates() };
});
// --- Frei angelegte Seiten (Regeln, Über uns, …) ---
// Adressen, die schon vom Frontend oder Server belegt sind
+2
View File
@@ -4,6 +4,7 @@
import { EmbedBuilder } from 'discord.js';
import { dueScheduledPosts, markScheduledRun } from '../db.js';
import { brandColor, brandName } from '../runtime-settings.js';
import { moduleEnabled } from '../modules.js';
const CHECK_INTERVAL_MS = 60 * 1000;
@@ -61,6 +62,7 @@ export function buildScheduledPayload(post) {
/** Fällige Posts senden — exportiert für Tests und den Timer */
export async function scheduledPostsTick(client) {
if (!moduleEnabled('scheduled_posts')) return;
for (const post of dueScheduledPosts()) {
try {
const channel = await client.channels.fetch(post.channel_id).catch(() => null);