feat: Radio Plugin – 3D Globe mit weltweiten Radiosendern

- Radio Garden API Client (30K+ Orte, Sender-Suche, Stream-URL Auflösung)
- Discord Voice Streaming via ffmpeg (PCM Pipeline)
- Interactive 3D Globe (globe.gl) mit allen Radiosender-Standorten
- Sender-Panel mit Play/Stop/Favoriten
- Live-Suche nach Sendern und Städten
- Now-Playing Bar mit Equalizer-Animation
- Guild/Voice-Channel Auswahl
- SSE Broadcasting für Live-Updates
- Favoriten-System mit Persistenz
- Responsive Design (Mobile/Tablet/Desktop)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Daniel 2026-03-05 23:23:52 +01:00
parent ae1c41f0ae
commit 847c963d86
7 changed files with 1487 additions and 9 deletions

View file

@ -4,6 +4,7 @@ import client from './core/discord.js';
import { addSSEClient, removeSSEClient, sseBroadcast, getSSEClientCount } from './core/sse.js';
import { loadState, getFullState } from './core/persistence.js';
import { getPlugins, registerPlugin, PluginContext } from './core/plugin.js';
import radioPlugin from './plugins/radio/index.js';
// ── Config ──
const PORT = Number(process.env.PORT ?? 8080);
@ -68,10 +69,7 @@ app.get('/api/plugins', (_req, res) => {
})));
});
// ── SPA Fallback ──
app.get('*', (_req, res) => {
res.sendFile(path.join(import.meta.dirname ?? __dirname, '..', '..', 'web', 'dist', 'index.html'));
});
// NOTE: SPA fallback is added in boot() AFTER plugin routes
// ── Discord Ready ──
client.once('ready', async () => {
@ -87,8 +85,8 @@ client.once('ready', async () => {
// ── Init Plugins ──
async function boot(): Promise<void> {
// --- Load plugins dynamically here ---
// Example: import('./plugins/soundboard/index.js').then(m => registerPlugin(m.default));
// ── Register plugins ──
registerPlugin(radioPlugin);
// Init all plugins
for (const p of getPlugins()) {
@ -101,6 +99,11 @@ async function boot(): Promise<void> {
}
}
// SPA Fallback (MUST be after plugin routes)
app.get('*', (_req, res) => {
res.sendFile(path.join(import.meta.dirname ?? __dirname, '..', '..', 'web', 'dist', 'index.html'));
});
// Start Express
app.listen(PORT, () => console.log(`[HTTP] Listening on :${PORT}`));