save tracks and queue

to add new added tracks and queue to the database so it can continue playing, when the node disconnected or crashed.

still not tested yet
This commit is contained in:
Amane Serenetia 2025-01-04 02:43:50 +07:00
parent 0bf035c71f
commit 2f0c2c387c
7 changed files with 151 additions and 0 deletions

View File

@ -1,5 +1,6 @@
const { EmbedBuilder, ApplicationCommandOptionType } = require("discord.js");
const { EMBED_COLORS, MUSIC } = require("@root/config");
const Queue = require("@src/database/schemas/Queue");
/**
* @type {import("@structures/Command")}
@ -118,6 +119,8 @@ async function play({ member, guild, channel }, searchQuery, source) {
case "playlist": {
player.queue.add(res.tracks);
await saveQueueToDatabase(player);
const playlistEmbed = new EmbedBuilder()
.setAuthor({ name: "Added Playlist to queue" })
.setThumbnail(res.playlist.thumbnail)
@ -148,6 +151,8 @@ async function play({ member, guild, channel }, searchQuery, source) {
const track = res.tracks[0];
player.queue.add(track);
await saveQueueToDatabase(player);
const trackEmbed = new EmbedBuilder()
.setAuthor({ name: "Added Track to queue" })
.setColor(EMBED_COLORS.BOT_EMBED)
@ -183,4 +188,29 @@ async function play({ member, guild, channel }, searchQuery, source) {
guild.client.logger.error("Search Exception", JSON.stringify(error));
return "🚫 An error occurred while searching for the song";
}
}
// Function to save the current queue and track to the database
async function saveQueueToDatabase(player) {
const queueData = {
guildId: player.guildId,
tracks: player.queue.tracks.map(track => ({
title: track.info.title,
uri: track.info.uri,
duration: track.info.duration,
requester: track.requester.id,
})),
currentTrack: player.queue.current ? {
title: player.queue.current.info.title,
uri: player.queue.current.info.uri,
duration: player.queue.current.info.duration,
requester: player.queue.current.requester.id,
} : null,
};
await Queue.findOneAndUpdate(
{ guildId: player.guildId },
queueData,
{ upsert: true, new: true }
);
}

View File

@ -6,6 +6,7 @@ const {
ComponentType,
} = require("discord.js");
const { EMBED_COLORS, MUSIC } = require("@root/config");
const Queue = require("@src/database/schemas/Queue");
/**
* @type {import("@structures/Command")}
@ -161,6 +162,9 @@ async function search({ member, guild, channel }, query, source) {
const selectedTrack = results[response.values[0]];
player.queue.add(selectedTrack);
// Save the current state to the database
await saveQueueToDatabase(player);
const trackEmbed = new EmbedBuilder()
.setAuthor({ name: "Added Track to queue" })
.setDescription(`[${selectedTrack.info.title}](${selectedTrack.info.uri})`)
@ -183,3 +187,28 @@ async function search({ member, guild, channel }, query, source) {
return "🚫 Failed to register your response";
}
}
// Function to save the current queue and track to the database
async function saveQueueToDatabase(player) {
const queueData = {
guildId: player.guildId,
tracks: player.queue.tracks.map(track => ({
title: track.info.title,
uri: track.info.uri,
duration: track.info.duration,
requester: track.requester.id,
})),
currentTrack: player.queue.current ? {
title: player.queue.current.info.title,
uri: player.queue.current.info.uri,
duration: player.queue.current.info.duration,
requester: player.queue.current.requester.id,
} : null,
};
await Queue.findOneAndUpdate(
{ guildId: player.guildId },
queueData,
{ upsert: true, new: true }
);
}

View File

@ -0,0 +1,21 @@
const mongoose = require("mongoose");
const queueSchema = new mongoose.Schema({
guildId: { type: String, required: true, unique: true },
tracks: [
{
title: String,
uri: String,
duration: Number,
requester: String,
},
],
currentTrack: {
title: String,
uri: String,
duration: Number,
requester: String,
},
});
module.exports = mongoose.model("Queue", queueSchema);

View File

@ -1,7 +1,32 @@
const Queue = require("@src/database/schemas/Queue");
module.exports = async (client, player) => {
const guild = client.guilds.cache.get(player.guildId);
if (!guild) return;
// Save the current track and queue to the database
const queueData = {
guildId: player.guildId,
tracks: player.queue.tracks.map(track => ({
title: track.info.title,
uri: track.info.uri,
duration: track.info.duration,
requester: track.requester.id,
})),
currentTrack: player.queue.current ? {
title: player.queue.current.info.title,
uri: player.queue.current.info.uri,
duration: player.queue.current.info.duration,
requester: player.queue.current.requester.id,
} : null,
};
await Queue.findOneAndUpdate(
{ guildId: player.guildId },
queueData,
{ upsert: true, new: true }
);
if (player.voiceChannelId) {
await client.utils.setVoiceStatus(client, player.voiceChannelId, "");
}

View File

@ -1,5 +1,6 @@
const { MUSIC, EMBED_COLORS } = require("@root/config");
const { EmbedBuilder } = require("discord.js");
const Queue = require("@src/database/schemas/Queue");
module.exports = async (client, player) => {
const guild = client.guilds.cache.get(player.guildId);
@ -27,4 +28,7 @@ module.exports = async (client, player) => {
10
);
}
// Clean up the queue from the database if all tracks are played
await Queue.deleteOne({ guildId: player.guildId });
};

View File

@ -1,5 +1,6 @@
const { autoplayFunction } = require("@handlers/player");
const { MUSIC } = require("@root/config.js");
const Queue = require("@src/database/schemas/Queue");
module.exports = async (client, player, track) => {
const guild = client.guilds.cache.get(player.guildId);
@ -14,6 +15,18 @@ module.exports = async (client, player, track) => {
await msg.delete().catch(() => {});
}
// Check if the current track was saved in the database
const queueData = await Queue.findOne({ guildId: player.guildId });
// Remove the current track from the database after it has been played
if (queueData) {
const updatedTracks = queueData.tracks.filter(t => t.uri !== track.info.uri);
await Queue.updateOne(
{ guildId: player.guildId },
{ tracks: updatedTracks, currentTrack: null }
);
}
if (player.get("autoplay") === true) {
await autoplayFunction(client, track, player);
}

View File

@ -1,10 +1,39 @@
const { EmbedBuilder, ButtonBuilder, ButtonStyle, ActionRowBuilder } = require("discord.js");
const { EMBED_COLORS } = require("@root/config");
const Queue = require("@src/database/schemas/Queue");
module.exports = async (client, player, track) => {
const guild = client.guilds.cache.get(player.guildId);
if (!guild) return;
// Check if the queue exists in the database
const queueData = await Queue.findOne({ guildId: player.guildId });
if (queueData) {
// Restore the queue
player.queue.add(queueData.tracks.map(track => ({
info: {
title: track.title,
uri: track.uri,
duration: track.duration,
},
requester: { id: track.requester },
})));
if (queueData.currentTrack) {
player.queue.current = {
info: {
title: queueData.currentTrack.title,
uri: queueData.currentTrack.uri,
duration: queueData.currentTrack.duration,
},
requester: { id: queueData.currentTrack.requester },
};
}
// Clear the database entry after restoring
await Queue.deleteOne({ guildId: player.guildId });
}
if (!player.textChannelId || !track) return;
const channel = guild.channels.cache.get(player.textChannelId);