import { SlashCommandBuilder } from 'discord.js'; import { Interaction } from 'discord.js'; // Maps to track queues and voice connections per guild const queueMap = new Map(); // { guildId: [track1, track2, ...] } const connectionMap = new Map(); // { guildId: VoiceConnection } const data = new SlashCommandBuilder() .setName('music') .setDescription('Perform ButlerBot music operations.') .addSubcommand((subcommand) => subcommand .setName('play') .setDescription('Play a track.') .addStringOption((option) => option .setName('track') .setDescription('The track to play.') .setRequired(true) ) .addStringOption((option) => option .setName('provider') .setDescription('The provider of the track.') .setRequired(false) .addChoices( { name: 'YouTube', value: 'youtube' }, { name: 'Spotify', value: 'spotify' }, { name: 'Local', value: 'local' } ) ) ) .addSubcommand((subcommand) => subcommand.setName('pause').setDescription('Pause the current track.') ) .addSubcommand((subcommand) => subcommand.setName('resume').setDescription('Resume the current track.') ) .addSubcommand((subcommand) => subcommand.setName('skip').setDescription('Skip the current track.') ) .addSubcommand((subcommand) => subcommand.setName('stop').setDescription('Stop the current track.') ) .addSubcommand((subcommand) => subcommand.setName('queue').setDescription('Show the current track queue.') ) .addSubcommand((subcommand) => subcommand.setName('clear').setDescription('Clear the current track queue.') ) .addSubcommand((subcommand) => subcommand.setName('leave').setDescription('Leave the voice channel.') ) .addSubcommand((subcommand) => subcommand.setName('join').setDescription('Join the voice channel.') ); /** * Handles the music command. * @param {Interaction} interaction The interaction object. */ async function execute(interaction) { await interaction.deferReply(); const subcommand = interaction.options.getSubcommand(); const guildId = interaction.guild.id; switch (subcommand) { case 'play': await handlePlay(interaction, guildId); break; case 'pause': await handlePause(interaction, guildId); break; case 'resume': await handleResume(interaction, guildId); break; case 'skip': await handleSkip(interaction, guildId); break; case 'stop': await handleStop(interaction, guildId); break; case 'queue': await handleQueue(interaction, guildId); break; case 'clear': await handleClear(interaction, guildId); break; case 'leave': await handleLeave(interaction, guildId); break; case 'join': await handleJoin(interaction, guildId); break; default: await interaction.editReply('Invalid music subcommand.'); } } /** * Handles the play subcommand. * @param {Interaction} interaction The interaction object. * @param {string} guildId The guild ID. * @returns {Promise} */ async function handlePlay(interaction, guildId) { const track = interaction.options.getString('track'); const provider = interaction.options.getString('provider') || 'youtube'; // Check if the user is in a voice channel const voiceChannel = interaction.member.voice.channel; if (!voiceChannel) { await interaction.editReply( 'You need to be in a voice channel to play music.' ); return; } // Get the queue for the guild const queue = queueMap.get(guildId) || []; queue.push({ track, provider }); queueMap.set(guildId, queue); // Join the voice channel await handleJoin(interaction, guildId); // Play the track await interaction.editReply(`Playing track: ${track}`); } export default { data, execute };