diff options
| -rw-r--r-- | AudioBackend.js | 38 | ||||
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | bot.js | 5 | ||||
| -rw-r--r-- | commands/about.js | 6 | ||||
| -rw-r--r-- | commands/control.js | 178 | ||||
| -rw-r--r-- | commands/help.js | 4 | ||||
| -rw-r--r-- | commands/list.js | 4 | ||||
| -rw-r--r-- | commands/ping.js | 4 | ||||
| -rw-r--r-- | commands/play.js | 5 |
9 files changed, 141 insertions, 105 deletions
diff --git a/AudioBackend.js b/AudioBackend.js index 53acc61..b5d5be6 100644 --- a/AudioBackend.js +++ b/AudioBackend.js @@ -29,12 +29,16 @@ import { import { MessageEmbed } from 'discord.js' import config from './config.json' assert {type: 'json'} import { readdirSync, writeFile } from 'node:fs' +import {controlEmbed} from "./commands/control.js"; export const player = createAudioPlayer(); export let audio; export let files = readdirSync('music'); let fileData; +export let playerState; +let isAudioStatePaused; + export async function voiceInit(bot) { bot.channels.fetch(config.voiceChannel).then(async channel => { const connection = joinVoiceChannel({ @@ -52,7 +56,7 @@ export async function voiceInit(bot) { }); player.on('idle', () => { - console.log("Beat has finished playing, shuffling the beats...") + console.log("Beat has finished playing, shuffling the beats..."); searchAudio(bot); }) @@ -76,14 +80,17 @@ export async function inputAudio(bot, integer) { export async function playAudio(bot) { let resource = createAudioResource('music/' + audio); - await player.play(resource); + player.play(resource); console.log('Now playing: ' + audio); + playerState = "Playing" + isAudioStatePaused = false + audio = audio.split('.').slice(0, -1).join('.'); if (config.txtFile === true) { - fileData = "Now Playing: " + audio; + fileData = "Now Playing: " + audio writeFile("./now-playing.txt", fileData, (err) => { if (err) console.log(err); @@ -100,7 +107,7 @@ export async function playAudio(bot) { } -export function destroyAudio(interaction) { +export async function destroyAudio(interaction) { if (config.txtFile === true) { fileData = "Now Playing: Nothing"; writeFile("now-playing.txt", fileData, (err) => { @@ -109,10 +116,25 @@ export function destroyAudio(interaction) { }); } - audio = "Not Playing"; - player.stop(); + audio = "Not Playing" + playerState = "Stopped" + isAudioStatePaused = true + const connection = getVoiceConnection(interaction.guild.id); - return connection.destroy(); + if (VoiceConnectionStatus.Ready) { + player.stop(); + return connection.destroy(); + } +} + +export function audioState() { + if (isAudioStatePaused === false) { + isAudioStatePaused = true + playerState = "Paused" + } else if (isAudioStatePaused === true) { + isAudioStatePaused = false + playerState = "Playing" + } } export async function stopBot(bot, interaction) { @@ -125,7 +147,7 @@ export async function stopBot(bot, interaction) { await statusChannel.send({embeds: [statusEmbed]}); console.log('Powering off...'); - destroyAudio(interaction); + await destroyAudio(interaction); bot.destroy(); return process.exit(0); }
\ No newline at end of file @@ -16,7 +16,7 @@ Make a new file called `config.json`. "statusChannel": "channel_id", "voiceChannel": "voice_channel_id" "guildID": "guild_id", - "clientID": "client_id", + "clientID": "client_id" } ``` @@ -31,8 +31,9 @@ bot.login(config.token); /** * Project Ideas: * New queue system - * List MP3 files * Shuffle or "Play by order" mode + * Audio streaming + * Attempt to disable buttons (for control command) for regular users */ // Slash Command Handler @@ -93,7 +94,7 @@ bot.on('interactionCreate', async interaction => { if (error == null) { await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }); } else { - await interaction.reply({ content: `There was an error while executing this command!\nShare this to the bot owner!\n\nDetails:\`\`\`${error}\`\`\``, ephemeral: true }); + await interaction.reply({ content: `There was an error while executing this command! Share this to the bot owner!\n\nDetails:\`\`\`${error}\`\`\``, ephemeral: true }); } } }); diff --git a/commands/about.js b/commands/about.js index bd54e25..36234a5 100644 --- a/commands/about.js +++ b/commands/about.js @@ -30,14 +30,14 @@ export default { async execute(interaction, bot) { const aboutEmbed = new MessageEmbed() .setAuthor({name:`About ${bot.user.username}`, iconURL:bot.user.avatarURL()}) - .addField('Information', 'A Discord bot that plays local MP3 audio tracks.') - .addField('Version', npmPackage.version) + .addField('Information', 'A Discord bot that plays local audio tracks.') + .addField('Version', `DLAP ${npmPackage.version}`) .addField('Original Creator', 'Andrew Lee (Alee#4277)') //.addField('Contributors', '[your name] (discord#0000)') //.addField('Forked by', '[your name] (discord#0000)') .addField('Frameworks', `Discord.JS ${version} + Voice`) .addField('License', 'GNU General Public License v3.0') - .setFooter({text:'© Copyright 2020-2022 Andrew Lee. Licensed with GPL-3.0.'}) + .setFooter({text:'© Copyright 2020-2022 Andrew Lee'}) .setColor('#0066ff') const srcOrig = new MessageActionRow() diff --git a/commands/control.js b/commands/control.js index 83f603f..bac86d0 100644 --- a/commands/control.js +++ b/commands/control.js @@ -21,10 +21,11 @@ import { SlashCommandBuilder } from '@discordjs/builders' import { MessageEmbed, MessageActionRow, MessageButton } from 'discord.js' -import { audio, player, destroyAudio, voiceInit, stopBot, searchAudio } from '../AudioBackend.js' +import { audio, player, destroyAudio, voiceInit, stopBot, searchAudio, playerState, audioState } from '../AudioBackend.js' import config from '../config.json' assert {type: 'json'} export let controlEmbed +let runOnce = false export default { data: new SlashCommandBuilder() @@ -32,94 +33,105 @@ export default { .setDescription('Controlling the music'), async execute(interaction, bot) { if (![config.botOwner].includes(interaction.user.id)) return await interaction.reply({ content: "You do not have permissions to execute this command.", ephemeral: true }); - controlEmbed = new MessageEmbed() - .setAuthor({name: `${bot.user.username} Control Panel`, iconURL: bot.user.avatarURL()}) - .addField('State', 'Playing') - .addField('Currently Playing', audio) - //.addField('Next Music', '(a possible feature when queue system is implemented?)') - .setColor('#0066ff') + if (runOnce === false) { + controlEmbed = new MessageEmbed() + .setAuthor({name: `${bot.user.username} Control Panel`, iconURL: bot.user.avatarURL()}) + .addField('State', playerState) + .addField('Currently Playing', audio) + //.addField('Next Music', '(a possible feature when queue system is implemented?)') + .setColor('#0066ff') - const controlButtons = new MessageActionRow() - .addComponents( - new MessageButton() - .setStyle('SUCCESS') - .setLabel('Join') - .setCustomId('join'), - new MessageButton() - .setStyle('PRIMARY') - .setLabel('Play') - .setCustomId('play'), - new MessageButton() - .setStyle('PRIMARY') - .setLabel('Pause') - .setCustomId('pause'), - new MessageButton() - .setStyle('SECONDARY') - .setLabel('Skip') - .setCustomId('skip'), - new MessageButton() - .setStyle('SECONDARY') - .setLabel('>>') - .setCustomId('next'), - ); + const controlButtons = new MessageActionRow() + .addComponents( + new MessageButton() + .setStyle('SUCCESS') + .setLabel('Join') + .setCustomId('join'), + new MessageButton() + .setStyle('PRIMARY') + .setLabel('Play') + .setCustomId('play'), + new MessageButton() + .setStyle('PRIMARY') + .setLabel('Pause') + .setCustomId('pause'), + new MessageButton() + .setStyle('SECONDARY') + .setLabel('Skip') + .setCustomId('skip'), + new MessageButton() + .setStyle('SECONDARY') + .setLabel('>>') + .setCustomId('next'), + ); - const controlButtons2 = new MessageActionRow() - .addComponents( - new MessageButton() - .setStyle('SECONDARY') - .setLabel('<<') - .setCustomId('back'), - new MessageButton() - .setStyle('DANGER') - .setLabel('Leave') - .setCustomId('leave'), - new MessageButton() - .setStyle('DANGER') - .setLabel('Power Off') - .setCustomId('stop') - ) + const controlButtons2 = new MessageActionRow() + .addComponents( + new MessageButton() + .setStyle('SECONDARY') + .setLabel('<<') + .setCustomId('back'), + new MessageButton() + .setStyle('DANGER') + .setLabel('Leave') + .setCustomId('leave'), + new MessageButton() + .setStyle('DANGER') + .setLabel('Power Off') + .setCustomId('stop') + ) - const filter = i => i.user.id === config.botOwner; + const filter = i => i.user.id === config.botOwner; - const collector = interaction.channel.createMessageComponentCollector({filter}); + const collector = interaction.channel.createMessageComponentCollector({filter}); - collector.on('collect', async ctlButton => { - if (ctlButton.customId === 'join') { - await ctlButton.reply({content:'Joining voice channel', ephemeral:true}) - return await voiceInit(bot); - } - if (ctlButton.customId === 'play') { - await ctlButton.reply({content:'Resuming music', ephemeral:true}) - return player.unpause(); - } - if (ctlButton.customId === 'pause') { - await ctlButton.reply({content:'Pausing music', ephemeral:true}) - return player.pause(); - } - if (ctlButton.customId === 'skip') { - await ctlButton.reply({content:`Skipping \`${audio}\`...`, ephemeral:true}) - player.stop(); - return await searchAudio(bot); - } - if (ctlButton.customId === 'next') { - return await interaction.editReply({ components: [controlButtons2] }); - } - if (ctlButton.customId === 'back') { - return await interaction.editReply({ components: [controlButtons] }); - } - if (ctlButton.customId === 'leave') { - await ctlButton.reply({content:'Leaving voice channel.', ephemeral:true}) - console.log('Leaving voice channel...'); - return destroyAudio(interaction); - } - if (ctlButton.customId === 'stop') { - await ctlButton.reply({content:'Powering off...', ephemeral:true}) - return await stopBot(bot, interaction); - } - }); + collector.on('collect', async ctlButton => { + if (ctlButton.customId === 'join') { + await ctlButton.reply({content:'Joining voice channel', ephemeral:true}); + return await voiceInit(bot); + } + if (ctlButton.customId === 'play') { + await ctlButton.reply({content:'Resuming music', ephemeral:true}); + audioState(); + return player.unpause(); + } + if (ctlButton.customId === 'pause') { + await ctlButton.reply({content:'Pausing music', ephemeral:true}); + audioState(); + return player.pause(); + } + if (ctlButton.customId === 'skip') { + await ctlButton.reply({content:`Skipping ${audio}`, ephemeral:true}); + player.stop(); + return await searchAudio(bot, interaction); + } + if (ctlButton.customId === 'next') { + return await interaction.editReply({ components: [controlButtons2] }).then(ctlButton.deferUpdate()); + } + if (ctlButton.customId === 'back') { + return await interaction.editReply({ components: [controlButtons] }).then(ctlButton.deferUpdate()); + } + if (ctlButton.customId === 'leave') { + await ctlButton.reply({content:'Leaving voice channel', ephemeral:true}); + console.log('Leaving voice channel...'); + runOnce = false + await interaction.deleteReply(); + return await destroyAudio(interaction); + } + if (ctlButton.customId === 'stop') { + await ctlButton.reply({content:`Powering off ${bot.user.username}...`, ephemeral:true}); + runOnce = false + await interaction.deleteReply(); + return await stopBot(bot, interaction); + } + }); - collector.on('end', collected => console.log(`Collected ${collected.size} items`)); + collector.on('end', collected => console.log(`Collected ${collected.size} items`)); - return await interaction.reply({embeds:[controlEmbed], components:[controlButtons]}); + runOnce = true + return await interaction.reply({embeds:[controlEmbed], components:[controlButtons]}); + } else { + return await interaction.reply({content:'You already executed this command', ephemeral:true}) + } }, };
\ No newline at end of file diff --git a/commands/help.js b/commands/help.js index 291f5fe..11d9d60 100644 --- a/commands/help.js +++ b/commands/help.js @@ -20,7 +20,7 @@ ***************************************************************************/ import { SlashCommandBuilder } from '@discordjs/builders' -import { MessageEmbed } from 'discord.js'; +import { MessageEmbed } from 'discord.js' import { audio } from '../AudioBackend.js' export default { @@ -33,7 +33,7 @@ export default { .setDescription(`Currently playing \`${audio}\``) .addField('Public Commands', `/help\n/ping\n/about\n`, true) .addField('Bot Owner Only', `/join\n/control\n/stop\n`, true) - .setFooter({text:'© Copyright 2020-2022 Andrew Lee. Licensed with GPL-3.0.'}) + .setFooter({text:'© Copyright 2020-2022 Andrew Lee'}) .setColor('#0066ff') return await interaction.reply({ embeds: [helpEmbed]}); diff --git a/commands/list.js b/commands/list.js index 247e060..2d7c5aa 100644 --- a/commands/list.js +++ b/commands/list.js @@ -29,7 +29,9 @@ export default { .setName('list') .setDescription('Lists the available audio tracks'), async execute(interaction) { + //If someone figures out how to either split the list or make pages when the max character reaches, please do so and make a pull request. + const beats = readdirSync(musicFolder).join('\n'); - await interaction.reply(`Listing the available audio tracks...\`\`\`${beats}\`\`\``); + await interaction.reply(`Listing the available audio tracks...\n\`\`\`\n${beats}\n\`\`\``); }, };
\ No newline at end of file diff --git a/commands/ping.js b/commands/ping.js index fc25135..3a77d08 100644 --- a/commands/ping.js +++ b/commands/ping.js @@ -25,7 +25,7 @@ export default { data: new SlashCommandBuilder() .setName('ping') .setDescription('Pong!'), - async execute(interaction) { - return await interaction.reply('Pong!'); + async execute(interaction, bot) { + return await interaction.reply(`Pong! ${Math.round(bot.ws.ping)}ms`); }, };
\ No newline at end of file diff --git a/commands/play.js b/commands/play.js index f53ac21..cc88bb3 100644 --- a/commands/play.js +++ b/commands/play.js @@ -31,13 +31,12 @@ export default { .setDescription('Plays the audio by number') .addIntegerOption(option => option.setName('int') - .setDescription('Input a number for the selection for the audio file.') - .setRequired(false), + .setDescription('Input a number for the selection for the audio file.'), ), async execute(interaction, bot) { if (![config.botOwner].includes(interaction.user.id)) return await interaction.reply({ content: "You do not have permissions to execute this command.", ephemeral: true }); integer = interaction.options.getInteger('int'); await inputAudio(bot, integer); - return await interaction.reply({ content: `Now playing: ${audio}`, ephemeral: true}); + return await interaction.reply({ content: `Now playing: ${audio}`, ephemeral: true }); }, };
\ No newline at end of file |
