diff options
| author | Andrew Lee <alee14498@protonmail.com> | 2024-02-17 00:07:31 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-02-17 00:07:31 -0500 |
| commit | 214a83c0f696ac731c54b00bf7503f87e497afa6 (patch) | |
| tree | 15d57b08e69d19fb4c2f3effb9937aec8d042bdc /Commands | |
| parent | b29ab06623fd24cfc2a611bdd658b4d2ef934335 (diff) | |
| parent | c848f1d90fef40ffa81915d7dd875a2ee6d6c8d5 (diff) | |
| download | DLAP-214a83c0f696ac731c54b00bf7503f87e497afa6.tar.gz DLAP-214a83c0f696ac731c54b00bf7503f87e497afa6.tar.bz2 DLAP-214a83c0f696ac731c54b00bf7503f87e497afa6.zip | |
Merge pull request #17 from Alee14/testing
Merging testing branch
Diffstat (limited to 'Commands')
| -rw-r--r-- | Commands/about.js | 23 | ||||
| -rw-r--r-- | Commands/join.js | 14 | ||||
| -rw-r--r-- | Commands/leave.js | 13 | ||||
| -rw-r--r-- | Commands/list.js | 11 | ||||
| -rw-r--r-- | Commands/next.js | 9 | ||||
| -rw-r--r-- | Commands/pause.js | 20 | ||||
| -rw-r--r-- | Commands/ping.js | 5 | ||||
| -rw-r--r-- | Commands/play.js | 24 | ||||
| -rw-r--r-- | Commands/previous.js | 8 | ||||
| -rw-r--r-- | Commands/reshuffle.js | 16 | ||||
| -rw-r--r-- | Commands/shutdown.js | 7 | ||||
| -rw-r--r-- | Commands/status.js | 44 |
12 files changed, 115 insertions, 79 deletions
diff --git a/Commands/about.js b/Commands/about.js index 23c750e..d74a9e9 100644 --- a/Commands/about.js +++ b/Commands/about.js @@ -21,33 +21,34 @@ import { EmbedBuilder, version, ActionRowBuilder, ButtonBuilder, ButtonStyle, SlashCommandBuilder } from 'discord.js'; // import npmPackage from '../package.json' assert { type:'json' } +import i18next from '../Utilities/i18n.js'; import { readFileSync } from 'node:fs'; const npmPackage = JSON.parse(readFileSync('./package.json', 'utf-8')); - +const t = i18next.t; export default { data: new SlashCommandBuilder() .setName('about') .setDescription('Information about the bot'), async execute(interaction, bot) { const aboutEmbed = new EmbedBuilder() - .setAuthor({ name: `About ${bot.user.username}`, iconURL: bot.user.avatarURL() }) + .setAuthor({ name: t('aboutBot', { bot: bot.user.username }), iconURL: bot.user.avatarURL() }) .addFields( - { name: 'Information', value: 'A Discord bot that plays local audio tracks.' }, - { name: 'Version', value: `DLAP ${npmPackage.version}` }, - { name: 'Original Creator', value: 'Andrew Lee (Alee#4277)' }, // Do not remove this since I created this :) - // { name: 'Contributors', value: '[your name] (discord#0000)' }, - // { name: 'Forked by', value: '[your name] (discord#0000)' }, - { name: 'Frameworks', value: `Discord.JS ${version} + Voice` }, - { name: 'License', value: 'GNU General Public License v3.0' } + { name: t('aboutInfo'), value: t('aboutInfoValue') }, + { name: t('aboutBotVersion'), value: `DLAP ${npmPackage.version}` }, + { name: t('aboutCreator'), value: 'Andrew Lee (alee)' }, // Do not remove this since I created this :) + { name: t('aboutContributors'), value: 'Victor Moraes (Vicktor#7232) (Improving README)' }, + // { name: t('aboutForked'), value: '[your name] (username)' }, + { name: t('aboutFrameworks'), value: `Discord.JS ${version}\nmusic-metadata\ni18next` }, + { name: t('aboutLicense'), value: 'GNU General Public License v3.0' } ) - .setFooter({ text: '© Copyright 2020-2022 Andrew Lee' }) + .setFooter({ text: '© Copyright 2020-2024 Andrew Lee' }) .setColor('#0066ff'); const srcOrig = new ActionRowBuilder() .addComponents( new ButtonBuilder() .setStyle(ButtonStyle.Link) - .setLabel('Original Source Code') + .setLabel(t('aboutSrc')) .setURL('https://github.com/Alee14/DLAP') ); diff --git a/Commands/join.js b/Commands/join.js index 2649784..dd49969 100644 --- a/Commands/join.js +++ b/Commands/join.js @@ -23,17 +23,23 @@ import { SlashCommandBuilder } from 'discord.js'; import { voiceInit } from '../AudioBackend/VoiceInitialization.js'; import { PermissionFlagsBits } from 'discord-api-types/v10'; import { readFileSync } from 'node:fs'; +import { getVoiceConnection } from '@discordjs/voice'; +import i18next from '../Utilities/i18n.js'; const { djRole, ownerID } = JSON.parse(readFileSync('./config.json', 'utf-8')); - +const t = i18next.t; export default { data: new SlashCommandBuilder() .setName('join') .setDescription('Joins voice chat'), 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 }); - if (!interaction.member.roles.cache.has(djRole) && interaction.user.id !== ownerID && !interaction.member.permission.has(PermissionFlagsBits.ManageGuild)) return interaction.reply({ content: 'You need a specific role to execute this command', ephemeral: true }); + if (!interaction.member.voice.channel) return await interaction.reply({ content: t('voicePermission'), ephemeral: true }); + if (!interaction.member.roles.cache.has(djRole) && interaction.user.id !== ownerID && !interaction.memberPermissions.has(PermissionFlagsBits.ManageGuild)) return interaction.reply({ content: t('rolePermission'), ephemeral: true }); - await interaction.reply({ content: 'Joining voice channel', ephemeral: true }); + const connection = getVoiceConnection(interaction.guild.id); + if (connection) { + return await interaction.reply({ content: t('alreadyJoin'), ephemeral: true }); + } + await interaction.reply({ content: t('joinVoice'), ephemeral: true }); return await voiceInit(bot); } }; diff --git a/Commands/leave.js b/Commands/leave.js index 5d01822..c78cfe0 100644 --- a/Commands/leave.js +++ b/Commands/leave.js @@ -23,18 +23,21 @@ import { SlashCommandBuilder } from 'discord.js'; import { destroyAudio } from '../AudioBackend/Shutdown.js'; import { PermissionFlagsBits } from 'discord-api-types/v10'; import { readFileSync } from 'node:fs'; +import i18next from '../Utilities/i18n.js'; +import { playerStatus } from '../AudioBackend/AudioControl.js'; const { djRole, ownerID } = JSON.parse(readFileSync('./config.json', 'utf-8')); - +const t = i18next.t; export default { data: new SlashCommandBuilder() .setName('leave') .setDescription('Leaves the voice chat'), 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 }); - if (!interaction.member.roles.cache.has(djRole) && interaction.user.id !== ownerID && !interaction.member.permission.has(PermissionFlagsBits.ManageGuild)) return interaction.reply({ content: 'You need a specific role to execute this command', ephemeral: true }); + if (!interaction.member.voice.channel) return await interaction.reply({ content: t('voicePermission'), ephemeral: true }); + if (!interaction.member.roles.cache.has(djRole) && interaction.user.id !== ownerID && !interaction.memberPermissions.has(PermissionFlagsBits.ManageGuild)) return interaction.reply({ content: t('rolePermission'), ephemeral: true }); + if (playerStatus === 2) return await interaction.reply({ content: t('alreadyLeave'), ephemeral: true }); - console.log('Leaving voice channel...'); + console.log(t('leaveVoice')); await destroyAudio(interaction); - return await interaction.reply({ content: 'Leaving voice channel', ephemeral: true }); + return await interaction.reply({ content: t('leaveVoice'), ephemeral: true }); } }; diff --git a/Commands/list.js b/Commands/list.js index 90d3cc6..4713a63 100644 --- a/Commands/list.js +++ b/Commands/list.js @@ -21,9 +21,10 @@ import { EmbedBuilder, SlashCommandBuilder } from 'discord.js'; import { readdir } from 'node:fs'; +import i18next from '../Utilities/i18n.js'; const musicFolder = './music'; - +const t = i18next.t; export default { data: new SlashCommandBuilder() .setName('list') @@ -42,7 +43,7 @@ export default { const pageSize = 20; // Number of tracks per page const numPages = Math.ceil(trackList.length / pageSize); // Total number of pages if (page < 1 || page > numPages) { // Check if the page number is valid - return await interaction.reply({ content: `Invalid page number. Please specify a number between 1 and ${numPages}.`, ephemeral: true }); + return await interaction.reply({ content: t('invalidPage', { numPages }), ephemeral: true }); } // Split the track list into pages const pages = []; @@ -53,9 +54,9 @@ export default { } // Send the specified page with the page number and total number of pages const listEmbed = new EmbedBuilder(); - listEmbed.setAuthor({ name: `${bot.user.username} List`, iconURL: bot.user.avatarURL() }); - listEmbed.addFields({ name: `Listing ${trackList.length} audio tracks...`, value: `\`\`\`\n${pages[page - 1].join('\n')}\n\`\`\`` }); - listEmbed.setFooter({ text: `Page ${page}/${numPages}` }); + listEmbed.setAuthor({ name: t('listTitle', { bot: bot.user.username }), iconURL: bot.user.avatarURL() }); + listEmbed.addFields({ name: t('listTracks', { trackList: trackList.length }), value: `\`\`\`\n${pages[page - 1].join('\n')}\n\`\`\`` }); + listEmbed.setFooter({ text: t('listPage') + ` ${page}/${numPages}` }); listEmbed.setColor('#0066ff'); await interaction.reply({ embeds: [listEmbed] }); } diff --git a/Commands/next.js b/Commands/next.js index 082bf25..c99fd6b 100644 --- a/Commands/next.js +++ b/Commands/next.js @@ -21,20 +21,21 @@ import { SlashCommandBuilder } from 'discord.js'; import { voteSkip } from '../Utilities/Voting.js'; - +import i18next from '../Utilities/i18n.js'; +const t = i18next.t; export default { data: new SlashCommandBuilder() .setName('next') .setDescription('Goes to next music') - /* .addSubcommand(subcommand => + .addSubcommand(subcommand => subcommand.setName('vote') - .setDescription('Voting to skip this audio track')) */ + .setDescription('Voting to skip this audio track')) .addSubcommand(subcommand => subcommand.setName('force') .setDescription('Forces skip this audio track')), 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 }); + if (!interaction.member.voice.channel) return await interaction.reply({ content: t('voicePermission'), ephemeral: true }); await voteSkip(interaction, bot); } }; diff --git a/Commands/pause.js b/Commands/pause.js index 9e6026c..1d04404 100644 --- a/Commands/pause.js +++ b/Commands/pause.js @@ -20,23 +20,29 @@ ***************************************************************************/ import { SlashCommandBuilder } from 'discord.js'; -import { toggleAudioState, isAudioStatePaused } from '../AudioBackend/AudioControl.js'; +import { toggleAudioState, isAudioStatePaused, playerStatus } from '../AudioBackend/AudioControl.js'; import { PermissionFlagsBits } from 'discord-api-types/v10'; import { readFileSync } from 'node:fs'; +import i18next from '../Utilities/i18n.js'; +const t = i18next.t; const { djRole, ownerID } = JSON.parse(readFileSync('./config.json', 'utf-8')); export default { data: new SlashCommandBuilder() .setName('pause') .setDescription('Pauses music'), 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 }); - if (!interaction.member.roles.cache.has(djRole) && interaction.user.id !== ownerID && !interaction.member.permission.has(PermissionFlagsBits.ManageGuild)) return interaction.reply({ content: 'You need a specific role to execute this command', ephemeral: true }); + if (!interaction.member.voice.channel) return await interaction.reply({ content: t('voicePermission'), ephemeral: true }); + if (!interaction.member.roles.cache.has(djRole) && interaction.user.id !== ownerID && !interaction.memberPermissions.has(PermissionFlagsBits.ManageGuild)) return interaction.reply({ content: t('rolePermission'), ephemeral: true }); - if (!isAudioStatePaused) { - toggleAudioState(); - return await interaction.reply({ content: 'Pausing music', ephemeral: true }); + if (playerStatus === 2) { + return await interaction.reply({ content: t('alreadyLeave'), ephemeral: true }); } else { - return await interaction.reply({ content: 'Music is already paused', ephemeral: true }); + if (!isAudioStatePaused) { + toggleAudioState(); + return await interaction.reply({ content: t('pausingMusic'), ephemeral: true }); + } else { + return await interaction.reply({ content: t('pausedAlready'), ephemeral: true }); + } } } }; diff --git a/Commands/ping.js b/Commands/ping.js index 72ef024..3ee61e0 100644 --- a/Commands/ping.js +++ b/Commands/ping.js @@ -20,12 +20,13 @@ ***************************************************************************/ import { SlashCommandBuilder } from 'discord.js'; - +import i18next from '../Utilities/i18n.js'; +const t = i18next.t; export default { data: new SlashCommandBuilder() .setName('ping') .setDescription('Pong!'), async execute(interaction, bot) { - return await interaction.reply(`Pong! ${Math.round(bot.ws.ping)}ms`); + return await interaction.reply(`${t('pong')} ${Math.round(bot.ws.ping)}ms`); } }; diff --git a/Commands/play.js b/Commands/play.js index 49f0d3e..d514cfe 100644 --- a/Commands/play.js +++ b/Commands/play.js @@ -21,12 +21,14 @@ import { SlashCommandBuilder } from 'discord.js'; import { inputAudio } from '../AudioBackend/QueueSystem.js'; -import { files, isAudioStatePaused, toggleAudioState } from '../AudioBackend/AudioControl.js'; +import { files, isAudioStatePaused, playerStatus, toggleAudioState } from '../AudioBackend/AudioControl.js'; import { audio } from '../AudioBackend/PlayAudio.js'; import { PermissionFlagsBits } from 'discord-api-types/v10'; import { readFileSync } from 'node:fs'; import { votes } from '../Utilities/Voting.js'; +import i18next from '../Utilities/i18n.js'; +const t = i18next.t; const { djRole, ownerID } = JSON.parse(readFileSync('./config.json', 'utf-8')); export let integer; @@ -41,24 +43,28 @@ export default { ), 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 }); - if (!interaction.member.roles.cache.has(djRole) && interaction.user.id !== ownerID && !interaction.member.permission.has(PermissionFlagsBits.ManageGuild)) return interaction.reply({ content: 'You need a specific role to execute this command', ephemeral: true }); + if (!interaction.member.voice.channel) return await interaction.reply({ content: t('voicePermission'), ephemeral: true }); + if (!interaction.member.roles.cache.has(djRole) && interaction.user.id !== ownerID && !interaction.memberPermissions.has(PermissionFlagsBits.ManageGuild)) return interaction.reply({ content: t('rolePermission'), ephemeral: true }); integer = interaction.options.getInteger('int'); if (integer) { if (integer < files.length) { await inputAudio(bot, integer); await votes.clear(); - return await interaction.reply({ content: `Now playing: ${audio}`, ephemeral: true }); + return await interaction.reply({ content: t('nowPlayingFile', { audio }), ephemeral: true }); } else { - return await interaction.reply({ content: 'Number is too big, choose a number that\'s less than ' + files.length + '.', ephemeral: true }); + return await interaction.reply({ content: t('numBig', { files: files.length }), ephemeral: true }); } } - if (isAudioStatePaused) { - toggleAudioState(); - return await interaction.reply({ content: 'Resuming music', ephemeral: true }); + if (playerStatus === 2) { + return await interaction.reply({ content: t('statusStopped'), ephemeral: true }); } else { - return await interaction.reply({ content: 'Music is already playing', ephemeral: true }); + if (isAudioStatePaused) { + toggleAudioState(); + return await interaction.reply({ content: t('resumingMusic'), ephemeral: true }); + } else { + return await interaction.reply({ content: t('resumedAlready'), ephemeral: true }); + } } } }; diff --git a/Commands/previous.js b/Commands/previous.js index 5acca47..c5a45b5 100644 --- a/Commands/previous.js +++ b/Commands/previous.js @@ -21,19 +21,21 @@ import { SlashCommandBuilder } from 'discord.js'; import { voteSkip } from '../Utilities/Voting.js'; +import i18next from '../Utilities/i18n.js'; +const t = i18next.t; export default { data: new SlashCommandBuilder() .setName('previous') .setDescription('Goes to previous music') - /* .addSubcommand(subcommand => + .addSubcommand(subcommand => subcommand.setName('vote') - .setDescription('Voting to skip this audio track')) */ + .setDescription('Voting to skip this audio track')) .addSubcommand(subcommand => subcommand.setName('force') .setDescription('Forces skip this audio track')), 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 }); + if (!interaction.member.voice.channel) return await interaction.reply({ content: t('voicePermission'), ephemeral: true }); await voteSkip(interaction, bot); } }; diff --git a/Commands/reshuffle.js b/Commands/reshuffle.js index 340c91b..459575f 100644 --- a/Commands/reshuffle.js +++ b/Commands/reshuffle.js @@ -23,23 +23,25 @@ import { SlashCommandBuilder } from 'discord.js'; import { shufflePlaylist } from '../AudioBackend/QueueSystem.js'; import { PermissionFlagsBits } from 'discord-api-types/v10'; import { readFileSync } from 'node:fs'; -import { audioState } from '../AudioBackend/AudioControl.js'; +import { audioState, playerStatus } from '../AudioBackend/AudioControl.js'; +import i18next from '../Utilities/i18n.js'; + // import config from './config.json' assert {type: 'json'} const { shuffle, djRole, ownerID } = JSON.parse(readFileSync('./config.json', 'utf-8')); - +const t = i18next.t; export default { data: new SlashCommandBuilder() .setName('reshuffle') .setDescription('Reshuffles the playlist'), 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 }); - if (!interaction.member.roles.cache.has(djRole) && interaction.user.id !== ownerID && !interaction.member.permission.has(PermissionFlagsBits.ManageGuild)) return interaction.reply({ content: 'You need a specific role to execute this command', ephemeral: true }); - + if (!interaction.member.voice.channel) return await interaction.reply({ content: t('voicePermission'), ephemeral: true }); + if (!interaction.member.roles.cache.has(djRole) && interaction.user.id !== ownerID && !interaction.memberPermissions.has(PermissionFlagsBits.ManageGuild)) return interaction.reply({ content: t('rolePermission'), ephemeral: true }); + if (playerStatus === 2) return await interaction.reply({ content: t('playerStopped'), ephemeral: true }); async function shuffleDetected(bot) { - await interaction.reply({ content: 'Reshuffling the playlist...', ephemeral: true }); + await interaction.reply({ content: t('reshufflePlaylist'), ephemeral: true }); await audioState(2); await shufflePlaylist(bot); } - 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 }); + return (shuffle) ? await shuffleDetected(bot) : await interaction.reply({ content: t('reShuffleDisabled'), ephemeral: true }); } }; diff --git a/Commands/shutdown.js b/Commands/shutdown.js index eefbab3..6e26f83 100644 --- a/Commands/shutdown.js +++ b/Commands/shutdown.js @@ -22,14 +22,17 @@ import { SlashCommandBuilder } from 'discord.js'; import { stopBot } from '../AudioBackend/Shutdown.js'; import { readFileSync } from 'node:fs'; +import i18next from '../Utilities/i18n.js'; + +const t = i18next.t; const { ownerID } = JSON.parse(readFileSync('./config.json', 'utf-8')); export default { data: new SlashCommandBuilder() .setName('shutdown') .setDescription('Powers off the bot'), async execute(interaction, bot) { - if (interaction.user.id !== ownerID) return interaction.reply({ content: 'You need to be the creator of this bot to execute this command', ephemeral: true }); - await interaction.reply({ content: 'Powering off...', ephemeral: true }); + if (interaction.user.id !== ownerID) return interaction.reply({ content: t('creatorPermission'), ephemeral: true }); + await interaction.reply({ content: t('powerOff', { bot: bot.user.username }), ephemeral: true }); return await stopBot(bot, interaction); } }; diff --git a/Commands/status.js b/Commands/status.js index aeb909d..ee02126 100644 --- a/Commands/status.js +++ b/Commands/status.js @@ -22,9 +22,11 @@ import { EmbedBuilder, SlashCommandBuilder } from 'discord.js'; import { parseFile } from 'music-metadata'; import { audio, metadataEmpty, duration, audioTitle, currentTrack } from '../AudioBackend/PlayAudio.js'; -import { files, playerState } from '../AudioBackend/AudioControl.js'; +import { files, playerState, playerStatus } from '../AudioBackend/AudioControl.js'; import { votes } from '../Utilities/Voting.js'; +import i18next from '../Utilities/i18n.js'; +const t = i18next.t; export default { data: new SlashCommandBuilder() .setName('status') @@ -38,19 +40,19 @@ export default { // Get the members of the voice channel who have not voted yet const voiceChannel = interaction.member.voice.channel; - const members = voiceChannel.members.filter(m => !votes.has(m.id)); + const members = voiceChannel.members.filter(m => !votes.has(m.id) && !m.user.bot); // Calculate the number of votes required to skip the audio track - const votesRequired = Math.ceil((members.size - votes.size) / 2); + const votesRequired = Math.ceil(members.size / 2); if (audioID >= files.length) { - audioName = 'Playlist Finished'; + audioName = t('playlistDone'); } else { audioName = files[audioID]; if (!metadataEmpty) { try { const { common } = await parseFile('music/' + audioName); - audioName = common.title; + audioName = common.title ? common.title : audioName.split('.').slice(0, -1).join('.'); } catch (error) { console.error(error.message); } @@ -60,25 +62,27 @@ export default { } const controlEmbed = new EmbedBuilder() - .setAuthor({ name: `${bot.user.username} Status`, iconURL: bot.user.avatarURL() }) + .setAuthor({ name: t('statusTitle', { bot: bot.user.username }), iconURL: bot.user.avatarURL() }) .addFields( - { name: 'State', value: `${playerState}` }, - { name: 'Tracks', value: `${audioID}/${files.length}` }, - { name: 'Duration', value: `${duration}` }, - { name: 'Votes Needed', value: `${votesRequired}` } + { name: t('statusState'), value: `${playerState}` }, + { name: t('statusTracks'), value: `${audioID}/${files.length}` }, + { name: t('musicDuration'), value: `${duration}` }, + { name: t('statusVotesNeeded'), value: `${votesRequired}` } ) .setColor('#0066ff'); - if (metadataEmpty) { - controlEmbed.addFields( - { name: 'Currently Playing', value: `${audio}` }, - { name: 'Up Next', value: `${audioName}` } - ); - } else { - controlEmbed.addFields( - { name: 'Currently Playing', value: `${audioTitle}` }, - { name: 'Up Next', value: `${audioName}` } - ); + if (playerStatus === 0 || playerStatus === 1) { + if (metadataEmpty) { + controlEmbed.addFields( + { name: t('currentlyPlaying'), value: `${audio}` }, + { name: t('upNext'), value: `${audioName}` } + ); + } else { + controlEmbed.addFields( + { name: t('currentlyPlaying'), value: `${audioTitle}` }, + { name: t('upNext'), value: `${audioName}` } + ); + } } interaction.reply({ embeds: [controlEmbed] }); } |
