diff --git a/api/src/routes/channels.js b/api/src/routes/channels.js index f28fcac..52596f3 100644 --- a/api/src/routes/channels.js +++ b/api/src/routes/channels.js @@ -36,4 +36,23 @@ router.post('/join', async (req, res) => { } }); +// Disconnect from voice channel +router.post('/disconnect', async (req, res) => { + try { + const response = await fetch(`${req.app.locals.botUrl}/disconnect`, { + method: 'POST' + }); + const result = await response.json(); + + if (response.ok) { + req.app.locals.broadcast('channelChange', { disconnected: true }); + } + + res.status(response.status).json(result); + } catch (error) { + req.app.locals.logger.error(`Error disconnecting: ${error.message}`); + res.status(500).json({ error: 'Failed to disconnect' }); + } +}); + export default router; diff --git a/bot/src/index.js b/bot/src/index.js index 8460ab0..3602e4b 100644 --- a/bot/src/index.js +++ b/bot/src/index.js @@ -503,6 +503,31 @@ app.post('/join', async (req, res) => { } }); +app.post('/disconnect', async (req, res) => { + try { + if (connection) { + connection.destroy(); + connection = null; + + // Pause playback when disconnecting + if (currentState.state === 'playing') { + currentState.state = 'paused'; + if (player) { + player.pause(); + } + } + + logger.info('Disconnected from voice channel'); + res.json({ success: true, message: 'Disconnected from voice channel' }); + } else { + res.json({ success: true, message: 'Already disconnected' }); + } + } catch (error) { + logger.error(`Failed to disconnect: ${error.message}`); + res.status(500).json({ error: 'Failed to disconnect' }); + } +}); + app.listen(INTERNAL_PORT, () => { logger.info(`Internal API listening on port ${INTERNAL_PORT}`); }); diff --git a/web/src/App.jsx b/web/src/App.jsx index 139fc6d..42838ea 100644 --- a/web/src/App.jsx +++ b/web/src/App.jsx @@ -4,6 +4,7 @@ import Controls from './components/Controls'; import TrackList from './components/TrackList'; import UploadZone from './components/UploadZone'; import ChannelSelector from './components/ChannelSelector'; +import ConnectionStatus from './components/ConnectionStatus'; import useWebSocket from './hooks/useWebSocket'; const API_URL = import.meta.env.VITE_API_URL || '/api'; @@ -131,10 +132,13 @@ function App() {
-

10node christmas bot

-

+

+

10node christmas bot

+ +
+

- {connected ? 'Connected' : 'Disconnected'} + WebSocket: {connected ? 'Connected' : 'Disconnected'}