aboutsummaryrefslogtreecommitdiff
path: root/Commands
diff options
context:
space:
mode:
Diffstat (limited to 'Commands')
-rw-r--r--Commands/about.js23
-rw-r--r--Commands/join.js14
-rw-r--r--Commands/leave.js13
-rw-r--r--Commands/list.js11
-rw-r--r--Commands/next.js9
-rw-r--r--Commands/pause.js20
-rw-r--r--Commands/ping.js5
-rw-r--r--Commands/play.js24
-rw-r--r--Commands/previous.js8
-rw-r--r--Commands/reshuffle.js16
-rw-r--r--Commands/shutdown.js7
-rw-r--r--Commands/status.js44
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] });
}