DZ-Musicbot/utils/queueManager.js

177 lines
5.1 KiB
JavaScript
Raw Normal View History

2024-08-17 19:30:48 -04:00
const { createAudioPlayer, createAudioResource, AudioPlayerStatus, joinVoiceChannel, VoiceConnectionStatus } = require('@discordjs/voice');
2024-08-17 11:11:10 -04:00
const fs = require('fs');
const queueMap = new Map();
const playerMap = new Map();
2024-08-17 11:23:30 -04:00
const currentTrackMap = new Map();
2024-08-17 14:58:17 -04:00
const repeatMap = new Map();
2024-08-17 16:53:07 -04:00
const voiceChannelMap = new Map();
2024-08-17 11:11:10 -04:00
function addToQueue(guildId, filePath, title, voiceChannel, url, requester, avatarURL) {
2024-08-17 11:11:10 -04:00
if (!queueMap.has(guildId)) {
queueMap.set(guildId, []);
}
queueMap.get(guildId).push({ filePath, title, url, requester, avatarURL });
2024-08-17 16:53:07 -04:00
if (voiceChannel) {
voiceChannelMap.set(guildId, voiceChannel);
}
const audioPlayer = playerMap.get(guildId);
if (!audioPlayer || audioPlayer.state.status !== AudioPlayerStatus.Playing) {
playNextInQueue(guildId);
}
2024-08-17 11:11:10 -04:00
}
2024-08-17 18:05:36 -04:00
function removeFromQueue(guildId, index) {
const queue = getQueue(guildId);
if (index >= 0 && index < queue.length) {
return queue.splice(index, 1)[0];
}
return null;
}
2024-08-17 11:11:10 -04:00
function getQueue(guildId) {
return queueMap.get(guildId) || [];
}
2024-08-17 18:08:42 -04:00
function getPlayer(guildId) {
return playerMap.get(guildId);
}
function getCurrentTrack(guildId) {
return currentTrackMap.get(guildId) || null;
}
2024-08-17 14:58:17 -04:00
function toggleRepeat(guildId) {
const currentRepeat = repeatMap.get(guildId) || false;
repeatMap.set(guildId, !currentRepeat);
return !currentRepeat;
}
2024-08-17 16:53:07 -04:00
function playNextInQueue(guildId) {
2024-08-17 11:11:10 -04:00
const queue = getQueue(guildId);
const currentTrack = getCurrentTrack(guildId);
2024-08-17 15:09:26 -04:00
const repeat = repeatMap.get(guildId);
2024-08-17 16:53:07 -04:00
const voiceChannel = voiceChannelMap.get(guildId);
if (!voiceChannel) {
console.error("Voice channel is undefined. Cannot play track.");
return false;
}
2024-08-17 15:09:26 -04:00
if (currentTrack && !repeat) {
return false;
2024-08-17 15:09:26 -04:00
}
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;
2024-08-17 15:09:26 -04:00
}
2024-08-17 14:58:17 -04:00
}
2024-08-17 11:11:10 -04:00
playTrack(guildId, voiceChannel, trackToPlay);
2024-08-17 15:09:26 -04:00
}
2024-08-17 15:09:26 -04:00
function playTrack(guildId, voiceChannel, track) {
2024-08-17 19:30:48 -04:00
let connection = joinVoiceChannel({
2024-08-17 11:11:10 -04:00
channelId: voiceChannel.id,
guildId: guildId,
adapterCreator: voiceChannel.guild.voiceAdapterCreator,
});
2024-08-17 19:30:48 -04:00
connection.on(VoiceConnectionStatus.Disconnected, async (oldState, newState) => {
try {
await Promise.race([
entersState(connection, VoiceConnectionStatus.Signalling, 5_000),
entersState(connection, VoiceConnectionStatus.Connecting, 5_000),
]);
} catch (error) {
connection.destroy();
currentTrackMap.delete(guildId);
queueMap.delete(guildId);
}
});
2024-08-17 11:11:10 -04:00
2024-08-17 14:58:17 -04:00
const audioPlayer = playerMap.get(guildId) || createAudioPlayer();
playerMap.set(guildId, audioPlayer);
2024-08-17 11:11:10 -04:00
2024-08-17 15:09:26 -04:00
if (!fs.existsSync(track.filePath)) {
console.error('Audio file not found:', track.filePath);
2024-08-17 11:11:10 -04:00
return false;
}
2024-08-17 15:09:26 -04:00
const resource = createAudioResource(track.filePath);
2024-08-17 11:11:10 -04:00
audioPlayer.play(resource);
connection.subscribe(audioPlayer);
currentTrackMap.set(guildId, { ...track, resource });
2024-08-17 11:11:10 -04:00
audioPlayer.on(AudioPlayerStatus.Idle, () => {
2024-08-17 15:09:26 -04:00
if (!repeatMap.get(guildId)) {
currentTrackMap.delete(guildId);
fs.unlink(track.filePath, (err) => {
if (err) console.error('Error deleting file:', track.filePath, err);
});
}
2024-08-17 14:58:17 -04:00
2024-08-17 15:09:26 -04:00
const queue = getQueue(guildId);
if (queue.length > 0 || repeatMap.get(guildId)) {
2024-08-17 16:53:07 -04:00
playNextInQueue(guildId);
2024-08-17 11:11:10 -04:00
} else {
2024-08-17 15:09:26 -04:00
if (connection && connection.state.status !== 'destroyed') {
connection.destroy();
}
2024-08-17 11:11:10 -04:00
}
});
audioPlayer.on('error', (err) => {
console.error('AudioPlayer error:', err);
currentTrackMap.delete(guildId);
2024-08-17 15:09:26 -04:00
if (connection && connection.state.status !== 'destroyed') {
connection.destroy();
}
2024-08-17 11:11:10 -04:00
});
}
2024-08-17 16:53:07 -04:00
function skipTrack(guildId) {
const player = playerMap.get(guildId);
2024-08-17 11:11:10 -04:00
const queue = getQueue(guildId);
2024-08-17 14:58:17 -04:00
if (!player) {
console.error('No player found for this guild.');
return;
}
2024-08-17 14:58:17 -04:00
currentTrackMap.delete(guildId);
player.stop();
if (queue.length > 0) {
2024-08-17 16:53:07 -04:00
playNextInQueue(guildId);
} else {
2024-08-17 15:09:26 -04:00
const connection = playerMap.get(guildId)?._state?.subscription?.connection;
if (connection && connection.state.status !== 'destroyed') {
connection.destroy();
}
2024-08-17 11:11:10 -04:00
}
}
function clearQueue(guildId) {
queueMap.set(guildId, []);
}
2024-08-17 18:08:42 -04:00
module.exports = { addToQueue, getQueue, getCurrentTrack, playNextInQueue, skipTrack, toggleRepeat, clearQueue, removeFromQueue, getPlayer };