// Einstiegspunkt — startet Discord-Bot, Webserver und den Wochen-Rückblick-Scheduler import { startBot } from './bot/client.js'; import { startWebServer } from './web/server.js'; import { scheduleWeeklyRecap } from './bot/weekly-recap.js'; import { startWatchdog } from './bot/watchdog.js'; import { scheduleBackups } from './backup.js'; import { startServerMonitor } from './bot/server-monitor.js'; import { startLsFarm } from './bot/ls-farm.js'; import { startRadio, radioBeenden } from './bot/radio.js'; import { startMusik } from './bot/radio-musik.js'; import { startGiveaways } from './bot/giveaways.js'; import { startScheduledPosts } from './web/scheduled-posts.js'; import { startSocialNotify } from './bot/social-notify.js'; import { startBirthdays } from './bot/birthdays.js'; import { scheduleRepoBackups } from './repo-backup.js'; process.on('unhandledRejection', (error) => { console.error('[main] Unhandled Rejection:', error); }); let client = null; let app = null; /** * Geordnet herunterfahren. * * Ohne das räumt `docker stop` den Prozess nach der Schonfrist einfach ab. * Zwei Dinge geben dann falsche Auskunft: der Bot steht in Discord noch eine * Weile als online, und die Statuszeile am Sprachkanal behauptet weiter, es * liefe Musik. Beides überlebt den Container, der es geschrieben hat. * * Reihenfolge ist wichtig: erst das Radio, denn zum Abräumen der Statuszeile * braucht es die Verbindung zu Discord noch. */ let laeuftAus = false; async function beenden(signal) { if (laeuftAus) return; // zweites SIGTERM nicht doppelt abarbeiten laeuftAus = true; console.log(`[main] ${signal} — fahre herunter`); // Docker wartet vorgabemässig zehn Sekunden und schiesst dann. Lieber // vorher selbst aufhören, als mitten im Aufräumen abgeschossen zu werden. const frist = setTimeout(() => { console.error('[main] Herunterfahren dauert zu lange — breche ab'); process.exit(1); }, 8000); frist.unref?.(); for (const [was, tun] of [ ['Radio', () => radioBeenden()], ['Webserver', () => app?.close()], ['Discord', () => client?.destroy()], ]) { try { await tun(); } catch (error) { // Ein Fehler beim Aufräumen darf das restliche Aufräumen nicht // verhindern — sonst bleibt wegen der Statuszeile der Bot online. console.error(`[main] ${was} beim Herunterfahren:`, error.message); } } clearTimeout(frist); console.log('[main] beendet'); process.exit(0); } process.on('SIGTERM', () => beenden('SIGTERM')); process.on('SIGINT', () => beenden('SIGINT')); try { client = await startBot(); app = await startWebServer(client); scheduleWeeklyRecap(client); startWatchdog(client); scheduleBackups(client); startServerMonitor(client); startLsFarm(client); startRadio(client); startMusik(); startGiveaways(client); startScheduledPosts(client); startSocialNotify(client); startBirthdays(client); scheduleRepoBackups(); } catch (error) { console.error('[main] Start fehlgeschlagen:', error); process.exit(1); }