const { createAudioPlayer, createAudioResource, AudioPlayerStatus, joinVoiceChannel } = require('@discordjs/voice'); const fs = require('fs'); const queueMap = new Map(); const playerMap = new Map(); const currentTrackMap = new Map(); const repeatMap = new Map(); function addToQueue(guildId, filePath, title) { if (!queueMap.has(guildId)) { queueMap.set(guildId, []); } queueMap.get(guildId).push({ filePath, title }); } function getQueue(guildId) { return queueMap.get(guildId) || []; } function getCurrentTrack(guildId) { return currentTrackMap.get(guildId) || null; } function toggleRepeat(guildId) { const currentRepeat = repeatMap.get(guildId) || false; repeatMap.set(guildId, !currentRepeat); return !currentRepeat; } function playNextInQueue(guildId, voiceChannel) { const queue = getQueue(guildId); const currentTrack = getCurrentTrack(guildId); const repeat = repeatMap.get(guildId); if (currentTrack && !repeat) { return false; } let trackToPlay = currentTrack; if (!trackToPlay) { if (queue.length > 0) { trackToPlay = queue.shift(); currentTrackMap.set(guildId, trackToPlay); } else if (repeat && currentTrack) { trackToPlay = currentTrack; } else { const connection = playerMap.get(guildId)?._state?.subscription?.connection; if (connection && connection.state.status !== 'destroyed') { connection.destroy(); } return false; } } playTrack(guildId, voiceChannel, trackToPlay); } function playTrack(guildId, voiceChannel, track) { const connection = joinVoiceChannel({ channelId: voiceChannel.id, guildId: guildId, adapterCreator: voiceChannel.guild.voiceAdapterCreator, }); const audioPlayer = playerMap.get(guildId) || createAudioPlayer(); playerMap.set(guildId, audioPlayer); if (!fs.existsSync(track.filePath)) { console.error('Audio file not found:', track.filePath); return false; } const resource = createAudioResource(track.filePath); audioPlayer.play(resource); connection.subscribe(audioPlayer); audioPlayer.on(AudioPlayerStatus.Idle, () => { if (!repeatMap.get(guildId)) { currentTrackMap.delete(guildId); fs.unlink(track.filePath, (err) => { if (err) console.error('Error deleting file:', track.filePath, err); }); } const queue = getQueue(guildId); if (queue.length > 0 || repeatMap.get(guildId)) { playNextInQueue(guildId, voiceChannel); } else { if (connection && connection.state.status !== 'destroyed') { connection.destroy(); } } }); audioPlayer.on('error', (err) => { console.error('AudioPlayer error:', err); currentTrackMap.delete(guildId); if (connection && connection.state.status !== 'destroyed') { connection.destroy(); } }); } function skipTrack(guildId, voiceChannel) { const player = playerMap.get(guildId); const queue = getQueue(guildId); if (!player) { console.error('No player found for this guild.'); return; } currentTrackMap.delete(guildId); player.stop(); if (queue.length > 0) { playNextInQueue(guildId, voiceChannel); } else { const connection = playerMap.get(guildId)?._state?.subscription?.connection; if (connection && connection.state.status !== 'destroyed') { connection.destroy(); } } } function clearQueue(guildId) { queueMap.set(guildId, []); } module.exports = { addToQueue, getQueue, getCurrentTrack, playNextInQueue, skipTrack, toggleRepeat, clearQueue };