diff --git a/src/bot.ts b/src/bot.ts index 29bf7046..18269053 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -4,6 +4,7 @@ import {Logger} from "./logger"; import {container, LogLevel, SapphireClient} from "@sapphire/framework"; import "@sapphire/plugin-logger/register"; import "@sapphire/plugin-i18next/register"; +import "./container"; config(); const client = new SapphireClient({ diff --git a/src/commands/clear.ts b/src/commands/clear.ts index 96561cb2..2160ac06 100644 --- a/src/commands/clear.ts +++ b/src/commands/clear.ts @@ -1,26 +1,26 @@ -import { SlashCommandBuilder } from "@discordjs/builders"; -import { ApplyOptions } from "@sapphire/decorators"; -import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; -import { CommandInteraction, MessageEmbed } from "discord.js"; -@ApplyOptions({ - description: "clear the queue", - preconditions: ["GuildOnly", "BotInVoice", "InSameVoice"] -}) -export class ClearCommand extends Command { - public registerApplicationCommands(registry: ApplicationCommandRegistry) { - registry.registerChatInputCommand(new SlashCommandBuilder().setName(this.name).setDescription(this.description)); - } - public async chatInputRun(interaction: CommandInteraction) { - await interaction.deferReply(); - this.container.player.getQueue(interaction.guild).clear(); - interaction.editReply({ - embeds: [ - new MessageEmbed({ - color: "GREEN", - title: "Queue cleared", - description: "The queue has been cleared." - }) - ] - }); - } -} +import { SlashCommandBuilder } from "@discordjs/builders"; +import { ApplyOptions } from "@sapphire/decorators"; +import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; +import { CommandInteraction, MessageEmbed } from "discord.js"; +@ApplyOptions({ + description: "clear the queue", + preconditions: ["GuildOnly", "BotInVoice", "InSameVoice"] +}) +export class ClearCommand extends Command { + public registerApplicationCommands(registry: ApplicationCommandRegistry) { + registry.registerChatInputCommand(new SlashCommandBuilder().setName(this.name).setDescription(this.description)); + } + public async chatInputRun(interaction: CommandInteraction) { + await interaction.deferReply(); + this.container.player.getQueue(interaction.guild).clear(); + interaction.editReply({ + embeds: [ + new MessageEmbed({ + color: "GREEN", + title: this.container.getTranslation(interaction, "commands/clear:success.title"), + description: this.container.getTranslation(interaction, "commands/clear:success.description") + }) + ] + }); + } +} diff --git a/src/commands/disconnect.ts b/src/commands/disconnect.ts index 11979b5e..950e5a80 100644 --- a/src/commands/disconnect.ts +++ b/src/commands/disconnect.ts @@ -1,33 +1,33 @@ -import { SlashCommandBuilder } from "@discordjs/builders"; -import { ApplyOptions } from "@sapphire/decorators"; -import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; -import { CommandInteraction, MessageEmbed } from "discord.js"; - -@ApplyOptions({ - description: "let the bot disconnect from the currently joined voice channel", - preconditions: ["GuildOnly", "BotInVoice", "InSameVoice"] -}) -export class DisconnectCommand extends Command { - public registerApplicationCommands(registry: ApplicationCommandRegistry) { - registry.registerChatInputCommand(new SlashCommandBuilder().setName(this.name).setDescription(this.description)); - } - - public async chatInputRun(interaction: CommandInteraction) { - await interaction.deferReply(); - - const {guild} = interaction, - {channel} = guild.me.voice; - - this.container.player.deleteQueue(guild); - - interaction.editReply({ - embeds: [ - new MessageEmbed({ - color: "GREEN", - title: "Disconnect", - description: `Disconnected from \`${channel.name}\` 🔊` - }) - ] - }); - } +import { SlashCommandBuilder } from "@discordjs/builders"; +import { ApplyOptions } from "@sapphire/decorators"; +import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; +import { CommandInteraction, MessageEmbed } from "discord.js"; + +@ApplyOptions({ + description: "let the bot disconnect from the currently joined voice channel", + preconditions: ["GuildOnly", "BotInVoice", "InSameVoice"] +}) +export class DisconnectCommand extends Command { + public registerApplicationCommands(registry: ApplicationCommandRegistry) { + registry.registerChatInputCommand(new SlashCommandBuilder().setName(this.name).setDescription(this.description)); + } + + public async chatInputRun(interaction: CommandInteraction) { + await interaction.deferReply(); + + const {guild} = interaction, + {channel} = guild.me.voice; + + this.container.player.deleteQueue(guild); + + interaction.editReply({ + embeds: [ + new MessageEmbed({ + color: "GREEN", + title: this.container.getTranslation(interaction, "commands/disconnect:success.title"), + description: this.container.getTranslation(interaction, "commands/disconnect:success.description", { replace: { channel: channel.name } }) + }) + ] + }); + } } \ No newline at end of file diff --git a/src/commands/invite.ts b/src/commands/invite.ts index f6ca5e3c..d0f27629 100644 --- a/src/commands/invite.ts +++ b/src/commands/invite.ts @@ -1,37 +1,37 @@ -import { SlashCommandBuilder } from "@discordjs/builders"; -import { ApplyOptions } from "@sapphire/decorators"; -import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; -import { stripIndents } from "common-tags"; -import { CommandInteraction, MessageEmbed } from "discord.js"; - -@ApplyOptions({ - description: "get the invite link of the bot" -}) -export class InviteCommand extends Command { - public registerApplicationCommands(registry: ApplicationCommandRegistry) { - registry.registerChatInputCommand(new SlashCommandBuilder().setName(this.name).setDescription(this.description)); - } - - public async chatInputRun(interaction: CommandInteraction) { - await interaction.deferReply({ephemeral: true}); - - const {client} = interaction; - interaction.editReply({ - embeds: [ - new MessageEmbed({ - color: "BLUE", - title: "OurTube invite links", - description: stripIndents` - [Recommended](${client.generateInvite({ - scopes: ["bot", "applications.commands"] - })}) - [Admin](${client.generateInvite({ - scopes: ["bot", "applications.commands"], - permissions: ["ADMINISTRATOR"] - })}) - ` - }) - ] - }); - } +import { SlashCommandBuilder } from "@discordjs/builders"; +import { ApplyOptions } from "@sapphire/decorators"; +import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; +import { stripIndents } from "common-tags"; +import { CommandInteraction, MessageEmbed } from "discord.js"; + +@ApplyOptions({ + description: "get the invite link of the bot" +}) +export class InviteCommand extends Command { + public registerApplicationCommands(registry: ApplicationCommandRegistry) { + registry.registerChatInputCommand(new SlashCommandBuilder().setName(this.name).setDescription(this.description)); + } + + public async chatInputRun(interaction: CommandInteraction) { + await interaction.deferReply({ephemeral: true}); + + const {client} = interaction; + interaction.editReply({ + embeds: [ + new MessageEmbed({ + color: "BLUE", + title: this.container.getTranslation(interaction, "commands/invite:success.title"), + description: stripIndents` + [${this.container.getTranslation(interaction, "commands/invite:success.recommended")}](${client.generateInvite({ + scopes: ["bot", "applications.commands"] + })}) + [${this.container.getTranslation(interaction, "commands/invite:success.admin")}](${client.generateInvite({ + scopes: ["bot", "applications.commands"], + permissions: ["ADMINISTRATOR"] + })}) + ` + }) + ] + }); + } } \ No newline at end of file diff --git a/src/commands/join.ts b/src/commands/join.ts index 471bafc3..b24831e7 100644 --- a/src/commands/join.ts +++ b/src/commands/join.ts @@ -1,70 +1,70 @@ -import { SlashCommandBuilder } from "@discordjs/builders"; -import { ApplyOptions } from "@sapphire/decorators"; -import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; -import { CommandInteraction, GuildMember, MessageEmbed } from "discord.js"; - -@ApplyOptions({ - description: "let the bot join your voice channel", - preconditions: ["GuildOnly", "UserInVoice"], - requiredClientPermissions: ["CONNECT"] -}) -export class JoinCommand extends Command { - public registerApplicationCommands(registry: ApplicationCommandRegistry) { - registry.registerChatInputCommand(new SlashCommandBuilder().setName(this.name).setDescription(this.description)); - } - - /** - * Join the voice channel of the interaction member - * @param interaction The interaction to get guild data from - * @returns The created queue of the interaction guild - */ - public async joinChannel(interaction: CommandInteraction) { - const {member, guild} = interaction, - {player} = this.container, - {voice} = member as GuildMember; - - const queue = player.createQueue(guild, { - leaveOnEmpty: false, - leaveOnEnd: false, - ytdlOptions: { - quality: "highest", - filter: "audioonly", - highWaterMark: 1 << 25, - dlChunkSize: 0 - }, - metadata: interaction - }); - - try { - if (!queue.connection) await queue.connect(voice.channel); - } catch { - player.deleteQueue(guild); - return void interaction.editReply({ - embeds: [ - new MessageEmbed({ - color: "RED", - title: "Can't join voice channel", - description: "Unable to join your voice channel" - }) - ] - }); - } - - return queue; - } - - public async chatInputRun(interaction: CommandInteraction) { - await interaction.deferReply(); - if(!await this.joinChannel(interaction)) return; - - interaction.editReply({ - embeds: [ - new MessageEmbed({ - color: "GREEN", - title: "Join", - description: `Joined \`${(interaction.member as GuildMember).voice.channel.name}\` 🔊` - }) - ] - }); - } +import { SlashCommandBuilder } from "@discordjs/builders"; +import { ApplyOptions } from "@sapphire/decorators"; +import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; +import { CommandInteraction, GuildMember, MessageEmbed } from "discord.js"; + +@ApplyOptions({ + description: "let the bot join your voice channel", + preconditions: ["GuildOnly", "UserInVoice"], + requiredClientPermissions: ["CONNECT"] +}) +export class JoinCommand extends Command { + public registerApplicationCommands(registry: ApplicationCommandRegistry) { + registry.registerChatInputCommand(new SlashCommandBuilder().setName(this.name).setDescription(this.description)); + } + + /** + * Join the voice channel of the interaction member + * @param interaction The interaction to get guild data from + * @returns The created queue of the interaction guild + */ + public async joinChannel(interaction: CommandInteraction) { + const {member, guild} = interaction, + {player} = this.container, + {voice} = member as GuildMember; + + const queue = player.createQueue(guild, { + leaveOnEmpty: false, + leaveOnEnd: false, + ytdlOptions: { + quality: "highest", + filter: "audioonly", + highWaterMark: 1 << 25, + dlChunkSize: 0 + }, + metadata: interaction + }); + + try { + if (!queue.connection) await queue.connect(voice.channel); + } catch { + player.deleteQueue(guild); + return void interaction.editReply({ + embeds: [ + new MessageEmbed({ + color: "RED", + title: this.container.getTranslation(interaction, "commands/join:error.title"), + description: this.container.getTranslation(interaction, "commands/join:error.description") + }) + ] + }); + } + + return queue; + } + + public async chatInputRun(interaction: CommandInteraction) { + await interaction.deferReply(); + if(!await this.joinChannel(interaction)) return; + + interaction.editReply({ + embeds: [ + new MessageEmbed({ + color: "GREEN", + title: this.container.getTranslation(interaction, "commands/join:success.title"), + description: this.container.getTranslation(interaction, "commands/join:success.description", { replace: { channel: (interaction.member as GuildMember).voice.channel.name}}) + }) + ] + }); + } } \ No newline at end of file diff --git a/src/commands/nowPlaying.ts b/src/commands/nowPlaying.ts index 9db5a5fc..d486ddbf 100644 --- a/src/commands/nowPlaying.ts +++ b/src/commands/nowPlaying.ts @@ -1,48 +1,48 @@ -import { SlashCommandBuilder } from "@discordjs/builders"; -import { ApplyOptions } from "@sapphire/decorators"; -import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; -import { stripIndents } from "common-tags"; -import { CommandInteraction, MessageEmbed } from "discord.js"; - -@ApplyOptions({ - description: "show the current playing song", - preconditions: ["GuildOnly", "BotInVoice", "InSameVoice"] -}) -export class NowPlayingCommand extends Command { - public registerApplicationCommands(registry: ApplicationCommandRegistry) { - registry.registerChatInputCommand(new SlashCommandBuilder().setName("nowplaying").setDescription(this.description)); - } - - public async chatInputRun(interaction: CommandInteraction) { - await interaction.deferReply({ephemeral: true}); - - const queue = this.container.player.getQueue(interaction.guild), - nowPlaying = queue?.nowPlaying(); - - if (!nowPlaying) - return interaction.editReply({ - embeds: [ - new MessageEmbed({ - color: "RED", - title: "Not playing", - description: "I'm not playing anything" - }) - ] - }); - - interaction.editReply({ - embeds: [ - new MessageEmbed({ - color: "BLUE", - title: "Now playing", - description: stripIndents` - [${nowPlaying.title}](${nowPlaying.url}) - ${queue.createProgressBar()} - - Requested by: ${nowPlaying.requestedBy} - ` - }) - ] - }); - } +import { SlashCommandBuilder } from "@discordjs/builders"; +import { ApplyOptions } from "@sapphire/decorators"; +import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; +import { stripIndents } from "common-tags"; +import { CommandInteraction, MessageEmbed } from "discord.js"; + +@ApplyOptions({ + description: "show the current playing song", + preconditions: ["GuildOnly", "BotInVoice", "InSameVoice"] +}) +export class NowPlayingCommand extends Command { + public registerApplicationCommands(registry: ApplicationCommandRegistry) { + registry.registerChatInputCommand(new SlashCommandBuilder().setName("nowplaying").setDescription(this.description)); + } + + public async chatInputRun(interaction: CommandInteraction) { + await interaction.deferReply({ephemeral: true}); + + const queue = this.container.player.getQueue(interaction.guild), + nowPlaying = queue?.nowPlaying(); + + if (!nowPlaying) + return interaction.editReply({ + embeds: [ + new MessageEmbed({ + color: "RED", + title: this.container.getTranslation(interaction, "commands/nowplaying:error.title"), + description: this.container.getTranslation(interaction, "commands/nowplaying:error.description") + }) + ] + }); + + interaction.editReply({ + embeds: [ + new MessageEmbed({ + color: "BLUE", + title: this.container.getTranslation(interaction, "commands/nowplaying:success.title"), + description: stripIndents` + [${nowPlaying.title}](${nowPlaying.url}) + ${queue.createProgressBar()} + + ${this.container.getTranslation(interaction, "commands/nowplaying:success.requestedBy", { replace: { user: nowPlaying.requestedBy.toString() } })} + ` + }) + ] + }); + } } \ No newline at end of file diff --git a/src/commands/pause.ts b/src/commands/pause.ts index c3a13e27..a4d0942c 100644 --- a/src/commands/pause.ts +++ b/src/commands/pause.ts @@ -1,32 +1,32 @@ -import { SlashCommandBuilder } from "@discordjs/builders"; -import { ApplyOptions } from "@sapphire/decorators"; -import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; -import { CommandInteraction, MessageEmbed } from "discord.js"; - -@ApplyOptions({ - description: "pause the current song", - preconditions: ["GuildOnly", "BotInVoice", "InSameVoice"] -}) -export class PauseCommand extends Command { - public registerApplicationCommands(registry: ApplicationCommandRegistry) { - registry.registerChatInputCommand(new SlashCommandBuilder().setName(this.name).setDescription(this.description)); - } - - public async chatInputRun(interaction: CommandInteraction) { - await interaction.deferReply({ephemeral: true}); - - const queue = this.container.player.getQueue(interaction.guild); - - queue.setPaused(true); - - interaction.editReply({ - embeds: [ - new MessageEmbed({ - color: "GREEN", - title: "Pause", - description: `Paused the current playing song` - }) - ] - }); - } +import { SlashCommandBuilder } from "@discordjs/builders"; +import { ApplyOptions } from "@sapphire/decorators"; +import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; +import { CommandInteraction, MessageEmbed } from "discord.js"; + +@ApplyOptions({ + description: "pause the current song", + preconditions: ["GuildOnly", "BotInVoice", "InSameVoice"] +}) +export class PauseCommand extends Command { + public registerApplicationCommands(registry: ApplicationCommandRegistry) { + registry.registerChatInputCommand(new SlashCommandBuilder().setName(this.name).setDescription(this.description)); + } + + public async chatInputRun(interaction: CommandInteraction) { + await interaction.deferReply({ephemeral: true}); + + const queue = this.container.player.getQueue(interaction.guild); + + queue.setPaused(true); + + interaction.editReply({ + embeds: [ + new MessageEmbed({ + color: "GREEN", + title: this.container.getTranslation(interaction, "commands/pause:success.title"), + description: this.container.getTranslation(interaction, "commands/pause:success.description") + }) + ] + }); + } } \ No newline at end of file diff --git a/src/commands/play.ts b/src/commands/play.ts index cc814352..0e9489af 100644 --- a/src/commands/play.ts +++ b/src/commands/play.ts @@ -1,78 +1,78 @@ -import { SlashCommandBuilder } from "@discordjs/builders"; -import { ApplyOptions } from "@sapphire/decorators"; -import { ApplicationCommandRegistry, Command, CommandOptions, SapphireClient } from "@sapphire/framework"; -import { QueryType } from "discord-player"; -import { CommandInteraction, MessageEmbed } from "discord.js"; -import { JoinCommand } from "./join"; - -@ApplyOptions({ - description: "play a song", - preconditions: ["GuildOnly", "UserInVoice"], - requiredClientPermissions: ["CONNECT", "SPEAK"] -}) -export class PlayCommand extends Command { - public registerApplicationCommands(registry: ApplicationCommandRegistry) { - registry.registerChatInputCommand( - new SlashCommandBuilder() - .setName(this.name) - .setDescription(this.description) - .addStringOption(input => - input - .setName("query") - .setDescription("the song to play") - .setRequired(true) - ) - .addStringOption(input => - input - .setName("type") - .setDescription("where to search for the song") - .addChoices(Object.values(QueryType) - .filter(value => !["auto", "facebook", "vimeo", "arbitrary", "reverbnation"].includes(value.toString())) - .map(value => [ - value.toString().replace("_", " "), - value.toString() - ]) - ) - ) - ); - } - - public async chatInputRun(interaction: CommandInteraction) { - await interaction.deferReply(); - - const client = interaction.client as SapphireClient, - query = interaction.options.getString("query", true), - result = await this.container.player.search(query, { - requestedBy: interaction.user, - searchEngine: interaction.options.getString("type") ?? QueryType.AUTO - }); - - if (!result || !result.tracks.length) - return interaction.editReply({ - embeds: [ - new MessageEmbed({ - color: "RED", - title: "No song found", - description: "No results were found" - }) - ] - }); - - const queue = await (client.stores.get("commands").get("join") as JoinCommand).joinChannel(interaction); - if (!queue) return; - - const type = result.playlist ? "playlist" : "song"; - - await interaction.editReply({ - embeds: [ - new MessageEmbed({ - color: "BLUE", - title: `Loading ${type}`, - description: `Now loading your requested ${type}` - }) - ] - }); - result.playlist ? queue.addTracks(result.tracks) : queue.addTrack(result.tracks[0]); - if (!queue.playing) await queue.play(); - } +import { SlashCommandBuilder } from "@discordjs/builders"; +import { ApplyOptions } from "@sapphire/decorators"; +import { ApplicationCommandRegistry, Command, CommandOptions, SapphireClient } from "@sapphire/framework"; +import { QueryType } from "discord-player"; +import { CommandInteraction, MessageEmbed } from "discord.js"; +import { JoinCommand } from "./join"; + +@ApplyOptions({ + description: "play a song", + preconditions: ["GuildOnly", "UserInVoice"], + requiredClientPermissions: ["CONNECT", "SPEAK"] +}) +export class PlayCommand extends Command { + public registerApplicationCommands(registry: ApplicationCommandRegistry) { + registry.registerChatInputCommand( + new SlashCommandBuilder() + .setName(this.name) + .setDescription(this.description) + .addStringOption(input => + input + .setName("query") + .setDescription("the song to play") + .setRequired(true) + ) + .addStringOption(input => + input + .setName("type") + .setDescription("where to search for the song") + .addChoices(Object.values(QueryType) + .filter(value => !["auto", "facebook", "vimeo", "arbitrary", "reverbnation"].includes(value.toString())) + .map(value => [ + value.toString().replace("_", " "), + value.toString() + ]) + ) + ) + ); + } + + public async chatInputRun(interaction: CommandInteraction) { + await interaction.deferReply(); + + const client = interaction.client as SapphireClient, + query = interaction.options.getString("query", true), + result = await this.container.player.search(query, { + requestedBy: interaction.user, + searchEngine: interaction.options.getString("type") ?? QueryType.AUTO + }); + + if (!result || !result.tracks.length) + return interaction.editReply({ + embeds: [ + new MessageEmbed({ + color: "RED", + title: this.container.getTranslation(interaction, "commands/play:error.title"), + description: this.container.getTranslation(interaction, "commands/play:error.description") + }) + ] + }); + + const queue = await (client.stores.get("commands").get("join") as JoinCommand).joinChannel(interaction); + if (!queue) return; + + const type = result.playlist ? "playlist" : "song"; + + await interaction.editReply({ + embeds: [ + new MessageEmbed({ + color: "BLUE", + title: this.container.getTranslation(interaction, `commands/play:success.title.${type}`), + description: this.container.getTranslation(interaction, `commands/play:success.description.${type}`) + }) + ] + }); + result.playlist ? queue.addTracks(result.tracks) : queue.addTrack(result.tracks[0]); + if (!queue.playing) await queue.play(); + } } \ No newline at end of file diff --git a/src/commands/queue.ts b/src/commands/queue.ts index 329599d3..828c626f 100644 --- a/src/commands/queue.ts +++ b/src/commands/queue.ts @@ -1,59 +1,59 @@ -import { SlashCommandBuilder } from "@discordjs/builders"; -import { ApplyOptions } from "@sapphire/decorators"; -import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; -import { CommandInteraction, MessageEmbed } from "discord.js"; - -@ApplyOptions({ - description: "show the current queue", - preconditions: ["GuildOnly", "BotInVoice", "InSameVoice"] -}) -export class QueueCommand extends Command { - public registerApplicationCommands(registry: ApplicationCommandRegistry) { - registry.registerChatInputCommand(new SlashCommandBuilder().setName(this.name).setDescription(this.description)); - } - - public async chatInputRun(interaction: CommandInteraction) { - await interaction.deferReply({ephemeral: true}); - - const queue = this.container.player.getQueue(interaction.guild), - nowPlaying = queue?.nowPlaying(); - - if (!queue.tracks.length && !nowPlaying) { - return interaction.editReply({ - embeds: [ - new MessageEmbed({ - color: "RED", - title: "Queue empty", - description: "There are no songs in the queue" - }) - ] - }); - } - - interaction.editReply({ - embeds: [ - new MessageEmbed({ - color: "BLUE", - title: "Queue", - fields: [ - { - name: "__Now Playing__", - value: `${nowPlaying.author} | [${nowPlaying.title}](${nowPlaying.url}) | \`${nowPlaying.duration}\`` - }, - { - name: "__Up Next__", - value: queue.tracks - .map( - (track, index) => - `${index + 1}. ${track.author} | [${track.title}](${track.url}) | \`${ - track.duration - }\`` - ) - .join("\n") - } - ].filter(field => field.value) - }) - ] - }); - } +import { SlashCommandBuilder } from "@discordjs/builders"; +import { ApplyOptions } from "@sapphire/decorators"; +import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; +import { CommandInteraction, MessageEmbed } from "discord.js"; + +@ApplyOptions({ + description: "show the current queue", + preconditions: ["GuildOnly", "BotInVoice", "InSameVoice"] +}) +export class QueueCommand extends Command { + public registerApplicationCommands(registry: ApplicationCommandRegistry) { + registry.registerChatInputCommand(new SlashCommandBuilder().setName(this.name).setDescription(this.description)); + } + + public async chatInputRun(interaction: CommandInteraction) { + await interaction.deferReply({ephemeral: true}); + + const queue = this.container.player.getQueue(interaction.guild), + nowPlaying = queue?.nowPlaying(); + + if (!queue.tracks.length && !nowPlaying) { + return interaction.editReply({ + embeds: [ + new MessageEmbed({ + color: "RED", + title: this.container.getTranslation(interaction, "commands/queue:error.title"), + description: this.container.getTranslation(interaction, "commands/queue:error.description") + }) + ] + }); + } + + interaction.editReply({ + embeds: [ + new MessageEmbed({ + color: "BLUE", + title: this.container.getTranslation(interaction, "commands/queue:success.title"), + fields: [ + { + name: `__${this.container.getTranslation(interaction, "commands/queue:success.nowPlaying")}__`, + value: `${nowPlaying.author} | [${nowPlaying.title}](${nowPlaying.url}) | \`${nowPlaying.duration}\`` + }, + { + name: `__${this.container.getTranslation(interaction, "commands/queue:success.upNext")}__`, + value: queue.tracks + .map( + (track, index) => + `${index + 1}. ${track.author} | [${track.title}](${track.url}) | \`${ + track.duration + }\`` + ) + .join("\n") + } + ].filter(field => field.value) + }) + ] + }); + } } \ No newline at end of file diff --git a/src/commands/remove.ts b/src/commands/remove.ts index fa7d73ef..1c49a7af 100644 --- a/src/commands/remove.ts +++ b/src/commands/remove.ts @@ -1,42 +1,42 @@ -import { SlashCommandBuilder } from "@discordjs/builders"; -import { ApplyOptions } from "@sapphire/decorators"; -import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; -import { CommandInteraction, MessageEmbed } from "discord.js"; - -@ApplyOptions({ - description: "remove a song from the current queue", - preconditions: ["GuildOnly", "BotInVoice", "InSameVoice"] -}) -export class RemoveCommand extends Command { - public registerApplicationCommands(registry: ApplicationCommandRegistry) { - registry.registerChatInputCommand( - new SlashCommandBuilder() - .setName(this.name) - .setDescription(this.description) - .addIntegerOption(input => - input - .setName("index") - .setDescription("The queue index of the song to remove") - .setRequired(true) - ) - ); - } - - public async chatInputRun(interaction: CommandInteraction) { - await interaction.deferReply({ephemeral: true}); - - const queue = this.container.player.getQueue(interaction.guild), - index = interaction.options.getInteger("index"), - removed = queue.remove(index-1); - - interaction.editReply({ - embeds: [ - new MessageEmbed({ - color: "GREEN", - title: "Remove", - description: `Removed [${removed.title}](${removed.url}) from the queue at index ${index}` - }) - ] - }); - } +import { SlashCommandBuilder } from "@discordjs/builders"; +import { ApplyOptions } from "@sapphire/decorators"; +import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; +import { CommandInteraction, MessageEmbed } from "discord.js"; + +@ApplyOptions({ + description: "remove a song from the current queue", + preconditions: ["GuildOnly", "BotInVoice", "InSameVoice"] +}) +export class RemoveCommand extends Command { + public registerApplicationCommands(registry: ApplicationCommandRegistry) { + registry.registerChatInputCommand( + new SlashCommandBuilder() + .setName(this.name) + .setDescription(this.description) + .addIntegerOption(input => + input + .setName("index") + .setDescription("The queue index of the song to remove") + .setRequired(true) + ) + ); + } + + public async chatInputRun(interaction: CommandInteraction) { + await interaction.deferReply({ephemeral: true}); + + const queue = this.container.player.getQueue(interaction.guild), + index = interaction.options.getInteger("index"), + removed = queue.remove(index-1); + + interaction.editReply({ + embeds: [ + new MessageEmbed({ + color: "GREEN", + title: this.container.getTranslation(interaction, "commands/remove:success.title"), + description: this.container.getTranslation(interaction, "commands/remove:success.description", { replace: { track: `[${removed.title}](${removed.url})`, index } }) + }) + ] + }); + } } \ No newline at end of file diff --git a/src/commands/resume.ts b/src/commands/resume.ts index ea7fc42e..39935cb4 100644 --- a/src/commands/resume.ts +++ b/src/commands/resume.ts @@ -1,32 +1,32 @@ -import { SlashCommandBuilder } from "@discordjs/builders"; -import { ApplyOptions } from "@sapphire/decorators"; -import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; -import { CommandInteraction, MessageEmbed } from "discord.js"; - -@ApplyOptions({ - description: "resume the current song", - preconditions: ["GuildOnly", "BotInVoice", "InSameVoice"] -}) -export class ResumeCommand extends Command { - public registerApplicationCommands(registry: ApplicationCommandRegistry) { - registry.registerChatInputCommand(new SlashCommandBuilder().setName(this.name).setDescription(this.description)); - } - - public async chatInputRun(interaction: CommandInteraction) { - await interaction.deferReply({ephemeral: true}); - - const queue = this.container.player.getQueue(interaction.guild); - - queue.setPaused(false); - - interaction.editReply({ - embeds: [ - new MessageEmbed({ - color: "GREEN", - title: "Resume", - description: `Resumed the current playing song` - }) - ] - }); - } +import { SlashCommandBuilder } from "@discordjs/builders"; +import { ApplyOptions } from "@sapphire/decorators"; +import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; +import { CommandInteraction, MessageEmbed } from "discord.js"; + +@ApplyOptions({ + description: "resume the current song", + preconditions: ["GuildOnly", "BotInVoice", "InSameVoice"] +}) +export class ResumeCommand extends Command { + public registerApplicationCommands(registry: ApplicationCommandRegistry) { + registry.registerChatInputCommand(new SlashCommandBuilder().setName(this.name).setDescription(this.description)); + } + + public async chatInputRun(interaction: CommandInteraction) { + await interaction.deferReply({ephemeral: true}); + + const queue = this.container.player.getQueue(interaction.guild); + + queue.setPaused(false); + + interaction.editReply({ + embeds: [ + new MessageEmbed({ + color: "GREEN", + title: this.container.getTranslation(interaction, "commands/resume:success.title"), + description: this.container.getTranslation(interaction, "commands/resume:success.description") + }) + ] + }); + } } \ No newline at end of file diff --git a/src/commands/skip.ts b/src/commands/skip.ts index f650ccb0..a46c74f5 100644 --- a/src/commands/skip.ts +++ b/src/commands/skip.ts @@ -26,8 +26,8 @@ export class SkipCommand extends Command { embeds: [ new MessageEmbed({ color: "GREEN", - title: "Skipped", - description: `Skipped to next song` + title: this.container.getTranslation(interaction, "commands/skip:success.title"), + description: this.container.getTranslation(interaction, "commands/skip:success.description") }) ] }); diff --git a/src/commands/support.ts b/src/commands/support.ts index 03a86569..06fe8c92 100644 --- a/src/commands/support.ts +++ b/src/commands/support.ts @@ -1,34 +1,34 @@ -import { SlashCommandBuilder } from "@discordjs/builders"; -import { ApplyOptions } from "@sapphire/decorators"; -import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; -import { CommandInteraction, MessageEmbed } from "discord.js"; - -@ApplyOptions({ - description: "get the invite link of the support server" -}) -export class SupportCommand extends Command { - public registerApplicationCommands(registry: ApplicationCommandRegistry) { - registry.registerChatInputCommand(new SlashCommandBuilder().setName(this.name).setDescription(this.description)); - } - - public async chatInputRun(interaction: CommandInteraction) { - await interaction.deferReply({ephemeral: true}); - - const guild = await interaction.client.guilds.fetch(process.env.GUILD); - interaction.editReply({ - embeds: [ - new MessageEmbed({ - color: "RED", - title: "Support", - description: `Here is the invite for the [support server](${await guild.invites.create( - guild.systemChannel, - { - maxAge: 0, - reason: `${interaction.user} used the support command` - } - )})` - }) - ] - }); - } +import { SlashCommandBuilder } from "@discordjs/builders"; +import { ApplyOptions } from "@sapphire/decorators"; +import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; +import { CommandInteraction, MessageEmbed } from "discord.js"; + +@ApplyOptions({ + description: "get the invite link of the support server" +}) +export class SupportCommand extends Command { + public registerApplicationCommands(registry: ApplicationCommandRegistry) { + registry.registerChatInputCommand(new SlashCommandBuilder().setName(this.name).setDescription(this.description)); + } + + public async chatInputRun(interaction: CommandInteraction) { + await interaction.deferReply({ephemeral: true}); + + const guild = await interaction.client.guilds.fetch(process.env.GUILD); + interaction.editReply({ + embeds: [ + new MessageEmbed({ + color: "RED", + title: this.container.getTranslation(interaction, "commands/support:success.title"), + description: this.container.getTranslation(interaction, "commands/support:success.description", { replace: { invite: (await guild.invites.create( + guild.systemChannel, + { + maxAge: 0, + reason: `${interaction.user} used the support command` + } + )).url } }) + }) + ] + }); + } } \ No newline at end of file diff --git a/src/commands/volume.ts b/src/commands/volume.ts index 350bde64..e9579cb4 100644 --- a/src/commands/volume.ts +++ b/src/commands/volume.ts @@ -1,57 +1,57 @@ -import { ApplyOptions } from "@sapphire/decorators"; -import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; -import { CommandInteraction, MessageEmbed } from "discord.js"; - -@ApplyOptions({ - description: "set the volume of the player", - preconditions: ["GuildOnly", "BotInVoice", "InSameVoice"] -}) -export class VolumeCommand extends Command { - public registerApplicationCommands(registry: ApplicationCommandRegistry) { - registry.registerChatInputCommand({ - name: this.name, - description: this.description, - options: [ - { - type: "INTEGER", - name: "volume", - description: "the volume to set the player to", - minValue: 10, - maxValue: 200, - required: false - } - ] - }); - } - - public async chatInputRun(interaction: CommandInteraction) { - await interaction.deferReply(); - - const volume = interaction.options.getInteger("volume"); - const queue = this.container.player.getQueue(interaction.guild); - - if (!volume) { - return interaction.editReply({ - embeds: [ - new MessageEmbed({ - color: "BLUE", - title: "Volume", - description: `The current volume is ${queue.volume}%` - }) - ] - }); - } - - queue.setVolume(volume); - - interaction.editReply({ - embeds: [ - new MessageEmbed({ - color: "GREEN", - title: "Volume", - description: `The volume has been set to ${volume}%` - }) - ] - }); - } -} +import { ApplyOptions } from "@sapphire/decorators"; +import { ApplicationCommandRegistry, Command, CommandOptions } from "@sapphire/framework"; +import { CommandInteraction, MessageEmbed } from "discord.js"; + +@ApplyOptions({ + description: "set the volume of the player", + preconditions: ["GuildOnly", "BotInVoice", "InSameVoice"] +}) +export class VolumeCommand extends Command { + public registerApplicationCommands(registry: ApplicationCommandRegistry) { + registry.registerChatInputCommand({ + name: this.name, + description: this.description, + options: [ + { + type: "INTEGER", + name: "volume", + description: "the volume to set the player to", + minValue: 10, + maxValue: 200, + required: false + } + ] + }); + } + + public async chatInputRun(interaction: CommandInteraction) { + await interaction.deferReply(); + + const volume = interaction.options.getInteger("volume"); + const queue = this.container.player.getQueue(interaction.guild); + + if (!volume) { + return interaction.editReply({ + embeds: [ + new MessageEmbed({ + color: "BLUE", + title: "Volume", + description: this.container.getTranslation(interaction, "commands/volume:success.description.current", { replace: { volume: queue.volume } }) + }) + ] + }); + } + + queue.setVolume(volume); + + interaction.editReply({ + embeds: [ + new MessageEmbed({ + color: "GREEN", + title: this.container.getTranslation(interaction, "commands/volume:success.title"), + description: this.container.getTranslation(interaction, "commands/volume:success.description.changed", { replace: { volume } }) + }) + ] + }); + } +} diff --git a/src/container.ts b/src/container.ts new file mode 100644 index 00000000..a4dd0bd1 --- /dev/null +++ b/src/container.ts @@ -0,0 +1,21 @@ +import { container } from "@sapphire/pieces"; +import { TOptions } from "@sapphire/plugin-i18next"; +import type { CommandInteraction } from "discord.js"; + +declare module "@sapphire/pieces" { + export interface Container { + getLanguage(interaction: CommandInteraction): string; + getTranslation(interaction: CommandInteraction, key: string, options?: TOptions): string; + } +} + +container.getLanguage = function(interaction) { + const {locale} = interaction; + if (!locale.includes("-")) return `${locale}-${locale}`; + return locale; +} + +container.getTranslation = function(this: typeof container, interaction, key, options) { + const lang = this.getLanguage(interaction); + return this.i18n.format(this.i18n.languages.has(lang) ? lang : "en-US", key, options); +} \ No newline at end of file diff --git a/src/languages/en-US/commands/clear.json b/src/languages/en-US/commands/clear.json new file mode 100644 index 00000000..a86bae74 --- /dev/null +++ b/src/languages/en-US/commands/clear.json @@ -0,0 +1,6 @@ +{ + "success": { + "title": "Queue cleared", + "description": "The queue has been cleared" + } +} \ No newline at end of file diff --git a/src/languages/en-US/commands/disconnect.json b/src/languages/en-US/commands/disconnect.json new file mode 100644 index 00000000..b4daea61 --- /dev/null +++ b/src/languages/en-US/commands/disconnect.json @@ -0,0 +1,6 @@ +{ + "success": { + "title": "Disconnect", + "description": "Disconnected from `{{channel}}` 🔊" + } +} \ No newline at end of file diff --git a/src/languages/en-US/commands/invite.json b/src/languages/en-US/commands/invite.json new file mode 100644 index 00000000..14c0c815 --- /dev/null +++ b/src/languages/en-US/commands/invite.json @@ -0,0 +1,7 @@ +{ + "success": { + "title": "OurTube invite links", + "recommended": "Recommended", + "admin": "Admin" + } +} \ No newline at end of file diff --git a/src/languages/en-US/commands/join.json b/src/languages/en-US/commands/join.json new file mode 100644 index 00000000..a2bfb32e --- /dev/null +++ b/src/languages/en-US/commands/join.json @@ -0,0 +1,10 @@ +{ + "success": { + "title": "Join", + "description": "Joined `{{channel}}` 🔊" + }, + "error": { + "title": "Can't join voice channel", + "description": "Unable to join your voice channel" + } +} \ No newline at end of file diff --git a/src/languages/en-US/commands/nowplaying.json b/src/languages/en-US/commands/nowplaying.json new file mode 100644 index 00000000..deba85e9 --- /dev/null +++ b/src/languages/en-US/commands/nowplaying.json @@ -0,0 +1,10 @@ +{ + "success": { + "title": "Now Playing", + "requestedBy": "Requested by {{user}}" + }, + "error": { + "title": "Not playing", + "description": "I'm not playing anything" + } +} \ No newline at end of file diff --git a/src/languages/en-US/commands/pause.json b/src/languages/en-US/commands/pause.json new file mode 100644 index 00000000..232a5afb --- /dev/null +++ b/src/languages/en-US/commands/pause.json @@ -0,0 +1,6 @@ +{ + "success": { + "title": "Pause", + "description": "Paused the current playing song" + } +} \ No newline at end of file diff --git a/src/languages/en-US/commands/play.json b/src/languages/en-US/commands/play.json new file mode 100644 index 00000000..7c1e6916 --- /dev/null +++ b/src/languages/en-US/commands/play.json @@ -0,0 +1,16 @@ +{ + "success": { + "title": { + "playlist": "Loading playlist", + "song": "Loading song" + }, + "description": { + "playlist": "Now loading your requested playlist", + "song": "Now loading your requested song" + } + }, + "error": { + "title": "No song found", + "description": "No results were found" + } +} \ No newline at end of file diff --git a/src/languages/en-US/commands/queue.json b/src/languages/en-US/commands/queue.json new file mode 100644 index 00000000..590b02cd --- /dev/null +++ b/src/languages/en-US/commands/queue.json @@ -0,0 +1,11 @@ +{ + "success": { + "title": "Queue", + "nowPlaying": "Now Playing", + "upNext": "Up Next" + }, + "error": { + "title": "Queue empty", + "description": "There are no songs in the queue" + } +} \ No newline at end of file diff --git a/src/languages/en-US/commands/remove.json b/src/languages/en-US/commands/remove.json new file mode 100644 index 00000000..bad20cad --- /dev/null +++ b/src/languages/en-US/commands/remove.json @@ -0,0 +1,6 @@ +{ + "success": { + "title": "Remove", + "description": "Removed {{track}} from the queue at index {{index}}" + } +} \ No newline at end of file diff --git a/src/languages/en-US/commands/resume.json b/src/languages/en-US/commands/resume.json new file mode 100644 index 00000000..dfaf7abf --- /dev/null +++ b/src/languages/en-US/commands/resume.json @@ -0,0 +1,6 @@ +{ + "success": { + "title": "Resume", + "description": "Resumed the current playing song" + } +} \ No newline at end of file diff --git a/src/languages/en-US/commands/skip.json b/src/languages/en-US/commands/skip.json new file mode 100644 index 00000000..d4b10f4c --- /dev/null +++ b/src/languages/en-US/commands/skip.json @@ -0,0 +1,6 @@ +{ + "success": { + "title": "Skipped", + "description": "Skipped to next song" + } +} \ No newline at end of file diff --git a/src/languages/en-US/commands/support.json b/src/languages/en-US/commands/support.json new file mode 100644 index 00000000..96669a8a --- /dev/null +++ b/src/languages/en-US/commands/support.json @@ -0,0 +1,6 @@ +{ + "success": { + "title": "Support", + "description": "Here is the invite for the [support server]({{invite}})" + } +} \ No newline at end of file diff --git a/src/languages/en-US/commands/volume.json b/src/languages/en-US/commands/volume.json new file mode 100644 index 00000000..16b032f1 --- /dev/null +++ b/src/languages/en-US/commands/volume.json @@ -0,0 +1,9 @@ +{ + "success": { + "title": "Volume", + "description": { + "current": "The current volume is {{volume}}%", + "changed": "The volume has been set to {{volume}}%" + } + } +} \ No newline at end of file diff --git a/src/languages/en-US/listeners/commanddenied.json b/src/languages/en-US/listeners/commanddenied.json new file mode 100644 index 00000000..d74ab8b7 --- /dev/null +++ b/src/languages/en-US/listeners/commanddenied.json @@ -0,0 +1,3 @@ +{ + "title": "Command Failed" +} \ No newline at end of file diff --git a/src/languages/en-US/listeners/trackadd.json b/src/languages/en-US/listeners/trackadd.json new file mode 100644 index 00000000..b8cbcc2b --- /dev/null +++ b/src/languages/en-US/listeners/trackadd.json @@ -0,0 +1,4 @@ +{ + "title": "Play", + "description": "{{track}} has been added to the queue" +} \ No newline at end of file diff --git a/src/languages/en-US/listeners/tracksadd.json b/src/languages/en-US/listeners/tracksadd.json new file mode 100644 index 00000000..f2eb85b9 --- /dev/null +++ b/src/languages/en-US/listeners/tracksadd.json @@ -0,0 +1,4 @@ +{ + "title": "Play", + "description": "{{count}} songs added" +} \ No newline at end of file diff --git a/src/languages/en-US/listeners/trackstart.json b/src/languages/en-US/listeners/trackstart.json new file mode 100644 index 00000000..5325bc82 --- /dev/null +++ b/src/languages/en-US/listeners/trackstart.json @@ -0,0 +1,4 @@ +{ + "title": "Play", + "description": "Now Playing {{track}}" +} \ No newline at end of file diff --git a/src/languages/en-US/preconditions/botinvoice.json b/src/languages/en-US/preconditions/botinvoice.json new file mode 100644 index 00000000..913f4c7d --- /dev/null +++ b/src/languages/en-US/preconditions/botinvoice.json @@ -0,0 +1,3 @@ +{ + "error": "I'm not connected to a voice channel" +} \ No newline at end of file diff --git a/src/languages/en-US/preconditions/insamevoice.json b/src/languages/en-US/preconditions/insamevoice.json new file mode 100644 index 00000000..42c370b2 --- /dev/null +++ b/src/languages/en-US/preconditions/insamevoice.json @@ -0,0 +1,3 @@ +{ + "error": "You need to be in the same voice channel as me to use this command" +} \ No newline at end of file diff --git a/src/languages/en-US/preconditions/userinvoice.json b/src/languages/en-US/preconditions/userinvoice.json new file mode 100644 index 00000000..680bfca5 --- /dev/null +++ b/src/languages/en-US/preconditions/userinvoice.json @@ -0,0 +1,3 @@ +{ + "error": "You need to join a voice channel to use this command" +} \ No newline at end of file diff --git a/src/languages/nl-nl/commands/clear.json b/src/languages/nl-nl/commands/clear.json new file mode 100644 index 00000000..da40e269 --- /dev/null +++ b/src/languages/nl-nl/commands/clear.json @@ -0,0 +1,6 @@ +{ + "success": { + "title": "Wachtrij geleegd", + "description": "De wachtrij is geleegd" + } +} \ No newline at end of file diff --git a/src/languages/nl-nl/commands/disconnect.json b/src/languages/nl-nl/commands/disconnect.json new file mode 100644 index 00000000..0e9b421d --- /dev/null +++ b/src/languages/nl-nl/commands/disconnect.json @@ -0,0 +1,6 @@ +{ + "success": { + "title": "Verbinding verbroken", + "description": "Verbinden verbroken van `{{channel}}` 🔊" + } +} \ No newline at end of file diff --git a/src/languages/nl-nl/commands/invite.json b/src/languages/nl-nl/commands/invite.json new file mode 100644 index 00000000..8ab4a55e --- /dev/null +++ b/src/languages/nl-nl/commands/invite.json @@ -0,0 +1,7 @@ +{ + "success": { + "title": "OurTube uitnodigingslinks", + "recommended": "Aanbevolen", + "admin": "Beheerder" + } +} \ No newline at end of file diff --git a/src/languages/nl-nl/commands/join.json b/src/languages/nl-nl/commands/join.json new file mode 100644 index 00000000..72c14bd7 --- /dev/null +++ b/src/languages/nl-nl/commands/join.json @@ -0,0 +1,10 @@ +{ + "success": { + "title": "Verbonden", + "description": "Verbonden met `{{channel}}` 🔊" + }, + "error": { + "title": "Kan geen verbinding maken met spraakkanaal", + "description": "Het lukt niet om met je spraakkanaal te verbinden" + } +} \ No newline at end of file diff --git a/src/languages/nl-nl/commands/nowplaying.json b/src/languages/nl-nl/commands/nowplaying.json new file mode 100644 index 00000000..3ada7448 --- /dev/null +++ b/src/languages/nl-nl/commands/nowplaying.json @@ -0,0 +1,10 @@ +{ + "success": { + "title": "Nu aan het afspelen", + "requestedBy": "Aangevraagd door {{user}}" + }, + "error": { + "title": "Niks aan het afspelen", + "description": "Ik ben niks aan het afspelen" + } +} \ No newline at end of file diff --git a/src/languages/nl-nl/commands/pause.json b/src/languages/nl-nl/commands/pause.json new file mode 100644 index 00000000..4750dc03 --- /dev/null +++ b/src/languages/nl-nl/commands/pause.json @@ -0,0 +1,6 @@ +{ + "success": { + "title": "Pauze", + "description": "Het huidige nummer is gepauzeerd" + } +} \ No newline at end of file diff --git a/src/languages/nl-nl/commands/play.json b/src/languages/nl-nl/commands/play.json new file mode 100644 index 00000000..468f759a --- /dev/null +++ b/src/languages/nl-nl/commands/play.json @@ -0,0 +1,16 @@ +{ + "success": { + "title": { + "playlist": "Afspeellijst aan het laden", + "song": "Nummer aan het laden" + }, + "description": { + "playlist": "Nu je aangevraagde afspeellijst aan het laden", + "song": "Nu je aangevraagde nummer aan het laden" + } + }, + "error": { + "title": "Geen nummer gevonden", + "description": "Er zijn geen resultaten gevonden" + } +} \ No newline at end of file diff --git a/src/languages/nl-nl/commands/queue.json b/src/languages/nl-nl/commands/queue.json new file mode 100644 index 00000000..0bb1cbc1 --- /dev/null +++ b/src/languages/nl-nl/commands/queue.json @@ -0,0 +1,11 @@ +{ + "success": { + "title": "Wachtrij", + "nowPlaying": "Nu aan het afspelen", + "upNext": "Volgende" + }, + "error": { + "title": "Wachtrij leeg", + "description": "Er zitten geen nummers in de wachtrij" + } +} \ No newline at end of file diff --git a/src/languages/nl-nl/commands/remove.json b/src/languages/nl-nl/commands/remove.json new file mode 100644 index 00000000..0eadbeee --- /dev/null +++ b/src/languages/nl-nl/commands/remove.json @@ -0,0 +1,6 @@ +{ + "success": { + "title": "Verwijderen", + "description": "{{track}} verwijderd van de wachtrij op index {{index}}" + } +} \ No newline at end of file diff --git a/src/languages/nl-nl/commands/resume.json b/src/languages/nl-nl/commands/resume.json new file mode 100644 index 00000000..414f8f36 --- /dev/null +++ b/src/languages/nl-nl/commands/resume.json @@ -0,0 +1,6 @@ +{ + "success": { + "title": "Gehervat", + "description": "Het huidige nummer is gehervat" + } +} \ No newline at end of file diff --git a/src/languages/nl-nl/commands/skip.json b/src/languages/nl-nl/commands/skip.json new file mode 100644 index 00000000..354b721c --- /dev/null +++ b/src/languages/nl-nl/commands/skip.json @@ -0,0 +1,6 @@ +{ + "success": { + "title": "Overgeslagen", + "description": "Overgeslagen naar het volgende nummer" + } +} \ No newline at end of file diff --git a/src/languages/nl-nl/commands/support.json b/src/languages/nl-nl/commands/support.json new file mode 100644 index 00000000..3a65ba0b --- /dev/null +++ b/src/languages/nl-nl/commands/support.json @@ -0,0 +1,6 @@ +{ + "success": { + "title": "Ondersteuning", + "description": "Hier is de uitnodigingslink voor de [ondersteuning server]({{invite}})" + } +} \ No newline at end of file diff --git a/src/languages/nl-nl/commands/volume.json b/src/languages/nl-nl/commands/volume.json new file mode 100644 index 00000000..32ef48a9 --- /dev/null +++ b/src/languages/nl-nl/commands/volume.json @@ -0,0 +1,9 @@ +{ + "success": { + "title": "Volume", + "description": { + "current": "Het huidige volume is {{volume}}%", + "changed": "Het volume is veranderd naar {{volume}}%" + } + } +} \ No newline at end of file diff --git a/src/languages/nl-nl/listeners/commanddenied.json b/src/languages/nl-nl/listeners/commanddenied.json new file mode 100644 index 00000000..3b737714 --- /dev/null +++ b/src/languages/nl-nl/listeners/commanddenied.json @@ -0,0 +1,3 @@ +{ + "title": "Opdracht mislukt" +} \ No newline at end of file diff --git a/src/languages/nl-nl/listeners/trackadd.json b/src/languages/nl-nl/listeners/trackadd.json new file mode 100644 index 00000000..3a96c932 --- /dev/null +++ b/src/languages/nl-nl/listeners/trackadd.json @@ -0,0 +1,4 @@ +{ + "title": "Speel", + "description": "{{track}} is toegevoegd aan de wachtrij" +} \ No newline at end of file diff --git a/src/languages/nl-nl/listeners/tracksadd.json b/src/languages/nl-nl/listeners/tracksadd.json new file mode 100644 index 00000000..d563a2f9 --- /dev/null +++ b/src/languages/nl-nl/listeners/tracksadd.json @@ -0,0 +1,4 @@ +{ + "title": "Speel", + "description": "{{count}} nummers toegevoegd" +} \ No newline at end of file diff --git a/src/languages/nl-nl/listeners/trackstart.json b/src/languages/nl-nl/listeners/trackstart.json new file mode 100644 index 00000000..ef602e70 --- /dev/null +++ b/src/languages/nl-nl/listeners/trackstart.json @@ -0,0 +1,4 @@ +{ + "title": "Speel", + "description": "{{track}} nu aan het afspelen" +} \ No newline at end of file diff --git a/src/languages/nl-nl/preconditions/botinvoice.json b/src/languages/nl-nl/preconditions/botinvoice.json new file mode 100644 index 00000000..6ff6b4d6 --- /dev/null +++ b/src/languages/nl-nl/preconditions/botinvoice.json @@ -0,0 +1,3 @@ +{ + "error": "Ik ben niet verbonden met een spraakkanaal" +} \ No newline at end of file diff --git a/src/languages/nl-nl/preconditions/insamevoice.json b/src/languages/nl-nl/preconditions/insamevoice.json new file mode 100644 index 00000000..a54124bc --- /dev/null +++ b/src/languages/nl-nl/preconditions/insamevoice.json @@ -0,0 +1,3 @@ +{ + "error": "Je moet in hetzelfde spraakkanaal als ik zitten om deze opdracht te gebruiken" +} \ No newline at end of file diff --git a/src/languages/nl-nl/preconditions/userinvoice.json b/src/languages/nl-nl/preconditions/userinvoice.json new file mode 100644 index 00000000..5970d57c --- /dev/null +++ b/src/languages/nl-nl/preconditions/userinvoice.json @@ -0,0 +1,3 @@ +{ + "error": "Je moet verbinding maken met een spraakkanaal om deze opdracht te gebruiken" +} \ No newline at end of file diff --git a/src/listeners/client/commandDenied.ts b/src/listeners/client/commandDenied.ts index bdd5b7de..b44eb071 100644 --- a/src/listeners/client/commandDenied.ts +++ b/src/listeners/client/commandDenied.ts @@ -1,20 +1,20 @@ -import { ApplyOptions } from "@sapphire/decorators"; -import { ChatInputCommandDeniedPayload, Listener, ListenerOptions, UserError } from "@sapphire/framework"; -import { MessageEmbed } from "discord.js"; - -@ApplyOptions({ - event: "chatInputCommandDenied" -}) -export class CommandDeniedListener extends Listener<"chatInputCommandDenied"> { - run(error: UserError, {interaction}: ChatInputCommandDeniedPayload) { - return interaction.reply({ - embeds: [ - new MessageEmbed({ - color: "RED", - title: "Command Failed", - description: error.message - }) - ] - }); - } +import { ApplyOptions } from "@sapphire/decorators"; +import { ChatInputCommandDeniedPayload, Listener, ListenerOptions, UserError } from "@sapphire/framework"; +import { MessageEmbed } from "discord.js"; + +@ApplyOptions({ + event: "chatInputCommandDenied" +}) +export class CommandDeniedListener extends Listener<"chatInputCommandDenied"> { + run(error: UserError, {interaction}: ChatInputCommandDeniedPayload) { + return interaction.reply({ + embeds: [ + new MessageEmbed({ + color: "RED", + title: this.container.getTranslation(interaction, "listeners/commanddenied:title"), + description: error.message + }) + ] + }); + } } \ No newline at end of file diff --git a/src/listeners/player/trackAdd.ts b/src/listeners/player/trackAdd.ts index 305b8e12..696c8a9b 100644 --- a/src/listeners/player/trackAdd.ts +++ b/src/listeners/player/trackAdd.ts @@ -1,23 +1,23 @@ -import { ApplyOptions } from "@sapphire/decorators"; -import { container, Listener, ListenerOptions } from "@sapphire/framework"; -import { Queue, Track } from "discord-player"; -import { CommandInteraction, MessageEmbed } from "discord.js"; - -@ApplyOptions({ - emitter: container.player, - event: "trackAdd" -}) -export class TrackAddListener extends Listener { - public run(queue: Queue, track: Track) { - if (queue.nowPlaying() == track) return; - queue.metadata.followUp({ - embeds: [ - new MessageEmbed({ - color: "BLUE", - title: "Play", - description: `[${track.title}](${track.url}) has been added to the queue` - }) - ] - }); - } +import { ApplyOptions } from "@sapphire/decorators"; +import { container, Listener, ListenerOptions } from "@sapphire/framework"; +import { Queue, Track } from "discord-player"; +import { CommandInteraction, MessageEmbed } from "discord.js"; + +@ApplyOptions({ + emitter: container.player, + event: "trackAdd" +}) +export class TrackAddListener extends Listener { + public run(queue: Queue, track: Track) { + if (queue.nowPlaying() == track) return; + queue.metadata.followUp({ + embeds: [ + new MessageEmbed({ + color: "BLUE", + title: this.container.getTranslation(queue.metadata, "listeners/trackadd:title"), + description: this.container.getTranslation(queue.metadata, "listeners/trackadd:description", { replace: { track: `[${track.title}](${track.url})` } }) + }) + ] + }); + } } \ No newline at end of file diff --git a/src/listeners/player/trackStart.ts b/src/listeners/player/trackStart.ts index d87a2cbb..ac7c5e6e 100644 --- a/src/listeners/player/trackStart.ts +++ b/src/listeners/player/trackStart.ts @@ -1,22 +1,22 @@ -import { ApplyOptions } from "@sapphire/decorators"; -import { container, Listener, ListenerOptions } from "@sapphire/framework"; -import { Queue, Track } from "discord-player"; -import { CommandInteraction, MessageEmbed } from "discord.js"; - -@ApplyOptions({ - emitter: container.player, - event: "trackStart" -}) -export class TrackStartListener extends Listener { - public run(queue: Queue, track: Track) { - queue.metadata.followUp({ - embeds: [ - new MessageEmbed({ - color: "BLUE", - title: "Play", - description: `Now Playing [${track.title}](${track.url})` - }) - ] - }); - } +import { ApplyOptions } from "@sapphire/decorators"; +import { container, Listener, ListenerOptions } from "@sapphire/framework"; +import { Queue, Track } from "discord-player"; +import { CommandInteraction, MessageEmbed } from "discord.js"; + +@ApplyOptions({ + emitter: container.player, + event: "trackStart" +}) +export class TrackStartListener extends Listener { + public run(queue: Queue, track: Track) { + queue.metadata.followUp({ + embeds: [ + new MessageEmbed({ + color: "BLUE", + title: this.container.getTranslation(queue.metadata, "listeners/trackstart:title"), + description: this.container.getTranslation(queue.metadata, "listeners/trackstart:description", { replace: { track: `[${track.title}](${track.url})` } }) + }) + ] + }); + } } \ No newline at end of file diff --git a/src/listeners/player/tracksAdd.ts b/src/listeners/player/tracksAdd.ts index 6ce91a39..4440927a 100644 --- a/src/listeners/player/tracksAdd.ts +++ b/src/listeners/player/tracksAdd.ts @@ -1,22 +1,22 @@ -import { ApplyOptions } from "@sapphire/decorators"; -import { container, Listener, ListenerOptions } from "@sapphire/framework"; -import { Queue, Track } from "discord-player"; -import { CommandInteraction, MessageEmbed } from "discord.js"; - -@ApplyOptions({ - emitter: container.player, - event: "tracksAdd" -}) -export class TracksAddListener extends Listener { - public run(queue: Queue, tracks: Track[]) { - queue.metadata.followUp({ - embeds: [ - new MessageEmbed({ - color: "BLUE", - title: "Play", - description: `${tracks.length} songs added` - }) - ] - }); - } +import { ApplyOptions } from "@sapphire/decorators"; +import { container, Listener, ListenerOptions } from "@sapphire/framework"; +import { Queue, Track } from "discord-player"; +import { CommandInteraction, MessageEmbed } from "discord.js"; + +@ApplyOptions({ + emitter: container.player, + event: "tracksAdd" +}) +export class TracksAddListener extends Listener { + public run(queue: Queue, tracks: Track[]) { + queue.metadata.followUp({ + embeds: [ + new MessageEmbed({ + color: "BLUE", + title: this.container.getTranslation(queue.metadata, "listeners/tracksadd:title"), + description: this.container.getTranslation(queue.metadata, "listeners/tracksadd:description", { replace: { count: tracks.length } }) + }) + ] + }); + } } \ No newline at end of file diff --git a/src/preconditions/BotInVoice.ts b/src/preconditions/BotInVoice.ts index ff9c8f0b..37604bdb 100644 --- a/src/preconditions/BotInVoice.ts +++ b/src/preconditions/BotInVoice.ts @@ -1,14 +1,14 @@ -import { Precondition } from "@sapphire/framework"; -import { CommandInteraction } from "discord.js"; - -export class BotInVoicePrecondition extends Precondition { - public chatInputRun(interaction: CommandInteraction) { - return interaction.guild.me.voice.channel ? this.ok() : this.error({message: "I'm not connected to a voice channel"}); - } -} - -declare module "@sapphire/framework" { - interface Preconditions { - BotInVoice: never; - } +import { Precondition } from "@sapphire/framework"; +import { CommandInteraction } from "discord.js"; + +export class BotInVoicePrecondition extends Precondition { + public chatInputRun(interaction: CommandInteraction) { + return interaction.guild.me.voice.channel ? this.ok() : this.error({message: this.container.getTranslation(interaction, "preconditions/botinvoice:error")}); + } +} + +declare module "@sapphire/framework" { + interface Preconditions { + BotInVoice: never; + } } \ No newline at end of file diff --git a/src/preconditions/InSameVoice.ts b/src/preconditions/InSameVoice.ts index 6ae65805..e46cb341 100644 --- a/src/preconditions/InSameVoice.ts +++ b/src/preconditions/InSameVoice.ts @@ -1,16 +1,16 @@ -import { Precondition } from "@sapphire/framework"; -import { CommandInteraction, GuildMember } from "discord.js"; - -export class InSameVoicePrecondition extends Precondition { - public chatInputRun(interaction: CommandInteraction) { - return interaction.guild.me.voice.channel.equals((interaction.member as GuildMember).voice.channel) ? - this.ok() : - this.error({message: "You need to be in the same voice channel as me to use this command"}); - } -} - -declare module "@sapphire/framework" { - interface Preconditions { - InSameVoice: never; - } +import { Precondition } from "@sapphire/framework"; +import { CommandInteraction, GuildMember } from "discord.js"; + +export class InSameVoicePrecondition extends Precondition { + public chatInputRun(interaction: CommandInteraction) { + return interaction.guild.me.voice.channel.equals((interaction.member as GuildMember).voice.channel) ? + this.ok() : + this.error({message: this.container.getTranslation(interaction, "preconditions/insamevoice:error")}); + } +} + +declare module "@sapphire/framework" { + interface Preconditions { + InSameVoice: never; + } } \ No newline at end of file diff --git a/src/preconditions/UserInVoice.ts b/src/preconditions/UserInVoice.ts index 0acbf678..9068ed96 100644 --- a/src/preconditions/UserInVoice.ts +++ b/src/preconditions/UserInVoice.ts @@ -1,15 +1,15 @@ -import { Precondition } from "@sapphire/framework"; -import { CommandInteraction, GuildMember } from "discord.js"; - -export class UserInVoicePrecondition extends Precondition { - public chatInputRun(interaction: CommandInteraction) { - return (interaction.member as GuildMember).voice.channel ? - this.ok() : this.error({message: "You need to join a voice channel to use this command"}); - } -} - -declare module "@sapphire/framework" { - interface Preconditions { - UserInVoice: never; - } +import { Precondition } from "@sapphire/framework"; +import { CommandInteraction, GuildMember } from "discord.js"; + +export class UserInVoicePrecondition extends Precondition { + public chatInputRun(interaction: CommandInteraction) { + return (interaction.member as GuildMember).voice.channel ? + this.ok() : this.error({message: this.container.getTranslation(interaction, "preconditions/userinvoice:error")}); + } +} + +declare module "@sapphire/framework" { + interface Preconditions { + UserInVoice: never; + } } \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index f60206e8..bd0080b3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,12 +1,13 @@ -{ - "compilerOptions": { - "target": "ESNext", - "module": "CommonJS", - "outDir": "dist", - "allowJs": true, - "removeComments": true, - "esModuleInterop": true, - "experimentalDecorators": true - }, - "include": ["src"] +{ + "compilerOptions": { + "target": "ESNext", + "module": "CommonJS", + "outDir": "dist", + "allowJs": true, + "removeComments": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "resolveJsonModule": true + }, + "include": ["src", "src/languages/**/*.json"] } \ No newline at end of file