const { SlashCommandBuilder } = require('discord.js'); const { joinVoiceChannel, getVoiceConnection, VoiceConnectionStatus, entersState, createAudioPlayer, AudioPlayerStatus, NoSubscriberBehavior, createAudioResource } = require('@discordjs/voice'); module.exports = { data: new SlashCommandBuilder() .setName('playmusic') .setDescription('Play music in a voice channel') .addStringOption(option => option.setName('track').setDescription('The track to play').setRequired(true)), async execute(interaction) { const track = interaction.options.getString('track'); const channel = interaction.member.voice.channel; if (!channel) return interaction.reply({ content: 'You need to be in a voice channel to play music!', ephemeral: true }); const connection = joinVoiceChannel({ channelId: channel.id, guildId: channel.guild.id, adapterCreator: channel.guild.voiceAdapterCreator, }); const player = createAudioPlayer({ behaviors: { noSubscriber: NoSubscriberBehavior.Pause, }, }); const resource = createAudioResource(track); player.play(resource); connection.subscribe(player); connection.on(VoiceConnectionStatus.Disconnected, async () => { try { await Promise.race([ entersState(connection, VoiceConnectionStatus.Signalling, 5000), entersState(connection, VoiceConnectionStatus.Connecting, 5000), ]); // Seems to be reconnecting to a new channel - ignore disconnect } catch (error) { // Seems to be a real disconnect which SHOULDN'T be recovered from connection.destroy(); } }); player.on(AudioPlayerStatus.Idle, () => { player.stop(); connection.destroy(); interaction.followUp({ content: 'Playback finished.' }); }); player.on('error', error => { console.error(`Error: ${error.message} with resource ${error.resource.metadata.title}`); player.stop(); connection.destroy(); interaction.followUp({ content: `Error occurred: ${error.message}` }); }); await interaction.reply({ content: `Now playing: ${track}` }); } };