From f91f277a30a081cde95805bf39adeb835be98c3f Mon Sep 17 00:00:00 2001 From: Andrew Lee Date: Sun, 4 Dec 2022 01:55:58 -0500 Subject: [PATCH] Added repeat toggle; Did some optiminizations to the code --- README.md | 2 ++ backend/AudioControl.js | 19 +++++++++++++++---- backend/PlayAudio.js | 2 +- backend/VoiceInitialization.js | 2 +- bot.js | 9 +++------ commands/next.js | 12 ++++++++---- commands/pause.js | 2 +- commands/previous.js | 8 ++++++-- commands/reshuffle.js | 2 +- commands/status.js | 4 ++-- package.json | 1 + yarn.lock | 19 +++++++++++++++++++ 12 files changed, 60 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 6f46bb5..4dcd8aa 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,10 @@ Make a new file called `config.json`. "token": "token_here", "txtFile": true/false, "shuffle": true/false, + "repeat": true/false, "statusChannel": "channel_id", "voiceChannel": "voice_channel_id", + "presenceActivity": "activity_here", "clientID": "client_id" } ``` diff --git a/backend/AudioControl.js b/backend/AudioControl.js index 71952c1..2b314d2 100644 --- a/backend/AudioControl.js +++ b/backend/AudioControl.js @@ -22,20 +22,31 @@ import { readdirSync, readFileSync } from 'node:fs'; import { shufflePlaylist, orderPlaylist } from './QueueSystem.js'; import { playAudio, currentTrack, updatePlaylist } from './PlayAudio.js'; import { player } from './VoiceInitialization.js'; +import { destroyAudio } from './Shutdown.js'; -const { shuffle } = JSON.parse(readFileSync('./config.json', 'utf-8')); +const { shuffle, repeat } = JSON.parse(readFileSync('./config.json', 'utf-8')); export const files = readdirSync('music'); export let playerState; export let isAudioStatePaused; let totalTrack = files.length; +async function repeatCheck(bot) { + if (repeat) { + console.log('All beats in the playlist has finished, repeating beats...'); + totalTrack = files.length; + return (shuffle) ? await shufflePlaylist(bot) : await orderPlaylist(bot); + } else { + console.log('All beats in the playlist has finished.'); + updatePlaylist('stop'); + audioState(2); + } +} + export async function nextAudio(bot) { totalTrack--; if (currentTrack >= totalTrack) { - console.log('All beats in the playlist has finished, repeating beats...'); - totalTrack = files.length; - return (shuffle === true) ? await shufflePlaylist(bot) : await orderPlaylist(bot); + await repeatCheck(bot); } else { updatePlaylist('next'); return await playAudio(bot); diff --git a/backend/PlayAudio.js b/backend/PlayAudio.js index 3ae2b91..d698798 100644 --- a/backend/PlayAudio.js +++ b/backend/PlayAudio.js @@ -77,7 +77,7 @@ export async function playAudio(bot) { } const statusEmbed = new EmbedBuilder(); - if (metadataEmpty === true) { + if (metadataEmpty) { statusEmbed.setTitle('Now Playing'); statusEmbed.addFields( { name: 'Title', value: audio }, diff --git a/backend/VoiceInitialization.js b/backend/VoiceInitialization.js index d95bfa6..a9e1149 100644 --- a/backend/VoiceInitialization.js +++ b/backend/VoiceInitialization.js @@ -39,7 +39,7 @@ export async function voiceInit(bot) { connection.on(VoiceConnectionStatus.Ready, async() => { console.log('Ready to blast some beats!'); - return (shuffle === true) ? await shufflePlaylist(bot) : await orderPlaylist(bot); + return (shuffle) ? await shufflePlaylist(bot) : await orderPlaylist(bot); }); connection.on(VoiceConnectionStatus.Destroyed, () => { diff --git a/bot.js b/bot.js index c53d40f..ef01d55 100644 --- a/bot.js +++ b/bot.js @@ -22,7 +22,7 @@ import { Client, GatewayIntentBits, EmbedBuilder, Collection, version, Interacti import { voiceInit } from './backend/VoiceInitialization.js'; import { readdirSync, readFileSync } from 'node:fs'; // import config from './config.json' assert { type: 'json' } Not supported by ESLint yet -const { token, statusChannel, voiceChannel, shuffle, presenceActivity } = JSON.parse(readFileSync('./config.json', 'utf-8')); +const { token, statusChannel, voiceChannel, shuffle, repeat, presenceActivity } = JSON.parse(readFileSync('./config.json', 'utf-8')); const bot = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildVoiceStates] }); bot.login(token); @@ -49,6 +49,7 @@ bot.once('ready', async() => { console.log(`Voice Channel: ${voiceChannel}`); console.log(`Status Channel: ${statusChannel}`); console.log(`Shuffle Enabled: ${shuffle}`); + console.log(`Repeat Enabled: ${repeat}`); // Set bots' presence bot.user.setPresence({ @@ -86,10 +87,6 @@ bot.on('interactionCreate', async interaction => { await command.execute(interaction, bot); } catch (e) { console.error(e); - if (e == 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:\`\`\`${e}\`\`\``, ephemeral: true }); - } + await interaction.reply({ content: `There was an error while executing this command!\nShare this to the bot owner!\n\nDetails:\`\`\`${e}\`\`\``, ephemeral: true }); } }); diff --git a/commands/next.js b/commands/next.js index 88dac40..759c5bb 100644 --- a/commands/next.js +++ b/commands/next.js @@ -21,7 +21,7 @@ import { SlashCommandBuilder } from 'discord.js'; import { player } from '../backend/VoiceInitialization.js'; -import { nextAudio } from '../backend/AudioControl.js'; +import { nextAudio, playerState } from '../backend/AudioControl.js'; import { PermissionFlagsBits } from 'discord-api-types/v10'; export default { @@ -31,8 +31,12 @@ export default { .setDefaultMemberPermissions(PermissionFlagsBits.Administrator), async execute(interaction, bot) { if (!interaction.member.voice.channel) return await interaction.reply({ content: 'You need to be in a voice channel to use this command.', ephemeral: true }); - await interaction.reply({ content: 'Playing next music', ephemeral: true }); - player.stop(); - return await nextAudio(bot); + if (playerState === 'Playing' || playerState === 'Paused') { + await interaction.reply({ content: 'Playing next music', ephemeral: true }); + player.stop(); + return await nextAudio(bot); + } else if (playerState === 'Stopped') { + return await interaction.reply({ content: 'Cannot play next music. Player is currently stopped...', ephemeral: true }); + } } }; diff --git a/commands/pause.js b/commands/pause.js index c467675..61b9e21 100644 --- a/commands/pause.js +++ b/commands/pause.js @@ -30,7 +30,7 @@ export default { .setDefaultMemberPermissions(PermissionFlagsBits.Administrator), async execute(interaction) { if (!interaction.member.voice.channel) return await interaction.reply({ content: 'You need to be in a voice channel to use this command.', ephemeral: true }); - if (isAudioStatePaused === false) { + if (!isAudioStatePaused) { toggleAudioState(); return await interaction.reply({ content: 'Pausing music', ephemeral: true }); } else { diff --git a/commands/previous.js b/commands/previous.js index 66c1930..ebedbb6 100644 --- a/commands/previous.js +++ b/commands/previous.js @@ -20,7 +20,7 @@ ***************************************************************************/ import { SlashCommandBuilder } from 'discord.js'; -import { previousAudio } from '../backend/AudioControl.js'; +import { playerState, previousAudio } from '../backend/AudioControl.js'; import { PermissionFlagsBits } from 'discord-api-types/v10'; export default { @@ -30,6 +30,10 @@ export default { .setDefaultMemberPermissions(PermissionFlagsBits.Administrator), async execute(interaction, bot) { if (!interaction.member.voice.channel) return await interaction.reply({ content: 'You need to be in a voice channel to use this command.', ephemeral: true }); - return await previousAudio(bot, interaction); + if (playerState === 'Playing' || playerState === 'Paused') { + return await previousAudio(bot, interaction); + } else if (playerState === 'Stopped') { + return await interaction.reply({ content: 'Cannot play next music. Player is currently stopped...', ephemeral: true }); + } } }; diff --git a/commands/reshuffle.js b/commands/reshuffle.js index f60bb1c..e1d37d0 100644 --- a/commands/reshuffle.js +++ b/commands/reshuffle.js @@ -39,6 +39,6 @@ export default { await audioState(2); await shufflePlaylist(bot); } - return (shuffle === true) ? await shuffleDetected(bot) : await interaction.reply({ content: 'Shuffle mode is disabled, enable it in the configuration file to access this command.', ephemeral: true }); + return (shuffle) ? await shuffleDetected(bot) : await interaction.reply({ content: 'Shuffle mode is disabled, enable it in the configuration file to access this command.', ephemeral: true }); } }; diff --git a/commands/status.js b/commands/status.js index cf49509..d19e4ac 100644 --- a/commands/status.js +++ b/commands/status.js @@ -38,7 +38,7 @@ export default { if (audioName === undefined) { audioName = 'Playlist Finished'; } else { - if (metadataEmpty === false) { + if (!metadataEmpty) { try { const { common } = await parseFile('music/' + audioName); audioName = common.title; @@ -59,7 +59,7 @@ export default { ) .setColor('#0066ff'); - if (metadataEmpty === true) { + if (metadataEmpty) { controlEmbed.addFields( { name: 'Currently Playing', value: audio }, { name: 'Up Next', value: audioName } diff --git a/package.json b/package.json index 71ad367..aeb0672 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "discord-api-types": "^0.37.15", "discord.js": "^14.6.0", "ffmpeg-static": "^5.1.0", + "i18next": "^22.0.6", "music-metadata": "^8.1.0", "sodium": "^3.0.2" }, diff --git a/yarn.lock b/yarn.lock index 1d37b27..20807be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,13 @@ # yarn lockfile v1 +"@babel/runtime@^7.17.2": + version "7.20.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.6.tgz#facf4879bfed9b5326326273a64220f099b0fce3" + integrity sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA== + dependencies: + regenerator-runtime "^0.13.11" + "@derhuerst/http-basic@^8.2.0": version "8.2.4" resolved "https://registry.yarnpkg.com/@derhuerst/http-basic/-/http-basic-8.2.4.tgz#d021ebb8f65d54bea681ae6f4a8733ce89e7f59b" @@ -981,6 +988,13 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +i18next@^22.0.6: + version "22.0.6" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-22.0.6.tgz#d7029912f8aa74ff295c0d9afd1b7dea45859b49" + integrity sha512-RlreNGoPIdDP4QG+qSA9PxZKGwlzmcozbI9ObI6+OyUa/Rp0EjZZA9ubyBjw887zVNZsC+7FI3sXX8oiTzAfig== + dependencies: + "@babel/runtime" "^7.17.2" + ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" @@ -1526,6 +1540,11 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +regenerator-runtime@^0.13.11: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + regexp.prototype.flags@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac"