From 1ac077a400b3f2b6a174dc89b48ca7904bb13555 Mon Sep 17 00:00:00 2001 From: Allvaa <52526068+Allvaa@users.noreply.github.com> Date: Sat, 7 Aug 2021 19:25:07 +0700 Subject: [PATCH 01/28] filters (#106) Co-authored-by: rajamoulimallareddy <68652418+rajamoulimallareddy@users.noreply.github.com> --- src/commands/8d.js | 18 ++++++++ src/commands/bassboost.js | 26 ++++++++++++ src/commands/doubletime.js | 17 ++++++++ src/commands/nightcore.js | 17 ++++++++ src/commands/vaporwave.js | 16 ++++++++ src/constants/FiltersValues.js | 17 ++++++++ src/structures/MusicHandler.js | 75 ++++++++++++++++++++++++++++++++++ 7 files changed, 186 insertions(+) create mode 100644 src/commands/8d.js create mode 100644 src/commands/bassboost.js create mode 100644 src/commands/doubletime.js create mode 100644 src/commands/nightcore.js create mode 100644 src/commands/vaporwave.js create mode 100644 src/constants/FiltersValues.js diff --git a/src/commands/8d.js b/src/commands/8d.js new file mode 100644 index 0000000..52e0032 --- /dev/null +++ b/src/commands/8d.js @@ -0,0 +1,18 @@ +const util = require("../util"); +module.exports = { + name: "8d", + aliases: ["rotation"], + exec: async (msg) => { + const { music } = msg.guild; + if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!msg.member.voice.channel) + return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) + return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + + music.set8D(!music.filters["8d"]); + msg.channel.send(util.embed().setDescription(`✅ | ${music.filters["8d"] ? "Enabled" : "Disabled"} **8D**`)); + + } + +}; diff --git a/src/commands/bassboost.js b/src/commands/bassboost.js new file mode 100644 index 0000000..0c7f39c --- /dev/null +++ b/src/commands/bassboost.js @@ -0,0 +1,26 @@ +const util = require("../util"); +module.exports = { + name: "bassboost", + description: "Set bassboost for player", + aliases: ["bb"], + exec: async(msg, args) => { + const { music } = msg.guild; + if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!msg.member.voice.channel) + return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) + return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + + if (!args[0]) { + msg.channel.send(util.embed().setDescription(`${music.filters.bassboost ? `✅ | BassBoost **${music.bassboost * 100}%**` : "❌ | BassBoost **off**"}`)); + } else if (args[0].toLowerCase() == "off") { + music.setBassboost(0); + msg.react("✅").catch(e => e); + } else { + if (isNaN(args[0])) return msg.channel.send(util.embed().setDescription("❌ | Specify a number")); + if (args[0] < 1 || args[0] > 100) return msg.channel.send(util.embed().setDescription("❌ | You can only set the bassboost from 1 to 100.")); + music.setBassboost(parseInt(args[0])); + msg.channel.send(util.embed().setDescription(`✅ | BassBoost set to **${music.bassboost * 100}%**`)); + } + } +}; diff --git a/src/commands/doubletime.js b/src/commands/doubletime.js new file mode 100644 index 0000000..9ad2f2e --- /dev/null +++ b/src/commands/doubletime.js @@ -0,0 +1,17 @@ +const util = require("../util"); +module.exports = { + name: "doubletime", + aliases: ["dt"], + exec: async (msg) => { + const { music } = msg.guild; + if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!msg.member.voice.channel) + return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) + return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + + music.setDoubleTime(!music.filters.doubleTime); + msg.channel.send(util.embed().setDescription(`✅ | ${music.filters.doubleTime ? "Enabled" : "Disabled"} **Double Time**`)); + + } +}; diff --git a/src/commands/nightcore.js b/src/commands/nightcore.js new file mode 100644 index 0000000..08a96ae --- /dev/null +++ b/src/commands/nightcore.js @@ -0,0 +1,17 @@ +const util = require("../util"); +module.exports = { + name: "nightcore", + aliases: ["nc"], + exec: async (msg) => { + const { music } = msg.guild; + if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!msg.member.voice.channel) + return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) + return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + + music.setNightcore(!music.filters.nightcore); + msg.channel.send(util.embed().setDescription(`✅ | ${music.filters.nightcore ? "Enabled" : "Disabled"} **Nightcore**`)); + + } +}; diff --git a/src/commands/vaporwave.js b/src/commands/vaporwave.js new file mode 100644 index 0000000..1ff9b91 --- /dev/null +++ b/src/commands/vaporwave.js @@ -0,0 +1,16 @@ +const util = require("../util"); +module.exports = { + name: "vaporwave", + aliases: ["vp"], + exec: async (msg) => { + const { music } = msg.guild; + if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!msg.member.voice.channel) + return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) + return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + + music.setVaporwave(!music.filters.vaporwave); + msg.channel.send(util.embed().setDescription(`✅ | ${music.filters.vaporwave ? "Enabled" : "Disabled"} **Vaporwave**`)); + } +}; diff --git a/src/constants/FiltersValues.js b/src/constants/FiltersValues.js new file mode 100644 index 0000000..c155894 --- /dev/null +++ b/src/constants/FiltersValues.js @@ -0,0 +1,17 @@ +module.exports = { + doubleTime: { + timescale: { speed: 1.5 } + }, + nightcore: { + timescale: { rate: 1.5 } + }, + vaporwave: { + timescale: { pitch: 0.5 } + }, + "8d": { + rotation: { rotationHz: 0.2 } + }, + bassboost: { + equalizer: Array(6).fill(0.22) + } +}; diff --git a/src/structures/MusicHandler.js b/src/structures/MusicHandler.js index b29e813..1b5513a 100644 --- a/src/structures/MusicHandler.js +++ b/src/structures/MusicHandler.js @@ -1,5 +1,6 @@ const Rest = require("./Rest"); const util = require("../util"); +const FiltersValues = require("../constants/FiltersValues"); module.exports = class MusicHandler { /** @param {import("discord.js").Guild} guild */ @@ -10,6 +11,14 @@ module.exports = class MusicHandler { this.previous = null; this.current = null; this.queue = []; + this.filters = { + doubleTime: false, + nightcore: false, + vaporwave: false, + "8d": false, + bassboost: false + }; + this.bassboost = 0; /** @type {import("discord.js").TextChannel|null} */ this.textChannel = null; this.shouldSkipCurrent = false; @@ -39,6 +48,10 @@ module.exports = class MusicHandler { this.current = null; this.queue = []; this.textChannel = null; + for (const filter of Object.keys(this.filters)) { + this.filters[filter] = false; + } + this.bassboost = 0; } /** @param {import("discord.js").VoiceChannel} voice */ @@ -125,4 +138,66 @@ module.exports = class MusicHandler { await this.player.volume(parsed); this.volume = newVol; } + + async setDoubleTime(val) { + if (!this.player) return; + this.filters.doubleTime = val; + if (val) { + this.filters.nightcore = false; + this.filters.vaporwave = false; + } + await this.sendFilters(); + } + + async setNightcore(val) { + if (!this.player) return; + this.filters.nightcore = val; + if (val) { + this.filters.doubleTime = false; + this.filters.vaporwave = false; + } + await this.sendFilters(); + } + + async setVaporwave(val) { + if (!this.player) return; + this.filters.vaporwave = val; + if (val) { + this.filters.doubleTime = false; + this.filters.nightcore = false; + } + await this.sendFilters(); + } + + async set8D(val) { + if (!this.player) return; + this.filters["8d"] = val; + await this.sendFilters(); + } + + async setBassboost(val) { + if (!this.player) return; + this.filters.bassboost = !!val; + this.bassboost = val / 100; + await this.sendFilters(); + } + + async sendFilters() { + if (!this.player) return; + const filters = {}; + for (const [filter, enabled] of Object.entries(this.filters)) { + if (enabled && FiltersValues[filter]) { + const filterValue = { ...FiltersValues[filter] }; + if (filter === "bassboost") { + filterValue.equalizer = filterValue.equalizer.map((x, i) => ({ band: i, gain: x * this.bassboost })); + } + Object.assign(filters, filterValue); + } + } + await this.player.node.send({ + op: "filters", + guildId: this.guild.id, + ...filters + }); + } }; From 5ed827d1695298527553479b1703d7159090991d Mon Sep 17 00:00:00 2001 From: Allvaa Date: Sun, 8 Aug 2021 13:29:44 +0700 Subject: [PATCH 02/28] ?? --- .eslintrc | 2 +- package.json | 6 +- src/bot.js | 6 +- src/commands/8d.js | 17 +- src/commands/bassboost.js | 24 +- src/commands/clearqueue.js | 18 +- src/commands/doubletime.js | 16 +- src/commands/eval.js | 14 +- src/commands/help.js | 8 +- src/commands/loop.js | 20 +- src/commands/lyrics.js | 18 +- src/commands/move.js | 22 +- src/commands/nightcore.js | 16 +- src/commands/nowplaying.js | 8 +- src/commands/pause.js | 18 +- src/commands/ping.js | 10 +- src/commands/play.js | 40 +-- src/commands/previous.js | 20 +- src/commands/queue.js | 16 +- src/commands/remove.js | 22 +- src/commands/removedupes.js | 18 +- src/commands/resume.js | 18 +- src/commands/search.js | 38 +- src/commands/seek.js | 26 +- src/commands/shuffle.js | 18 +- src/commands/skip.js | 20 +- src/commands/source.js | 4 +- src/commands/stats.js | 8 +- src/commands/stop.js | 18 +- src/commands/vaporwave.js | 16 +- src/commands/volume.js | 22 +- src/extensions/Guild.js | 13 - src/extensions/index.js | 1 - .../{message.js => messageCreate.js} | 6 +- src/listeners/voiceStateUpdate.js | 7 +- src/structures/CommandContext.js | 43 +++ src/structures/MusicClient.js | 6 +- src/structures/MusicHandler.js | 4 +- yarn.lock | 333 +++++++++++------- 39 files changed, 514 insertions(+), 426 deletions(-) delete mode 100644 src/extensions/Guild.js delete mode 100644 src/extensions/index.js rename src/listeners/{message.js => messageCreate.js} (81%) create mode 100644 src/structures/CommandContext.js diff --git a/.eslintrc b/.eslintrc index 5442179..30ef645 100644 --- a/.eslintrc +++ b/.eslintrc @@ -6,7 +6,7 @@ }, "extends": "eslint:recommended", "parserOptions": { - "ecmaVersion": 10 + "ecmaVersion": 12 }, "rules": { "indent": ["warn", 4], diff --git a/package.json b/package.json index 0440f1a..bc900b9 100644 --- a/package.json +++ b/package.json @@ -18,12 +18,12 @@ "homepage": "https://github.com/Allvaa/lavalink-musicbot#readme", "dependencies": { "@lavacord/discord.js": "0.0.7", - "discord.js": "^12.5.3", + "discord.js": "^13.0.1", "dotenv": "^10.0.0", - "lavasfy": "2.2.1", + "lavasfy": "2.3.0", "pretty-ms": "^7.0.1" }, "devDependencies": { - "eslint": "^7.27.0" + "eslint": "^7.32.0" } } diff --git a/src/bot.js b/src/bot.js index bed9d55..9b2fc71 100644 --- a/src/bot.js +++ b/src/bot.js @@ -1,7 +1,11 @@ +const { Intents } = require("discord.js"); const MusicClient = require("./structures/MusicClient"); const client = new MusicClient({ - disableMentions: "everyone" + intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILD_VOICE_STATES], + allowedMentions: { + parse: ["users", "roles"] + } }); client.build(); \ No newline at end of file diff --git a/src/commands/8d.js b/src/commands/8d.js index 52e0032..8b77baf 100644 --- a/src/commands/8d.js +++ b/src/commands/8d.js @@ -2,17 +2,16 @@ const util = require("../util"); module.exports = { name: "8d", aliases: ["rotation"], - exec: async (msg) => { - const { music } = msg.guild; - if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + exec: async (ctx) => { + const { music } = ctx; + if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); music.set8D(!music.filters["8d"]); - msg.channel.send(util.embed().setDescription(`✅ | ${music.filters["8d"] ? "Enabled" : "Disabled"} **8D**`)); + ctx.respond(util.embed().setDescription(`✅ | ${music.filters["8d"] ? "Enabled" : "Disabled"} **8D**`)); } - }; diff --git a/src/commands/bassboost.js b/src/commands/bassboost.js index 0c7f39c..f954363 100644 --- a/src/commands/bassboost.js +++ b/src/commands/bassboost.js @@ -3,24 +3,24 @@ module.exports = { name: "bassboost", description: "Set bassboost for player", aliases: ["bb"], - exec: async(msg, args) => { - const { music } = msg.guild; - if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + exec: async (ctx) => { + const { music, args } = ctx; + if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); if (!args[0]) { - msg.channel.send(util.embed().setDescription(`${music.filters.bassboost ? `✅ | BassBoost **${music.bassboost * 100}%**` : "❌ | BassBoost **off**"}`)); + ctx.respond(util.embed().setDescription(`${music.filters.bassboost ? `✅ | BassBoost **${music.bassboost * 100}%**` : "❌ | BassBoost **off**"}`)); } else if (args[0].toLowerCase() == "off") { music.setBassboost(0); - msg.react("✅").catch(e => e); + ctx.react("✅").catch(e => e); } else { - if (isNaN(args[0])) return msg.channel.send(util.embed().setDescription("❌ | Specify a number")); - if (args[0] < 1 || args[0] > 100) return msg.channel.send(util.embed().setDescription("❌ | You can only set the bassboost from 1 to 100.")); + if (isNaN(args[0])) return ctx.respond(util.embed().setDescription("❌ | Specify a number")); + if (args[0] < 1 || args[0] > 100) return ctx.respond(util.embed().setDescription("❌ | You can only set the bassboost from 1 to 100.")); music.setBassboost(parseInt(args[0])); - msg.channel.send(util.embed().setDescription(`✅ | BassBoost set to **${music.bassboost * 100}%**`)); + ctx.respond(util.embed().setDescription(`✅ | BassBoost set to **${music.bassboost * 100}%**`)); } } }; diff --git a/src/commands/clearqueue.js b/src/commands/clearqueue.js index f1357b2..e8ff429 100644 --- a/src/commands/clearqueue.js +++ b/src/commands/clearqueue.js @@ -4,17 +4,17 @@ module.exports = { name: "clearqueue", description:"Clean up the queue.", aliases: ["clr", "clear"], - exec: (msg) => { - const { music } = msg.guild; - if (!music.player) return msg.channel.send(util.embed().setDescription("❌| Currently not playing anything.")); - if (!music.queue.length) return msg.channel.send(util.embed().setDescription("❌ | Queue is empty.")); + exec: (ctx) => { + const { music } = ctx; + if (!music.player) return ctx.respond(util.embed().setDescription("❌| Currently not playing anything.")); + if (!music.queue.length) return ctx.respond(util.embed().setDescription("❌ | Queue is empty.")); - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); music.queue.splice(0, 1); - msg.channel.send(util.embed().setDescription("✅ | Cleared the queue.")).catch(e => e); + ctx.respond(util.embed().setDescription("✅ | Cleared the queue.")).catch(e => e); } }; diff --git a/src/commands/doubletime.js b/src/commands/doubletime.js index 9ad2f2e..70bf0ae 100644 --- a/src/commands/doubletime.js +++ b/src/commands/doubletime.js @@ -2,16 +2,16 @@ const util = require("../util"); module.exports = { name: "doubletime", aliases: ["dt"], - exec: async (msg) => { - const { music } = msg.guild; - if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + exec: async (ctx) => { + const { music } = ctx; + if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); music.setDoubleTime(!music.filters.doubleTime); - msg.channel.send(util.embed().setDescription(`✅ | ${music.filters.doubleTime ? "Enabled" : "Disabled"} **Double Time**`)); + ctx.respond(util.embed().setDescription(`✅ | ${music.filters.doubleTime ? "Enabled" : "Disabled"} **Double Time**`)); } }; diff --git a/src/commands/eval.js b/src/commands/eval.js index 9c7fc2d..4fd3b10 100644 --- a/src/commands/eval.js +++ b/src/commands/eval.js @@ -4,11 +4,11 @@ const { isValidURL } = require("../util"); module.exports = { name: "eval", aliases: ["e"], - exec: async (msg, args) => { - if (msg.author.id !== process.env.OWNER_ID) return; - const isAsync = args.includes("--async"); - const isSilent = args.includes("--silent"); - const code = args.filter(e => !/^--(async|silent)$/.test(e)).join(" "); + exec: async (ctx) => { + if (ctx.author.id !== process.env.OWNER_ID) return; + const isAsync = ctx.args.includes("--async"); + const isSilent = ctx.args.includes("--silent"); + const code = ctx.args.filter(e => !/^--(async|silent)$/.test(e)).join(" "); try { let result = eval(isAsync ? `(async()=>{${code}})()` : code); let isResultPromise = false; @@ -19,9 +19,9 @@ module.exports = { if (isSilent) return; let inspectedResult = inspect(result, { depth: 0 }); if (isResultPromise) inspectedResult = `Promise<${inspectedResult}>`; - await msg.channel.send(`${isValidURL(inspectedResult) ? inspectedResult : `\`\`\`js\n${inspectedResult}\`\`\``}`); + await ctx.respond(`${isValidURL(inspectedResult) ? inspectedResult : `\`\`\`js\n${inspectedResult}\`\`\``}`); } catch (e) { - msg.channel.send(`\`\`\`js\n${e}\`\`\``); + ctx.respond(`\`\`\`js\n${e}\`\`\``); } } }; diff --git a/src/commands/help.js b/src/commands/help.js index ba0da61..885c31c 100644 --- a/src/commands/help.js +++ b/src/commands/help.js @@ -5,16 +5,16 @@ const unlisted = ["eval", "source"]; module.exports = { name: "help", aliases: ["commands", "?"], - exec: (msg) => { - const commands = msg.client.commands + exec: (ctx) => { + const commands = ctx.client.commands .filter(c => !unlisted.includes(c.name)) .map(c => `\`${c.name}\``); const embed = util.embed() - .setAuthor("Command List", msg.client.user.displayAvatarURL()) + .setAuthor("Command List", ctx.client.user.displayAvatarURL()) .setDescription(commands.join(", ")) .setTimestamp(); - msg.channel.send(embed); + ctx.respond(embed); } }; diff --git a/src/commands/loop.js b/src/commands/loop.js index 08a6c71..6f9eed3 100644 --- a/src/commands/loop.js +++ b/src/commands/loop.js @@ -18,27 +18,27 @@ const aliases = { module.exports = { name: "loop", aliases: ["repeat"], - exec: (msg, args) => { - const { music } = msg.guild; - if (!music.player) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); + exec: (ctx) => { + const { music, args } = ctx; + if (!music.player) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); if (args[0]) { - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); const loopMode = aliases[args[0].toLowerCase()]; if (loopMode && modes.includes(loopMode)) { music.loop = modes.indexOf(loopMode); - msg.channel.send(util.embed().setDescription(music.loop === 0 ? "✅ | Loop disabled." : `✅ | Set loop to ${modes[music.loop]}.`)); + ctx.respond(util.embed().setDescription(music.loop === 0 ? "✅ | Loop disabled." : `✅ | Set loop to ${modes[music.loop]}.`)); } else { - msg.channel.send( + ctx.respond( util.embed() .setDescription("❌ | Invalid loop mode. Try single/all/off.") ); } } else { - msg.channel.send(util.embed().setDescription(`✅ | Current loop mode: ${modes[music.loop]}`)); + ctx.respond(util.embed().setDescription(`✅ | Current loop mode: ${modes[music.loop]}`)); } } }; diff --git a/src/commands/lyrics.js b/src/commands/lyrics.js index dbc126a..4a14093 100644 --- a/src/commands/lyrics.js +++ b/src/commands/lyrics.js @@ -10,15 +10,15 @@ const getLyrics = async (query) => { module.exports = { name: "lyrics", aliases: ["ly"], - exec: async (msg, args) => { + exec: async (ctx, args) => { let query; if (args.length) { query = args.join(" "); - } else if (msg.guild.music.current) { - const separatedArtistAndTitle = /(.+) - (.+)/.test(msg.guild.music.current.info.title); - query = `${separatedArtistAndTitle ? msg.guild.music.current.info.title : msg.guild.music.current.info.author.replace(" - Topic", "")} - ${msg.guild.music.current.info.title}`; + } else if (ctx.music.current) { + const separatedArtistAndTitle = /(.+) - (.+)/.test(ctx.music.current.info.title); + query = `${separatedArtistAndTitle ? ctx.music.current.info.title : ctx.music.current.info.author.replace(" - Topic", "")} - ${ctx.music.current.info.title}`; } else { - return msg.channel.send(util.embed().setDescription("❌ | Missing args.")); + return ctx.respond(util.embed().setDescription("❌ | Missing args.")); } try { @@ -33,11 +33,11 @@ module.exports = { .setDescription(splittedLyrics[0]) .setFooter(`Page 1 of ${splittedLyrics.length}.`); - const lyricsMsg = await msg.channel.send(embed); - if (splittedLyrics.length > 1) await util.pagination(lyricsMsg, msg.author, splittedLyrics); + const lyricsctx = await ctx.respond(embed); + if (splittedLyrics.length > 1) await util.pagination(lyricsctx, ctx.author, splittedLyrics); } catch (e) { - if (e.message === "Sorry I couldn't find that song's lyrics") msg.channel.send(util.embed().setDescription(`❌ | ${e.message}`)); - else msg.channel.send(`An error occured: ${e.message}.`); + if (e.message === "Sorry I couldn't find that song's lyrics") ctx.respond(util.embed().setDescription(`❌ | ${e.message}`)); + else ctx.respond(`An error occured: ${e.message}.`); } } }; diff --git a/src/commands/move.js b/src/commands/move.js index 8e02609..26bd7aa 100644 --- a/src/commands/move.js +++ b/src/commands/move.js @@ -3,28 +3,28 @@ const util = require("../util"); module.exports = { name: "move", aliases: ["mv"], - exec: async (msg, args) => { - const { music } = msg.guild; + exec: async (ctx) => { + const { music, args } = ctx; const from = args[0] ? parseInt(args[0], 10) : null; const to = args[1] ? parseInt(args[1], 10) : null; - if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); - if (!music.queue.length) return msg.channel.send(util.embed().setDescription("❌ | Queue is empty.")); + if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.queue.length) return ctx.respond(util.embed().setDescription("❌ | Queue is empty.")); - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); if (from === null || to === null) - return msg.channel.send(util.embed().setDescription(`❌ | Missing args. Example usage e.g. \`${msg.client.prefix}move 2 1\``)); + return ctx.respond(util.embed().setDescription(`❌ | Missing args. Example usage e.g. \`${ctx.client.prefix}move 2 1\``)); if (from === to || (isNaN(from) || from < 1 || from > music.queue.length) || (isNaN(to) || to < 1 || to > music.queue.length)) - return msg.channel.send(util.embed().setDescription("❌ | Number is invalid or exceeds queue length.")); + return ctx.respond(util.embed().setDescription("❌ | Number is invalid or exceeds queue length.")); const moved = music.queue[from - 1]; util.moveArrayElement(music.queue, from - 1, to - 1); - msg.channel.send(util.embed().setDescription(`✅ | Moved **${moved.info.title}** to \`${to}\`.`)); + ctx.respond(util.embed().setDescription(`✅ | Moved **${moved.info.title}** to \`${to}\`.`)); } }; diff --git a/src/commands/nightcore.js b/src/commands/nightcore.js index 08a96ae..d3fde4b 100644 --- a/src/commands/nightcore.js +++ b/src/commands/nightcore.js @@ -2,16 +2,16 @@ const util = require("../util"); module.exports = { name: "nightcore", aliases: ["nc"], - exec: async (msg) => { - const { music } = msg.guild; - if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + exec: async (ctx) => { + const { music } = ctx; + if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); music.setNightcore(!music.filters.nightcore); - msg.channel.send(util.embed().setDescription(`✅ | ${music.filters.nightcore ? "Enabled" : "Disabled"} **Nightcore**`)); + ctx.respond(util.embed().setDescription(`✅ | ${music.filters.nightcore ? "Enabled" : "Disabled"} **Nightcore**`)); } }; diff --git a/src/commands/nowplaying.js b/src/commands/nowplaying.js index 63f83bb..7b3d24b 100644 --- a/src/commands/nowplaying.js +++ b/src/commands/nowplaying.js @@ -3,10 +3,10 @@ const util = require("../util"); module.exports = { name: "nowplaying", aliases: ["np", "nowplay"], - exec: (msg) => { - const { music } = msg.guild; - if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); + exec: (ctx) => { + const { music } = ctx; + if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); const progress = util.progress(music.player.state.position, music.current.info.length); - msg.channel.send(util.embed().setDescription(`🎶 | Now playing ${music.current.info.isStream ? "[**◉ LIVE**]" : ""}\n**${music.current.info.title}**.${music.current.info.isStream ? "" : `\n\n${util.millisToDuration(music.player.state.position)} ${progress.bar} ${util.millisToDuration(music.current.info.length)}`}`)); + ctx.respond(util.embed().setDescription(`🎶 | Now playing ${music.current.info.isStream ? "[**◉ LIVE**]" : ""}\n**${music.current.info.title}**.${music.current.info.isStream ? "" : `\n\n${util.millisToDuration(music.player.state.position)} ${progress.bar} ${util.millisToDuration(music.current.info.length)}`}`)); } }; diff --git a/src/commands/pause.js b/src/commands/pause.js index 5747855..c74a656 100644 --- a/src/commands/pause.js +++ b/src/commands/pause.js @@ -2,19 +2,19 @@ const util = require("../util"); module.exports = { name: "pause", - exec: async (msg) => { - const { music } = msg.guild; - if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + exec: async (ctx) => { + const { music } = ctx; + if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); try { await music.pause(); - msg.react("⏸️").catch(e => e); + ctx.react("⏸️").catch(e => e); } catch (e) { - msg.channel.send(`An error occured: ${e.message}.`); + ctx.respond(`An error occured: ${e.message}.`); } } }; diff --git a/src/commands/ping.js b/src/commands/ping.js index 5f3e37c..2c6eca2 100644 --- a/src/commands/ping.js +++ b/src/commands/ping.js @@ -1,12 +1,6 @@ -const util = require("../util"); module.exports = { name: "ping", - exec: (msg) => { - const responseTime = Date.now() - msg.createdTimestamp; - const apiLatency = msg.client.ws.ping; - msg.channel.send( - util.embed() - .setDescription(`**Response Time**: ${responseTime}ms\n**API Latency**: ${apiLatency}ms`) - ); + exec: (ctx) => { + ctx.respond(`🏓 Pong! \`${ctx.client.ws.ping}ms\``); } }; diff --git a/src/commands/play.js b/src/commands/play.js index d0506f8..8d15373 100644 --- a/src/commands/play.js +++ b/src/commands/play.js @@ -1,51 +1,51 @@ const util = require("../util"); -const getAttachmentURL = (msg) => (msg.attachments.first() || {}).url; +const getAttachmentURL = ctx => ctx.attachments.first()?.url; module.exports = { name: "play", aliases: ["p"], - exec: async (msg, args) => { - const { music } = msg.guild; - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + exec: async (ctx) => { + const { args, music } = ctx; + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); - const missingPerms = util.missingPerms(msg.guild.me.permissionsIn(msg.member.voice.channel), ["CONNECT", "SPEAK"]); + const missingPerms = util.missingPerms(ctx.guild.me.permissionsIn(ctx.member.voice.channel), ["CONNECT", "SPEAK"]); if ((!music.player || !music.player.playing) && missingPerms.length) - return msg.channel.send(util.embed().setDescription(`❌ | I need ${missingPerms.length > 1 ? "these" : "this"} permission${missingPerms.length > 1 ? "s" : ""} on your voice channel: ${missingPerms.map(x => `\`${x}\``).join(", ")}.`)); + return ctx.respond(util.embed().setDescription(`❌ | I need ${missingPerms.length > 1 ? "these" : "this"} permission${missingPerms.length > 1 ? "s" : ""} on your voice channel: ${missingPerms.map(x => `\`${x}\``).join(", ")}.`)); if (!music.node || !music.node.connected) - return msg.channel.send(util.embed().setDescription("❌ | Lavalink node not connected.")); + return ctx.respond(util.embed().setDescription("❌ | Lavalink node not connected.")); - const query = args.join(" ") || getAttachmentURL(msg); - if (!query) return msg.channel.send(util.embed().setDescription("❌ | Missing args.")); + const query = args.join(" ") || getAttachmentURL(ctx.message); + if (!query) return ctx.respond(util.embed().setDescription("❌ | Missing args.")); try { const { loadType, playlistInfo: { name }, tracks } = await music.load(util.isValidURL(query) ? query : `ytsearch:${query}`); - if (!tracks.length) return msg.channel.send(util.embed().setDescription("❌ | Couldn't find any results.")); + if (!tracks.length) return ctx.respond(util.embed().setDescription("❌ | Couldn't find any results.")); if (loadType === "PLAYLIST_LOADED") { for (const track of tracks) { - track.requester = msg.author; + track.requester = ctx.author; music.queue.push(track); } - msg.channel.send(util.embed().setDescription(`✅ | Loaded \`${tracks.length}\` tracks from **${name}**.`)); + ctx.respond(util.embed().setDescription(`✅ | Loaded \`${tracks.length}\` tracks from **${name}**.`)); } else { const track = tracks[0]; - track.requester = msg.author; + track.requester = ctx.author; music.queue.push(track); if (music.player && music.player.playing) - msg.channel.send(util.embed().setDescription(`✅ | **${track.info.title}** added to the queue.`)); + ctx.respond(util.embed().setDescription(`✅ | **${track.info.title}** added to the queue.`)); } - if (!music.player) await music.join(msg.member.voice.channel); + if (!music.player) await music.join(ctx.member.voice.channel); if (!music.player.playing) await music.start(); - music.setTextCh(msg.channel); + music.setTextCh(ctx.channel); } catch (e) { - msg.channel.send(`An error occured: ${e.message}.`); + ctx.respond(`An error occured: ${e.message}.`); } } }; diff --git a/src/commands/previous.js b/src/commands/previous.js index 3f8f18a..4bcf900 100644 --- a/src/commands/previous.js +++ b/src/commands/previous.js @@ -3,22 +3,22 @@ const util = require("../util"); module.exports = { name: "previous", aliases: ["prev"], - exec: async (msg) => { - const { music } = msg.guild; - if (!music.player) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); - if (!music.previous) return msg.channel.send(util.embed().setDescription("❌ | No previous track.")); + exec: async (ctx) => { + const { music } = ctx; + if (!music.player) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.previous) return ctx.respond(util.embed().setDescription("❌ | No previous track.")); - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); try { music.queue.unshift(music.previous); await music.skip(); - msg.react("⏮️").catch(e => e); + ctx.react("⏮️").catch(e => e); } catch (e) { - msg.channel.send(`An error occured: ${e.message}.`); + ctx.respond(`An error occured: ${e.message}.`); } } }; diff --git a/src/commands/queue.js b/src/commands/queue.js index 50e7f61..f74770b 100644 --- a/src/commands/queue.js +++ b/src/commands/queue.js @@ -3,24 +3,24 @@ const util = require("../util"); module.exports = { name: "queue", aliases: ["q"], - exec: async (msg) => { - const { music } = msg.guild; - if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); - if (!music.queue.length) return msg.channel.send(util.embed().setDescription("❌ | Queue is empty.")); + exec: async (ctx) => { + const { music } = ctx; + if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.queue.length) return ctx.respond(util.embed().setDescription("❌ | Queue is empty.")); const queue = music.queue.map((t, i) => `\`${++i}.\` **${t.info.title}** ${t.requester}`); const chunked = util.chunk(queue, 10).map(x => x.join("\n")); const embed = util.embed() - .setAuthor(`${msg.guild.name} Music Queue`, msg.guild.iconURL({ dynamic: true })) + .setAuthor(`${ctx.guild.name} Music Queue`, ctx.guild.iconURL({ dynamic: true })) .setDescription(chunked[0]) .setFooter(`Page 1 of ${chunked.length}.`); try { - const queueMsg = await msg.channel.send(embed); - if (chunked.length > 1) await util.pagination(queueMsg, msg.author, chunked); + const queuectx = await ctx.respond(embed); + if (chunked.length > 1) await util.pagination(queuectx, ctx.author, chunked); } catch (e) { - msg.channel.send(`An error occured: ${e.message}.`); + ctx.respond(`An error occured: ${e.message}.`); } } }; diff --git a/src/commands/remove.js b/src/commands/remove.js index 7bf1a0b..ec6d8ab 100644 --- a/src/commands/remove.js +++ b/src/commands/remove.js @@ -3,23 +3,23 @@ const util = require("../util"); module.exports = { name: "remove", aliases: ["rm"], - exec: async (msg, args) => { - const { music } = msg.guild; - if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌| Currently not playing anything.")); - if (!music.queue.length) return msg.channel.send(util.embed().setDescription("❌ | Queue is empty.")); + exec: async (ctx) => { + const { music, args } = ctx; + if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌| Currently not playing anything.")); + if (!music.queue.length) return ctx.respond(util.embed().setDescription("❌ | Queue is empty.")); - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); - if (!args[0]) return msg.channel.send(util.embed().setDescription("❌ | Missing args.")); + if (!args[0]) return ctx.respond(util.embed().setDescription("❌ | Missing args.")); let iToRemove = parseInt(args[0], 10); if (isNaN(iToRemove) || iToRemove < 1 || iToRemove > music.queue.length) - return msg.channel.send(util.embed().setDescription("❌ | Invalid number to remove.")); + return ctx.respond(util.embed().setDescription("❌ | Invalid number to remove.")); const removed = music.queue.splice(--iToRemove, 1)[0]; - msg.channel.send(util.embed().setDescription(`✅ | Removed **${removed.info.title}** from the queue.`)); + ctx.respond(util.embed().setDescription(`✅ | Removed **${removed.info.title}** from the queue.`)); } }; diff --git a/src/commands/removedupes.js b/src/commands/removedupes.js index 0db4462..c0328c0 100644 --- a/src/commands/removedupes.js +++ b/src/commands/removedupes.js @@ -4,23 +4,23 @@ module.exports = { name: "removedupes", aliases: ["rdp"], description: "Removes duplicated tracks from the queue.", - exec: (msg) => { - const { music } = msg.guild; + exec: (ctx) => { + const { music } = ctx; const seen = {}; - if (!music.player) return msg.channel.send(util.embed().setDescription("❌| Currently not playing anything.")); - if (!music.queue.length) return msg.channel.send(util.embed().setDescription("❌ | Queue is empty.")); + if (!music.player) return ctx.respond(util.embed().setDescription("❌| Currently not playing anything.")); + if (!music.queue.length) return ctx.respond(util.embed().setDescription("❌ | Queue is empty.")); - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); for (const song of music.queue) { if (seen[song.info.indentifier] === undefined) seen[song.info.indentifier] = song; } music.queue = Object.values(seen); - msg.channel.send(util.embed().setDescription("✅ | Removed all Dupes")).catch(e => e); + ctx.respond(util.embed().setDescription("✅ | Removed all Dupes")).catch(e => e); } }; diff --git a/src/commands/resume.js b/src/commands/resume.js index 9b4a36a..45ed151 100644 --- a/src/commands/resume.js +++ b/src/commands/resume.js @@ -2,19 +2,19 @@ const util = require("../util"); module.exports = { name: "resume", - exec: async (msg) => { - const { music } = msg.guild; - if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌| Currently not playing anything.")); - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + exec: async (ctx) => { + const { music } = ctx; + if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌| Currently not playing anything.")); + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); try { await music.resume(); - msg.react("▶️").catch(e => e); + ctx.react("▶️").catch(e => e); } catch (e) { - msg.channel.send(`An error occured: ${e.message}.`); + ctx.respond(`An error occured: ${e.message}.`); } } }; diff --git a/src/commands/search.js b/src/commands/search.js index 4adcc3c..c26d37a 100644 --- a/src/commands/search.js +++ b/src/commands/search.js @@ -2,31 +2,31 @@ const util = require("../util"); module.exports = { name: "search", - exec: async (msg, args) => { - const { music } = msg.guild; - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + exec: async (ctx) => { + const { music, args } = ctx; + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); - const missingPerms = util.missingPerms(msg.guild.me.permissionsIn(msg.member.voice.channel), ["CONNECT", "SPEAK"]); + const missingPerms = util.missingPerms(ctx.guild.me.permissionsIn(ctx.member.voice.channel), ["CONNECT", "SPEAK"]); if ((!music.player || !music.player.playing) && missingPerms.length) - return msg.channel.send(util.embed().setDescription(`❌ | I need ${missingPerms.length > 1 ? "these" : "this"} permission${missingPerms.length > 1 ? "s" : ""} on your voice channel: ${missingPerms.map(x => `\`${x}\``).join(", ")}.`)); + return ctx.respond(util.embed().setDescription(`❌ | I need ${missingPerms.length > 1 ? "these" : "this"} permission${missingPerms.length > 1 ? "s" : ""} on your voice channel: ${missingPerms.map(x => `\`${x}\``).join(", ")}.`)); if (!music.node || !music.node.connected) - return msg.channel.send(util.embed().setDescription("❌ | Lavalink node not connected.")); + return ctx.respond(util.embed().setDescription("❌ | Lavalink node not connected.")); const query = args.join(" "); - if (!query) return msg.channel.send(util.embed().setDescription("❌ | Missing args.")); + if (!query) return ctx.respond(util.embed().setDescription("❌ | Missing args.")); try { let { tracks } = await music.load(`ytsearch:${query}`); - if (!tracks.length) return msg.channel.send(util.embed().setDescription("❌ | Couldn't find any results.")); + if (!tracks.length) return ctx.respond(util.embed().setDescription("❌ | Couldn't find any results.")); tracks = tracks.slice(0, 10); - const resultMessage = await msg.channel.send(util.embed() - .setAuthor("Search Result", msg.client.user.displayAvatarURL()) + const resultMessage = await ctx.respond(util.embed() + .setAuthor("Search Result", ctx.client.user.displayAvatarURL()) .setDescription(tracks.map((x, i) => `\`${++i}.\` **${x.info.title}**`)) .setFooter("Select from 1 to 10 or type \"cancel\" to cancel the command.")); @@ -40,7 +40,7 @@ module.exports = { return resultMessage.edit(util.embed().setDescription("✅ | Cancelled.")); const track = tracks[response.content - 1]; - track.requester = msg.author; + track.requester = ctx.author; music.queue.push(track); if (music.player && music.player.playing) { @@ -49,18 +49,18 @@ module.exports = { resultMessage.delete(); } - if (!music.player) await music.join(msg.member.voice.channel); + if (!music.player) await music.join(ctx.member.voice.channel); if (!music.player.playing) await music.start(); - music.setTextCh(msg.channel); + music.setTextCh(ctx.channel); } catch (e) { - msg.channel.send(`An error occured: ${e.message}.`); + ctx.respond(`An error occured: ${e.message}.`); } async function awaitMessages() { try { - const collector = await msg.channel.awaitMessages( - m => m.author.equals(msg.author) && (/^cancel$/i.exec(m.content) || (!isNaN(parseInt(m.content, 10)) && (m.content >= 1 && m.content <= 10))), + const collector = await ctx.channel.awaitMessages( + m => m.author.equals(ctx.author) && (/^cancel$/i.exec(m.content) || (!isNaN(parseInt(m.content, 10)) && (m.content >= 1 && m.content <= 10))), { time: 10000, max: 1, diff --git a/src/commands/seek.js b/src/commands/seek.js index 508a801..420f993 100644 --- a/src/commands/seek.js +++ b/src/commands/seek.js @@ -4,32 +4,32 @@ const durationPattern = /^[0-5]?[0-9](:[0-5][0-9]){1,2}$/; module.exports = { name: "seek", - exec: async (msg, args) => { - const { music } = msg.guild; - if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + exec: async (ctx) => { + const { music, args } = ctx; + if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); if (!music.current.info.isSeekable) - return msg.channel.send(util.embed().setDescription("❌ | Current track isn't seekable.")); + return ctx.respond(util.embed().setDescription("❌ | Current track isn't seekable.")); const duration = args[0]; if (!duration) - return msg.channel.send(util.embed().setDescription("❌ | You must provide duration to seek. Valid duration e.g. `1:34`.")); + return ctx.respond(util.embed().setDescription("❌ | You must provide duration to seek. Valid duration e.g. `1:34`.")); if (!durationPattern.test(duration)) - return msg.channel.send(util.embed().setDescription("❌ | You provided an invalid duration. Valid duration e.g. `1:34`.")); + return ctx.respond(util.embed().setDescription("❌ | You provided an invalid duration. Valid duration e.g. `1:34`.")); const durationMs = util.durationToMillis(duration); if (durationMs > music.current.info.length) - return msg.channel.send(util.embed().setDescription("❌ | The duration you provide exceeds the duration of the current track.")); + return ctx.respond(util.embed().setDescription("❌ | The duration you provide exceeds the duration of the current track.")); try { await music.player.seek(durationMs); - msg.channel.send(util.embed().setDescription(`✅ | Seeked to ${util.millisToDuration(durationMs)}.`)); + ctx.respond(util.embed().setDescription(`✅ | Seeked to ${util.millisToDuration(durationMs)}.`)); } catch (e) { - msg.channel.send(`An error occured: ${e.message}.`); + ctx.respond(`An error occured: ${e.message}.`); } } }; diff --git a/src/commands/shuffle.js b/src/commands/shuffle.js index 00949f8..12071d5 100644 --- a/src/commands/shuffle.js +++ b/src/commands/shuffle.js @@ -3,17 +3,17 @@ const util = require("../util"); module.exports = { name: "shuffle", aliases: ["sf"], - exec: async (msg) => { - const { music } = msg.guild; - if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); - if (!music.queue.length) return msg.channel.send(util.embed().setDescription("❌ | Queue is empty.")); - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + exec: async (ctx) => { + const { music } = ctx; + if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.queue.length) return ctx.respond(util.embed().setDescription("❌ | Queue is empty.")); + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); music.queue = util.shuffleArray(music.queue); - msg.channel.send(util.embed().setDescription(`✅ | Queue shuffled! Type \`${msg.client.prefix}queue\` to see changes.`)); + ctx.respond(util.embed().setDescription(`✅ | Queue shuffled! Type \`${ctx.client.prefix}queue\` to see changes.`)); } }; diff --git a/src/commands/skip.js b/src/commands/skip.js index e35b588..28cc1a4 100644 --- a/src/commands/skip.js +++ b/src/commands/skip.js @@ -3,24 +3,24 @@ const util = require("../util"); module.exports = { name: "skip", aliases: ["skipto"], - exec: async (msg, args) => { - const { music } = msg.guild; + exec: async (ctx) => { + const { music, args } = ctx; const skipTo = args[0] ? parseInt(args[0], 10) : null; - if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); if (skipTo !== null && (isNaN(skipTo) || skipTo < 1 || skipTo > music.queue.length)) - return msg.channel.send(util.embed().setDescription("❌ | Invalid number to skip.")); + return ctx.respond(util.embed().setDescription("❌ | Invalid number to skip.")); try { await music.skip(skipTo); - msg.react("⏭️").catch(e => e); + ctx.react("⏭️").catch(e => e); } catch (e) { - msg.channel.send(`An error occured: ${e.message}.`); + ctx.respond(`An error occured: ${e.message}.`); } } }; diff --git a/src/commands/source.js b/src/commands/source.js index 0c9f2ab..b613c99 100644 --- a/src/commands/source.js +++ b/src/commands/source.js @@ -3,7 +3,7 @@ const util = require("../util"); module.exports = { name: "source", aliases: ["src"], - exec: (msg) => { - msg.channel.send(util.embed().setDescription("✅ | [Here](https://github.com/Allvaa/lavalink-musicbot) is the open source repository this bot uses.")); + exec: (ctx) => { + ctx.respond(util.embed().setDescription("✅ | [Here](https://github.com/Allvaa/lavalink-musicbot) is the open source repository this bot uses.")); } }; diff --git a/src/commands/stats.js b/src/commands/stats.js index 55102e9..1ab103d 100644 --- a/src/commands/stats.js +++ b/src/commands/stats.js @@ -3,12 +3,12 @@ const util = require("../util"); module.exports = { name: "stats", - exec: (msg) => { + exec: (ctx) => { /** @type {import("lavacord").LavalinkNode[]} */ - const nodes = [...msg.client.manager.nodes.values()]; + const nodes = [...ctx.client.manager.nodes.values()]; - msg.channel.send(util.embed() - .setAuthor("Lavalink Node(s) Stats", msg.client.user.displayAvatarURL()) + ctx.respond(util.embed() + .setAuthor("Lavalink Node(s) Stats", ctx.client.user.displayAvatarURL()) .setTitle("Source Code") .setURL("https://github.com/Allvaa/lavalink-musicbot") .setDescription( diff --git a/src/commands/stop.js b/src/commands/stop.js index 0eb618f..b8930e5 100644 --- a/src/commands/stop.js +++ b/src/commands/stop.js @@ -3,19 +3,19 @@ const util = require("../util"); module.exports = { name: "stop", aliases: ["leave", "dc"], - exec: async (msg) => { - const { music } = msg.guild; - if (!music.player) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + exec: async (ctx) => { + const { music } = ctx; + if (!music.player) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); try { await music.stop(); - msg.react("⏹️").catch(e => e); + ctx.react("⏹️").catch(e => e); } catch (e) { - msg.channel.send(`An error occured: ${e.message}.`); + ctx.respond(`An error occured: ${e.message}.`); } } }; diff --git a/src/commands/vaporwave.js b/src/commands/vaporwave.js index 1ff9b91..31f53d8 100644 --- a/src/commands/vaporwave.js +++ b/src/commands/vaporwave.js @@ -2,15 +2,15 @@ const util = require("../util"); module.exports = { name: "vaporwave", aliases: ["vp"], - exec: async (msg) => { - const { music } = msg.guild; - if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + exec: async (ctx) => { + const { music } = ctx; + if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); music.setVaporwave(!music.filters.vaporwave); - msg.channel.send(util.embed().setDescription(`✅ | ${music.filters.vaporwave ? "Enabled" : "Disabled"} **Vaporwave**`)); + ctx.respond(util.embed().setDescription(`✅ | ${music.filters.vaporwave ? "Enabled" : "Disabled"} **Vaporwave**`)); } }; diff --git a/src/commands/volume.js b/src/commands/volume.js index e4cf45c..f1ce2a5 100644 --- a/src/commands/volume.js +++ b/src/commands/volume.js @@ -3,27 +3,27 @@ const util = require("../util"); module.exports = { name: "volume", aliases: ["vol"], - exec: async (msg, args) => { - const { music } = msg.guild; + exec: async (ctx) => { + const { music, args } = ctx; const newVolume = parseInt(args[0], 10); - if (!music.player || !music.player.playing) return msg.channel.send(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); try { if (isNaN(newVolume)) { - msg.channel.send(util.embed().setDescription(`🔉 | Current volume \`${music.volume}\`.`)); + ctx.respond(util.embed().setDescription(`🔉 | Current volume \`${music.volume}\`.`)); } else { - if (!msg.member.voice.channel) - return msg.channel.send(util.embed().setDescription("❌ | You must be on a voice channel.")); - if (msg.guild.me.voice.channel && !msg.guild.me.voice.channel.equals(msg.member.voice.channel)) - return msg.channel.send(util.embed().setDescription(`❌ | You must be on ${msg.guild.me.voice.channel} to use this command.`)); + if (!ctx.member.voice.channel) + return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); if (newVolume < 0 || newVolume > 150) - return msg.channel.send(util.embed().setDescription("❌ | You can only set the volume from 0 to 150.")); + return ctx.respond(util.embed().setDescription("❌ | You can only set the volume from 0 to 150.")); await music.setVolume(newVolume); - msg.channel.send(util.embed().setDescription(`🔉 | Volume set to \`${music.volume}\`.`)); + ctx.respond(util.embed().setDescription(`🔉 | Volume set to \`${music.volume}\`.`)); } } catch (e) { - msg.channel.send(`An error occured: ${e.message}.`); + ctx.respond(`An error occured: ${e.message}.`); } } }; diff --git a/src/extensions/Guild.js b/src/extensions/Guild.js deleted file mode 100644 index da71c01..0000000 --- a/src/extensions/Guild.js +++ /dev/null @@ -1,13 +0,0 @@ -const { Structures } = require("discord.js"); -const MusicHandler = require("../structures/MusicHandler"); - -const Guild = Structures.get("Guild"); - -class MusicGuild extends Guild { - constructor(client, data) { - super(client, data); - this.music = new MusicHandler(this); - } -} - -Structures.extend("Guild", () => MusicGuild); diff --git a/src/extensions/index.js b/src/extensions/index.js deleted file mode 100644 index 5dfb8a8..0000000 --- a/src/extensions/index.js +++ /dev/null @@ -1 +0,0 @@ -require("./Guild"); diff --git a/src/listeners/message.js b/src/listeners/messageCreate.js similarity index 81% rename from src/listeners/message.js rename to src/listeners/messageCreate.js index f7f4dd7..60eceda 100644 --- a/src/listeners/message.js +++ b/src/listeners/messageCreate.js @@ -1,5 +1,7 @@ +const CommandContext = require("../structures/CommandContext"); + module.exports = { - name: "message", + name: "messageCreate", exec: async (client, msg) => { if (!msg.guild) return; if (msg.author.bot) return; @@ -12,7 +14,7 @@ module.exports = { const command = client.commands.get(commandName) || client.commands.find(c => c.aliases && c.aliases.includes(commandName)); if (command) { try { - await command.exec(msg, args); + await command.exec(new CommandContext(command, msg, args)); } catch (e) { console.error(e); } diff --git a/src/listeners/voiceStateUpdate.js b/src/listeners/voiceStateUpdate.js index 39bd55e..f9bf0d5 100644 --- a/src/listeners/voiceStateUpdate.js +++ b/src/listeners/voiceStateUpdate.js @@ -1,11 +1,8 @@ module.exports = { name: "voiceStateUpdate", exec: async (client, oldState, newState) => { - // if the member was not cached - if (!newState.member) await newState.guild.members.fetch(newState.id); - - const { guild: { music } } = newState; - if (newState.member.user.equals(client.user) && !newState.channel && music.player) { + const music = client.musics.get(newState.guild.id); + if (newState.member.user.equals(client.user) && !newState.channel && music?.player) { if (music.player.playing) await music.stop(); if (music.player) await client.manager.leave(music.guild.id); } diff --git a/src/structures/CommandContext.js b/src/structures/CommandContext.js new file mode 100644 index 0000000..64d5979 --- /dev/null +++ b/src/structures/CommandContext.js @@ -0,0 +1,43 @@ +const { MessageEmbed } = require("discord.js"); +const MusicHandler = require("./MusicHandler"); + +module.exports = class CommandContext { + constructor(command, message, args) { + this.command = command; + this.message = message; + this.args = args; + } + + get client() { + return this.message.client; + } + + get guild() { + return this.message.guild; + } + + get channel() { + return this.message.channel; + } + + get member() { + return this.message.member; + } + + get author() { + return this.message.author; + } + + get music() { + if (this.client.musics.has(this.guild.id)) { + return this.client.musics.get(this.guild.id); + } + const musicHandler = new MusicHandler(this.guild); + this.client.musics.set(this.guild.id, musicHandler); + return musicHandler; + } + + respond(opt) { + this.channel.send(opt instanceof MessageEmbed ? { embeds: [opt] } : opt); + } +}; diff --git a/src/structures/MusicClient.js b/src/structures/MusicClient.js index 2d10a19..17e67a7 100644 --- a/src/structures/MusicClient.js +++ b/src/structures/MusicClient.js @@ -4,12 +4,11 @@ const { promises: { readdir } } = require("fs"); const { join } = require("path"); const { LavasfyClient } = require("lavasfy"); -require("../extensions"); - module.exports = class MusicClient extends Client { /** @param {import("discord.js").ClientOptions} [opt] */ constructor(opt) { super(opt); + this.musics = new Collection(); this.commands = new Collection(); this.manager = new Manager(this, [ { @@ -25,7 +24,8 @@ module.exports = class MusicClient extends Client { clientSecret: process.env.SPOTIFY_SECRET, playlistLoadLimit: process.env.SPOTIFY_PLAYLIST_PAGE_LIMIT, audioOnlyResults: true, - useSpotifyMetadata: true + useSpotifyMetadata: true, + autoResolve: true }, [...[...this.manager.nodes.values()]]) : null; diff --git a/src/structures/MusicHandler.js b/src/structures/MusicHandler.js index 1b5513a..008b8f3 100644 --- a/src/structures/MusicHandler.js +++ b/src/structures/MusicHandler.js @@ -66,7 +66,7 @@ module.exports = class MusicHandler { this.player .on("start", () => { this.current = this.queue.shift(); - if (this.textChannel) this.textChannel.send(util.embed().setDescription(`🎶 | Now playing **${this.current.info.title}**.`)); + if (this.textChannel) this.textChannel.send({embeds:[util.embed().setDescription(`🎶 | Now playing **${this.current.info.title}**.`)]}); }) .on("end", (data) => { if (data.reason === "REPLACED") return; @@ -80,7 +80,7 @@ module.exports = class MusicHandler { if (!this.queue.length) { this.client.manager.leave(this.guild.id); - if (this.textChannel) this.textChannel.send(util.embed().setDescription("✅ | Queue is empty. Leaving voice channel..")); + if (this.textChannel) this.textChannel.send({embeds:[util.embed().setDescription("✅ | Queue is empty. Leaving voice channel..")]}); this.reset(); return; } diff --git a/yarn.lock b/yarn.lock index 50d2e33..36b3590 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,24 +9,35 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/helper-validator-identifier@^7.10.4": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" - integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== +"@babel/helper-validator-identifier@^7.14.5": + version "7.14.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48" + integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g== "@babel/highlight@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" - integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" + integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== dependencies: - "@babel/helper-validator-identifier" "^7.10.4" + "@babel/helper-validator-identifier" "^7.14.5" chalk "^2.0.0" js-tokens "^4.0.0" -"@discordjs/collection@^0.1.6": - version "0.1.6" - resolved "https://registry.yarnpkg.com/@discordjs/collection/-/collection-0.1.6.tgz#9e9a7637f4e4e0688fd8b2b5c63133c91607682c" - integrity sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ== +"@discordjs/builders@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@discordjs/builders/-/builders-0.4.0.tgz#bb41573ce4824aa9194a53b52c29c5219b610010" + integrity sha512-EiwLltKph6TSaPJIzJYdzNc1PnA2ZNaaE0t0ODg3ghnpVHqfgd0YX9/srsleYHW2cw1sfIq+kbM+h0etf7GWLA== + dependencies: + "@sindresorhus/is" "^4.0.1" + discord-api-types "^0.22.0" + ow "^0.27.0" + ts-mixer "^6.0.0" + tslib "^2.3.0" + +"@discordjs/collection@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@discordjs/collection/-/collection-0.2.1.tgz#ea4bc7b41b7b7b6daa82e439141222ec95c469b2" + integrity sha512-vhxqzzM8gkomw0TYRF3tgx7SwElzUlXT/Aa41O7mOcyN6wIJfj5JmDWaO5XGKsGSsNx7F3i5oIlrucCCWV1Nog== "@discordjs/form-data@^3.0.1": version "3.0.1" @@ -37,21 +48,35 @@ combined-stream "^1.0.8" mime-types "^2.1.12" -"@eslint/eslintrc@^0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.1.tgz#442763b88cecbe3ee0ec7ca6d6dd6168550cbf14" - integrity sha512-5v7TDE9plVhvxQeWLXDTvFvJBdH6pEsdnl2g/dAptmuFEPedQ4Erq5rsDsX+mvAM610IhNaO2W5V1dOOnDKxkQ== +"@eslint/eslintrc@^0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" + integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== dependencies: ajv "^6.12.4" debug "^4.1.1" espree "^7.3.0" - globals "^12.1.0" + globals "^13.9.0" ignore "^4.0.6" import-fresh "^3.2.1" js-yaml "^3.13.1" minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@humanwhocodes/config-array@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" + integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== + dependencies: + "@humanwhocodes/object-schema" "^1.2.0" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf" + integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w== + "@lavacord/discord.js@0.0.7": version "0.0.7" resolved "https://registry.yarnpkg.com/@lavacord/discord.js/-/discord.js-0.0.7.tgz#8ba1e944cb5853693a72274ead66798a79e1c07a" @@ -59,17 +84,32 @@ dependencies: lavacord "1.1.9" -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== +"@sapphire/async-queue@^1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@sapphire/async-queue/-/async-queue-1.1.4.tgz#ae431310917a8880961cebe8e59df6ffa40f2957" + integrity sha512-fFrlF/uWpGOX5djw5Mu2Hnnrunao75WGey0sP0J3jnhmrJ5TAPzHYOmytD5iN/+pMxS+f+u/gezqHa9tPhRHEA== + +"@sindresorhus/is@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.0.1.tgz#d26729db850fa327b7cacc5522252194404226f5" + integrity sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g== + +"@types/node@*": + version "16.4.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.4.13.tgz#7dfd9c14661edc65cccd43a29eb454174642370d" + integrity sha512-bLL69sKtd25w7p1nvg9pigE4gtKVpGTPojBFLMkGHXuUgap2sLqQt2qUnqmVCDfzGUL0DRNZP+1prIZJbMeAXg== + +"@types/ws@^7.4.7": + version "7.4.7" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" + integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww== dependencies: - event-target-shim "^5.0.0" + "@types/node" "*" acorn-jsx@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" - integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn@^7.4.0: version "7.4.1" @@ -87,9 +127,9 @@ ajv@^6.10.0, ajv@^6.12.4: uri-js "^4.2.2" ajv@^8.0.1: - version "8.5.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.5.0.tgz#695528274bcb5afc865446aa275484049a18ae4b" - integrity sha512-Y2l399Tt1AguU3BPRP9Fn4eN+Or+StUGWCUpbnFyXSo8NZ9S4uj+AG2pjs5apK+ZMOwYOz1+a+VKvKH7CudXgQ== + version "8.6.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.6.2.tgz#2fb45e0e5fcbc0813326c1c3da535d1881bb0571" + integrity sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" @@ -138,9 +178,9 @@ asynckit@^0.4.0: integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== brace-expansion@^1.1.7: version "1.1.11" @@ -150,7 +190,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -callsites@^3.0.0: +callsites@^3.0.0, callsites@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== @@ -165,9 +205,9 @@ chalk@^2.0.0: supports-color "^5.3.0" chalk@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" - integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== dependencies: ansi-styles "^4.1.0" supports-color "^7.1.0" @@ -218,9 +258,9 @@ cross-spawn@^7.0.2: which "^2.0.1" debug@^4.0.1, debug@^4.1.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" - integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + version "4.3.2" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" + integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== dependencies: ms "2.1.2" @@ -234,19 +274,24 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -discord.js@^12.5.3: - version "12.5.3" - resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-12.5.3.tgz#56820d473c24320871df9ea0bbc6b462f21cf85c" - integrity sha512-D3nkOa/pCkNyn6jLZnAiJApw2N9XrIsXUAdThf01i7yrEuqUmDGc7/CexVWwEcgbQR97XQ+mcnqJpmJ/92B4Aw== +discord-api-types@^0.22.0: + version "0.22.0" + resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.22.0.tgz#34dc57fe8e016e5eaac5e393646cd42a7e1ccc2a" + integrity sha512-l8yD/2zRbZItUQpy7ZxBJwaLX/Bs2TGaCthRppk8Sw24LOIWg12t9JEreezPoYD0SQcC2htNNo27kYEpYW/Srg== + +discord.js@^13.0.1: + version "13.0.1" + resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-13.0.1.tgz#58f009706d1d7587fe9ff6c6c781e4540ae085f9" + integrity sha512-pEODCFfxypBnGEYpSgjkn1jt70raCS1um7Zp0AXEfW1DcR29wISzQ/WeWdnjP5KTXGi0LTtkRiUjOsMgSoukxA== dependencies: - "@discordjs/collection" "^0.1.6" + "@discordjs/builders" "^0.4.0" + "@discordjs/collection" "^0.2.1" "@discordjs/form-data" "^3.0.1" - abort-controller "^3.0.0" + "@sapphire/async-queue" "^1.1.4" + "@types/ws" "^7.4.7" + discord-api-types "^0.22.0" node-fetch "^2.6.1" - prism-media "^1.2.9" - setimmediate "^1.0.5" - tweetnacl "^1.0.3" - ws "^7.4.4" + ws "^7.5.1" doctrine@^3.0.0: version "3.0.0" @@ -255,6 +300,13 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dot-prop@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-6.0.1.tgz#fc26b3cf142b9e59b74dbd39ed66ce620c681083" + integrity sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA== + dependencies: + is-obj "^2.0.0" + dotenv@^10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" @@ -303,17 +355,18 @@ eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== eslint-visitor-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" - integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint@^7.27.0: - version "7.27.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.27.0.tgz#665a1506d8f95655c9274d84bd78f7166b07e9c7" - integrity sha512-JZuR6La2ZF0UD384lcbnd0Cgg6QJjiCwhMD6eU4h/VGPcVGwawNNzKU41tgokGXnfjOOyI6QIffthhJTPzzuRA== +eslint@^7.32.0: + version "7.32.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" + integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== dependencies: "@babel/code-frame" "7.12.11" - "@eslint/eslintrc" "^0.4.1" + "@eslint/eslintrc" "^0.4.3" + "@humanwhocodes/config-array" "^0.5.0" ajv "^6.10.0" chalk "^4.0.0" cross-spawn "^7.0.2" @@ -330,7 +383,7 @@ eslint@^7.27.0: fast-deep-equal "^3.1.3" file-entry-cache "^6.0.1" functional-red-black-tree "^1.0.1" - glob-parent "^5.0.0" + glob-parent "^5.1.2" globals "^13.6.0" ignore "^4.0.6" import-fresh "^3.0.0" @@ -395,11 +448,6 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -event-target-shim@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -431,9 +479,9 @@ flat-cache@^3.0.4: rimraf "^3.0.2" flatted@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.0.tgz#a5d06b4a8b01e3a63771daa5cb7a1903e2e57067" - integrity sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA== + version "3.2.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.2.tgz#64bfed5cb68fe3ca78b3eb214ad97b63bedce561" + integrity sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA== form-data@^4.0.0: version "4.0.0" @@ -454,17 +502,17 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -glob-parent@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" - integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" glob@^7.1.3: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -473,17 +521,10 @@ glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -globals@^12.1.0: - version "12.4.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" - integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== - dependencies: - type-fest "^0.8.1" - -globals@^13.6.0: - version "13.6.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.6.0.tgz#d77138e53738567bb96a3916ff6f6b487af20ef7" - integrity sha512-YFKCX0SiPg7l5oKYCJ2zZGxcXprVXHcSnVuvzrT3oSENQonVLqM5pf9fN5dLGZGyCjhw8TN8Btwe/jKnZ0pjvQ== +globals@^13.6.0, globals@^13.9.0: + version "13.10.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.10.0.tgz#60ba56c3ac2ca845cfbf4faeca727ad9dd204676" + integrity sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g== dependencies: type-fest "^0.20.2" @@ -545,6 +586,11 @@ is-glob@^4.0.0, is-glob@^4.0.1: dependencies: is-extglob "^2.1.1" +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -586,10 +632,10 @@ lavacord@1.1.9: node-fetch "^2.6.0" ws "^7.3.0" -lavasfy@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/lavasfy/-/lavasfy-2.2.1.tgz#e5331f82651e561cefae776fe4c90634329344cd" - integrity sha512-7zCntk7MN/wfvZyBiJcKL+z3BU+4d8ZSx6MaUe1sxhNcYMNiWfc2MPdAde/CQsgOlXhO+5joNiWOb2RU2+Pc8A== +lavasfy@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/lavasfy/-/lavasfy-2.3.0.tgz#31ae6937f8ad76bfc20b61d44616f2f2638afaf9" + integrity sha512-3nFlxifCcFBl+qHSiux/ywUly4gVEweBbMbWHXci2QyzTIEtn0mBKFnrjKTCMy/kGaZQrHBUho3bCg7/kNX9Cg== dependencies: node-superfetch "^0.2.2" @@ -606,6 +652,11 @@ lodash.clonedeep@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= + lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" @@ -623,17 +674,17 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -mime-db@1.45.0: - version "1.45.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" - integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== +mime-db@1.49.0: + version "1.49.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed" + integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA== mime-types@^2.1.12: - version "2.1.28" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" - integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ== + version "2.1.32" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.32.tgz#1d00e89e7de7fe02008db61001d9e02852670fd5" + integrity sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A== dependencies: - mime-db "1.45.0" + mime-db "1.49.0" minimatch@^3.0.4: version "3.0.4" @@ -658,9 +709,9 @@ node-fetch@^2.6.0, node-fetch@^2.6.1: integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== node-superfetch@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/node-superfetch/-/node-superfetch-0.2.2.tgz#e0d4ff43b2290dab09ae9c4b6fd1633521d4f930" - integrity sha512-u/nnm1B5itxgGbMIGOGxLqFRrMFkB9bRbT0YwdM61/KhOXd25PZugX++bzpS+arQimcsIekntapdSSFI2CoCEw== + version "0.2.3" + resolved "https://registry.yarnpkg.com/node-superfetch/-/node-superfetch-0.2.3.tgz#bcbf4b03942134946248e3a96341c9e927fe292d" + integrity sha512-xOqifvw/3N+tIeeC80/TNJXkoxDZm8JWc7/0VBkJ86ttQTlJvoicuVaeJlKKHYRlmC2O6ygNIhNPwLYX4bxqdA== dependencies: form-data "^4.0.0" node-fetch "^2.6.1" @@ -684,6 +735,18 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" +ow@^0.27.0: + version "0.27.0" + resolved "https://registry.yarnpkg.com/ow/-/ow-0.27.0.tgz#d44da088e8184fa11de64b5813206f9f86ab68d0" + integrity sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ== + dependencies: + "@sindresorhus/is" "^4.0.1" + callsites "^3.1.0" + dot-prop "^6.0.1" + lodash.isequal "^4.5.0" + type-fest "^1.2.1" + vali-date "^1.0.0" + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -718,11 +781,6 @@ pretty-ms@^7.0.1: dependencies: parse-ms "^2.1.0" -prism-media@^1.2.9: - version "1.2.9" - resolved "https://registry.yarnpkg.com/prism-media/-/prism-media-1.2.9.tgz#8d4f97b36efdfc82483eb8d3db64020767866f36" - integrity sha512-UHCYuqHipbTR1ZsXr5eg4JUmHER8Ss4YEb9Azn+9zzJ7/jlTtD1h0lc4g6tNx3eMlB8Mp6bfll0LPMAV4R6r3Q== - progress@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" @@ -734,9 +792,9 @@ punycode@^2.1.0: integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== regexpp@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" - integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== require-from-string@^2.0.2: version "2.0.2" @@ -756,17 +814,12 @@ rimraf@^3.0.2: glob "^7.1.3" semver@^7.2.1: - version "7.3.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" - integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== dependencies: lru-cache "^6.0.0" -setimmediate@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -794,9 +847,9 @@ sprintf-js@~1.0.2: integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= string-width@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" - integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + version "4.2.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" + integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" @@ -845,10 +898,15 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= -tweetnacl@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" - integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== +ts-mixer@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/ts-mixer/-/ts-mixer-6.0.0.tgz#4e631d3a36e3fa9521b973b132e8353bc7267f9f" + integrity sha512-nXIb1fvdY5CBSrDIblLn73NW0qRDk5yJ0Sk1qPBF560OdJfQp9jhl+0tzcY09OZ9U+6GpeoI9RjwoIKFIoB9MQ== + +tslib@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" + integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" @@ -862,22 +920,27 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== -type-fest@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== +type-fest@^1.2.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" + integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== uri-js@^4.2.2: - version "4.4.0" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" - integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" v8-compile-cache@^2.0.3: - version "2.2.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132" - integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + +vali-date@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6" + integrity sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY= which@^2.0.1: version "2.0.2" @@ -896,10 +959,10 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -ws@^7.3.0, ws@^7.4.4: - version "7.4.6" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" - integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== +ws@^7.3.0, ws@^7.5.1: + version "7.5.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74" + integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg== yallist@^4.0.0: version "4.0.0" From 1905348af588cb480d5af372188ce842f75a4f12 Mon Sep 17 00:00:00 2001 From: Allvaa Date: Wed, 11 Aug 2021 17:15:31 +0700 Subject: [PATCH 03/28] switch to shoukaku --- package.json | 4 +- src/commands/8d.js | 2 +- src/commands/bassboost.js | 2 +- src/commands/doubletime.js | 2 +- src/commands/move.js | 2 +- src/commands/nightcore.js | 2 +- src/commands/nowplaying.js | 2 +- src/commands/pause.js | 2 +- src/commands/play.js | 13 ++-- src/commands/queue.js | 2 +- src/commands/remove.js | 2 +- src/commands/resume.js | 2 +- src/commands/seek.js | 2 +- src/commands/shuffle.js | 2 +- src/commands/skip.js | 2 +- src/commands/vaporwave.js | 2 +- src/commands/volume.js | 2 +- src/listeners/ready.js | 9 --- src/structures/MusicClient.js | 32 ++++++---- src/structures/MusicHandler.js | 109 ++++++++++++++------------------- src/structures/Rest.js | 12 ---- yarn.lock | 49 ++++++++++----- 22 files changed, 120 insertions(+), 138 deletions(-) delete mode 100644 src/structures/Rest.js diff --git a/package.json b/package.json index bc900b9..962756b 100644 --- a/package.json +++ b/package.json @@ -17,11 +17,11 @@ }, "homepage": "https://github.com/Allvaa/lavalink-musicbot#readme", "dependencies": { - "@lavacord/discord.js": "0.0.7", "discord.js": "^13.0.1", "dotenv": "^10.0.0", "lavasfy": "2.3.0", - "pretty-ms": "^7.0.1" + "pretty-ms": "^7.0.1", + "shoukaku": "Deivu/Shoukaku#next" }, "devDependencies": { "eslint": "^7.32.0" diff --git a/src/commands/8d.js b/src/commands/8d.js index 8b77baf..f48745c 100644 --- a/src/commands/8d.js +++ b/src/commands/8d.js @@ -4,7 +4,7 @@ module.exports = { aliases: ["rotation"], exec: async (ctx) => { const { music } = ctx; - if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); if (!ctx.member.voice.channel) return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) diff --git a/src/commands/bassboost.js b/src/commands/bassboost.js index f954363..c6f60a7 100644 --- a/src/commands/bassboost.js +++ b/src/commands/bassboost.js @@ -5,7 +5,7 @@ module.exports = { aliases: ["bb"], exec: async (ctx) => { const { music, args } = ctx; - if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); if (!ctx.member.voice.channel) return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) diff --git a/src/commands/doubletime.js b/src/commands/doubletime.js index 70bf0ae..1e213f9 100644 --- a/src/commands/doubletime.js +++ b/src/commands/doubletime.js @@ -4,7 +4,7 @@ module.exports = { aliases: ["dt"], exec: async (ctx) => { const { music } = ctx; - if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); if (!ctx.member.voice.channel) return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) diff --git a/src/commands/move.js b/src/commands/move.js index 26bd7aa..24fba69 100644 --- a/src/commands/move.js +++ b/src/commands/move.js @@ -7,7 +7,7 @@ module.exports = { const { music, args } = ctx; const from = args[0] ? parseInt(args[0], 10) : null; const to = args[1] ? parseInt(args[1], 10) : null; - if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); if (!music.queue.length) return ctx.respond(util.embed().setDescription("❌ | Queue is empty.")); if (!ctx.member.voice.channel) diff --git a/src/commands/nightcore.js b/src/commands/nightcore.js index d3fde4b..7112b99 100644 --- a/src/commands/nightcore.js +++ b/src/commands/nightcore.js @@ -4,7 +4,7 @@ module.exports = { aliases: ["nc"], exec: async (ctx) => { const { music } = ctx; - if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); if (!ctx.member.voice.channel) return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) diff --git a/src/commands/nowplaying.js b/src/commands/nowplaying.js index 7b3d24b..0a00712 100644 --- a/src/commands/nowplaying.js +++ b/src/commands/nowplaying.js @@ -5,7 +5,7 @@ module.exports = { aliases: ["np", "nowplay"], exec: (ctx) => { const { music } = ctx; - if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); const progress = util.progress(music.player.state.position, music.current.info.length); ctx.respond(util.embed().setDescription(`🎶 | Now playing ${music.current.info.isStream ? "[**◉ LIVE**]" : ""}\n**${music.current.info.title}**.${music.current.info.isStream ? "" : `\n\n${util.millisToDuration(music.player.state.position)} ${progress.bar} ${util.millisToDuration(music.current.info.length)}`}`)); } diff --git a/src/commands/pause.js b/src/commands/pause.js index c74a656..479f639 100644 --- a/src/commands/pause.js +++ b/src/commands/pause.js @@ -4,7 +4,7 @@ module.exports = { name: "pause", exec: async (ctx) => { const { music } = ctx; - if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); if (!ctx.member.voice.channel) return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) diff --git a/src/commands/play.js b/src/commands/play.js index 8d15373..35b8426 100644 --- a/src/commands/play.js +++ b/src/commands/play.js @@ -16,32 +16,31 @@ module.exports = { if ((!music.player || !music.player.playing) && missingPerms.length) return ctx.respond(util.embed().setDescription(`❌ | I need ${missingPerms.length > 1 ? "these" : "this"} permission${missingPerms.length > 1 ? "s" : ""} on your voice channel: ${missingPerms.map(x => `\`${x}\``).join(", ")}.`)); - if (!music.node || !music.node.connected) + if (music.node.state !== 1) return ctx.respond(util.embed().setDescription("❌ | Lavalink node not connected.")); const query = args.join(" ") || getAttachmentURL(ctx.message); if (!query) return ctx.respond(util.embed().setDescription("❌ | Missing args.")); try { - const { loadType, playlistInfo: { name }, tracks } = await music.load(util.isValidURL(query) ? query : `ytsearch:${query}`); + const { type, playlistName, tracks } = await music.load(util.isValidURL(query) ? query : `ytsearch:${query}`); if (!tracks.length) return ctx.respond(util.embed().setDescription("❌ | Couldn't find any results.")); - if (loadType === "PLAYLIST_LOADED") { + if (type === "PLAYLIST") { for (const track of tracks) { track.requester = ctx.author; music.queue.push(track); } - ctx.respond(util.embed().setDescription(`✅ | Loaded \`${tracks.length}\` tracks from **${name}**.`)); + ctx.respond(util.embed().setDescription(`✅ | Loaded \`${tracks.length}\` tracks from **${playlistName}**.`)); } else { const track = tracks[0]; track.requester = ctx.author; music.queue.push(track); - if (music.player && music.player.playing) + if (music.player?.track) ctx.respond(util.embed().setDescription(`✅ | **${track.info.title}** added to the queue.`)); } - if (!music.player) await music.join(ctx.member.voice.channel); - if (!music.player.playing) await music.start(); + if (!music.player.track) await music.start(); music.setTextCh(ctx.channel); } catch (e) { diff --git a/src/commands/queue.js b/src/commands/queue.js index f74770b..15d6647 100644 --- a/src/commands/queue.js +++ b/src/commands/queue.js @@ -5,7 +5,7 @@ module.exports = { aliases: ["q"], exec: async (ctx) => { const { music } = ctx; - if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); if (!music.queue.length) return ctx.respond(util.embed().setDescription("❌ | Queue is empty.")); const queue = music.queue.map((t, i) => `\`${++i}.\` **${t.info.title}** ${t.requester}`); diff --git a/src/commands/remove.js b/src/commands/remove.js index ec6d8ab..c7afc4c 100644 --- a/src/commands/remove.js +++ b/src/commands/remove.js @@ -5,7 +5,7 @@ module.exports = { aliases: ["rm"], exec: async (ctx) => { const { music, args } = ctx; - if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌| Currently not playing anything.")); + if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌| Currently not playing anything.")); if (!music.queue.length) return ctx.respond(util.embed().setDescription("❌ | Queue is empty.")); if (!ctx.member.voice.channel) diff --git a/src/commands/resume.js b/src/commands/resume.js index 45ed151..7eefe00 100644 --- a/src/commands/resume.js +++ b/src/commands/resume.js @@ -4,7 +4,7 @@ module.exports = { name: "resume", exec: async (ctx) => { const { music } = ctx; - if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌| Currently not playing anything.")); + if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌| Currently not playing anything.")); if (!ctx.member.voice.channel) return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) diff --git a/src/commands/seek.js b/src/commands/seek.js index 420f993..28c7cb2 100644 --- a/src/commands/seek.js +++ b/src/commands/seek.js @@ -6,7 +6,7 @@ module.exports = { name: "seek", exec: async (ctx) => { const { music, args } = ctx; - if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); if (!ctx.member.voice.channel) return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) diff --git a/src/commands/shuffle.js b/src/commands/shuffle.js index 12071d5..bb0e9c5 100644 --- a/src/commands/shuffle.js +++ b/src/commands/shuffle.js @@ -5,7 +5,7 @@ module.exports = { aliases: ["sf"], exec: async (ctx) => { const { music } = ctx; - if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); if (!music.queue.length) return ctx.respond(util.embed().setDescription("❌ | Queue is empty.")); if (!ctx.member.voice.channel) return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); diff --git a/src/commands/skip.js b/src/commands/skip.js index 28cc1a4..03de757 100644 --- a/src/commands/skip.js +++ b/src/commands/skip.js @@ -6,7 +6,7 @@ module.exports = { exec: async (ctx) => { const { music, args } = ctx; const skipTo = args[0] ? parseInt(args[0], 10) : null; - if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); if (!ctx.member.voice.channel) return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); diff --git a/src/commands/vaporwave.js b/src/commands/vaporwave.js index 31f53d8..feaf8ad 100644 --- a/src/commands/vaporwave.js +++ b/src/commands/vaporwave.js @@ -4,7 +4,7 @@ module.exports = { aliases: ["vp"], exec: async (ctx) => { const { music } = ctx; - if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); if (!ctx.member.voice.channel) return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) diff --git a/src/commands/volume.js b/src/commands/volume.js index f1ce2a5..f841733 100644 --- a/src/commands/volume.js +++ b/src/commands/volume.js @@ -6,7 +6,7 @@ module.exports = { exec: async (ctx) => { const { music, args } = ctx; const newVolume = parseInt(args[0], 10); - if (!music.player || !music.player.playing) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); try { if (isNaN(newVolume)) { ctx.respond(util.embed().setDescription(`🔉 | Current volume \`${music.volume}\`.`)); diff --git a/src/listeners/ready.js b/src/listeners/ready.js index 5a33445..228c6e6 100644 --- a/src/listeners/ready.js +++ b/src/listeners/ready.js @@ -4,14 +4,5 @@ module.exports = { console.log(`Logged in as ${client.user.tag}`); if (client.spotify) await client.spotify.requestToken(); - - const nodes = [...client.manager.nodes.values()]; - for (const node of nodes) { - try { - await node.connect(); - } catch (e) { - client.manager.emit("error", e, node); - } - } } }; diff --git a/src/structures/MusicClient.js b/src/structures/MusicClient.js index 17e67a7..dc6c1fb 100644 --- a/src/structures/MusicClient.js +++ b/src/structures/MusicClient.js @@ -1,8 +1,8 @@ -const { Manager } = require("@lavacord/discord.js"); const { Client, Collection } = require("discord.js"); const { promises: { readdir } } = require("fs"); const { join } = require("path"); const { LavasfyClient } = require("lavasfy"); +const { Shoukaku, Libraries } = require("shoukaku"); module.exports = class MusicClient extends Client { /** @param {import("discord.js").ClientOptions} [opt] */ @@ -10,12 +10,12 @@ module.exports = class MusicClient extends Client { super(opt); this.musics = new Collection(); this.commands = new Collection(); - this.manager = new Manager(this, [ + this.shoukaku = new Shoukaku(new Libraries.DiscordJS(this), [ { - id: "main", - host: process.env.LAVA_HOST, - port: process.env.LAVA_PORT, - password: process.env.LAVA_PASS + name: "main", + url: `${process.env.LAVA_HOST}:${process.env.LAVA_PORT}`, + auth: process.env.LAVA_PASS, + secure: true } ]); this.spotify = process.env.ENABLE_SPOTIFY === "true" @@ -26,7 +26,15 @@ module.exports = class MusicClient extends Client { audioOnlyResults: true, useSpotifyMetadata: true, autoResolve: true - }, [...[...this.manager.nodes.values()]]) + }, [ + { + id: "main", + host: process.env.LAVA_HOST, + port: process.env.LAVA_PORT, + password: process.env.LAVA_PASS, + secure: true + } + ]) : null; this.prefix = process.env.PREFIX.toLowerCase(); @@ -37,11 +45,11 @@ module.exports = class MusicClient extends Client { this.loadEventListeners(); this.login(process.env.TOKEN); - this.manager - .on("ready", node => console.log(`Node ${node.id} is ready!`)) - .on("disconnect", (ws, node) => console.log(`Node ${node.id} disconnected.`)) - .on("reconnecting", (node) => console.log(`Node ${node.id} tries to reconnect.`)) - .on("error", (error, node) => console.log(`Node ${node.id} got an error: ${error.message}`)); + this.shoukaku + .on("ready", (node, reconnect) => console.log(`Node ${node} is now ready.${reconnect ? " (reconnected)": ""}`)) + .on("disconnect", node => console.log(`Node ${node} disconnected.`)) + .on("close", (node, code, reason) => console.log(`Node ${node} closed. Code: ${code}. Reason: ${reason}.`)) + .on("error", (node, error) => console.log(`Encountered an error in node ${node}.`, error)); } /** @private */ diff --git a/src/structures/MusicHandler.js b/src/structures/MusicHandler.js index 008b8f3..86cebad 100644 --- a/src/structures/MusicHandler.js +++ b/src/structures/MusicHandler.js @@ -1,12 +1,9 @@ -const Rest = require("./Rest"); const util = require("../util"); -const FiltersValues = require("../constants/FiltersValues"); module.exports = class MusicHandler { /** @param {import("discord.js").Guild} guild */ constructor(guild) { this.guild = guild; - this.volume = 100; this.loop = 0; // 0 = none; 1 = track; 2 = queue; this.previous = null; this.current = null; @@ -34,16 +31,19 @@ module.exports = class MusicHandler { } get player() { - return this.client.manager.players.get(this.guild.id) || null; + return this.client.shoukaku.players.get(this.guild.id); } get node() { - return this.client.manager.nodes.get("main"); + return this.client.shoukaku.nodes.get("main"); + } + + get volume() { + return this.player?.filters.volume * 100 ?? 100; } reset() { this.loop = 0; - this.volume = 100; this.previous = null; this.current = null; this.queue = []; @@ -57,11 +57,12 @@ module.exports = class MusicHandler { /** @param {import("discord.js").VoiceChannel} voice */ async join(voice) { if (this.player) return; - await this.client.manager.join({ - channel: voice.id, - guild: this.guild.id, - node: this.node.id - }, { selfdeaf: true }); + await this.node.joinChannel({ + channelId: voice.id, + guildId: this.guild.id, + shardId: 0, + deaf: true + }); this.player .on("start", () => { @@ -79,7 +80,7 @@ module.exports = class MusicHandler { if (this.shouldSkipCurrent) this.shouldSkipCurrent = false; if (!this.queue.length) { - this.client.manager.leave(this.guild.id); + this.node.leaveChannel(this.guild.id); if (this.textChannel) this.textChannel.send({embeds:[util.embed().setDescription("✅ | Queue is empty. Leaving voice channel..")]}); this.reset(); return; @@ -95,109 +96,89 @@ module.exports = class MusicHandler { } async load(query) { - const res = await Rest.load(this.node, query, this.client.spotify); - return res; + const spotify = this.client.spotify.getNode(this.node.name); + if (this.client.spotify.isValidURL(query)) { + const { loadType: type, tracks, playlistInfo: { name } } = await spotify.load(query); + return { + type, + tracks, + playlistName: name + }; + } + return this.node.rest.resolve(query); } - async start() { - if (!this.player) return; - await this.player.play(this.queue[0].track); + start() { + this.player?.playTrack(this.queue[0].track); } - async pause() { - if (!this.player) return; - if (!this.player.paused) await this.player.pause(true); + pause() { + if (!this.player?.paused) this.player?.setPaused(true); } - async resume() { - if (!this.player) return; - if (this.player.paused) await this.player.pause(false); + resume() { + if (this.player?.paused) this.player?.setPaused(false); } - async skip(to = 1) { - if (!this.player) return; + skip(to = 1) { if (to > 1) { this.queue.unshift(this.queue[to - 1]); this.queue.splice(to, 1); } if (this.loop === 1 && this.queue[0]) this.shouldSkipCurrent = true; - await this.player.stop(); + this.player?.stopTrack(); } - async stop() { - if (!this.player) return; + stop() { this.loop = 0; this.queue = []; - await this.skip(); + this.skip(); } - async setVolume(newVol) { - if (!this.player) return; - const parsed = parseInt(newVol, 10); - if (isNaN(parsed)) return; - await this.player.volume(parsed); - this.volume = newVol; + setVolume(volume) { + this.player?.setVolume(volume / 100); } - async setDoubleTime(val) { + setDoubleTime(val) { if (!this.player) return; this.filters.doubleTime = val; if (val) { this.filters.nightcore = false; this.filters.vaporwave = false; } - await this.sendFilters(); + this.player.setTimescale(val ? { speed: 1.5 } : null); } - async setNightcore(val) { + setNightcore(val) { if (!this.player) return; this.filters.nightcore = val; if (val) { this.filters.doubleTime = false; this.filters.vaporwave = false; } - await this.sendFilters(); + this.player.setTimescale(val ? { rate: 1.5 } : null); } - async setVaporwave(val) { + setVaporwave(val) { if (!this.player) return; this.filters.vaporwave = val; if (val) { this.filters.doubleTime = false; this.filters.nightcore = false; } - await this.sendFilters(); + this.player.setTimescale(val ? { pitch: 0.5 } : null); } - async set8D(val) { + set8D(val) { if (!this.player) return; this.filters["8d"] = val; - await this.sendFilters(); + this.player.setRotation(val ? { rotationHz: 0.2 } : null); } - async setBassboost(val) { + setBassboost(val) { if (!this.player) return; this.filters.bassboost = !!val; this.bassboost = val / 100; - await this.sendFilters(); - } - - async sendFilters() { - if (!this.player) return; - const filters = {}; - for (const [filter, enabled] of Object.entries(this.filters)) { - if (enabled && FiltersValues[filter]) { - const filterValue = { ...FiltersValues[filter] }; - if (filter === "bassboost") { - filterValue.equalizer = filterValue.equalizer.map((x, i) => ({ band: i, gain: x * this.bassboost })); - } - Object.assign(filters, filterValue); - } - } - await this.player.node.send({ - op: "filters", - guildId: this.guild.id, - ...filters - }); + this.player.setEqualizer(val ? Array(6).fill(0.22).map((x, i) => ({ band: i, gain: x * val })) : []); } }; diff --git a/src/structures/Rest.js b/src/structures/Rest.js deleted file mode 100644 index 50d8cb7..0000000 --- a/src/structures/Rest.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = class Rest extends require("lavacord").Rest { - /** - * @param {import("lavacord").LavalinkNode} node - * @param {string} query - * @param {import("lavasfy").LavasfyClient} lsClient - * @returns {Promise} - */ - static async load(node, query, lsClient) { - const spotify = lsClient ? lsClient.nodes.get(node.id) : undefined; - return lsClient && lsClient.isValidURL(query) ? await spotify.load(query) : await super.load(node, query); - } -}; diff --git a/yarn.lock b/yarn.lock index 36b3590..dae1c62 100644 --- a/yarn.lock +++ b/yarn.lock @@ -77,13 +77,6 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf" integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w== -"@lavacord/discord.js@0.0.7": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@lavacord/discord.js/-/discord.js-0.0.7.tgz#8ba1e944cb5853693a72274ead66798a79e1c07a" - integrity sha512-EJ3Jz7Eeepbb+fTirLmVGRshtACuzkhDFccR+6hrTRAmEV9P3dFsfbCtsZfLhRa2j2geJ73VqpjfiJmml0AMuQ== - dependencies: - lavacord "1.1.9" - "@sapphire/async-queue@^1.1.4": version "1.1.4" resolved "https://registry.yarnpkg.com/@sapphire/async-queue/-/async-queue-1.1.4.tgz#ae431310917a8880961cebe8e59df6ffa40f2957" @@ -106,6 +99,13 @@ dependencies: "@types/node" "*" +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + acorn-jsx@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -448,6 +448,11 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -624,14 +629,6 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= -lavacord@1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/lavacord/-/lavacord-1.1.9.tgz#e7e355f969eb082a36e20814fdc6a9b01f3f81a1" - integrity sha512-haZghbblO1w3Hodc9q63ZWgV5zA/jB6xFKS17fImK5aIdn0PkKuZ6AsJBxMFpR275v8GNYOxg6cTQBYBQ+batQ== - dependencies: - node-fetch "^2.6.0" - ws "^7.3.0" - lavasfy@2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/lavasfy/-/lavasfy-2.3.0.tgz#31ae6937f8ad76bfc20b61d44616f2f2638afaf9" @@ -703,7 +700,7 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -node-fetch@^2.6.0, node-fetch@^2.6.1: +node-fetch@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== @@ -769,6 +766,11 @@ path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== +petitio@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/petitio/-/petitio-1.3.2.tgz#01590497972a2dbfd3bf4e49d1efa4f3b1fdc693" + integrity sha512-hbbT+rOvovz39ZneGW+C8B4YsKH20KLXYVDT/IzSUxaY8H7al/TO+vFCm+H5cnYe62gIqF9ak5p8OJktV/I0Ig== + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -832,6 +834,14 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +shoukaku@Deivu/Shoukaku#next: + version "2.0.0" + resolved "https://codeload.github.com/Deivu/Shoukaku/tar.gz/dc887bfcf0ad53acbe873ea043ab71d1ffde639a" + dependencies: + abort-controller "^3.0.0" + petitio "^1.3.2" + ws "^8.0.0" + slice-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" @@ -959,11 +969,16 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -ws@^7.3.0, ws@^7.5.1: +ws@^7.5.1: version "7.5.3" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74" integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg== +ws@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.0.0.tgz#550605d13dfc1437c9ec1396975709c6d7ffc57d" + integrity sha512-6AcSIXpBlS0QvCVKk+3cWnWElLsA6SzC0lkQ43ciEglgXJXiCWK3/CGFEJ+Ybgp006CMibamAsqOlxE9s4AvYA== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" From 785df74cac970fab2908fd5fb29fa4aeb61b357e Mon Sep 17 00:00:00 2001 From: Allvaa Date: Wed, 11 Aug 2021 17:22:55 +0700 Subject: [PATCH 04/28] delete this --- src/constants/FiltersValues.js | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 src/constants/FiltersValues.js diff --git a/src/constants/FiltersValues.js b/src/constants/FiltersValues.js deleted file mode 100644 index c155894..0000000 --- a/src/constants/FiltersValues.js +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = { - doubleTime: { - timescale: { speed: 1.5 } - }, - nightcore: { - timescale: { rate: 1.5 } - }, - vaporwave: { - timescale: { pitch: 0.5 } - }, - "8d": { - rotation: { rotationHz: 0.2 } - }, - bassboost: { - equalizer: Array(6).fill(0.22) - } -}; From 002d5e5882905f6c4efe06bc483ac6a17bcab60f Mon Sep 17 00:00:00 2001 From: rajamoulimallareddy <68652418+rajamoulimallareddy@users.noreply.github.com> Date: Sun, 15 Aug 2021 14:49:46 +0530 Subject: [PATCH 05/28] Update search.js (#131) --- src/commands/search.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/commands/search.js b/src/commands/search.js index c26d37a..2781bcd 100644 --- a/src/commands/search.js +++ b/src/commands/search.js @@ -59,9 +59,11 @@ module.exports = { async function awaitMessages() { try { + const filter = (m) => m.author.equals(ctx.author) && (/^cancel$/i.exec(m.content) || (!isNaN(parseInt(m.content, 10)) && (m.content >= 1 && m.content <= 10))), + const collector = await ctx.channel.awaitMessages( - m => m.author.equals(ctx.author) && (/^cancel$/i.exec(m.content) || (!isNaN(parseInt(m.content, 10)) && (m.content >= 1 && m.content <= 10))), - { + { + filter, time: 10000, max: 1, errors: ["time"] From c71f745675a8e0298a82053873eebc4dfd7956b9 Mon Sep 17 00:00:00 2001 From: rajamoulimallareddy <68652418+rajamoulimallareddy@users.noreply.github.com> Date: Sun, 15 Aug 2021 15:36:50 +0530 Subject: [PATCH 06/28] Update search.js (#132) my mistake sry --- src/commands/search.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/search.js b/src/commands/search.js index 2781bcd..0d47bb0 100644 --- a/src/commands/search.js +++ b/src/commands/search.js @@ -59,8 +59,8 @@ module.exports = { async function awaitMessages() { try { - const filter = (m) => m.author.equals(ctx.author) && (/^cancel$/i.exec(m.content) || (!isNaN(parseInt(m.content, 10)) && (m.content >= 1 && m.content <= 10))), - + const filter = (m) => m.author.equals(ctx.author) && (/^cancel$/i.exec(m.content) || (!isNaN(parseInt(m.content, 10)) && (m.content >= 1 && m.content <= 10))); + const collector = await ctx.channel.awaitMessages( { filter, From 4529d38d1d256c50eb8d603f3d824ec52d875177 Mon Sep 17 00:00:00 2001 From: Allvaa Date: Tue, 17 Aug 2021 16:57:22 +0700 Subject: [PATCH 07/28] fix breaking changes --- src/commands/8d.js | 17 ++++++++++++----- src/commands/bassboost.js | 12 +++++++++--- src/commands/clearqueue.js | 14 +++++++++----- src/commands/doubletime.js | 15 ++++++++++----- src/commands/help.js | 2 +- src/commands/loop.js | 24 ++++++++++++++++-------- src/commands/lyrics.js | 4 ++-- src/commands/move.js | 28 +++++++++++++++++++++------- src/commands/nightcore.js | 15 ++++++++++----- src/commands/nowplaying.js | 6 ++++-- src/commands/pause.js | 18 ++++++++++++------ src/commands/play.js | 32 ++++++++++++++++++++++++-------- src/commands/previous.js | 16 ++++++++++++---- src/commands/queue.js | 6 +++--- src/commands/remove.js | 14 +++++++------- src/commands/removedupes.js | 10 +++++----- src/commands/resume.js | 8 +++++--- src/commands/search.js | 31 +++++++++++++++++-------------- src/commands/seek.js | 16 ++++++++-------- src/commands/shuffle.js | 10 +++++----- src/commands/skip.js | 16 +++++++++------- src/commands/source.js | 2 +- src/commands/stats.js | 14 +++++++------- src/commands/stop.js | 14 ++++++++------ src/commands/vaporwave.js | 8 ++++---- src/commands/volume.js | 12 ++++++------ src/structures/CommandContext.js | 3 +-- 27 files changed, 228 insertions(+), 139 deletions(-) diff --git a/src/commands/8d.js b/src/commands/8d.js index f48745c..6ca6aad 100644 --- a/src/commands/8d.js +++ b/src/commands/8d.js @@ -4,14 +4,21 @@ module.exports = { aliases: ["rotation"], exec: async (ctx) => { const { music } = ctx; - if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond({ + embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] + }); if (!ctx.member.voice.channel) - return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + return ctx.respond({ + embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] + }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); + return ctx.respond({ + embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] + }); music.set8D(!music.filters["8d"]); - ctx.respond(util.embed().setDescription(`✅ | ${music.filters["8d"] ? "Enabled" : "Disabled"} **8D**`)); - + ctx.respond({ + embeds: [util.embed().setDescription(`✅ | ${music.filters["8d"] ? "Enabled" : "Disabled"} **8D**`)] + }); } }; diff --git a/src/commands/bassboost.js b/src/commands/bassboost.js index c6f60a7..e132bbd 100644 --- a/src/commands/bassboost.js +++ b/src/commands/bassboost.js @@ -5,11 +5,17 @@ module.exports = { aliases: ["bb"], exec: async (ctx) => { const { music, args } = ctx; - if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond({ + embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] + }); if (!ctx.member.voice.channel) - return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + return ctx.respond({ + embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] + }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); + return ctx.respond({ + embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] + }); if (!args[0]) { ctx.respond(util.embed().setDescription(`${music.filters.bassboost ? `✅ | BassBoost **${music.bassboost * 100}%**` : "❌ | BassBoost **off**"}`)); diff --git a/src/commands/clearqueue.js b/src/commands/clearqueue.js index e8ff429..040a40a 100644 --- a/src/commands/clearqueue.js +++ b/src/commands/clearqueue.js @@ -6,13 +6,17 @@ module.exports = { aliases: ["clr", "clear"], exec: (ctx) => { const { music } = ctx; - if (!music.player) return ctx.respond(util.embed().setDescription("❌| Currently not playing anything.")); - if (!music.queue.length) return ctx.respond(util.embed().setDescription("❌ | Queue is empty.")); - + if (!music.queue.length) return ctx.respond({ + embeds: [util.embed().setDescription("❌ | Queue is empty.")] + }); if (!ctx.member.voice.channel) - return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + return ctx.respond({ + embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] + }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); + return ctx.respond({ + embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] + }); music.queue.splice(0, 1); ctx.respond(util.embed().setDescription("✅ | Cleared the queue.")).catch(e => e); diff --git a/src/commands/doubletime.js b/src/commands/doubletime.js index 1e213f9..ff9ebfa 100644 --- a/src/commands/doubletime.js +++ b/src/commands/doubletime.js @@ -4,14 +4,19 @@ module.exports = { aliases: ["dt"], exec: async (ctx) => { const { music } = ctx; - if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond({ embded: [util.embed().setDescription("❌ | Currently not playing anything.")]}); if (!ctx.member.voice.channel) - return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + return ctx.respond({ + embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] + }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); + return ctx.respond({ + embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] + }); music.setDoubleTime(!music.filters.doubleTime); - ctx.respond(util.embed().setDescription(`✅ | ${music.filters.doubleTime ? "Enabled" : "Disabled"} **Double Time**`)); - + ctx.respond({ + embeds: [util.embed().setDescription(`✅ | ${music.filters.doubleTime ? "Enabled" : "Disabled"} **Double Time**`)] + }); } }; diff --git a/src/commands/help.js b/src/commands/help.js index 885c31c..80e5783 100644 --- a/src/commands/help.js +++ b/src/commands/help.js @@ -1,6 +1,6 @@ const util = require("../util"); -const unlisted = ["eval", "source"]; +const unlisted = ["eval"]; module.exports = { name: "help", diff --git a/src/commands/loop.js b/src/commands/loop.js index 6f9eed3..611c2eb 100644 --- a/src/commands/loop.js +++ b/src/commands/loop.js @@ -20,25 +20,33 @@ module.exports = { aliases: ["repeat"], exec: (ctx) => { const { music, args } = ctx; - if (!music.player) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player) return ctx.respond({ + embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] + }); if (args[0]) { if (!ctx.member.voice.channel) - return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + return ctx.respond({ + embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] + }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); + return ctx.respond({ + embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] + }); const loopMode = aliases[args[0].toLowerCase()]; if (loopMode && modes.includes(loopMode)) { music.loop = modes.indexOf(loopMode); - ctx.respond(util.embed().setDescription(music.loop === 0 ? "✅ | Loop disabled." : `✅ | Set loop to ${modes[music.loop]}.`)); + ctx.respond({ + embeds: util.embed().setDescription(music.loop === 0 ? "✅ | Loop disabled." : `✅ | Set loop to ${modes[music.loop]}.`) + }); } else { - ctx.respond( - util.embed() + ctx.respond({ + embeds: util.embed() .setDescription("❌ | Invalid loop mode. Try single/all/off.") - ); + }); } } else { - ctx.respond(util.embed().setDescription(`✅ | Current loop mode: ${modes[music.loop]}`)); + ctx.respond({ embeds: [util.embed().setDescription(`✅ | Current loop mode: ${modes[music.loop]}`)] }); } } }; diff --git a/src/commands/lyrics.js b/src/commands/lyrics.js index 4a14093..3d306c2 100644 --- a/src/commands/lyrics.js +++ b/src/commands/lyrics.js @@ -18,7 +18,7 @@ module.exports = { const separatedArtistAndTitle = /(.+) - (.+)/.test(ctx.music.current.info.title); query = `${separatedArtistAndTitle ? ctx.music.current.info.title : ctx.music.current.info.author.replace(" - Topic", "")} - ${ctx.music.current.info.title}`; } else { - return ctx.respond(util.embed().setDescription("❌ | Missing args.")); + return ctx.respond({ embeds: [util.embed().setDescription("❌ | Missing args.")] }); } try { @@ -36,7 +36,7 @@ module.exports = { const lyricsctx = await ctx.respond(embed); if (splittedLyrics.length > 1) await util.pagination(lyricsctx, ctx.author, splittedLyrics); } catch (e) { - if (e.message === "Sorry I couldn't find that song's lyrics") ctx.respond(util.embed().setDescription(`❌ | ${e.message}`)); + if (e.message === "Sorry I couldn't find that song's lyrics") ctx.respond({ embeds: [util.embed().setDescription(`❌ | ${e.message}`)] }); else ctx.respond(`An error occured: ${e.message}.`); } } diff --git a/src/commands/move.js b/src/commands/move.js index 24fba69..0c7e2b5 100644 --- a/src/commands/move.js +++ b/src/commands/move.js @@ -7,24 +7,38 @@ module.exports = { const { music, args } = ctx; const from = args[0] ? parseInt(args[0], 10) : null; const to = args[1] ? parseInt(args[1], 10) : null; - if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); - if (!music.queue.length) return ctx.respond(util.embed().setDescription("❌ | Queue is empty.")); + if (!music.player?.track) return ctx.respond({ + embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] + }); + if (!music.queue.length) return ctx.respond({ + embeds: [util.embed().setDescription("❌ | Queue is empty.")] + }); if (!ctx.member.voice.channel) - return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + return ctx.respond({ + embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] + }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); + return ctx.respond({ + embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] + }); if (from === null || to === null) - return ctx.respond(util.embed().setDescription(`❌ | Missing args. Example usage e.g. \`${ctx.client.prefix}move 2 1\``)); + return ctx.respond({ + embeds: [util.embed().setDescription(`❌ | Missing args. Example usage e.g. \`${ctx.client.prefix}move 2 1\``)] + }); if (from === to || (isNaN(from) || from < 1 || from > music.queue.length) || (isNaN(to) || to < 1 || to > music.queue.length)) - return ctx.respond(util.embed().setDescription("❌ | Number is invalid or exceeds queue length.")); + return ctx.respond({ + embeds: [util.embed().setDescription("❌ | Number is invalid or exceeds queue length.")] + }); const moved = music.queue[from - 1]; util.moveArrayElement(music.queue, from - 1, to - 1); - ctx.respond(util.embed().setDescription(`✅ | Moved **${moved.info.title}** to \`${to}\`.`)); + ctx.respond({ + embeds: [util.embed().setDescription(`✅ | Moved **${moved.info.title}** to \`${to}\`.`)] + }); } }; diff --git a/src/commands/nightcore.js b/src/commands/nightcore.js index 7112b99..7bc9306 100644 --- a/src/commands/nightcore.js +++ b/src/commands/nightcore.js @@ -4,14 +4,19 @@ module.exports = { aliases: ["nc"], exec: async (ctx) => { const { music } = ctx; - if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); if (!ctx.member.voice.channel) - return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + return ctx.respond({ + embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] + }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); + return ctx.respond({ + embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] + }); music.setNightcore(!music.filters.nightcore); - ctx.respond(util.embed().setDescription(`✅ | ${music.filters.nightcore ? "Enabled" : "Disabled"} **Nightcore**`)); - + ctx.respond({ + embeds: [util.embed().setDescription(`✅ | ${music.filters.nightcore ? "Enabled" : "Disabled"} **Nightcore**`)] + }); } }; diff --git a/src/commands/nowplaying.js b/src/commands/nowplaying.js index 0a00712..1588916 100644 --- a/src/commands/nowplaying.js +++ b/src/commands/nowplaying.js @@ -5,8 +5,10 @@ module.exports = { aliases: ["np", "nowplay"], exec: (ctx) => { const { music } = ctx; - if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); const progress = util.progress(music.player.state.position, music.current.info.length); - ctx.respond(util.embed().setDescription(`🎶 | Now playing ${music.current.info.isStream ? "[**◉ LIVE**]" : ""}\n**${music.current.info.title}**.${music.current.info.isStream ? "" : `\n\n${util.millisToDuration(music.player.state.position)} ${progress.bar} ${util.millisToDuration(music.current.info.length)}`}`)); + ctx.respond({ + embeds: [util.embed().setDescription(`🎶 | Now playing ${music.current.info.isStream ? "[**◉ LIVE**]" : ""}\n**${music.current.info.title}**.${music.current.info.isStream ? "" : `\n\n${util.millisToDuration(music.player.state.position)} ${progress.bar} ${util.millisToDuration(music.current.info.length)}`}`)] + }); } }; diff --git a/src/commands/pause.js b/src/commands/pause.js index 479f639..e3d7104 100644 --- a/src/commands/pause.js +++ b/src/commands/pause.js @@ -2,17 +2,23 @@ const util = require("../util"); module.exports = { name: "pause", - exec: async (ctx) => { + exec: (ctx) => { const { music } = ctx; - if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); if (!ctx.member.voice.channel) - return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + return ctx.respond({ + embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] + }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); + return ctx.respond({ + embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] + }); try { - await music.pause(); - ctx.react("⏸️").catch(e => e); + music.pause(); + ctx.respond({ + embeds: [util.embed().setDescription("⏸️ | Paused")] + }); } catch (e) { ctx.respond(`An error occured: ${e.message}.`); } diff --git a/src/commands/play.js b/src/commands/play.js index 35b8426..e588682 100644 --- a/src/commands/play.js +++ b/src/commands/play.js @@ -8,36 +8,52 @@ module.exports = { exec: async (ctx) => { const { args, music } = ctx; if (!ctx.member.voice.channel) - return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + return ctx.respond({ + embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] + }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); + return ctx.respond({ + embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] + }); const missingPerms = util.missingPerms(ctx.guild.me.permissionsIn(ctx.member.voice.channel), ["CONNECT", "SPEAK"]); if ((!music.player || !music.player.playing) && missingPerms.length) - return ctx.respond(util.embed().setDescription(`❌ | I need ${missingPerms.length > 1 ? "these" : "this"} permission${missingPerms.length > 1 ? "s" : ""} on your voice channel: ${missingPerms.map(x => `\`${x}\``).join(", ")}.`)); + return ctx.respond({ + embeds: [util.embed().setDescription(`❌ | I need ${missingPerms.length > 1 ? "these" : "this"} permission${missingPerms.length > 1 ? "s" : ""} on your voice channel: ${missingPerms.map(x => `\`${x}\``).join(", ")}.`)] + }); if (music.node.state !== 1) - return ctx.respond(util.embed().setDescription("❌ | Lavalink node not connected.")); + return ctx.respond({ + embeds: [util.embed().setDescription("❌ | Lavalink node not connected.")] + }); const query = args.join(" ") || getAttachmentURL(ctx.message); - if (!query) return ctx.respond(util.embed().setDescription("❌ | Missing args.")); + if (!query) return ctx.respond({ + embeds: [util.embed().setDescription("❌ | Missing args.")] + }); try { const { type, playlistName, tracks } = await music.load(util.isValidURL(query) ? query : `ytsearch:${query}`); - if (!tracks.length) return ctx.respond(util.embed().setDescription("❌ | Couldn't find any results.")); + if (!tracks.length) return ctx.respond({ + embeds: [util.embed().setDescription("❌ | Couldn't find any results.")] + }); if (type === "PLAYLIST") { for (const track of tracks) { track.requester = ctx.author; music.queue.push(track); } - ctx.respond(util.embed().setDescription(`✅ | Loaded \`${tracks.length}\` tracks from **${playlistName}**.`)); + ctx.respond({ + embeds: [util.embed().setDescription(`✅ | Loaded \`${tracks.length}\` tracks from **${playlistName}**.`)] + }); } else { const track = tracks[0]; track.requester = ctx.author; music.queue.push(track); if (music.player?.track) - ctx.respond(util.embed().setDescription(`✅ | **${track.info.title}** added to the queue.`)); + ctx.respond({ + embeds: [util.embed().setDescription(`✅ | **${track.info.title}** added to the queue.`)] + }); } if (!music.player) await music.join(ctx.member.voice.channel); if (!music.player.track) await music.start(); diff --git a/src/commands/previous.js b/src/commands/previous.js index 4bcf900..e0bc3af 100644 --- a/src/commands/previous.js +++ b/src/commands/previous.js @@ -5,13 +5,21 @@ module.exports = { aliases: ["prev"], exec: async (ctx) => { const { music } = ctx; - if (!music.player) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); - if (!music.previous) return ctx.respond(util.embed().setDescription("❌ | No previous track.")); + if (!music.player) return ctx.respond({ + embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] + }); + if (!music.previous) return ctx.respond({ + embeds: [util.embed().setDescription("❌ | No previous track.")] + }); if (!ctx.member.voice.channel) - return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + return ctx.respond({ + embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] + }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); + return ctx.respond({ + embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] + }); try { music.queue.unshift(music.previous); diff --git a/src/commands/queue.js b/src/commands/queue.js index 15d6647..d1a47f0 100644 --- a/src/commands/queue.js +++ b/src/commands/queue.js @@ -5,8 +5,8 @@ module.exports = { aliases: ["q"], exec: async (ctx) => { const { music } = ctx; - if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); - if (!music.queue.length) return ctx.respond(util.embed().setDescription("❌ | Queue is empty.")); + if (!music.player?.track) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); + if (!music.queue.length) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Queue is empty.")] }); const queue = music.queue.map((t, i) => `\`${++i}.\` **${t.info.title}** ${t.requester}`); const chunked = util.chunk(queue, 10).map(x => x.join("\n")); @@ -17,7 +17,7 @@ module.exports = { .setFooter(`Page 1 of ${chunked.length}.`); try { - const queuectx = await ctx.respond(embed); + const queuectx = await ctx.respond({embeds: [embed] }); if (chunked.length > 1) await util.pagination(queuectx, ctx.author, chunked); } catch (e) { ctx.respond(`An error occured: ${e.message}.`); diff --git a/src/commands/remove.js b/src/commands/remove.js index c7afc4c..01716d4 100644 --- a/src/commands/remove.js +++ b/src/commands/remove.js @@ -5,21 +5,21 @@ module.exports = { aliases: ["rm"], exec: async (ctx) => { const { music, args } = ctx; - if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌| Currently not playing anything.")); - if (!music.queue.length) return ctx.respond(util.embed().setDescription("❌ | Queue is empty.")); + if (!music.player?.track) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); + if (!music.queue.length) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Queue is empty.")] }); if (!ctx.member.voice.channel) - return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + return ctx.respond({ embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); + return ctx.respond({ embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] }); - if (!args[0]) return ctx.respond(util.embed().setDescription("❌ | Missing args.")); + if (!args[0]) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Missing args.")] }); let iToRemove = parseInt(args[0], 10); if (isNaN(iToRemove) || iToRemove < 1 || iToRemove > music.queue.length) - return ctx.respond(util.embed().setDescription("❌ | Invalid number to remove.")); + return ctx.respond({ embeds: [util.embed().setDescription("❌ | Invalid number to remove.")] }); const removed = music.queue.splice(--iToRemove, 1)[0]; - ctx.respond(util.embed().setDescription(`✅ | Removed **${removed.info.title}** from the queue.`)); + ctx.respond({ embeds: [util.embed().setDescription(`✅ | Removed **${removed.info.title}** from the queue.`)] }); } }; diff --git a/src/commands/removedupes.js b/src/commands/removedupes.js index c0328c0..88ecfad 100644 --- a/src/commands/removedupes.js +++ b/src/commands/removedupes.js @@ -8,19 +8,19 @@ module.exports = { const { music } = ctx; const seen = {}; - if (!music.player) return ctx.respond(util.embed().setDescription("❌| Currently not playing anything.")); - if (!music.queue.length) return ctx.respond(util.embed().setDescription("❌ | Queue is empty.")); + if (!music.player) return ctx.respond({ embeds: [util.embed().setDescription("❌| Currently not playing anything.")] }); + if (!music.queue.length) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Queue is empty.")] }); if (!ctx.member.voice.channel) - return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + return ctx.respond({ embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); + return ctx.respond({ embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] }); for (const song of music.queue) { if (seen[song.info.indentifier] === undefined) seen[song.info.indentifier] = song; } music.queue = Object.values(seen); - ctx.respond(util.embed().setDescription("✅ | Removed all Dupes")).catch(e => e); + ctx.respond({ embeds: [util.embed().setDescription("✅ | Removed all Dupes")] }).catch(e => e); } }; diff --git a/src/commands/resume.js b/src/commands/resume.js index 7eefe00..67d4833 100644 --- a/src/commands/resume.js +++ b/src/commands/resume.js @@ -2,7 +2,7 @@ const util = require("../util"); module.exports = { name: "resume", - exec: async (ctx) => { + exec: (ctx) => { const { music } = ctx; if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌| Currently not playing anything.")); if (!ctx.member.voice.channel) @@ -11,8 +11,10 @@ module.exports = { return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); try { - await music.resume(); - ctx.react("▶️").catch(e => e); + music.resume(); + ctx.respond({ + embeds: [util.embed().setDescription("▶️ | Resumed")] + }); } catch (e) { ctx.respond(`An error occured: ${e.message}.`); } diff --git a/src/commands/search.js b/src/commands/search.js index 2781bcd..36e8729 100644 --- a/src/commands/search.js +++ b/src/commands/search.js @@ -5,46 +5,49 @@ module.exports = { exec: async (ctx) => { const { music, args } = ctx; if (!ctx.member.voice.channel) - return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + return ctx.respond({ embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); + return ctx.respond({ embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] }); const missingPerms = util.missingPerms(ctx.guild.me.permissionsIn(ctx.member.voice.channel), ["CONNECT", "SPEAK"]); if ((!music.player || !music.player.playing) && missingPerms.length) - return ctx.respond(util.embed().setDescription(`❌ | I need ${missingPerms.length > 1 ? "these" : "this"} permission${missingPerms.length > 1 ? "s" : ""} on your voice channel: ${missingPerms.map(x => `\`${x}\``).join(", ")}.`)); + return ctx.respond({ embeds: [util.embed().setDescription(`❌ | I need ${missingPerms.length > 1 ? "these" : "this"} permission${missingPerms.length > 1 ? "s" : ""} on your voice channel: ${missingPerms.map(x => `\`${x}\``).join(", ")}.`)] }); if (!music.node || !music.node.connected) - return ctx.respond(util.embed().setDescription("❌ | Lavalink node not connected.")); + return ctx.respond({ embeds: [util.embed().setDescription("❌ | Lavalink node not connected.")] }); const query = args.join(" "); - if (!query) return ctx.respond(util.embed().setDescription("❌ | Missing args.")); + if (!query) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Missing args.")] }); try { let { tracks } = await music.load(`ytsearch:${query}`); - if (!tracks.length) return ctx.respond(util.embed().setDescription("❌ | Couldn't find any results.")); + if (!tracks.length) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Couldn't find any results.")] }); tracks = tracks.slice(0, 10); - const resultMessage = await ctx.respond(util.embed() - .setAuthor("Search Result", ctx.client.user.displayAvatarURL()) - .setDescription(tracks.map((x, i) => `\`${++i}.\` **${x.info.title}**`)) - .setFooter("Select from 1 to 10 or type \"cancel\" to cancel the command.")); + const resultMessage = await ctx.respond({ + embeds: [util.embed() + .setAuthor("Search Result", ctx.client.user.displayAvatarURL()) + .setDescription(tracks.map((x, i) => `\`${++i}.\` **${x.info.title}**`)) + .setFooter("Select from 1 to 10 or type \"cancel\" to cancel the command.") + ] + }); const collector = await awaitMessages(); - if (!collector) return resultMessage.edit(util.embed().setDescription("❌ | Time is up!")); + if (!collector) return resultMessage.edit({ embeds: [util.embed().setDescription("❌ | Time is up!")] }); const response = collector.first(); if (response.deletable) response.delete(); if (/^cancel$/i.exec(response.content)) - return resultMessage.edit(util.embed().setDescription("✅ | Cancelled.")); + return resultMessage.edit({ embeds: [util.embed().setDescription("✅ | Cancelled.")] }); const track = tracks[response.content - 1]; track.requester = ctx.author; music.queue.push(track); if (music.player && music.player.playing) { - resultMessage.edit(util.embed().setDescription(`✅ | **${track.info.title}** added to the queue.`)); + resultMessage.edit({ embeds: [util.embed().setDescription(`✅ | **${track.info.title}** added to the queue.`)] }); } else { resultMessage.delete(); } @@ -59,7 +62,7 @@ module.exports = { async function awaitMessages() { try { - const filter = (m) => m.author.equals(ctx.author) && (/^cancel$/i.exec(m.content) || (!isNaN(parseInt(m.content, 10)) && (m.content >= 1 && m.content <= 10))), + const filter = (m) => m.author.equals(ctx.author) && (/^cancel$/i.exec(m.content) || (!isNaN(parseInt(m.content, 10)) && (m.content >= 1 && m.content <= 10))); const collector = await ctx.channel.awaitMessages( { diff --git a/src/commands/seek.js b/src/commands/seek.js index 28c7cb2..fbe7d1e 100644 --- a/src/commands/seek.js +++ b/src/commands/seek.js @@ -6,28 +6,28 @@ module.exports = { name: "seek", exec: async (ctx) => { const { music, args } = ctx; - if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); if (!ctx.member.voice.channel) - return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + return ctx.respond({ embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); + return ctx.respond({ embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] }); if (!music.current.info.isSeekable) - return ctx.respond(util.embed().setDescription("❌ | Current track isn't seekable.")); + return ctx.respond({ embeds: [util.embed().setDescription("❌ | Current track isn't seekable.")] }); const duration = args[0]; if (!duration) - return ctx.respond(util.embed().setDescription("❌ | You must provide duration to seek. Valid duration e.g. `1:34`.")); + return ctx.respond({ embeds: [util.embed().setDescription("❌ | You must provide duration to seek. Valid duration e.g. `1:34`.")] }); if (!durationPattern.test(duration)) - return ctx.respond(util.embed().setDescription("❌ | You provided an invalid duration. Valid duration e.g. `1:34`.")); + return ctx.respond({ embeds: [util.embed().setDescription("❌ | You provided an invalid duration. Valid duration e.g. `1:34`.")] }); const durationMs = util.durationToMillis(duration); if (durationMs > music.current.info.length) - return ctx.respond(util.embed().setDescription("❌ | The duration you provide exceeds the duration of the current track.")); + return ctx.respond({ embeds: [util.embed().setDescription("❌ | The duration you provide exceeds the duration of the current track.")] }); try { await music.player.seek(durationMs); - ctx.respond(util.embed().setDescription(`✅ | Seeked to ${util.millisToDuration(durationMs)}.`)); + ctx.respond({ embeds: [util.embed().setDescription(`✅ | Seeked to ${util.millisToDuration(durationMs)}.`)] }); } catch (e) { ctx.respond(`An error occured: ${e.message}.`); } diff --git a/src/commands/shuffle.js b/src/commands/shuffle.js index bb0e9c5..3a0c083 100644 --- a/src/commands/shuffle.js +++ b/src/commands/shuffle.js @@ -5,15 +5,15 @@ module.exports = { aliases: ["sf"], exec: async (ctx) => { const { music } = ctx; - if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); - if (!music.queue.length) return ctx.respond(util.embed().setDescription("❌ | Queue is empty.")); + if (!music.player?.track) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); + if (!music.queue.length) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Queue is empty.")] }); if (!ctx.member.voice.channel) - return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + return ctx.respond({ embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); + return ctx.respond({ embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] }); music.queue = util.shuffleArray(music.queue); - ctx.respond(util.embed().setDescription(`✅ | Queue shuffled! Type \`${ctx.client.prefix}queue\` to see changes.`)); + ctx.respond({ embeds: [util.embed().setDescription(`✅ | Queue shuffled! Type \`${ctx.client.prefix}queue\` to see changes.`)] }); } }; diff --git a/src/commands/skip.js b/src/commands/skip.js index 03de757..4ccad7b 100644 --- a/src/commands/skip.js +++ b/src/commands/skip.js @@ -3,22 +3,24 @@ const util = require("../util"); module.exports = { name: "skip", aliases: ["skipto"], - exec: async (ctx) => { + exec: (ctx) => { const { music, args } = ctx; const skipTo = args[0] ? parseInt(args[0], 10) : null; - if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); if (!ctx.member.voice.channel) - return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + return ctx.respond({ embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); + return ctx.respond({ embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] }); if (skipTo !== null && (isNaN(skipTo) || skipTo < 1 || skipTo > music.queue.length)) - return ctx.respond(util.embed().setDescription("❌ | Invalid number to skip.")); + return ctx.respond({ embeds: [util.embed().setDescription("❌ | Invalid number to skip.")] }); try { - await music.skip(skipTo); - ctx.react("⏭️").catch(e => e); + music.skip(skipTo); + ctx.respond({ + embeds: [util.embed().setDescription("⏭️ | Skipped")] + }); } catch (e) { ctx.respond(`An error occured: ${e.message}.`); } diff --git a/src/commands/source.js b/src/commands/source.js index b613c99..43d2279 100644 --- a/src/commands/source.js +++ b/src/commands/source.js @@ -4,6 +4,6 @@ module.exports = { name: "source", aliases: ["src"], exec: (ctx) => { - ctx.respond(util.embed().setDescription("✅ | [Here](https://github.com/Allvaa/lavalink-musicbot) is the open source repository this bot uses.")); + ctx.respond({ embeds: [util.embed().setDescription("✅ | [Here](https://github.com/Allvaa/lavalink-musicbot) is the open source repository this bot uses.")] }); } }; diff --git a/src/commands/stats.js b/src/commands/stats.js index 1ab103d..2cf7a43 100644 --- a/src/commands/stats.js +++ b/src/commands/stats.js @@ -5,9 +5,9 @@ module.exports = { name: "stats", exec: (ctx) => { /** @type {import("lavacord").LavalinkNode[]} */ - const nodes = [...ctx.client.manager.nodes.values()]; + const nodes = [...ctx.client.shoukaku.nodes.values()]; - ctx.respond(util.embed() + ctx.respond({ embeds: [util.embed() .setAuthor("Lavalink Node(s) Stats", ctx.client.user.displayAvatarURL()) .setTitle("Source Code") .setURL("https://github.com/Allvaa/lavalink-musicbot") @@ -18,16 +18,16 @@ module.exports = { const uptime = prettyMs(node.stats.uptime, { verbose: true, secondsDecimalDigits: 0 }); return `\`\`\`asciidoc -ID :: ${node.id} -Status :: ${node.connected ? "Connected" : "Disconnected"} -${node.connected ? ` +ID :: ${node.name} +Status :: ${node.state === 1 ? "Connected" : "Disconnected"} +${node.state === 1 ? ` CPU Load :: ${cpuLoad}% Mem Usage :: ${memUsage} MB Uptime :: ${uptime} Players :: ${node.stats.playingPlayers} of ${node.stats.players} playing` : ""}\`\`\``; - }) + }).join("\n") ) .setTimestamp() - ); + ] }); } }; diff --git a/src/commands/stop.js b/src/commands/stop.js index b8930e5..c39fa37 100644 --- a/src/commands/stop.js +++ b/src/commands/stop.js @@ -3,17 +3,19 @@ const util = require("../util"); module.exports = { name: "stop", aliases: ["leave", "dc"], - exec: async (ctx) => { + exec: (ctx) => { const { music } = ctx; - if (!music.player) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); if (!ctx.member.voice.channel) - return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + return ctx.respond({ embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); + return ctx.respond({ embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] }); try { - await music.stop(); - ctx.react("⏹️").catch(e => e); + music.stop(); + ctx.respond({ + embeds: [util.embed().setDescription("⏹️ | Stopped")] + }); } catch (e) { ctx.respond(`An error occured: ${e.message}.`); } diff --git a/src/commands/vaporwave.js b/src/commands/vaporwave.js index feaf8ad..c6a4fc3 100644 --- a/src/commands/vaporwave.js +++ b/src/commands/vaporwave.js @@ -4,13 +4,13 @@ module.exports = { aliases: ["vp"], exec: async (ctx) => { const { music } = ctx; - if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); if (!ctx.member.voice.channel) - return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + return ctx.respond({ embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); + return ctx.respond({ embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] }); music.setVaporwave(!music.filters.vaporwave); - ctx.respond(util.embed().setDescription(`✅ | ${music.filters.vaporwave ? "Enabled" : "Disabled"} **Vaporwave**`)); + ctx.respond({ embeds: [util.embed().setDescription(`✅ | ${music.filters.vaporwave ? "Enabled" : "Disabled"} **Vaporwave**`)] }); } }; diff --git a/src/commands/volume.js b/src/commands/volume.js index f841733..79d16b8 100644 --- a/src/commands/volume.js +++ b/src/commands/volume.js @@ -6,21 +6,21 @@ module.exports = { exec: async (ctx) => { const { music, args } = ctx; const newVolume = parseInt(args[0], 10); - if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌ | Currently not playing anything.")); + if (!music.player?.track) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); try { if (isNaN(newVolume)) { - ctx.respond(util.embed().setDescription(`🔉 | Current volume \`${music.volume}\`.`)); + ctx.respond({ embeds: [util.embed().setDescription(`🔉 | Current volume \`${music.volume}\`.`)] }); } else { if (!ctx.member.voice.channel) - return ctx.respond(util.embed().setDescription("❌ | You must be on a voice channel.")); + return ctx.respond({ embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond(util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)); + return ctx.respond({ embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] }); if (newVolume < 0 || newVolume > 150) - return ctx.respond(util.embed().setDescription("❌ | You can only set the volume from 0 to 150.")); + return ctx.respond({ embeds: [util.embed().setDescription("❌ | You can only set the volume from 0 to 150.")] }); await music.setVolume(newVolume); - ctx.respond(util.embed().setDescription(`🔉 | Volume set to \`${music.volume}\`.`)); + ctx.respond({ embeds: [util.embed().setDescription(`🔉 | Volume set to \`${music.volume}\`.`)] }); } } catch (e) { ctx.respond(`An error occured: ${e.message}.`); diff --git a/src/structures/CommandContext.js b/src/structures/CommandContext.js index 64d5979..a8b1b4e 100644 --- a/src/structures/CommandContext.js +++ b/src/structures/CommandContext.js @@ -1,4 +1,3 @@ -const { MessageEmbed } = require("discord.js"); const MusicHandler = require("./MusicHandler"); module.exports = class CommandContext { @@ -38,6 +37,6 @@ module.exports = class CommandContext { } respond(opt) { - this.channel.send(opt instanceof MessageEmbed ? { embeds: [opt] } : opt); + this.channel.send(opt); } }; From bd2ab5800f191d7d9e8511fffad48a117b861638 Mon Sep 17 00:00:00 2001 From: Allvaa Date: Tue, 17 Aug 2021 17:01:58 +0700 Subject: [PATCH 08/28] use shoukaku from npm --- package.json | 2 +- yarn.lock | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 962756b..31a66f5 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "dotenv": "^10.0.0", "lavasfy": "2.3.0", "pretty-ms": "^7.0.1", - "shoukaku": "Deivu/Shoukaku#next" + "shoukaku": "^2.0.0" }, "devDependencies": { "eslint": "^7.32.0" diff --git a/yarn.lock b/yarn.lock index dae1c62..76ca900 100644 --- a/yarn.lock +++ b/yarn.lock @@ -834,9 +834,10 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shoukaku@Deivu/Shoukaku#next: +shoukaku@^2.0.0: version "2.0.0" - resolved "https://codeload.github.com/Deivu/Shoukaku/tar.gz/dc887bfcf0ad53acbe873ea043ab71d1ffde639a" + resolved "https://registry.yarnpkg.com/shoukaku/-/shoukaku-2.0.0.tgz#e0155c42d5708013768465de13ea9ca87802a313" + integrity sha512-0qWy3ItXMHVqmXmUOagItfVZcJESKgFnKOgn7xs5ghjZvBkKG+omBRL3vFQzxmvJfGARvCXy1Lo9FL/kz/pyxw== dependencies: abort-controller "^3.0.0" petitio "^1.3.2" From 7b140577a932ce9310d6375ced54fb45d2cae3e1 Mon Sep 17 00:00:00 2001 From: Allvaa Date: Tue, 17 Aug 2021 19:21:08 +0700 Subject: [PATCH 09/28] reactions -> buttons --- package.json | 2 +- src/commands/queue.js | 19 ++++++++++++++-- src/structures/CommandContext.js | 2 +- src/util.js | 37 ++++++++++++++++---------------- yarn.lock | 18 ++++++++-------- 5 files changed, 47 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index 31a66f5..29e48d0 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ }, "homepage": "https://github.com/Allvaa/lavalink-musicbot#readme", "dependencies": { - "discord.js": "^13.0.1", + "discord.js": "^13.1.0", "dotenv": "^10.0.0", "lavasfy": "2.3.0", "pretty-ms": "^7.0.1", diff --git a/src/commands/queue.js b/src/commands/queue.js index d1a47f0..1263523 100644 --- a/src/commands/queue.js +++ b/src/commands/queue.js @@ -1,3 +1,4 @@ +const { MessageButton, MessageActionRow } = require("discord.js"); const util = require("../util"); module.exports = { @@ -17,8 +18,22 @@ module.exports = { .setFooter(`Page 1 of ${chunked.length}.`); try { - const queuectx = await ctx.respond({embeds: [embed] }); - if (chunked.length > 1) await util.pagination(queuectx, ctx.author, chunked); + const queueMsg = await ctx.respond({ + embeds: [embed], + components: + chunked.length > 1 + ? [ + new MessageActionRow() + .addComponents( + ...util.paginationEmojis.map((x, i) => new MessageButton({ + customId: x, + emoji: x, + style: i === 1 ? "DANGER" : "PRIMARY" + }))) + ] + : [] + }); + if (chunked.length > 1) util.pagination(queueMsg, ctx.author, chunked); } catch (e) { ctx.respond(`An error occured: ${e.message}.`); } diff --git a/src/structures/CommandContext.js b/src/structures/CommandContext.js index a8b1b4e..2e9edbd 100644 --- a/src/structures/CommandContext.js +++ b/src/structures/CommandContext.js @@ -37,6 +37,6 @@ module.exports = class CommandContext { } respond(opt) { - this.channel.send(opt); + return this.channel.send(opt); } }; diff --git a/src/util.js b/src/util.js index 6238e3f..11a0f71 100644 --- a/src/util.js +++ b/src/util.js @@ -1,4 +1,4 @@ -const { MessageEmbed, Permissions } = require("discord.js"); +const { MessageEmbed, Permissions, MessageActionRow } = require("discord.js"); const prettyMilliseconds = require("pretty-ms"); module.exports = class Util { @@ -40,36 +40,37 @@ module.exports = class Util { return ["◀", "⛔", "▶"]; } - static async pagination(msg, author, contents, init = true, currPage = 0) { - if (init) for (const emoji of this.paginationEmojis) await msg.react(emoji); - - const collector = msg.createReactionCollector((reaction, user) => { - return this.paginationEmojis.includes(reaction.emoji.name) && user.id === author.id; - }, { + static async pagination(msg, author, contents, currPage = 0) { + /** @type {import("discord.js").InteractionCollector} */ + const collector = msg.createMessageComponentCollector({ + filter: interaction => this.paginationEmojis.includes(interaction.customId) && interaction.user.id === author.id, + componentType: "BUTTON", max: 1, - time: 30000 + time: 15000 }); collector - .on("collect", (reaction) => { - reaction.users.remove(author); - - const emoji = reaction.emoji.name; + .on("collect", async (interaction) => { + await interaction.deferUpdate(); + const emoji = interaction.customId; if (emoji === this.paginationEmojis[0]) currPage--; - if (emoji === this.paginationEmojis[1]) return collector.stop(); + if (emoji === this.paginationEmojis[1]) { + await interaction.editReply({ components: [new MessageActionRow().addComponents(...interaction.message.components[0].components.map(x => x.setDisabled(true)))] }); + return; + } if (emoji === this.paginationEmojis[2]) currPage++; currPage = ((currPage % contents.length) + contents.length) % contents.length; - const embed = msg.embeds[0] + const embed = interaction.message.embeds[0] .setDescription(contents[currPage]) .setFooter(`Page ${currPage + 1} of ${contents.length}.`); - msg.edit(embed); + await interaction.editReply({ embeds: [embed] }); - this.pagination(msg, author, contents, false, currPage); + this.pagination(msg, author, contents, currPage); }) - .on("end", (_, reason) => { - if (["time", "user"].includes(reason)) msg.reactions.removeAll(); + .on("end", () => { + msg.edit({ components: [new MessageActionRow().addComponents(...msg.components[0].components.map(x => x.setDisabled(true)))] }); }); } diff --git a/yarn.lock b/yarn.lock index 76ca900..3a44da9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23,10 +23,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@discordjs/builders@^0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@discordjs/builders/-/builders-0.4.0.tgz#bb41573ce4824aa9194a53b52c29c5219b610010" - integrity sha512-EiwLltKph6TSaPJIzJYdzNc1PnA2ZNaaE0t0ODg3ghnpVHqfgd0YX9/srsleYHW2cw1sfIq+kbM+h0etf7GWLA== +"@discordjs/builders@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@discordjs/builders/-/builders-0.5.0.tgz#646cbea9cc67f68639e6fb70ed1278b26dacdb14" + integrity sha512-HP5y4Rqw68o61Qv4qM5tVmDbWi4mdTFftqIOGRo33SNPpLJ1Ga3KEIR2ibKofkmsoQhEpLmopD1AZDs3cKpHuw== dependencies: "@sindresorhus/is" "^4.0.1" discord-api-types "^0.22.0" @@ -279,12 +279,12 @@ discord-api-types@^0.22.0: resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.22.0.tgz#34dc57fe8e016e5eaac5e393646cd42a7e1ccc2a" integrity sha512-l8yD/2zRbZItUQpy7ZxBJwaLX/Bs2TGaCthRppk8Sw24LOIWg12t9JEreezPoYD0SQcC2htNNo27kYEpYW/Srg== -discord.js@^13.0.1: - version "13.0.1" - resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-13.0.1.tgz#58f009706d1d7587fe9ff6c6c781e4540ae085f9" - integrity sha512-pEODCFfxypBnGEYpSgjkn1jt70raCS1um7Zp0AXEfW1DcR29wISzQ/WeWdnjP5KTXGi0LTtkRiUjOsMgSoukxA== +discord.js@^13.1.0: + version "13.1.0" + resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-13.1.0.tgz#99f6a2a8be88d31906ff0148e9b1cb603ebb2e2e" + integrity sha512-gxO4CXKdHpqA+WKG+f5RNnd3srTDj5uFJHgOathksDE90YNq/Qijkd2WlMgTTMS6AJoEnHxI7G9eDQHCuZ+xDA== dependencies: - "@discordjs/builders" "^0.4.0" + "@discordjs/builders" "^0.5.0" "@discordjs/collection" "^0.2.1" "@discordjs/form-data" "^3.0.1" "@sapphire/async-queue" "^1.1.4" From 2ed352285a7431153acb593454dc2845f339403e Mon Sep 17 00:00:00 2001 From: Allvaa Date: Tue, 17 Aug 2021 19:26:04 +0700 Subject: [PATCH 10/28] looks better imo --- src/commands/queue.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/commands/queue.js b/src/commands/queue.js index 1263523..5c73e98 100644 --- a/src/commands/queue.js +++ b/src/commands/queue.js @@ -25,11 +25,13 @@ module.exports = { ? [ new MessageActionRow() .addComponents( - ...util.paginationEmojis.map((x, i) => new MessageButton({ - customId: x, - emoji: x, - style: i === 1 ? "DANGER" : "PRIMARY" - }))) + ...util.paginationEmojis.map((x, i) => + new MessageButton() + .setCustomId(x) + .setEmoji(x) + .setStyle(i === 1 ? "DANGER" : "PRIMARY") + ) + ) ] : [] }); From cebd3bf89b4e804ecb6e42dc137968ab14e98156 Mon Sep 17 00:00:00 2001 From: Allvaa Date: Tue, 17 Aug 2021 21:50:16 +0700 Subject: [PATCH 11/28] switch to select menu from await messages --- src/commands/search.js | 91 +++++++++++++++++++++++++++--------------- 1 file changed, 59 insertions(+), 32 deletions(-) diff --git a/src/commands/search.js b/src/commands/search.js index 9b34a2f..7c568ac 100644 --- a/src/commands/search.js +++ b/src/commands/search.js @@ -1,5 +1,8 @@ +const { MessageActionRow, MessageSelectMenu } = require("discord.js"); const util = require("../util"); +const emojiNumbers = ["1️⃣","2️⃣","3️⃣","4️⃣","5️⃣","6️⃣","7️⃣","8️⃣","9️⃣","🔟"]; + module.exports = { name: "search", exec: async (ctx) => { @@ -13,7 +16,7 @@ module.exports = { if ((!music.player || !music.player.playing) && missingPerms.length) return ctx.respond({ embeds: [util.embed().setDescription(`❌ | I need ${missingPerms.length > 1 ? "these" : "this"} permission${missingPerms.length > 1 ? "s" : ""} on your voice channel: ${missingPerms.map(x => `\`${x}\``).join(", ")}.`)] }); - if (!music.node || !music.node.connected) + if (music.node.state !== 1) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Lavalink node not connected.")] }); const query = args.join(" "); @@ -27,54 +30,78 @@ module.exports = { const resultMessage = await ctx.respond({ embeds: [util.embed() - .setAuthor("Search Result", ctx.client.user.displayAvatarURL()) - .setDescription(tracks.map((x, i) => `\`${++i}.\` **${x.info.title}**`)) - .setFooter("Select from 1 to 10 or type \"cancel\" to cancel the command.") + .setAuthor("Song Selection", ctx.client.user.displayAvatarURL()) + .setDescription("Pick one of the search results that you would like to add to the queue") + .setFooter("You can select \"cancel\" to cancel the command.") + ], + components: [ + new MessageActionRow() + .addComponents( + new MessageSelectMenu() + .setCustomId("selected") + .setPlaceholder("Nothing selected") + .addOptions([ + ...tracks + .map((x, i) => ( + { + label: x.info.title, + description: x.info.author, + value: i.toString(), + emoji: emojiNumbers[i] + } + )), + ...[ + { + label: "Cancel", + description: "Cancel selection", + value: "10", + emoji: "❌" + } + ] + ]) + ) ] }); - const collector = await awaitMessages(); - if (!collector) return resultMessage.edit({ embeds: [util.embed().setDescription("❌ | Time is up!")] }); - const response = collector.first(); - - if (response.deletable) response.delete(); + const selected = await awaitSelection(); + if (!selected) return resultMessage.edit({ embeds: [util.embed().setDescription("❌ | Time is up!")] }); + await selected.deferUpdate(); - if (/^cancel$/i.exec(response.content)) - return resultMessage.edit({ embeds: [util.embed().setDescription("✅ | Cancelled.")] }); + if (selected.values[0] === "10") + return selected.editReply({ embeds: [util.embed().setDescription("✅ | Cancelled.")], components: [] }); - const track = tracks[response.content - 1]; + const track = tracks[selected.values[0]]; track.requester = ctx.author; music.queue.push(track); - if (music.player && music.player.playing) { - resultMessage.edit({ embeds: [util.embed().setDescription(`✅ | **${track.info.title}** added to the queue.`)] }); + if (music.player?.track) { + selected.editReply({ embeds: [util.embed().setDescription(`✅ | **${track.info.title}** added to the queue.`)], components: [] }); } else { - resultMessage.delete(); + selected.deleteReply(); } if (!music.player) await music.join(ctx.member.voice.channel); if (!music.player.playing) await music.start(); music.setTextCh(ctx.channel); - } catch (e) { - ctx.respond(`An error occured: ${e.message}.`); - } - async function awaitMessages() { - try { - const filter = (m) => m.author.equals(ctx.author) && (/^cancel$/i.exec(m.content) || (!isNaN(parseInt(m.content, 10)) && (m.content >= 1 && m.content <= 10))); - const collector = await ctx.channel.awaitMessages( - { - filter, - time: 10000, - max: 1, - errors: ["time"] - } - ); - return collector; - } catch { - return null; + // eslint-disable-next-line no-inner-declarations + async function awaitSelection() { + try { + const selected = await resultMessage.awaitMessageComponent( + { + filter: interaction => interaction.user.equals(ctx.author), + time: 15000, + componentType: "SELECT_MENU" + } + ); + return selected; + } catch { + return null; + } } + } catch (e) { + ctx.respond(`An error occured: ${e.message}.`); } } }; From 1f77c1420babb8e23a32bc5b70a5541977dca542 Mon Sep 17 00:00:00 2001 From: Allvaa Date: Tue, 17 Aug 2021 21:54:42 +0700 Subject: [PATCH 12/28] . --- src/commands/play.js | 2 +- src/commands/search.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/play.js b/src/commands/play.js index e588682..f6a5155 100644 --- a/src/commands/play.js +++ b/src/commands/play.js @@ -24,7 +24,7 @@ module.exports = { if (music.node.state !== 1) return ctx.respond({ - embeds: [util.embed().setDescription("❌ | Lavalink node not connected.")] + embeds: [util.embed().setDescription("❌ | Lavalink node is not connected yet.")] }); const query = args.join(" ") || getAttachmentURL(ctx.message); diff --git a/src/commands/search.js b/src/commands/search.js index 7c568ac..8a71b78 100644 --- a/src/commands/search.js +++ b/src/commands/search.js @@ -17,7 +17,7 @@ module.exports = { return ctx.respond({ embeds: [util.embed().setDescription(`❌ | I need ${missingPerms.length > 1 ? "these" : "this"} permission${missingPerms.length > 1 ? "s" : ""} on your voice channel: ${missingPerms.map(x => `\`${x}\``).join(", ")}.`)] }); if (music.node.state !== 1) - return ctx.respond({ embeds: [util.embed().setDescription("❌ | Lavalink node not connected.")] }); + return ctx.respond({ embeds: [util.embed().setDescription("❌ | Lavalink node is not connected yet.")] }); const query = args.join(" "); if (!query) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Missing args.")] }); From fb7acf064141ac00e324dfb858e67c7afe72e3e2 Mon Sep 17 00:00:00 2001 From: Allvaa Date: Tue, 17 Aug 2021 21:58:35 +0700 Subject: [PATCH 13/28] . --- src/structures/MusicHandler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/MusicHandler.js b/src/structures/MusicHandler.js index 86cebad..cd3988e 100644 --- a/src/structures/MusicHandler.js +++ b/src/structures/MusicHandler.js @@ -60,7 +60,7 @@ module.exports = class MusicHandler { await this.node.joinChannel({ channelId: voice.id, guildId: this.guild.id, - shardId: 0, + shardId: this.guild.shardId, deaf: true }); From f20845ae8b614880610368695ead8a0f7829dce7 Mon Sep 17 00:00:00 2001 From: Allvaa Date: Tue, 17 Aug 2021 22:27:37 +0700 Subject: [PATCH 14/28] add secure option to .env --- .env.example | 1 + src/structures/MusicClient.js | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index c428118..7542ec7 100644 --- a/.env.example +++ b/.env.example @@ -4,6 +4,7 @@ OWNER_ID=190190190190190190 LAVA_HOST=localhost LAVA_PORT=2333 LAVA_PASS=youshallnotpass +LAVA_SECURE=false ENABLE_SPOTIFY=false # you will need these if you enabled spotify SPOTIFY_ID=00000A0000 diff --git a/src/structures/MusicClient.js b/src/structures/MusicClient.js index dc6c1fb..cc83a4f 100644 --- a/src/structures/MusicClient.js +++ b/src/structures/MusicClient.js @@ -15,7 +15,7 @@ module.exports = class MusicClient extends Client { name: "main", url: `${process.env.LAVA_HOST}:${process.env.LAVA_PORT}`, auth: process.env.LAVA_PASS, - secure: true + secure: process.env.LAVA_SECURE === "true" } ]); this.spotify = process.env.ENABLE_SPOTIFY === "true" @@ -32,7 +32,7 @@ module.exports = class MusicClient extends Client { host: process.env.LAVA_HOST, port: process.env.LAVA_PORT, password: process.env.LAVA_PASS, - secure: true + secure: process.env.LAVA_SECURE === "true" } ]) : null; From d21250c1f1c165b936fda2b34d4c79e7f6ee5ab6 Mon Sep 17 00:00:00 2001 From: Rajat Mishra <85543339+hydrox19@users.noreply.github.com> Date: Wed, 18 Aug 2021 14:51:35 +0530 Subject: [PATCH 15/28] Some minor changes, that might have not needed but yea fancy stuff (#133) --- README.md | 2 +- src/bot.js | 3 ++- src/structures/MusicHandler.js | 2 +- src/util.js | 4 +++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d7f31a0..123ccce 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Music bot that uses Lavalink for its audio player. ## Prerequisites - [Lavalink server](https://github.com/freyacodes/Lavalink#server-configuration). -- Node.js v12 or above. +- Node.js v16.6.x or above. ## Usage - Rename `.env.example` to `.env` and replace those values with yours. diff --git a/src/bot.js b/src/bot.js index 9b2fc71..b7ce297 100644 --- a/src/bot.js +++ b/src/bot.js @@ -1,8 +1,9 @@ const { Intents } = require("discord.js"); +const { GUILDS, GUILD_MESSAGES, GUILD_VOICE_STATES } = Intents.FLAGS; const MusicClient = require("./structures/MusicClient"); const client = new MusicClient({ - intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILD_VOICE_STATES], + intents: [GUILDS, GUILD_MESSAGES, GUILD_VOICE_STATES], allowedMentions: { parse: ["users", "roles"] } diff --git a/src/structures/MusicHandler.js b/src/structures/MusicHandler.js index cd3988e..a44e993 100644 --- a/src/structures/MusicHandler.js +++ b/src/structures/MusicHandler.js @@ -35,7 +35,7 @@ module.exports = class MusicHandler { } get node() { - return this.client.shoukaku.nodes.get("main"); + return this.client.shoukaku.getNode(); } get volume() { diff --git a/src/util.js b/src/util.js index 11a0f71..0f50b3f 100644 --- a/src/util.js +++ b/src/util.js @@ -1,7 +1,7 @@ const { MessageEmbed, Permissions, MessageActionRow } = require("discord.js"); const prettyMilliseconds = require("pretty-ms"); -module.exports = class Util { +class Util { static embed() { return new MessageEmbed() .setColor("#99AAB5"); @@ -98,3 +98,5 @@ module.exports = class Util { }; } }; + +module.exports = Util; \ No newline at end of file From f83253d6a08dadd55b06ddea16d5fd02c76d2116 Mon Sep 17 00:00:00 2001 From: Allvaa Date: Sat, 21 Aug 2021 14:27:27 +0700 Subject: [PATCH 16/28] clear components when time is up --- src/commands/search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/search.js b/src/commands/search.js index 8a71b78..368a7ab 100644 --- a/src/commands/search.js +++ b/src/commands/search.js @@ -64,7 +64,7 @@ module.exports = { }); const selected = await awaitSelection(); - if (!selected) return resultMessage.edit({ embeds: [util.embed().setDescription("❌ | Time is up!")] }); + if (!selected) return resultMessage.edit({ embeds: [util.embed().setDescription("❌ | Time is up!")], components: [] }); await selected.deferUpdate(); if (selected.values[0] === "10") From 8ed475e470cbc440071a9f43fca11239fa45a789 Mon Sep 17 00:00:00 2001 From: Allvaa Date: Sat, 21 Aug 2021 14:27:49 +0700 Subject: [PATCH 17/28] reply --- src/structures/CommandContext.js | 2 +- src/util.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/structures/CommandContext.js b/src/structures/CommandContext.js index 2e9edbd..d9a0c92 100644 --- a/src/structures/CommandContext.js +++ b/src/structures/CommandContext.js @@ -37,6 +37,6 @@ module.exports = class CommandContext { } respond(opt) { - return this.channel.send(opt); + return this.message.reply(opt); } }; diff --git a/src/util.js b/src/util.js index 0f50b3f..3f66fa4 100644 --- a/src/util.js +++ b/src/util.js @@ -97,6 +97,6 @@ class Util { percent }; } -}; +} module.exports = Util; \ No newline at end of file From 779f38bc8531e0f6e1e17797cfa16e829ef76cb8 Mon Sep 17 00:00:00 2001 From: Allvaa Date: Sat, 21 Aug 2021 14:58:48 +0700 Subject: [PATCH 18/28] . --- src/commands/help.js | 2 +- src/commands/previous.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/commands/help.js b/src/commands/help.js index 80e5783..90ef90b 100644 --- a/src/commands/help.js +++ b/src/commands/help.js @@ -15,6 +15,6 @@ module.exports = { .setDescription(commands.join(", ")) .setTimestamp(); - ctx.respond(embed); + ctx.respond({ embeds: [embed] }); } }; diff --git a/src/commands/previous.js b/src/commands/previous.js index e0bc3af..2e1da5c 100644 --- a/src/commands/previous.js +++ b/src/commands/previous.js @@ -23,7 +23,10 @@ module.exports = { try { music.queue.unshift(music.previous); - await music.skip(); + music.skip(); + ctx.respond({ + embeds: [util.embed().setDescription("⏮️ | Previous")] + }); ctx.react("⏮️").catch(e => e); } catch (e) { ctx.respond(`An error occured: ${e.message}.`); From bf5de157500a3fdfd03c50f1c5ae76fbf8a8411f Mon Sep 17 00:00:00 2001 From: Allvaa Date: Sat, 21 Aug 2021 15:40:50 +0700 Subject: [PATCH 19/28] switch to select menu --- src/commands/loop.js | 93 +++++++++++++++++++--------------- src/commands/play.js | 2 +- src/commands/search.js | 20 +------- src/structures/MusicHandler.js | 5 ++ src/util.js | 17 ++++++- 5 files changed, 77 insertions(+), 60 deletions(-) diff --git a/src/commands/loop.js b/src/commands/loop.js index 611c2eb..0738783 100644 --- a/src/commands/loop.js +++ b/src/commands/loop.js @@ -1,52 +1,65 @@ +const { MessageActionRow, MessageSelectMenu } = require("discord.js"); +const { awaitSelection } = require("../util"); const util = require("../util"); -const modes = ["none", "track", "queue"]; -const aliases = { - single: "track", - track: "track", - song: "track", - this: "track", - current: "track", - all: "queue", - every: "queue", - queue: "queue", - off: "none", - none: "none", - nothing: "none" -}; +const modes = ["None", "Track", "Queue"]; module.exports = { name: "loop", aliases: ["repeat"], - exec: (ctx) => { - const { music, args } = ctx; + exec: async (ctx) => { + const { music } = ctx; if (!music.player) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); - if (args[0]) { - if (!ctx.member.voice.channel) - return ctx.respond({ - embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] - }); - if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) - return ctx.respond({ - embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] - }); - const loopMode = aliases[args[0].toLowerCase()]; - if (loopMode && modes.includes(loopMode)) { - music.loop = modes.indexOf(loopMode); - ctx.respond({ - embeds: util.embed().setDescription(music.loop === 0 ? "✅ | Loop disabled." : `✅ | Set loop to ${modes[music.loop]}.`) - }); - } else { - ctx.respond({ - embeds: util.embed() - .setDescription("❌ | Invalid loop mode. Try single/all/off.") - }); - } - } else { - ctx.respond({ embeds: [util.embed().setDescription(`✅ | Current loop mode: ${modes[music.loop]}`)] }); - } + if (!ctx.member.voice.channel) + return ctx.respond({ + embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] + }); + if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) + return ctx.respond({ + embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] + }); + + const selectMsg = await ctx.respond({ + embeds: [ + util.embed() + .setDescription(`✅ | Current loop mode: ${modes[music.loop]}`) + .setFooter("Just click on the select menu if you wish to change it") + ], + components: [ + new MessageActionRow() + .addComponents( + new MessageSelectMenu() + .setCustomId("selected") + .setPlaceholder("Nothing selected") + .addOptions([ + { + label: "None", + description: "Disable loop", + value: "0", + }, + { + label: "Track", + description: "Repeat one track only", + value: "1", + }, + { + label: "Queue", + description: "Repeat all tracks in the queue", + value: "2", + } + ]) + ) + ] + }); + + const selected = await awaitSelection(selectMsg, interaction => interaction.user.equals(ctx.author)); + if (!selected) return selectMsg.edit({ embeds: [selectMsg.embeds[0].setFooter("")], components: [] }); + await selected.deferUpdate(); + + music.loop = parseInt(selected.values[0]); + selected.editReply({ embeds: [util.embed().setDescription(`✅ | Set loop mode to: ${modes[music.loop]}`)], components: [] }); } }; diff --git a/src/commands/play.js b/src/commands/play.js index f6a5155..d46744c 100644 --- a/src/commands/play.js +++ b/src/commands/play.js @@ -22,7 +22,7 @@ module.exports = { embeds: [util.embed().setDescription(`❌ | I need ${missingPerms.length > 1 ? "these" : "this"} permission${missingPerms.length > 1 ? "s" : ""} on your voice channel: ${missingPerms.map(x => `\`${x}\``).join(", ")}.`)] }); - if (music.node.state !== 1) + if (music.node?.state !== 1) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Lavalink node is not connected yet.")] }); diff --git a/src/commands/search.js b/src/commands/search.js index 368a7ab..6217dbb 100644 --- a/src/commands/search.js +++ b/src/commands/search.js @@ -16,7 +16,7 @@ module.exports = { if ((!music.player || !music.player.playing) && missingPerms.length) return ctx.respond({ embeds: [util.embed().setDescription(`❌ | I need ${missingPerms.length > 1 ? "these" : "this"} permission${missingPerms.length > 1 ? "s" : ""} on your voice channel: ${missingPerms.map(x => `\`${x}\``).join(", ")}.`)] }); - if (music.node.state !== 1) + if (music.node?.state !== 1) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Lavalink node is not connected yet.")] }); const query = args.join(" "); @@ -63,7 +63,7 @@ module.exports = { ] }); - const selected = await awaitSelection(); + const selected = await util.awaitSelection(resultMessage, interaction => interaction.user.equals(ctx.author)); if (!selected) return resultMessage.edit({ embeds: [util.embed().setDescription("❌ | Time is up!")], components: [] }); await selected.deferUpdate(); @@ -84,22 +84,6 @@ module.exports = { if (!music.player.playing) await music.start(); music.setTextCh(ctx.channel); - - // eslint-disable-next-line no-inner-declarations - async function awaitSelection() { - try { - const selected = await resultMessage.awaitMessageComponent( - { - filter: interaction => interaction.user.equals(ctx.author), - time: 15000, - componentType: "SELECT_MENU" - } - ); - return selected; - } catch { - return null; - } - } } catch (e) { ctx.respond(`An error occured: ${e.message}.`); } diff --git a/src/structures/MusicHandler.js b/src/structures/MusicHandler.js index a44e993..45a0940 100644 --- a/src/structures/MusicHandler.js +++ b/src/structures/MusicHandler.js @@ -19,6 +19,7 @@ module.exports = class MusicHandler { /** @type {import("discord.js").TextChannel|null} */ this.textChannel = null; this.shouldSkipCurrent = false; + this.state = null; } get voiceChannel() { @@ -52,6 +53,7 @@ module.exports = class MusicHandler { this.filters[filter] = false; } this.bassboost = 0; + this.state = null; } /** @param {import("discord.js").VoiceChannel} voice */ @@ -87,6 +89,9 @@ module.exports = class MusicHandler { } this.start(); }) + .on("update", ({ state }) => { + this.state = state; + }) .on("error", console.error); } diff --git a/src/util.js b/src/util.js index 3f66fa4..9cf1a0f 100644 --- a/src/util.js +++ b/src/util.js @@ -40,7 +40,7 @@ class Util { return ["◀", "⛔", "▶"]; } - static async pagination(msg, author, contents, currPage = 0) { + static pagination(msg, author, contents, currPage = 0) { /** @type {import("discord.js").InteractionCollector} */ const collector = msg.createMessageComponentCollector({ filter: interaction => this.paginationEmojis.includes(interaction.customId) && interaction.user.id === author.id, @@ -97,6 +97,21 @@ class Util { percent }; } + + static async awaitSelection(msg, filter) { + try { + const selected = await msg.awaitMessageComponent( + { + filter, + time: 15000, + componentType: "SELECT_MENU" + } + ); + return selected; + } catch { + return null; + } + } } module.exports = Util; \ No newline at end of file From ffa6c09046ffef609b190f2df04242cd14af2fd1 Mon Sep 17 00:00:00 2001 From: Allvaa Date: Sat, 21 Aug 2021 15:42:48 +0700 Subject: [PATCH 20/28] fix nowplaying command --- src/commands/nowplaying.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/nowplaying.js b/src/commands/nowplaying.js index 1588916..57ec4cd 100644 --- a/src/commands/nowplaying.js +++ b/src/commands/nowplaying.js @@ -6,9 +6,9 @@ module.exports = { exec: (ctx) => { const { music } = ctx; if (!music.player?.track) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); - const progress = util.progress(music.player.state.position, music.current.info.length); + const progress = util.progress(music.state.position, music.current.info.length); ctx.respond({ - embeds: [util.embed().setDescription(`🎶 | Now playing ${music.current.info.isStream ? "[**◉ LIVE**]" : ""}\n**${music.current.info.title}**.${music.current.info.isStream ? "" : `\n\n${util.millisToDuration(music.player.state.position)} ${progress.bar} ${util.millisToDuration(music.current.info.length)}`}`)] + embeds: [util.embed().setDescription(`🎶 | Now playing ${music.current.info.isStream ? "[**◉ LIVE**]" : ""}\n**${music.current.info.title}**.${music.current.info.isStream ? "" : `\n\n${util.millisToDuration(music.state.position)} ${progress.bar} ${util.millisToDuration(music.current.info.length)}`}`)] }); } }; From e3dc7455e288a407a2f16dba8261022e3515f6c8 Mon Sep 17 00:00:00 2001 From: Allvaa Date: Sat, 21 Aug 2021 16:39:32 +0700 Subject: [PATCH 21/28] fix manual disconnect --- src/listeners/voiceStateUpdate.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/listeners/voiceStateUpdate.js b/src/listeners/voiceStateUpdate.js index f9bf0d5..638a38a 100644 --- a/src/listeners/voiceStateUpdate.js +++ b/src/listeners/voiceStateUpdate.js @@ -3,8 +3,8 @@ module.exports = { exec: async (client, oldState, newState) => { const music = client.musics.get(newState.guild.id); if (newState.member.user.equals(client.user) && !newState.channel && music?.player) { - if (music.player.playing) await music.stop(); - if (music.player) await client.manager.leave(music.guild.id); + if (music.player.track) await music.stop(); + if (music.player) await music.node.leaveChannel(music.guild.id); } } }; From 2329417ef7a31be6c71b9f8f498ad4735f3de199 Mon Sep 17 00:00:00 2001 From: Allvaa Date: Sat, 21 Aug 2021 16:39:50 +0700 Subject: [PATCH 22/28] delete lyrics command --- src/commands/lyrics.js | 43 ------------------------------------------ 1 file changed, 43 deletions(-) delete mode 100644 src/commands/lyrics.js diff --git a/src/commands/lyrics.js b/src/commands/lyrics.js deleted file mode 100644 index 3d306c2..0000000 --- a/src/commands/lyrics.js +++ /dev/null @@ -1,43 +0,0 @@ -const fetch = require("node-fetch"); -const util = require("../util"); - -const getLyrics = async (query) => { - const body = await (await fetch(`https://some-random-api.ml/lyrics?title=${encodeURIComponent(query)}`)).json(); - if (body.error) throw Error(body.error); - return body; -}; - -module.exports = { - name: "lyrics", - aliases: ["ly"], - exec: async (ctx, args) => { - let query; - if (args.length) { - query = args.join(" "); - } else if (ctx.music.current) { - const separatedArtistAndTitle = /(.+) - (.+)/.test(ctx.music.current.info.title); - query = `${separatedArtistAndTitle ? ctx.music.current.info.title : ctx.music.current.info.author.replace(" - Topic", "")} - ${ctx.music.current.info.title}`; - } else { - return ctx.respond({ embeds: [util.embed().setDescription("❌ | Missing args.")] }); - } - - try { - const res = await getLyrics(query); - const splittedLyrics = util.chunk(res.lyrics, 1024); - - const embed = util.embed() - .setAuthor(res.author) - .setTitle(res.title) - .setURL(res.links.genius) - .setThumbnail(res.thumbnail.genius) - .setDescription(splittedLyrics[0]) - .setFooter(`Page 1 of ${splittedLyrics.length}.`); - - const lyricsctx = await ctx.respond(embed); - if (splittedLyrics.length > 1) await util.pagination(lyricsctx, ctx.author, splittedLyrics); - } catch (e) { - if (e.message === "Sorry I couldn't find that song's lyrics") ctx.respond({ embeds: [util.embed().setDescription(`❌ | ${e.message}`)] }); - else ctx.respond(`An error occured: ${e.message}.`); - } - } -}; From 6089035e7fee52f2ce31e7e17f78bd723d736cdb Mon Sep 17 00:00:00 2001 From: Allvaa Date: Sat, 21 Aug 2021 17:10:17 +0700 Subject: [PATCH 23/28] command desc --- src/commands/8d.js | 1 + src/commands/doubletime.js | 1 + src/commands/eval.js | 1 + src/commands/help.js | 1 + src/commands/loop.js | 1 + src/commands/move.js | 1 + src/commands/nightcore.js | 1 + src/commands/nowplaying.js | 1 + src/commands/pause.js | 1 + src/commands/ping.js | 1 + src/commands/play.js | 1 + src/commands/previous.js | 3 ++- src/commands/queue.js | 1 + src/commands/remove.js | 1 + src/commands/resume.js | 1 + src/commands/search.js | 1 + src/commands/seek.js | 1 + src/commands/shuffle.js | 1 + src/commands/skip.js | 1 + src/commands/source.js | 1 + src/commands/stats.js | 1 + src/commands/stop.js | 1 + src/commands/vaporwave.js | 1 + src/commands/volume.js | 1 + 24 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/commands/8d.js b/src/commands/8d.js index 6ca6aad..8486b75 100644 --- a/src/commands/8d.js +++ b/src/commands/8d.js @@ -1,6 +1,7 @@ const util = require("../util"); module.exports = { name: "8d", + description: "8D filter", aliases: ["rotation"], exec: async (ctx) => { const { music } = ctx; diff --git a/src/commands/doubletime.js b/src/commands/doubletime.js index ff9ebfa..695e1a5 100644 --- a/src/commands/doubletime.js +++ b/src/commands/doubletime.js @@ -1,6 +1,7 @@ const util = require("../util"); module.exports = { name: "doubletime", + description: "DT filter", aliases: ["dt"], exec: async (ctx) => { const { music } = ctx; diff --git a/src/commands/eval.js b/src/commands/eval.js index 4fd3b10..9599cd0 100644 --- a/src/commands/eval.js +++ b/src/commands/eval.js @@ -3,6 +3,7 @@ const { isValidURL } = require("../util"); module.exports = { name: "eval", + description: "Evaluate JS code", aliases: ["e"], exec: async (ctx) => { if (ctx.author.id !== process.env.OWNER_ID) return; diff --git a/src/commands/help.js b/src/commands/help.js index 90ef90b..f571a38 100644 --- a/src/commands/help.js +++ b/src/commands/help.js @@ -4,6 +4,7 @@ const unlisted = ["eval"]; module.exports = { name: "help", + description: "List of commands", aliases: ["commands", "?"], exec: (ctx) => { const commands = ctx.client.commands diff --git a/src/commands/loop.js b/src/commands/loop.js index 0738783..0e4c2f1 100644 --- a/src/commands/loop.js +++ b/src/commands/loop.js @@ -6,6 +6,7 @@ const modes = ["None", "Track", "Queue"]; module.exports = { name: "loop", + description: "Show and set loop mode", aliases: ["repeat"], exec: async (ctx) => { const { music } = ctx; diff --git a/src/commands/move.js b/src/commands/move.js index 0c7e2b5..a4025fe 100644 --- a/src/commands/move.js +++ b/src/commands/move.js @@ -2,6 +2,7 @@ const util = require("../util"); module.exports = { name: "move", + description: "Move track position in queue", aliases: ["mv"], exec: async (ctx) => { const { music, args } = ctx; diff --git a/src/commands/nightcore.js b/src/commands/nightcore.js index 7bc9306..4c638f7 100644 --- a/src/commands/nightcore.js +++ b/src/commands/nightcore.js @@ -1,6 +1,7 @@ const util = require("../util"); module.exports = { name: "nightcore", + description: "Nightcore filter", aliases: ["nc"], exec: async (ctx) => { const { music } = ctx; diff --git a/src/commands/nowplaying.js b/src/commands/nowplaying.js index 57ec4cd..6207c2b 100644 --- a/src/commands/nowplaying.js +++ b/src/commands/nowplaying.js @@ -2,6 +2,7 @@ const util = require("../util"); module.exports = { name: "nowplaying", + description: "Check what music is playing", aliases: ["np", "nowplay"], exec: (ctx) => { const { music } = ctx; diff --git a/src/commands/pause.js b/src/commands/pause.js index e3d7104..3a7a0c9 100644 --- a/src/commands/pause.js +++ b/src/commands/pause.js @@ -2,6 +2,7 @@ const util = require("../util"); module.exports = { name: "pause", + description: "Pause the player", exec: (ctx) => { const { music } = ctx; if (!music.player?.track) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); diff --git a/src/commands/ping.js b/src/commands/ping.js index 2c6eca2..4d7700f 100644 --- a/src/commands/ping.js +++ b/src/commands/ping.js @@ -1,5 +1,6 @@ module.exports = { name: "ping", + description: "WS latency", exec: (ctx) => { ctx.respond(`🏓 Pong! \`${ctx.client.ws.ping}ms\``); } diff --git a/src/commands/play.js b/src/commands/play.js index d46744c..6e532ad 100644 --- a/src/commands/play.js +++ b/src/commands/play.js @@ -4,6 +4,7 @@ const getAttachmentURL = ctx => ctx.attachments.first()?.url; module.exports = { name: "play", + description: "Add song to queue and play it", aliases: ["p"], exec: async (ctx) => { const { args, music } = ctx; diff --git a/src/commands/previous.js b/src/commands/previous.js index 2e1da5c..bdda58f 100644 --- a/src/commands/previous.js +++ b/src/commands/previous.js @@ -2,6 +2,7 @@ const util = require("../util"); module.exports = { name: "previous", + description: "Plays previous track", aliases: ["prev"], exec: async (ctx) => { const { music } = ctx; @@ -25,7 +26,7 @@ module.exports = { music.queue.unshift(music.previous); music.skip(); ctx.respond({ - embeds: [util.embed().setDescription("⏮️ | Previous")] + embeds: [util.embed().setDescription("⏮️ | Previous track")] }); ctx.react("⏮️").catch(e => e); } catch (e) { diff --git a/src/commands/queue.js b/src/commands/queue.js index 5c73e98..4f2478d 100644 --- a/src/commands/queue.js +++ b/src/commands/queue.js @@ -3,6 +3,7 @@ const util = require("../util"); module.exports = { name: "queue", + description: "Queued track list", aliases: ["q"], exec: async (ctx) => { const { music } = ctx; diff --git a/src/commands/remove.js b/src/commands/remove.js index 01716d4..87422d8 100644 --- a/src/commands/remove.js +++ b/src/commands/remove.js @@ -2,6 +2,7 @@ const util = require("../util"); module.exports = { name: "remove", + description: "Remove track from queue", aliases: ["rm"], exec: async (ctx) => { const { music, args } = ctx; diff --git a/src/commands/resume.js b/src/commands/resume.js index 67d4833..9753044 100644 --- a/src/commands/resume.js +++ b/src/commands/resume.js @@ -2,6 +2,7 @@ const util = require("../util"); module.exports = { name: "resume", + description: "Resme the player", exec: (ctx) => { const { music } = ctx; if (!music.player?.track) return ctx.respond(util.embed().setDescription("❌| Currently not playing anything.")); diff --git a/src/commands/search.js b/src/commands/search.js index 6217dbb..c3d93b8 100644 --- a/src/commands/search.js +++ b/src/commands/search.js @@ -5,6 +5,7 @@ const emojiNumbers = ["1️⃣","2️⃣","3️⃣","4️⃣","5️⃣","6️⃣ module.exports = { name: "search", + description: "Search song to play", exec: async (ctx) => { const { music, args } = ctx; if (!ctx.member.voice.channel) diff --git a/src/commands/seek.js b/src/commands/seek.js index fbe7d1e..65159a9 100644 --- a/src/commands/seek.js +++ b/src/commands/seek.js @@ -4,6 +4,7 @@ const durationPattern = /^[0-5]?[0-9](:[0-5][0-9]){1,2}$/; module.exports = { name: "seek", + description: "Seeks to specified timestamp", exec: async (ctx) => { const { music, args } = ctx; if (!music.player?.track) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); diff --git a/src/commands/shuffle.js b/src/commands/shuffle.js index 3a0c083..af3b2e8 100644 --- a/src/commands/shuffle.js +++ b/src/commands/shuffle.js @@ -2,6 +2,7 @@ const util = require("../util"); module.exports = { name: "shuffle", + description: "Shuffle the queue", aliases: ["sf"], exec: async (ctx) => { const { music } = ctx; diff --git a/src/commands/skip.js b/src/commands/skip.js index 4ccad7b..34456ef 100644 --- a/src/commands/skip.js +++ b/src/commands/skip.js @@ -2,6 +2,7 @@ const util = require("../util"); module.exports = { name: "skip", + description: "Skip current track", aliases: ["skipto"], exec: (ctx) => { const { music, args } = ctx; diff --git a/src/commands/source.js b/src/commands/source.js index 43d2279..db4f308 100644 --- a/src/commands/source.js +++ b/src/commands/source.js @@ -2,6 +2,7 @@ const util = require("../util"); module.exports = { name: "source", + description: "Bot's source code", aliases: ["src"], exec: (ctx) => { ctx.respond({ embeds: [util.embed().setDescription("✅ | [Here](https://github.com/Allvaa/lavalink-musicbot) is the open source repository this bot uses.")] }); diff --git a/src/commands/stats.js b/src/commands/stats.js index 2cf7a43..93181a7 100644 --- a/src/commands/stats.js +++ b/src/commands/stats.js @@ -3,6 +3,7 @@ const util = require("../util"); module.exports = { name: "stats", + description: "Check nodes stats", exec: (ctx) => { /** @type {import("lavacord").LavalinkNode[]} */ const nodes = [...ctx.client.shoukaku.nodes.values()]; diff --git a/src/commands/stop.js b/src/commands/stop.js index c39fa37..ba15dc9 100644 --- a/src/commands/stop.js +++ b/src/commands/stop.js @@ -2,6 +2,7 @@ const util = require("../util"); module.exports = { name: "stop", + description: "Stop the player", aliases: ["leave", "dc"], exec: (ctx) => { const { music } = ctx; diff --git a/src/commands/vaporwave.js b/src/commands/vaporwave.js index c6a4fc3..a3f9c79 100644 --- a/src/commands/vaporwave.js +++ b/src/commands/vaporwave.js @@ -1,6 +1,7 @@ const util = require("../util"); module.exports = { name: "vaporwave", + description: "Vaporwave filter", aliases: ["vp"], exec: async (ctx) => { const { music } = ctx; diff --git a/src/commands/volume.js b/src/commands/volume.js index 79d16b8..76d1446 100644 --- a/src/commands/volume.js +++ b/src/commands/volume.js @@ -2,6 +2,7 @@ const util = require("../util"); module.exports = { name: "volume", + description: "Check and set volume", aliases: ["vol"], exec: async (ctx) => { const { music, args } = ctx; From 0720ca820a9871f54fef1855cfcc3348c5457e7e Mon Sep 17 00:00:00 2001 From: AbdulRahman <61910010+Abdul1810@users.noreply.github.com> Date: Mon, 23 Aug 2021 14:51:20 +0530 Subject: [PATCH 24/28] Fixed seek (#136) --- src/commands/seek.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/seek.js b/src/commands/seek.js index 65159a9..2bafb23 100644 --- a/src/commands/seek.js +++ b/src/commands/seek.js @@ -27,7 +27,7 @@ module.exports = { return ctx.respond({ embeds: [util.embed().setDescription("❌ | The duration you provide exceeds the duration of the current track.")] }); try { - await music.player.seek(durationMs); + await music.player.seekTo(durationMs); ctx.respond({ embeds: [util.embed().setDescription(`✅ | Seeked to ${util.millisToDuration(durationMs)}.`)] }); } catch (e) { ctx.respond(`An error occured: ${e.message}.`); From 20836285d1b23f2a87aa6c73ee24e6f18df7db78 Mon Sep 17 00:00:00 2001 From: rajamoulimallareddy <68652418+rajamoulimallareddy@users.noreply.github.com> Date: Mon, 23 Aug 2021 15:19:55 +0530 Subject: [PATCH 25/28] fix pagination (#134) --- src/util.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/util.js b/src/util.js index 9cf1a0f..74a4eba 100644 --- a/src/util.js +++ b/src/util.js @@ -69,8 +69,8 @@ class Util { this.pagination(msg, author, contents, currPage); }) - .on("end", () => { - msg.edit({ components: [new MessageActionRow().addComponents(...msg.components[0].components.map(x => x.setDisabled(true)))] }); + .on("end", (_, reason) => { + if (['time', 'user'].includes(reason)) msg.edit({ components: [new MessageActionRow().addComponents(...msg.components[0].components.map(x => x.setDisabled(true)))] }); }); } @@ -114,4 +114,4 @@ class Util { } } -module.exports = Util; \ No newline at end of file +module.exports = Util; From a47e584e887e296c71385b02917ef05cde5e35b7 Mon Sep 17 00:00:00 2001 From: Allvaa Date: Tue, 24 Aug 2021 00:00:44 +0700 Subject: [PATCH 26/28] . --- src/util.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/util.js b/src/util.js index 74a4eba..b0b5b0d 100644 --- a/src/util.js +++ b/src/util.js @@ -54,10 +54,7 @@ class Util { await interaction.deferUpdate(); const emoji = interaction.customId; if (emoji === this.paginationEmojis[0]) currPage--; - if (emoji === this.paginationEmojis[1]) { - await interaction.editReply({ components: [new MessageActionRow().addComponents(...interaction.message.components[0].components.map(x => x.setDisabled(true)))] }); - return; - } + if (emoji === this.paginationEmojis[1]) return collector.stop(); if (emoji === this.paginationEmojis[2]) currPage++; currPage = ((currPage % contents.length) + contents.length) % contents.length; @@ -69,8 +66,13 @@ class Util { this.pagination(msg, author, contents, currPage); }) - .on("end", (_, reason) => { - if (['time', 'user'].includes(reason)) msg.edit({ components: [new MessageActionRow().addComponents(...msg.components[0].components.map(x => x.setDisabled(true)))] }); + .on("end", (collected, reason) => { + if (reason === "time" || collected.first()?.customId === this.paginationEmojis[1]) msg.edit({ + components: [ + new MessageActionRow() + .addComponents(...msg.components[0].components.map(x => x.setDisabled(true))) + ] + }); }); } From 02a32c341668df3e8bb24590aa561f9478b557d2 Mon Sep 17 00:00:00 2001 From: Allvaa Date: Tue, 31 Aug 2021 23:14:11 +0700 Subject: [PATCH 27/28] slash command? --- package.json | 3 ++- scripts/.env.example | 6 +++++ scripts/registerslashcommand.js | 42 ++++++++++++++++++++++++++++++ src/commands/bassboost.js | 21 ++++++++------- src/commands/eval.js | 20 +++++++++++--- src/commands/move.js | 16 +++++++++--- src/commands/play.js | 21 +++++++++------ src/commands/remove.js | 13 ++++++--- src/commands/search.js | 10 +++++-- src/commands/seek.js | 16 ++++++++---- src/commands/volume.js | 9 +++++-- src/listeners/interactionCreate.js | 23 ++++++++++++++++ src/listeners/messageCreate.js | 12 ++++++--- src/structures/CommandContext.js | 20 +++++++------- src/util.js | 18 +++++++++++++ 15 files changed, 202 insertions(+), 48 deletions(-) create mode 100644 scripts/.env.example create mode 100644 scripts/registerslashcommand.js create mode 100644 src/listeners/interactionCreate.js diff --git a/package.json b/package.json index 29e48d0..ebf4f73 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "Music bot that uses Lavalink for its audio player.", "main": "index.js", "scripts": { - "start": "node ." + "start": "node .", + "regscmd": "node scripts/registerslashcommand" }, "repository": { "type": "git", diff --git a/scripts/.env.example b/scripts/.env.example new file mode 100644 index 0000000..9913142 --- /dev/null +++ b/scripts/.env.example @@ -0,0 +1,6 @@ +# the bot token +TOKEN=AAAAAAAAAAAAAAa +# the bot id +ID=000000000000 +# guild id that used to develop the bot +DEV_GUILD=1111111111111111 diff --git a/scripts/registerslashcommand.js b/scripts/registerslashcommand.js new file mode 100644 index 0000000..b4e5729 --- /dev/null +++ b/scripts/registerslashcommand.js @@ -0,0 +1,42 @@ +const { Constants } = require("discord.js"); +const { readdirSync } = require("fs"); +const { resolve, join } = require("path"); +const petitio = require("petitio"); + +require("dotenv").config({ + path: resolve(__dirname, ".env") +}); + +process.argv[2] === "dev" ? console.log(`Running with dev arg. commands will only registered to dev guild (${process.env.DEV_GUILD})`) : console.log("Registering commands globally"); + +const baseURL = "https://discord.com/api/v9"; + +const commandsDir = resolve("src", "commands"); +const commands = readdirSync(commandsDir) + .map(cmdFile => require(resolve(commandsDir, cmdFile))) + .map(({ name, description, options }) => ({ + name, + description, + options: Object.entries(options ?? {}) + .map(([name, { description, type, required }]) => ({ + name, + description, + type: Constants.ApplicationCommandOptionTypes[type], + required + })) + })); + +(async () => { + const res = await petitio(baseURL, "PUT") + .body(commands) + .header("Authorization", `Bot ${process.env.TOKEN}`) + .path(join("applications", process.env.ID, ...(process.argv[2] === "dev" ? ["guilds", process.env.DEV_GUILD] : []), "commands")) + .send(); + + if (!(res.statusCode >= 200 && res.statusCode < 300)) { + console.log(res.json()); + return; + } + + console.log(res.json().map((x, i) => `${++i}. ${x.name} registered`).join("\n")); +})(); diff --git a/src/commands/bassboost.js b/src/commands/bassboost.js index e132bbd..2556e7d 100644 --- a/src/commands/bassboost.js +++ b/src/commands/bassboost.js @@ -3,8 +3,14 @@ module.exports = { name: "bassboost", description: "Set bassboost for player", aliases: ["bb"], + options: { + value: { + description: "Basboost value; 0 to disable", + type: "INTEGER", + } + }, exec: async (ctx) => { - const { music, args } = ctx; + const { music, options } = ctx; if (!music.player?.track) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); @@ -17,16 +23,13 @@ module.exports = { embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] }); - if (!args[0]) { + if (!options.value) { ctx.respond(util.embed().setDescription(`${music.filters.bassboost ? `✅ | BassBoost **${music.bassboost * 100}%**` : "❌ | BassBoost **off**"}`)); - } else if (args[0].toLowerCase() == "off") { - music.setBassboost(0); - ctx.react("✅").catch(e => e); } else { - if (isNaN(args[0])) return ctx.respond(util.embed().setDescription("❌ | Specify a number")); - if (args[0] < 1 || args[0] > 100) return ctx.respond(util.embed().setDescription("❌ | You can only set the bassboost from 1 to 100.")); - music.setBassboost(parseInt(args[0])); - ctx.respond(util.embed().setDescription(`✅ | BassBoost set to **${music.bassboost * 100}%**`)); + if (isNaN(options.value)) return ctx.respond(util.embed().setDescription("❌ | Specify a number")); + if (options.value < 1 || options.value > 100) return ctx.respond(util.embed().setDescription("❌ | You can only set the bassboost from 1 to 100.")); + music.setBassboost(parseInt(options.value)); + ctx.respond(util.embed().setDescription(`✅ | BassBoost set to **${ music.bassboost ? "off" : `${music.bassboost * 100}%` }**`)); } } }; diff --git a/src/commands/eval.js b/src/commands/eval.js index 9599cd0..30a0b47 100644 --- a/src/commands/eval.js +++ b/src/commands/eval.js @@ -5,11 +5,25 @@ module.exports = { name: "eval", description: "Evaluate JS code", aliases: ["e"], + options: { + code: { + description: "Code to eval", + type: "STRING", + required: true + }, + async: { + description: "Async eval", + type: "BOOLEAN", + }, + silent: { + description: "Dont send output", + type: "BOOLEAN", + } + }, exec: async (ctx) => { if (ctx.author.id !== process.env.OWNER_ID) return; - const isAsync = ctx.args.includes("--async"); - const isSilent = ctx.args.includes("--silent"); - const code = ctx.args.filter(e => !/^--(async|silent)$/.test(e)).join(" "); + console.log(ctx.options); + const { code, async: isAsync, silent: isSilent } = ctx.options; try { let result = eval(isAsync ? `(async()=>{${code}})()` : code); let isResultPromise = false; diff --git a/src/commands/move.js b/src/commands/move.js index a4025fe..ebbda13 100644 --- a/src/commands/move.js +++ b/src/commands/move.js @@ -4,10 +4,20 @@ module.exports = { name: "move", description: "Move track position in queue", aliases: ["mv"], + options: { + from: { + description: "Number of the song to move", + type: "INTEGER", + required: true + }, + to: { + description: "The new position", + type: "INTEGER", + required: true + } + }, exec: async (ctx) => { - const { music, args } = ctx; - const from = args[0] ? parseInt(args[0], 10) : null; - const to = args[1] ? parseInt(args[1], 10) : null; + const { music, options: { from, to } } = ctx; if (!music.player?.track) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); diff --git a/src/commands/play.js b/src/commands/play.js index 6e532ad..df68a10 100644 --- a/src/commands/play.js +++ b/src/commands/play.js @@ -1,13 +1,20 @@ const util = require("../util"); -const getAttachmentURL = ctx => ctx.attachments.first()?.url; +//const getAttachmentURL = ctx => ctx.attachments.first()?.url; module.exports = { name: "play", - description: "Add song to queue and play it", + description: "Adds song to queue and play it", aliases: ["p"], + options: { + query: { + description: "Song title/url", + type: "STRING", + required: true + } + }, exec: async (ctx) => { - const { args, music } = ctx; + const { music, options: { query } } = ctx; if (!ctx.member.voice.channel) return ctx.respond({ embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] @@ -28,7 +35,6 @@ module.exports = { embeds: [util.embed().setDescription("❌ | Lavalink node is not connected yet.")] }); - const query = args.join(" ") || getAttachmentURL(ctx.message); if (!query) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Missing args.")] }); @@ -51,10 +57,9 @@ module.exports = { const track = tracks[0]; track.requester = ctx.author; music.queue.push(track); - if (music.player?.track) - ctx.respond({ - embeds: [util.embed().setDescription(`✅ | **${track.info.title}** added to the queue.`)] - }); + ctx.respond({ + embeds: [util.embed().setDescription(`✅ | **${track.info.title}** added to the queue.`)] + }); } if (!music.player) await music.join(ctx.member.voice.channel); if (!music.player.track) await music.start(); diff --git a/src/commands/remove.js b/src/commands/remove.js index 87422d8..504dde1 100644 --- a/src/commands/remove.js +++ b/src/commands/remove.js @@ -4,8 +4,15 @@ module.exports = { name: "remove", description: "Remove track from queue", aliases: ["rm"], + options: { + toremove: { + description: "Number of the song to remove", + type: "INTEGER", + required: true + } + }, exec: async (ctx) => { - const { music, args } = ctx; + const { music, options: { toremove: toRemove } } = ctx; if (!music.player?.track) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); if (!music.queue.length) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Queue is empty.")] }); @@ -14,9 +21,9 @@ module.exports = { if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) return ctx.respond({ embeds: [util.embed().setDescription(`❌ | You must be on ${ctx.guild.me.voice.channel} to use this command.`)] }); - if (!args[0]) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Missing args.")] }); + if (!toRemove) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Missing args.")] }); - let iToRemove = parseInt(args[0], 10); + let iToRemove = parseInt(toRemove, 10); if (isNaN(iToRemove) || iToRemove < 1 || iToRemove > music.queue.length) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Invalid number to remove.")] }); diff --git a/src/commands/search.js b/src/commands/search.js index c3d93b8..cc27781 100644 --- a/src/commands/search.js +++ b/src/commands/search.js @@ -6,8 +6,15 @@ const emojiNumbers = ["1️⃣","2️⃣","3️⃣","4️⃣","5️⃣","6️⃣ module.exports = { name: "search", description: "Search song to play", + options: { + query: { + description: "Song title", + type: "STRING", + required: true + } + }, exec: async (ctx) => { - const { music, args } = ctx; + const { music, options: { query } } = ctx; if (!ctx.member.voice.channel) return ctx.respond({ embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] }); if (ctx.guild.me.voice.channel && !ctx.guild.me.voice.channel.equals(ctx.member.voice.channel)) @@ -20,7 +27,6 @@ module.exports = { if (music.node?.state !== 1) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Lavalink node is not connected yet.")] }); - const query = args.join(" "); if (!query) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Missing args.")] }); try { diff --git a/src/commands/seek.js b/src/commands/seek.js index 2bafb23..06801d7 100644 --- a/src/commands/seek.js +++ b/src/commands/seek.js @@ -5,8 +5,15 @@ const durationPattern = /^[0-5]?[0-9](:[0-5][0-9]){1,2}$/; module.exports = { name: "seek", description: "Seeks to specified timestamp", + options: { + toduration: { + description: "Duration with format mm:ss", + type: "INTEGER", + required: true + } + }, exec: async (ctx) => { - const { music, args } = ctx; + const { music, options: { toduration: toDuration } } = ctx; if (!music.player?.track) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); if (!ctx.member.voice.channel) return ctx.respond({ embeds: [util.embed().setDescription("❌ | You must be on a voice channel.")] }); @@ -16,13 +23,12 @@ module.exports = { if (!music.current.info.isSeekable) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Current track isn't seekable.")] }); - const duration = args[0]; - if (!duration) + if (!toDuration) return ctx.respond({ embeds: [util.embed().setDescription("❌ | You must provide duration to seek. Valid duration e.g. `1:34`.")] }); - if (!durationPattern.test(duration)) + if (!durationPattern.test(toDuration)) return ctx.respond({ embeds: [util.embed().setDescription("❌ | You provided an invalid duration. Valid duration e.g. `1:34`.")] }); - const durationMs = util.durationToMillis(duration); + const durationMs = util.durationToMillis(toDuration); if (durationMs > music.current.info.length) return ctx.respond({ embeds: [util.embed().setDescription("❌ | The duration you provide exceeds the duration of the current track.")] }); diff --git a/src/commands/volume.js b/src/commands/volume.js index 76d1446..52fdb74 100644 --- a/src/commands/volume.js +++ b/src/commands/volume.js @@ -4,9 +4,14 @@ module.exports = { name: "volume", description: "Check and set volume", aliases: ["vol"], + options: { + newvolume: { + description: "New volume to set", + type: "INTEGER", + } + }, exec: async (ctx) => { - const { music, args } = ctx; - const newVolume = parseInt(args[0], 10); + const { music, options: { newvolume: newVolume } } = ctx; if (!music.player?.track) return ctx.respond({ embeds: [util.embed().setDescription("❌ | Currently not playing anything.")] }); try { if (isNaN(newVolume)) { diff --git a/src/listeners/interactionCreate.js b/src/listeners/interactionCreate.js new file mode 100644 index 0000000..2207a26 --- /dev/null +++ b/src/listeners/interactionCreate.js @@ -0,0 +1,23 @@ +const CommandContext = require("../structures/CommandContext"); +const Util = require("../util"); + +module.exports = { + name: "interactionCreate", + exec: async (client, interaction) => { + if (!interaction.isCommand()) return; + const command = client.commands.get(interaction.commandName); + + if (command) { + const options = {}; + for (const name in command.options ?? {}) { + options[name] = Util.getOptionValue(interaction.options.data.find(x => x.name === name)); + } + try { + await interaction.deferReply(); + await command.exec(new CommandContext(command, interaction, options)); + } catch (e) { + console.error(e); + } + } + } +}; diff --git a/src/listeners/messageCreate.js b/src/listeners/messageCreate.js index 60eceda..8c8e52c 100644 --- a/src/listeners/messageCreate.js +++ b/src/listeners/messageCreate.js @@ -1,4 +1,5 @@ const CommandContext = require("../structures/CommandContext"); +const Util = require("../util"); module.exports = { name: "messageCreate", @@ -9,12 +10,17 @@ module.exports = { const prefix = msg.content.toLowerCase().startsWith(client.prefix) ? client.prefix : `<@!${client.user.id}>`; if (!msg.content.toLowerCase().startsWith(prefix)) return; - const args = msg.content.slice(prefix.length).trim().split(/ +/g); - const commandName = args.shift().toLowerCase(); + let [commandName, ...args] = msg.content.slice(prefix.length).trim().split(/ +/g); + args = args.join(" ").trim().split(/; +/g); const command = client.commands.get(commandName) || client.commands.find(c => c.aliases && c.aliases.includes(commandName)); + if (command) { + const options = {}; + for (const [name, { type }] of Object.entries(command.options ?? {})) { + options[name] = Util.parseArg(msg.guild, type, args.shift()); + } try { - await command.exec(new CommandContext(command, msg, args)); + await command.exec(new CommandContext(command, msg, options)); } catch (e) { console.error(e); } diff --git a/src/structures/CommandContext.js b/src/structures/CommandContext.js index d9a0c92..838add4 100644 --- a/src/structures/CommandContext.js +++ b/src/structures/CommandContext.js @@ -1,30 +1,31 @@ +const { Message, CommandInteraction } = require("discord.js"); const MusicHandler = require("./MusicHandler"); module.exports = class CommandContext { - constructor(command, message, args) { + constructor(command, from, options) { this.command = command; - this.message = message; - this.args = args; + this.from = from; + this.options = options; } get client() { - return this.message.client; + return this.from.client; } get guild() { - return this.message.guild; + return this.from.guild; } get channel() { - return this.message.channel; + return this.from.channel; } get member() { - return this.message.member; + return this.from.member; } get author() { - return this.message.author; + return this.member.user; } get music() { @@ -37,6 +38,7 @@ module.exports = class CommandContext { } respond(opt) { - return this.message.reply(opt); + if (this.from instanceof Message) return this.from.reply(opt); + else if (this.from instanceof CommandInteraction) return this.from.editReply(opt); } }; diff --git a/src/util.js b/src/util.js index b0b5b0d..3e98b9c 100644 --- a/src/util.js +++ b/src/util.js @@ -114,6 +114,24 @@ class Util { return null; } } + + static getOptionValue(option) { + if (["STRING", "INTEGER", "BOOLEAN", "NUMBER"].includes(option.type)) return option.value; + else if (option.type === "USER") return option.user ?? null; + else if (option.type === "MEMBER") return option.member ?? null; + else if (option.type === "ROLE") return option.role ?? null; + else return null; + } + + static parseArg(guild, type, input) { + if (type === "STRING") return input; + else if (type === "BOOLEAN") return input === "true" ? true : input === "false" ? false : null; + else if (["INTEGER", "NUMBER"].includes(type)) return parseInt(input, 10); + else if (type === "USER") return guild.client.users.resolve(input) ?? null; + else if (type === "MEMBER") return guild.members.resolve(input) ?? null; + else if (type === "ROLE") return guild.roles.resolve(input) ?? null; + else return null; + } } module.exports = Util; From db6316f4f4ad20c0d13e673bafe6e896dc5ad037 Mon Sep 17 00:00:00 2001 From: rajamoulimallareddy <68652418+rajamoulimallareddy@users.noreply.github.com> Date: Wed, 1 Sep 2021 09:51:30 +0530 Subject: [PATCH 28/28] Update util.js --- src/util.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/util.js b/src/util.js index 3e98b9c..6e05719 100644 --- a/src/util.js +++ b/src/util.js @@ -40,37 +40,37 @@ class Util { return ["◀", "⛔", "▶"]; } - static pagination(msg, author, contents, currPage = 0) { + static pagination(interaction, member, contents, currPage = 0) { /** @type {import("discord.js").InteractionCollector} */ - const collector = msg.createMessageComponentCollector({ - filter: interaction => this.paginationEmojis.includes(interaction.customId) && interaction.user.id === author.id, + const collector = interaction.channel.createMessageComponentCollector({ + filter: interaction => this.paginationEmojis.includes(interaction.customId) && interaction.user.id === member.id, componentType: "BUTTON", max: 1, time: 15000 }); collector - .on("collect", async (interaction) => { - await interaction.deferUpdate(); - const emoji = interaction.customId; + .on("collect", async (i) => { + await i.deferUpdate(); + const emoji = i.customId; if (emoji === this.paginationEmojis[0]) currPage--; if (emoji === this.paginationEmojis[1]) return collector.stop(); if (emoji === this.paginationEmojis[2]) currPage++; currPage = ((currPage % contents.length) + contents.length) % contents.length; - const embed = interaction.message.embeds[0] + const embed = i.message.embeds[0] .setDescription(contents[currPage]) .setFooter(`Page ${currPage + 1} of ${contents.length}.`); - await interaction.editReply({ embeds: [embed] }); + await i.editReply({ embeds: [embed] }); - this.pagination(msg, author, contents, currPage); + this.pagination(interaction, member, contents, currPage); }) .on("end", (collected, reason) => { - if (reason === "time" || collected.first()?.customId === this.paginationEmojis[1]) msg.edit({ + if (reason === "time" || collected.first()?.customId === this.paginationEmojis[1]) interaction.edit({ components: [ new MessageActionRow() - .addComponents(...msg.components[0].components.map(x => x.setDisabled(true))) + .addComponents(...interaction.components[0].components.map(x => x.setDisabled(true))) ] }); });