Fix: Voice claim system - radio stops when soundboard plays

Plugins now claim voice per guild via claimVoice(). When soundboard
plays a sound, radio's cleanup runs automatically (kills ffmpeg,
broadcasts SSE stop event). Fixes stale "now playing" UI on tab switch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Daniel 2026-03-06 10:21:11 +01:00
parent e0635b30ef
commit 1e4ccfb1f1
3 changed files with 30 additions and 0 deletions

View file

@ -16,6 +16,7 @@ import sodium from 'libsodium-wrappers';
import nacl from 'tweetnacl';
import { ChannelType, Events, type VoiceState, type Message } from 'discord.js';
import type { Plugin, PluginContext } from '../../core/plugin.js';
import { claimVoice } from '../../core/plugin.js';
import { sseBroadcast } from '../../core/sse.js';
// ── Config (env) ──
@ -332,6 +333,8 @@ let _pluginCtx: PluginContext | null = null;
async function playFilePath(guildId: string, channelId: string, filePath: string, volume?: number, relativeKey?: string): Promise<void> {
console.log(`${SB} playFilePath: guild=${guildId} channel=${channelId} file=${path.basename(filePath)} vol=${volume ?? 'default'}`);
// Claim voice for this guild (stops radio if playing)
claimVoice(guildId, 'soundboard', () => { /* soundboard cleanup handled by lifecycle */ });
const ctx = _pluginCtx!;
const guild = ctx.client.guilds.cache.get(guildId);
if (!guild) { console.error(`${SB} Guild ${guildId} not found in cache (cached: ${ctx.client.guilds.cache.map(g => g.id).join(', ')})`); throw new Error('Guild nicht gefunden'); }