const { Client, GatewayIntentBits } = require('discord.js'); require('dotenv').config(); const commands = require('./commands/definitions'); const { registerCommands } = require('./utils/commandRegistry'); const { handlePlay } = require('./handlers/playCommand'); const { handlePause, handleResume, handleSkip, handleClear, handleLoop, handleQuit } = require('./handlers/controlCommands'); const { handleQueue } = require('./handlers/queueCommand'); const { handleVolume } = require('./handlers/volumeCommand'); const { handleSeek } = require('./handlers/seekCommand'); const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates, ], }); const queues = new Map(); client.once('ready', async () => { console.log(`Bot ready: ${client.user.tag}`); console.log(`Ready at: ${new Date().toISOString()}`); await registerCommands(commands, process.env.DISCORD_TOKEN, process.env.CLIENT_ID); setInterval(() => { const activeQueues = queues.size; console.log(`[HEARTBEAT] ${new Date().toISOString()} - Active queues: ${activeQueues}`); }, 5 * 60 * 1000); }); function handleError(error, context = 'Unknown') { const timestamp = new Date().toISOString(); console.error(`[ERROR] ${timestamp} - Context: ${context}`); console.error(error); if (error.stack) { console.error('Stack trace:', error.stack); } } async function handleInteractionError(interaction, error, commandName) { handleError(error, `Command: ${commandName}`); try { const reply = interaction.deferred || interaction.replied ? 'editReply' : 'reply'; await interaction[reply]({ content: 'An error occurred while executing this command!', ephemeral: true }).catch(() => {}); } catch (replyError) { console.error('Failed to send error message to user:', replyError); } } client.on('interactionCreate', async (interaction) => { if (!interaction.isChatInputCommand()) return; try { switch (interaction.commandName) { case 'play': await handlePlay(interaction, queues); break; case 'pause': handlePause(interaction, queues); break; case 'resume': handleResume(interaction, queues); break; case 'skip': handleSkip(interaction, queues); break; case 'clear': handleClear(interaction, queues); break; case 'loop': handleLoop(interaction, queues); break; case 'quit': handleQuit(interaction, queues); break; case 'queue': handleQueue(interaction, queues); break; case 'volume': handleVolume(interaction, queues); break; case 'seek': handleSeek(interaction, queues); break; } } catch (error) { await handleInteractionError(interaction, error, interaction.commandName); } }); process.on('unhandledRejection', (error) => { handleError(error, 'Unhandled Promise Rejection'); }); process.on('uncaughtException', (error) => { handleError(error, 'Uncaught Exception'); }); client.on('error', (error) => { handleError(error, 'Discord Client Error'); }); client.on('warn', (info) => { console.warn(`[WARN] ${new Date().toISOString()} - ${info}`); }); client.login(process.env.DISCORD_TOKEN);