From 24e98fad9030aa8707b2c4d3e7e8349c890011df Mon Sep 17 00:00:00 2001 From: Kiera Affarantia Date: Sat, 4 Jan 2025 06:18:52 +0700 Subject: [PATCH] add join/resume button add join command, resume button when only node disconnected and music stopped to play --- src/commands/music/join.js | 84 +++++++++++++++++++++++++++++++++ src/events/buttonInteraction.js | 11 +++++ src/events/player/trackEnd.js | 23 ++++++++- src/events/player/trackStart.js | 1 + 4 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/commands/music/join.js create mode 100644 src/events/buttonInteraction.js diff --git a/src/commands/music/join.js b/src/commands/music/join.js new file mode 100644 index 0000000..d00283a --- /dev/null +++ b/src/commands/music/join.js @@ -0,0 +1,84 @@ +const { EmbedBuilder } = require("discord.js"); +const Queue = require("@src/database/schemas/Queue"); +const { MUSIC } = require("@root/config"); + +module.exports = { + name: "join", + description: "Join the voice channel and resume playback if there is a saved queue.", + category: "MUSIC", + validations: [], // Add any validations if necessary + command: { + enabled: true, + }, + slashCommand: { + enabled: true, + }, + + async messageRun(message, args) { + const response = await executeJoinCommand(message); + await message.safeReply(response); + }, + + async interactionRun(interaction) { + const response = await executeJoinCommand(interaction); + await interaction.followUp(response); + }, +}; + +async function executeJoinCommand(interaction) { + const { guild, member } = interaction; + const voiceChannel = member.voice.channel; + + if (!voiceChannel) { + return "You need to be in a voice channel to use this command."; + } + + // Get or create the player for the guild + let player = guild.client.musicManager.getPlayer(guild.id); + if (!player) { + player = await guild.client.musicManager.createPlayer({ + guildId: guild.id, + voiceChannelId: voiceChannel.id, + textChannelId: interaction.channel.id, + selfMute: false, + selfDeaf: true, + volume: MUSIC.DEFAULT_VOLUME, + }); + } + + // Check for saved queue in the database + const queueData = await Queue.findOne({ guildId: guild.id }); + 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 }, + }; + + // Set the current position if available + player.position = queueData.currentTrack.position || 0; // Default to 0 if not set + } + + // Join the voice channel and play the current track + await player.connect(voiceChannel.id); + await player.play({ paused: false }); + + return `Joined ${voiceChannel.name} and resumed playback of **${player.queue.current.info.title}**.`; + } else { + return "No saved queue found."; + } +} \ No newline at end of file diff --git a/src/events/buttonInteraction.js b/src/events/buttonInteraction.js new file mode 100644 index 0000000..4c9d33f --- /dev/null +++ b/src/events/buttonInteraction.js @@ -0,0 +1,11 @@ +const joinCommand = require("@src/commands/music/join"); + +client.on("interactionCreate", async (interaction) => { + if (!interaction.isButton()) return; + + const { customId } = interaction; + + if (customId === "resume") { + await joinCommand.execute(interaction); + } +}); \ No newline at end of file diff --git a/src/events/player/trackEnd.js b/src/events/player/trackEnd.js index b9363a4..10042f2 100644 --- a/src/events/player/trackEnd.js +++ b/src/events/player/trackEnd.js @@ -1,5 +1,6 @@ const { autoplayFunction } = require("@handlers/player"); -const { MUSIC } = require("@root/config.js"); +const { MUSIC, EMBED_COLORS } = require("@root/config.js"); +const { EmbedBuilder, ButtonBuilder, ButtonStyle, ActionRowBuilder } = require("discord.js"); const Queue = require("@src/database/schemas/Queue"); module.exports = async (client, player, track) => { @@ -32,6 +33,26 @@ module.exports = async (client, player, track) => { } } + // Send a message with a button to resume playback + const channel = guild.channels.cache.get(player.textChannelId); + if (channel) { + const row = new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setCustomId("resume") + .setLabel("Resume Music") + .setStyle(ButtonStyle.Primary) + ); + + await channel.safeSend({ + embeds: [ + new EmbedBuilder() + .setColor(EMBED_COLORS.BOT_EMBED) + .setDescription("The music has stopped. You can resume it by clicking the button below.") + ], + components: [row] + }); + } + if (player.get("autoplay") === true) { await autoplayFunction(client, track, player); } diff --git a/src/events/player/trackStart.js b/src/events/player/trackStart.js index a6e736a..d46ba1c 100644 --- a/src/events/player/trackStart.js +++ b/src/events/player/trackStart.js @@ -1,6 +1,7 @@ const { EmbedBuilder, ButtonBuilder, ButtonStyle, ActionRowBuilder } = require("discord.js"); const { EMBED_COLORS } = require("@root/config"); const Queue = require("@src/database/schemas/Queue"); +const joinCommand = require("@src/commands/music/join"); module.exports = async (client, player, track) => { const guild = client.guilds.cache.get(player.guildId);