diff --git a/.gitignore b/.gitignore index 4744b6c..0b0ad31 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Logs logs *.log +*.log.gz npm-debug.log* yarn-debug.log* yarn-error.log* diff --git a/PRIVACY.md b/PRIVACY.md index c183b99..ea64d02 100644 --- a/PRIVACY.md +++ b/PRIVACY.md @@ -7,7 +7,6 @@ esmBot uses the following user-related info: + User IDs (needed for many reasons such as the tag commands and replying to users) + Avatars (needed for some embeds and the avatar command) + Usernames (for embeds and avatar command) -+ Discriminators (userinfo command) + Permissions (for checking if a user has perms to run some commands) + Whether the user is a bot (needed to prevent other bots from running commands) @@ -17,8 +16,6 @@ esmBot uses the following guild-related info: + Guild IDs (for guild-specific settings) + Guild channel IDs (for getting where to send a message, storing disabled channels) + List of members (for getting permissions and obtaining user objects by ID) -+ Guild names (for embeds) -+ Icons (embeds) Out of these, **only guild and channel IDs are stored in the database** for configuration info and storing disabled channels/commands, prefixes, and tags. diff --git a/README.md b/README.md index 2a64608..9da0b28 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![esmBot Support](https://discordapp.com/api/guilds/592399417676529688/embed.png)](https://discord.gg/esmbot) ![GitHub license](https://img.shields.io/github/license/esmBot/esmBot.svg) -esmBot is an easily-extendable, multipurpose, and entertainment-focused Discord bot made using [Eris](https://abal.moe/Eris/) with image, music, and utility commands, alongside many others. +esmBot is an easily-extendable, multipurpose, and entertainment-focused Discord bot made using [Oceanic](https://oceanic.ws) with image, music, and utility commands, alongside many others. [![Top.gg](https://top.gg/api/widget/429305856241172480.svg)](https://top.gg/bot/429305856241172480) diff --git a/app.js b/app.js index 51fa68f..4316698 100644 --- a/app.js +++ b/app.js @@ -21,7 +21,7 @@ import { generateList, createPage } from "./utils/help.js"; import { reloadImageConnections } from "./utils/image.js"; // main services -import Eris from "eris"; +import { Client } from "oceanic.js"; import pm2 from "pm2"; // some utils import { promises, readFileSync } from "fs"; @@ -71,13 +71,13 @@ esmBot ${esmBotVersion} (${process.env.GIT_REV}) }); const intents = [ - "guildVoiceStates", - "directMessages" + "GUILD_VOICE_STATES", + "DIRECT_MESSAGES" ]; if (types.classic) { - intents.push("guilds"); - intents.push("guildMessages"); - intents.push("messageContent"); + intents.push("GUILDS"); + intents.push("GUILD_MESSAGES"); + intents.push("MESSAGE_CONTENT"); } // PM2-specific handling @@ -92,7 +92,7 @@ if (process.env.PM2_USAGE) { switch (packet.data?.type) { case "reload": var path = paths.get(packet.data.message); - await load(bot, path, await checkStatus(), true); + await load(client, path, await checkStatus(), true); break; case "soundreload": var soundStatus = await checkStatus(); @@ -104,10 +104,10 @@ if (process.env.PM2_USAGE) { await reloadImageConnections(); break; case "broadcastStart": - startBroadcast(bot, packet.data.message); + startBroadcast(client, packet.data.message); break; case "broadcastEnd": - endBroadcast(bot); + endBroadcast(client); break; case "serverCounts": pm2.sendDataToProcessId(0, { @@ -115,8 +115,8 @@ if (process.env.PM2_USAGE) { type: "process:msg", data: { type: "serverCounts", - guilds: bot.guilds.size, - shards: bot.shards.size + guilds: client.guilds.size, + shards: client.shards.size }, topic: true }, (err) => { @@ -142,35 +142,46 @@ if (!types.classic && !types.application) { process.exit(1); } -const bot = new Eris(`Bot ${process.env.TOKEN}`, { +const client = new Client({ + auth: `Bot ${process.env.TOKEN}`, allowedMentions: { everyone: false, roles: false, users: true, repliedUser: true }, - restMode: true, - maxShards: "auto", - messageLimit: 50, - intents, - connectionTimeout: 30000 + gateway: { + concurrency: "auto", + maxShards: "auto", + presence: { + status: "dnd", + activities: [{ + type: "GAME", + name: "Starting esmBot..." + }] + }, + intents + }, + collectionLimits: { + messages: 50 + } }); -bot.once("ready", async () => { +client.once("ready", async () => { // register commands and their info const soundStatus = await checkStatus(); logger.log("info", "Attempting to load commands..."); for await (const commandFile of getFiles(resolve(dirname(fileURLToPath(import.meta.url)), "./commands/"))) { logger.log("main", `Loading command from ${commandFile}...`); try { - await load(bot, commandFile, soundStatus); + await load(client, commandFile, soundStatus); } catch (e) { logger.error(`Failed to register command from ${commandFile}: ${e}`); } } if (types.application) { try { - await send(bot); + await send(client); } catch (e) { logger.log("error", e); logger.log("error", "Failed to send command data to Discord, slash/message commands may be unavailable."); @@ -192,7 +203,7 @@ bot.once("ready", async () => { continue; } const { default: event } = await import(file); - bot.on(eventName, event.bind(null, bot)); + client.on(eventName, event.bind(null, client)); } logger.log("info", "Finished loading events."); @@ -204,10 +215,10 @@ bot.once("ready", async () => { } // connect to lavalink - if (!status && !connected) connect(bot); + if (!status && !connected) connect(client); - checkBroadcast(bot); - activityChanger(bot); + checkBroadcast(client); + activityChanger(client); logger.log("info", "Started esmBot."); }); @@ -224,4 +235,4 @@ async function* getFiles(dir) { } } -bot.connect(); \ No newline at end of file +client.connect(); \ No newline at end of file diff --git a/classes/command.js b/classes/command.js index f5703fa..3fe3fa2 100644 --- a/classes/command.js +++ b/classes/command.js @@ -8,15 +8,16 @@ class Command { if (options.type === "classic") { this.message = options.message; this.channel = options.message.channel; + this.guild = options.message.guild; this.author = options.message.author; this.member = options.message.member; this.content = options.content; this.options = options.specialArgs; this.reference = { messageReference: { - channelID: this.channel.id, + channelID: this.message.channelID, messageID: this.message.id, - guildID: this.channel.guild ? this.channel.guild.id : undefined, + guildID: this.message.guildID ?? undefined, failIfNotExists: false }, allowedMentions: { @@ -27,13 +28,14 @@ class Command { this.interaction = options.interaction; this.args = []; this.channel = options.interaction.channel; + this.guild = options.interaction.guild; this.author = this.member = options.interaction.guildID ? options.interaction.member : options.interaction.user; if (options.interaction.data.options) { - this.options = options.interaction.data.options.reduce((obj, item) => { + this.options = options.interaction.data.options.raw.reduce((obj, item) => { obj[item.name] = item.value; return obj; }, {}); - this.optionsArray = options.interaction.data.options; + this.optionsArray = options.interaction.data.options.raw; } else { this.options = {}; } @@ -46,9 +48,10 @@ class Command { async acknowledge() { if (this.type === "classic") { - await this.client.sendChannelTyping(this.channel.id); + const channel = this.channel ?? await this.client.rest.channels.get(this.message.channelID); + await channel.sendTyping(); } else if (!this.interaction.acknowledged) { - await this.interaction.acknowledge(); + await this.interaction.defer(); } } diff --git a/classes/imageCommand.js b/classes/imageCommand.js index 632e62f..cab4e84 100644 --- a/classes/imageCommand.js +++ b/classes/imageCommand.js @@ -73,7 +73,7 @@ class ImageCommand extends Command { let status; if (imageParams.params.type === "image/gif" && this.type === "classic") { - status = await this.processMessage(this.message); + status = await this.processMessage(this.message.channel ?? await this.client.rest.channels.get(this.message.channelID)); } try { @@ -83,7 +83,7 @@ class ImageCommand extends Command { } this.success = true; return { - file: buffer, + contents: buffer, name: `${this.constructor.command}.${type}` }; } catch (e) { @@ -92,14 +92,17 @@ class ImageCommand extends Command { if (e === "No available servers") return "I can't seem to contact the image servers, they might be down or still trying to start up. Please wait a little bit."; throw e; } finally { - if (status && (status.channel.messages ? status.channel.messages.has(status.id) : await this.client.getMessage(status.channel.id, status.id).catch(() => undefined))) await status.delete(); + const statusChannel = status.channel ?? await this.client.rest.channels.get(status.channelID); + if (status && (statusChannel.messages ? statusChannel.messages.has(status.id) : await this.client.getMessage(statusChannel.id, status.id).catch(() => undefined))) await status.delete(); runningCommands.delete(this.author.id); } } - processMessage(message) { - return this.client.createMessage(message.channel.id, `${random(emotes) || process.env.PROCESSING_EMOJI || ""} Processing... This might take a while`); + processMessage(channel) { + return channel.createMessage({ + content: `${random(emotes) || process.env.PROCESSING_EMOJI || ""} Processing... This might take a while` + }); } static init() { diff --git a/classes/musicCommand.js b/classes/musicCommand.js index ea071ae..6ff3456 100644 --- a/classes/musicCommand.js +++ b/classes/musicCommand.js @@ -4,9 +4,9 @@ import { players, queues } from "../utils/soundplayer.js"; class MusicCommand extends Command { constructor(client, options) { super(client, options); - if (this.channel.guild) { - this.connection = players.get(this.channel.guild.id); - this.queue = queues.get(this.channel.guild.id); + if (this.guild) { + this.connection = players.get(this.guild.id); + this.queue = queues.get(this.guild.id); } } diff --git a/commands/general/avatar.js b/commands/general/avatar.js index a39b99f..9bd1c78 100644 --- a/commands/general/avatar.js +++ b/commands/general/avatar.js @@ -26,8 +26,8 @@ class AvatarCommand extends Command { } else { return self.dynamicAvatarURL(null, 512); } - } else if (this.args.join(" ") !== "" && this.channel.guild) { - const searched = await this.channel.guild.searchMembers(this.args.join(" ")); + } else if (this.args.join(" ") !== "" && this.guild) { + const searched = await this.guild.searchMembers(this.args.join(" ")); if (searched.length === 0) return self.dynamicAvatarURL(null, 512); const user = await this.client.getRESTUser(searched[0].user.id); return user ? user.dynamicAvatarURL(null, 512) : self.dynamicAvatarURL(null, 512); diff --git a/commands/general/banner.js b/commands/general/banner.js index 49fc46e..1280689 100644 --- a/commands/general/banner.js +++ b/commands/general/banner.js @@ -26,8 +26,8 @@ class BannerCommand extends Command { } else { return "This user doesn't have a banner!"; } - } else if (this.args.join(" ") !== "" && this.channel.guild) { - const searched = await this.channel.guild.searchMembers(this.args.join(" ")); + } else if (this.args.join(" ") !== "" && this.guild) { + const searched = await this.guild.searchMembers(this.args.join(" ")); if (searched.length === 0) return self.dynamicBannerURL(null, 512) ?? "This user doesn't have a banner!"; const user = await this.client.getRESTUser(searched[0].user.id); return user.dynamicBannerURL(null, 512) ?? (self.dynamicBannerURL(null, 512) ?? "This user doesn't have a banner!"); diff --git a/commands/general/channel.js b/commands/general/channel.js index f870ca0..a8d0187 100644 --- a/commands/general/channel.js +++ b/commands/general/channel.js @@ -4,20 +4,20 @@ import Command from "../../classes/command.js"; class ChannelCommand extends Command { async run() { this.success = false; - if (!this.channel.guild) return "This command only works in servers!"; + if (!this.guild) return "This command only works in servers!"; const owners = process.env.OWNER.split(","); if (!this.member.permissions.has("administrator") && !owners.includes(this.member.id)) return "You need to be an administrator to enable/disable me!"; if (this.args.length === 0) return "You need to provide whether I should be enabled or disabled in this channel!"; if (this.args[0] !== "disable" && this.args[0] !== "enable") return "That's not a valid option!"; - const guildDB = await db.getGuild(this.channel.guild.id); + const guildDB = await db.getGuild(this.guild.id); if (this.args[0].toLowerCase() === "disable") { let channel; if (this.args[1]?.match(/^?$/) && this.args[1] >= 21154535154122752n) { const id = this.args[1].replaceAll("@", "").replaceAll("#", "").replaceAll("!", "").replaceAll("&", "").replaceAll("<", "").replaceAll(">", ""); if (guildDB.disabled.includes(id)) return "I'm already disabled in this channel!"; - channel = this.channel.guild.channels.get(id); + channel = this.guild.channels.get(id); } else { if (guildDB.disabled.includes(this.channel.id)) return "I'm already disabled in this channel!"; channel = this.channel; @@ -31,7 +31,7 @@ class ChannelCommand extends Command { if (this.args[1]?.match(/^?$/) && this.args[1] >= 21154535154122752n) { const id = this.args[1].replaceAll("@", "").replaceAll("#", "").replaceAll("!", "").replaceAll("&", "").replaceAll("<", "").replaceAll(">", ""); if (!guildDB.disabled.includes(id)) return "I'm not disabled in that channel!"; - channel = this.channel.guild.channels.get(id); + channel = this.guild.channels.get(id); } else { if (!guildDB.disabled.includes(this.channel.id)) return "I'm not disabled in this channel!"; channel = this.channel; diff --git a/commands/general/command.js b/commands/general/command.js index d3b02c8..139f267 100644 --- a/commands/general/command.js +++ b/commands/general/command.js @@ -5,7 +5,7 @@ import * as collections from "../../utils/collections.js"; class CommandCommand extends Command { async run() { this.success = false; - if (!this.channel.guild) return "This command only works in servers!"; + if (!this.guild) return "This command only works in servers!"; const owners = process.env.OWNER.split(","); if (!this.member.permissions.has("administrator") && !owners.includes(this.member.id)) return "You need to be an administrator to enable/disable me!"; if (this.args.length === 0) return "You need to provide whether you want to enable/disable a command!"; @@ -13,7 +13,7 @@ class CommandCommand extends Command { if (!this.args[1]) return "You need to provide what command to enable/disable!"; if (!collections.commands.has(this.args[1].toLowerCase()) && !collections.aliases.has(this.args[1].toLowerCase())) return "That isn't a command!"; - const guildDB = await db.getGuild(this.channel.guild.id); + const guildDB = await db.getGuild(this.guild.id); const disabled = guildDB.disabled_commands ?? guildDB.disabledCommands; const command = collections.aliases.get(this.args[1].toLowerCase()) ?? this.args[1].toLowerCase(); @@ -21,13 +21,13 @@ class CommandCommand extends Command { if (command === "command") return "You can't disable that command!"; if (disabled?.includes(command)) return "That command is already disabled!"; - await db.disableCommand(this.channel.guild.id, command); + await db.disableCommand(this.guild.id, command); this.success = true; return `The command has been disabled. To re-enable it, just run \`${guildDB.prefix}command enable ${command}\`.`; } else if (this.args[0].toLowerCase() === "enable") { if (!disabled?.includes(command)) return "That command isn't disabled!"; - await db.enableCommand(this.channel.guild.id, command); + await db.enableCommand(this.guild.id, command); this.success = true; return `The command \`${command}\` has been re-enabled.`; } diff --git a/commands/general/count.js b/commands/general/count.js index 79266e6..1399253 100644 --- a/commands/general/count.js +++ b/commands/general/count.js @@ -4,7 +4,7 @@ import Command from "../../classes/command.js"; class CountCommand extends Command { async run() { - if (this.channel.guild && !this.channel.permissionsOf(this.client.user.id).has("embedLinks")) { + if (this.guild && !this.channel.permissionsOf(this.client.user.id.toString()).has("EMBED_LINKS")) { this.success = false; return "I don't have the `Embed Links` permission!"; } @@ -37,7 +37,7 @@ class CountCommand extends Command { description: value.join("\n"), author: { name: this.author.username, - icon_url: this.author.avatarURL + iconURL: this.author.avatarURL() } }] }); diff --git a/commands/general/help.js b/commands/general/help.js index 27abeea..b4a6c74 100644 --- a/commands/general/help.js +++ b/commands/general/help.js @@ -1,4 +1,4 @@ -import { Constants } from "eris"; +import { Constants } from "oceanic.js"; import database from "../../utils/database.js"; import * as collections from "../../utils/collections.js"; import { random } from "../../utils/misc.js"; @@ -10,7 +10,7 @@ const argTypes = Object.keys(Constants.ApplicationCommandOptionTypes); class HelpCommand extends Command { async run() { - const { prefix } = this.channel.guild ? await database.getGuild(this.channel.guild.id) : "N/A"; + const { prefix } = this.guild ? await database.getGuild(this.guild.id) : "N/A"; if (this.args.length !== 0 && (collections.commands.has(this.args[0].toLowerCase()) || collections.aliases.has(this.args[0].toLowerCase()))) { const command = collections.aliases.get(this.args[0].toLowerCase()) ?? this.args[0].toLowerCase(); const info = collections.info.get(command); @@ -19,9 +19,9 @@ class HelpCommand extends Command { embeds: [{ author: { name: "esmBot Help", - icon_url: this.client.user.avatarURL + iconURL: this.client.user.avatarURL() }, - title: `${this.channel.guild ? prefix : ""}${command}`, + title: `${this.guild ? prefix : ""}${command}`, url: "https://projectlounge.pw/esmBot/help.html", description: command === "tags" ? "The main tags command. Check the help page for more info: https://projectlounge.pw/esmBot/help.html" : info.description, color: 16711680, @@ -54,12 +54,12 @@ class HelpCommand extends Command { } return embed; } else { - if (this.channel.guild && !this.channel.permissionsOf(this.client.user.id).has("embedLinks")) { + if (this.guild && !this.channel.permissionsOf(this.client.user.id).has("EMBED_LINKS")) { this.success = false; return "I don't have the `Embed Links` permission!"; } const pages = []; - if (help.categories === help.categoryTemplate && !help.generated) await help.generateList(); + if (help.categories === help.categoryTemplate && !help.generated) help.generateList(); for (const category of Object.keys(help.categories)) { const splitPages = help.categories[category].map((item, index) => { return index % 15 === 0 ? help.categories[category].slice(index, index + 15) : null; @@ -83,7 +83,7 @@ class HelpCommand extends Command { embeds: [{ author: { name: "esmBot Help", - icon_url: this.client.user.avatarURL + iconURL: this.client.user.avatarURL() }, title: value.title, description: value.page.join("\n"), @@ -93,7 +93,7 @@ class HelpCommand extends Command { }, fields: [{ name: "Prefix", - value: this.channel.guild ? prefix : "N/A" + value: this.guild ? prefix : "N/A" }, { name: "Tip", value: random(tips) @@ -101,7 +101,7 @@ class HelpCommand extends Command { }] }); } - return paginator(this.client, { type: this.type, message: this.message, interaction: this.interaction, channel: this.channel, author: this.author }, embeds); + return paginator(this.client, { type: this.type, message: this.message, interaction: this.interaction, author: this.author }, embeds); } } diff --git a/commands/general/image.js b/commands/general/image.js index c030071..b3358c2 100644 --- a/commands/general/image.js +++ b/commands/general/image.js @@ -8,7 +8,7 @@ import Command from "../../classes/command.js"; class ImageSearchCommand extends Command { async run() { this.success = false; - if (this.channel.guild && !this.channel.permissionsOf(this.client.user.id).has("embedLinks")) return "I don't have the `Embed Links` permission!"; + if (this.channel && !this.channel.permissionsOf(this.client.user.id).has("EMBED_LINKS")) return "I don't have the `Embed Links` permission!"; const query = this.options.query ?? this.args.join(" "); if (!query || !query.trim()) return "You need to provide something to search for!"; await this.acknowledge(); @@ -30,7 +30,7 @@ class ImageSearchCommand extends Command { }, author: { name: this.author.username, - icon_url: this.author.avatarURL + iconURL: this.author.avatarURL() } }] }); diff --git a/commands/general/imagestats.js b/commands/general/imagestats.js index 74e15b2..591726b 100644 --- a/commands/general/imagestats.js +++ b/commands/general/imagestats.js @@ -8,7 +8,7 @@ class ImageStatsCommand extends Command { embeds: [{ "author": { "name": "esmBot Image Statistics", - "icon_url": this.client.user.avatarURL + "iconURL": this.client.user.avatarURL }, "color": 16711680, "description": `The bot is currently connected to ${connections.size} image server(s).`, diff --git a/commands/general/info.js b/commands/general/info.js index 1b60fc4..c13ea1f 100644 --- a/commands/general/info.js +++ b/commands/general/info.js @@ -5,7 +5,8 @@ import { getServers } from "../../utils/misc.js"; class InfoCommand extends Command { async run() { - const owner = await this.client.getRESTUser(process.env.OWNER.split(",")[0]); + let owner = this.client.users.get(process.env.OWNER.split(",")[0]); + if (!owner) owner = await this.client.getRESTUser(process.env.OWNER.split(",")[0]); const servers = await getServers(this.client); await this.acknowledge(); return { @@ -13,7 +14,7 @@ class InfoCommand extends Command { color: 16711680, author: { name: "esmBot Info/Credits", - icon_url: this.client.user.avatarURL + iconURL: this.client.user.avatarURL() }, description: `This instance is managed by **${owner.username}#${owner.discriminator}**.`, fields: [{ diff --git a/commands/general/ping.js b/commands/general/ping.js index 5e40723..325c182 100644 --- a/commands/general/ping.js +++ b/commands/general/ping.js @@ -3,14 +3,20 @@ import Command from "../../classes/command.js"; class PingCommand extends Command { async run() { if (this.type === "classic") { - const pingMessage = await this.client.createMessage(this.channel.id, Object.assign({ + const pingMessage = await this.client.rest.channels.createMessage(this.message.channelID, Object.assign({ content: "🏓 Ping?" }, this.reference)); - await pingMessage.edit(`🏓 Pong!\n\`\`\`\nLatency: ${pingMessage.timestamp - this.message.timestamp}ms${this.channel.guild ? `\nShard Latency: ${Math.round(this.client.shards.get(this.client.guildShardMap[this.channel.guild.id]).latency)}ms` : ""}\n\`\`\``); + await pingMessage.edit({ + content: `🏓 Pong!\n\`\`\`\nLatency: ${pingMessage.timestamp - this.message.timestamp}ms${this.message.guildID ? `\nShard Latency: ${Math.round(this.client.shards.get(this.client.guildShardMap[this.message.guildID]).latency)}ms` : ""}\n\`\`\`` + }); } else { - await this.interaction.createMessage("🏓 Ping?"); - const pingMessage = await this.interaction.getOriginalMessage(); - await this.interaction.editOriginalMessage(`🏓 Pong!\n\`\`\`\nLatency: ${pingMessage.timestamp - Math.floor((this.interaction.id / 4194304) + 1420070400000)}ms${this.interaction.guildID ? `\nShard Latency: ${Math.round(this.client.shards.get(this.client.guildShardMap[this.interaction.guildID]).latency)}ms` : ""}\n\`\`\``); + await this.interaction.createMessage({ + content: "🏓 Ping?" + }); + const pingMessage = await this.interaction.getOriginal(); + await this.interaction.editOriginal({ + content: `🏓 Pong!\n\`\`\`\nLatency: ${pingMessage.timestamp - Math.floor((this.interaction.id / 4194304) + 1420070400000)}ms${this.interaction.guildID ? `\nShard Latency: ${Math.round(this.client.shards.get(this.client.guildShardMap[this.interaction.guildID]).latency)}ms` : ""}\n\`\`\`` + }); } } diff --git a/commands/general/prefix.js b/commands/general/prefix.js index cbcebcd..2e701de 100644 --- a/commands/general/prefix.js +++ b/commands/general/prefix.js @@ -3,15 +3,15 @@ import Command from "../../classes/command.js"; class PrefixCommand extends Command { async run() { - if (!this.channel.guild) return `The current prefix is \`${process.env.PREFIX}\``; - const guild = await database.getGuild(this.channel.guild.id); + if (!this.guild) return `The current prefix is \`${process.env.PREFIX}\`.`; + const guild = await database.getGuild(this.guild.id); if (this.args.length !== 0) { const owners = process.env.OWNER.split(","); - if (!this.member.permissions.has("administrator") && !owners.includes(this.member.id)) { + if (!this.member.permissions.has("ADMINISTRATOR") && !owners.includes(this.member.id)) { this.success = false; return "You need to be an administrator to change the bot prefix!"; } - await database.setPrefix(this.args[0], this.channel.guild); + await database.setPrefix(this.args[0], this.guild); return `The prefix has been changed to ${this.args[0]}.`; } else { return `The current prefix is \`${guild.prefix}\`.`; diff --git a/commands/general/qrcreate.js b/commands/general/qrcreate.js index 3c0193c..79123d8 100644 --- a/commands/general/qrcreate.js +++ b/commands/general/qrcreate.js @@ -13,7 +13,7 @@ class QrCreateCommand extends Command { qrcode.toFileStream(writable, this.content, { margin: 1 }); const file = await this.streamToBuf(writable); return { - file: file, + contents: file, name: "qr.png" }; } diff --git a/commands/general/restart.js b/commands/general/restart.js index 6714b3e..5f4c496 100644 --- a/commands/general/restart.js +++ b/commands/general/restart.js @@ -7,7 +7,7 @@ class RestartCommand extends Command { this.success = false; return "Only the bot owner can restart me!"; } - await this.client.createMessage(this.channel.id, Object.assign({ + await this.message.channel.createMessage(Object.assign({ content: "esmBot is restarting." }, this.reference)); process.exit(1); diff --git a/commands/general/serverinfo.js b/commands/general/serverinfo.js deleted file mode 100644 index a420b50..0000000 --- a/commands/general/serverinfo.js +++ /dev/null @@ -1,58 +0,0 @@ -import Command from "../../classes/command.js"; - -class ServerInfoCommand extends Command { - async run() { - if (!this.channel.guild) { - this.success = false; - return "This command only works in servers!"; - } - const owner = await this.channel.guild.members.get(this.channel.guild.ownerID); - return { - embeds: [{ - title: this.channel.guild.name, - thumbnail: { - url: this.channel.guild.iconURL - }, - image: { - url: this.channel.guild.bannerURL - }, - color: 16711680, - fields: [ - { - name: "đŸ”ĸ **ID:**", - value: this.channel.guild.id - }, - { - name: "👤 **Owner:**", - value: owner ? `${owner.user.username}#${owner.user.discriminator}` : this.channel.guild.ownerID - }, - { - name: "🗓 **Created on:**", - value: `` - }, - { - name: "đŸ‘Ĩ **Users:**", - value: this.channel.guild.memberCount, - inline: true - }, - { - name: "đŸ’Ŧ **Channels:**", - value: this.channel.guild.channels.size, - inline: true - }, - { - name: "😃 **Emojis:**", - value: this.channel.guild.emojis.length, - inline: true - } - ] - }] - }; - } - - static description = "Gets some info about the server"; - static aliases = ["server"]; - static directAllowed = false; -} - -export default ServerInfoCommand; diff --git a/commands/general/stats.js b/commands/general/stats.js index 1752abd..27df115 100644 --- a/commands/general/stats.js +++ b/commands/general/stats.js @@ -2,7 +2,7 @@ import { readFileSync } from "fs"; const { version } = JSON.parse(readFileSync(new URL("../../package.json", import.meta.url))); import os from "os"; import Command from "../../classes/command.js"; -import { VERSION } from "eris"; +import { VERSION } from "oceanic.js"; import pm2 from "pm2"; import { getServers } from "../../utils/misc.js"; @@ -10,14 +10,15 @@ class StatsCommand extends Command { async run() { const uptime = process.uptime() * 1000; const connUptime = this.client.uptime; - const owner = await this.client.getRESTUser(process.env.OWNER.split(",")[0]); + let owner = this.client.users.get(process.env.OWNER.split(",")[0]); + if (!owner) owner = await this.client.getRESTUser(process.env.OWNER.split(",")[0]); const servers = await getServers(this.client); const processMem = `${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)} MB`; return { embeds: [{ "author": { "name": "esmBot Statistics", - "icon_url": this.client.user.avatarURL + "iconURL": this.client.user.avatarURL() }, "description": `This instance is managed by **${owner.username}#${owner.discriminator}**.`, "color": 16711680, @@ -50,7 +51,7 @@ class StatsCommand extends Command { }, { "name": "Library", - "value": `Eris ${VERSION}`, + "value": `Oceanic ${VERSION}`, "inline": true }, { @@ -60,7 +61,7 @@ class StatsCommand extends Command { }, { "name": "Shard", - "value": this.channel.guild ? this.client.guildShardMap[this.channel.guild.id] : "N/A", + "value": this.guild ? this.client.guildShardMap[this.guild.id] : "N/A", "inline": true }, { diff --git a/commands/general/userinfo.js b/commands/general/userinfo.js deleted file mode 100644 index e8b1fe5..0000000 --- a/commands/general/userinfo.js +++ /dev/null @@ -1,64 +0,0 @@ -import Command from "../../classes/command.js"; - -class UserInfoCommand extends Command { - async run() { - const getUser = this.message.mentions.length >= 1 ? this.message.mentions[0] : (this.args.length !== 0 ? this.client.users.get(this.args[0]) : this.author); - let user; - if (getUser) { - user = getUser; - } else if (this.args[0].match(/^?$/) && this.args[0] >= 21154535154122752n) { - try { - user = await this.client.getRESTUser(this.args[0]); - } catch { - user = this.author; - } - } else if (this.args.join(" ") !== "") { - const userRegex = new RegExp(this.args.join("|"), "i"); - const member = this.client.users.find(element => { - return userRegex.test(element.username); - }); - user = member ?? this.author; - } else { - user = this.author; - } - const member = this.channel.guild ? this.channel.guild.members.get(user.id) : undefined; - return { - embeds: [{ - title: `${user.username}#${user.discriminator}`, - thumbnail: { - url: user.avatarURL - }, - color: 16711680, - fields: [ - { - name: "đŸ”ĸ **ID:**", - value: user.id - }, - { - name: "📛 **Nickname:**", - value: member ? (member.nick ?? "None") : "N/A" - }, - { - name: "🤖 **Bot:**", - value: user.bot ? "Yes" : "No" - }, - { - name: "🗓ī¸ **Joined Discord on:**", - value: `` - }, - { - name: "đŸ’Ŧ **Joined this server on:**", - value: member ? `` : "N/A" - } - ] - }] - }; - } - - static description = "Gets info about a user"; - static aliases = ["user"]; - static arguments = ["[mention/id]"]; - static slashAllowed = false; -} - -export default UserInfoCommand; diff --git a/commands/music/host.js b/commands/music/host.js index ccafba8..6da3609 100644 --- a/commands/music/host.js +++ b/commands/music/host.js @@ -4,9 +4,9 @@ import MusicCommand from "../../classes/musicCommand.js"; class HostCommand extends MusicCommand { async run() { this.success = false; - if (!this.channel.guild) return "This command only works in servers!"; + if (!this.guild) return "This command only works in servers!"; if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!"; - if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; + if (!this.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; if (this.connection.host !== this.author.id && !process.env.OWNER.split(",").includes(this.connection.host)) return "Only the current voice session host can choose another host!"; const input = this.options.user ?? this.args.join(" "); if (input?.trim()) { @@ -33,15 +33,15 @@ class HostCommand extends MusicCommand { } if (!user) return "I can't find that user!"; if (user.bot) return "This is illegal, you know."; - const member = this.channel.guild ? this.channel.guild.members.get(user.id) : undefined; + const member = this.guild ? this.guild.members.get(user.id) : undefined; if (!member) return "That user isn't in this server!"; const object = this.connection; object.host = member.id; - players.set(this.channel.guild.id, object); + players.set(this.guildID, object); this.success = true; return `🔊 ${member.mention} is the new voice channel host.`; } else { - const member = this.channel.guild ? this.channel.guild.members.get(players.get(this.channel.guild.id).host) : undefined; + const member = this.guild ? this.guild.members.get(players.get(this.guild.id).host) : undefined; this.success = true; return `🔊 The current voice channel host is **${member?.username}#${member?.discriminator}**.`; } diff --git a/commands/music/loop.js b/commands/music/loop.js index 9f06701..071eba4 100644 --- a/commands/music/loop.js +++ b/commands/music/loop.js @@ -4,13 +4,13 @@ import MusicCommand from "../../classes/musicCommand.js"; class LoopCommand extends MusicCommand { async run() { this.success = false; - if (!this.channel.guild) return "This command only works in servers!"; + if (!this.guild) return "This command only works in servers!"; if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!"; - if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; + if (!this.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; if (this.connection.host !== this.author.id && !this.member.permissions.has("manageChannels")) return "Only the current voice session host can loop the music!"; const object = this.connection; object.loop = !object.loop; - players.set(this.channel.guild.id, object); + players.set(this.guild.id, object); this.success = true; return object.loop ? "🔊 The player is now looping." : "🔊 The player is no longer looping."; } diff --git a/commands/music/nowplaying.js b/commands/music/nowplaying.js index 31b4f57..bdeee76 100644 --- a/commands/music/nowplaying.js +++ b/commands/music/nowplaying.js @@ -4,9 +4,9 @@ import MusicCommand from "../../classes/musicCommand.js"; class NowPlayingCommand extends MusicCommand { async run() { this.success = false; - if (!this.channel.guild) return "This command only works in servers!"; + if (!this.guild) return "This command only works in servers!"; if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!"; - if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; + if (!this.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; const player = this.connection.player; if (!player) return "I'm not playing anything!"; const track = await player.node.rest.decode(player.track); @@ -17,7 +17,7 @@ class NowPlayingCommand extends MusicCommand { color: 16711680, author: { name: "Now Playing", - icon_url: this.client.user.avatarURL + iconURL: this.client.user.avatarURL }, fields: [{ name: "ℹī¸ Title", @@ -29,7 +29,7 @@ class NowPlayingCommand extends MusicCommand { }, { name: "đŸ’Ŧ Channel", - value: this.channel.guild.channels.get(this.member.voiceState.channelID).name + value: this.guild.channels.get(this.member.voiceState.channelID).name }, { name: "🌐 Node", diff --git a/commands/music/queue.js b/commands/music/queue.js index 2b6feb1..9f7857e 100644 --- a/commands/music/queue.js +++ b/commands/music/queue.js @@ -7,9 +7,9 @@ import MusicCommand from "../../classes/musicCommand.js"; class QueueCommand extends MusicCommand { async run() { this.success = false; - if (!this.channel.guild) return "This command only works in servers!"; + if (!this.guild) return "This command only works in servers!"; if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!"; - if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; + if (!this.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; if (!this.channel.permissionsOf(this.client.user.id).has("embedLinks")) return "I don't have the `Embed Links` permission!"; const player = this.connection; const node = nodes.filter((val) => val.name === player.player.node.name)[0]; @@ -30,7 +30,7 @@ class QueueCommand extends MusicCommand { embeds: [{ author: { name: "Queue", - icon_url: this.client.user.avatarURL + iconURL: this.client.user.avatarURL }, color: 16711680, footer: { diff --git a/commands/music/remove.js b/commands/music/remove.js index fb0df5e..f56876a 100644 --- a/commands/music/remove.js +++ b/commands/music/remove.js @@ -4,16 +4,16 @@ import MusicCommand from "../../classes/musicCommand.js"; class RemoveCommand extends MusicCommand { async run() { this.success = false; - if (!this.channel.guild) return "This command only works in servers!"; + if (!this.guild) return "This command only works in servers!"; if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!"; - if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; + if (!this.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; if (this.connection.host !== this.author.id && !process.env.OWNER.split(",").includes(this.connection.host)) return "Only the current voice session host can remove songs from the queue!"; const pos = parseInt(this.options.position ?? this.args[0]); if (isNaN(pos) || pos > this.queue.length || pos < 1) return "That's not a valid position!"; const removed = this.queue.splice(pos, 1); if (removed.length === 0) return "That's not a valid position!"; const track = await this.connection.player.node.rest.decode(removed[0]); - queues.set(this.channel.guild.id, this.queue); + queues.set(this.guildID, this.queue); this.success = true; return `🔊 The song \`${track.title ? track.title : "(blank)"}\` has been removed from the queue.`; } diff --git a/commands/music/seek.js b/commands/music/seek.js index 85467bc..311e21f 100644 --- a/commands/music/seek.js +++ b/commands/music/seek.js @@ -3,9 +3,9 @@ import MusicCommand from "../../classes/musicCommand.js"; class SeekCommand extends MusicCommand { async run() { this.success = false; - if (!this.channel.guild) return "This command only works in servers!"; + if (!this.guild) return "This command only works in servers!"; if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!"; - if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; + if (!this.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; if (this.connection.host !== this.author.id) return "Only the current voice session host can seek the music!"; const player = this.connection.player; const track = await player.node.rest.decode(player.track); diff --git a/commands/music/shuffle.js b/commands/music/shuffle.js index cab7957..798f69e 100644 --- a/commands/music/shuffle.js +++ b/commands/music/shuffle.js @@ -4,13 +4,13 @@ import MusicCommand from "../../classes/musicCommand.js"; class ShuffleCommand extends MusicCommand { async run() { this.success = false; - if (!this.channel.guild) return "This command only works in servers!"; + if (!this.guild) return "This command only works in servers!"; if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!"; - if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; + if (!this.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; if (this.connection.host !== this.author.id) return "Only the current voice session host can shuffle the music!"; const object = this.connection; object.shuffle = !object.shuffle; - players.set(this.channel.guild.id, object); + players.set(this.guildID, object); this.success = true; return object.shuffle ? "🔊 The player is now shuffling." : "🔊 The player is no longer shuffling."; } diff --git a/commands/music/skip.js b/commands/music/skip.js index d8ee219..6e77c28 100644 --- a/commands/music/skip.js +++ b/commands/music/skip.js @@ -4,12 +4,12 @@ import MusicCommand from "../../classes/musicCommand.js"; class SkipCommand extends MusicCommand { async run() { this.success = false; - if (!this.channel.guild) return "This command only works in servers!"; + if (!this.guild) return "This command only works in servers!"; if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!"; - if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; + if (!this.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; const player = this.connection; if (player.host !== this.author.id && !this.member.permissions.has("manageChannels")) { - const votes = skipVotes.get(this.channel.guild.id) ?? { count: 0, ids: [], max: Math.min(3, player.voiceChannel.voiceMembers.filter((i) => i.id !== this.client.user.id && !i.bot).length) }; + const votes = skipVotes.get(this.guild.id) ?? { count: 0, ids: [], max: Math.min(3, player.voiceChannel.voiceMembers.filter((i) => i.id !== this.client.user.id && !i.bot).length) }; if (votes.ids.includes(this.author.id)) return "You've already voted to skip!"; const newObject = { count: votes.count + 1, @@ -17,12 +17,12 @@ class SkipCommand extends MusicCommand { max: votes.max }; if (votes.count + 1 === votes.max) { - await player.player.stopTrack(this.channel.guild.id); - skipVotes.set(this.channel.guild.id, { count: 0, ids: [], max: Math.min(3, player.voiceChannel.voiceMembers.filter((i) => i.id !== this.client.user.id && !i.bot).length) }); + await player.player.stopTrack(this.guild.id); + skipVotes.set(this.guild.id, { count: 0, ids: [], max: Math.min(3, player.voiceChannel.voiceMembers.filter((i) => i.id !== this.client.user.id && !i.bot).length) }); this.success = true; if (this.type === "application") return "🔊 The current song has been skipped."; } else { - skipVotes.set(this.channel.guild.id, newObject); + skipVotes.set(this.guild.id, newObject); this.success = true; return `🔊 Voted to skip song (${votes.count + 1}/${votes.max} people have voted).`; } diff --git a/commands/music/stop.js b/commands/music/stop.js index d11a59a..4aa6a5b 100644 --- a/commands/music/stop.js +++ b/commands/music/stop.js @@ -4,19 +4,19 @@ import MusicCommand from "../../classes/musicCommand.js"; class StopCommand extends MusicCommand { async run() { this.success = false; - if (!this.channel.guild) return "This command only works in servers!"; + if (!this.guild) return "This command only works in servers!"; if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!"; - if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; + if (!this.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; if (!this.connection) { - await manager.getNode().leaveChannel(this.channel.guild.id); + await manager.getNode().leaveChannel(this.guild.id); this.success = true; return "🔊 The current voice channel session has ended."; } if (this.connection.host !== this.author.id && !this.member.permissions.has("manageChannels")) return "Only the current voice session host can stop the music!"; const connection = this.connection.player; - connection.node.leaveChannel(this.channel.guild.id); - players.delete(this.channel.guild.id); - queues.delete(this.channel.guild.id); + connection.node.leaveChannel(this.guild.id); + players.delete(this.guild.id); + queues.delete(this.guild.id); this.success = true; return `🔊 The voice channel session in \`${this.connection.voiceChannel.name}\` has ended.`; } diff --git a/commands/music/toggle.js b/commands/music/toggle.js index 6499900..c15a993 100644 --- a/commands/music/toggle.js +++ b/commands/music/toggle.js @@ -3,9 +3,9 @@ import MusicCommand from "../../classes/musicCommand.js"; class ToggleCommand extends MusicCommand { async run() { this.success = false; - if (!this.channel.guild) return "This command only works in servers!"; + if (!this.guild) return "This command only works in servers!"; if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!"; - if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; + if (!this.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!"; if (this.connection.host !== this.author.id && !this.member.permissions.has("manageChannels")) return "Only the current voice session host can pause/resume the music!"; const player = this.connection.player; player.setPaused(!player.paused ? true : false); diff --git a/commands/tags/tags.js b/commands/tags/tags.js index 93defa0..23bc9ec 100644 --- a/commands/tags/tags.js +++ b/commands/tags/tags.js @@ -8,7 +8,7 @@ class TagsCommand extends Command { // todo: attempt to not make this file the worst thing that human eyes have ever seen async run() { this.success = false; - if (!this.channel.guild) return "This command only works in servers!"; + if (!this.guild) return "This command only works in servers!"; const cmd = this.type === "classic" ? (this.args[0] ?? "").toLowerCase() : this.optionsArray[0].name; if (!cmd || !cmd.trim()) return "You need to provide the name of the tag you want to view!"; const tagName = this.type === "classic" ? this.args.slice(1)[0] : (this.optionsArray[0].options[0] ?? {}).value; @@ -16,33 +16,33 @@ class TagsCommand extends Command { if (cmd === "create" || cmd === "add") { if (!tagName || !tagName.trim()) return "You need to provide the name of the tag you want to add!"; if (blacklist.includes(tagName)) return "You can't make a tag with that name!"; - const getResult = await database.getTag(this.channel.guild.id, tagName); + const getResult = await database.getTag(this.guild.id, tagName); if (getResult) return "This tag already exists!"; - const result = await database.setTag(tagName, { content: this.type === "classic" ? this.args.slice(2).join(" ") : this.optionsArray[0].options[1].value, author: this.member.id }, this.channel.guild); + const result = await database.setTag(tagName, { content: this.type === "classic" ? this.args.slice(2).join(" ") : this.optionsArray[0].options[1].value, author: this.member.id }, this.guild); this.success = true; if (result) return result; return `The tag \`${tagName}\` has been added!`; } else if (cmd === "delete" || cmd === "remove") { if (!tagName || !tagName.trim()) return "You need to provide the name of the tag you want to delete!"; - const getResult = await database.getTag(this.channel.guild.id, tagName); + const getResult = await database.getTag(this.guild.id, tagName); if (!getResult) return "This tag doesn't exist!"; const owners = process.env.OWNER.split(","); if (getResult.author !== this.author.id && !this.member.permissions.has("manageMessages") && !owners.includes(this.author.id)) return "You don't own this tag!"; - await database.removeTag(tagName, this.channel.guild); + await database.removeTag(tagName, this.guild); this.success = true; return `The tag \`${tagName}\` has been deleted!`; } else if (cmd === "edit") { if (!tagName || !tagName.trim()) return "You need to provide the name of the tag you want to edit!"; - const getResult = await database.getTag(this.channel.guild.id, tagName); + const getResult = await database.getTag(this.guild.id, tagName); if (!getResult) return "This tag doesn't exist!"; const owners = process.env.OWNER.split(","); if (getResult.author !== this.author.id && !this.member.permissions.has("manageMessages") && !owners.includes(this.author.id)) return "You don't own this tag!"; - await database.editTag(tagName, { content: this.type === "classic" ? this.args.slice(2).join(" ") : this.optionsArray[0].options[1].value, author: this.member.id }, this.channel.guild); + await database.editTag(tagName, { content: this.type === "classic" ? this.args.slice(2).join(" ") : this.optionsArray[0].options[1].value, author: this.member.id }, this.guild); this.success = true; return `The tag \`${tagName}\` has been edited!`; } else if (cmd === "own" || cmd === "owner") { if (!tagName || !tagName.trim()) return "You need to provide the name of the tag you want to check the owner of!"; - const getResult = await database.getTag(this.channel.guild.id, tagName); + const getResult = await database.getTag(this.guild.id, tagName); if (!getResult) return "This tag doesn't exist!"; const user = this.client.users.get(getResult.author); this.success = true; @@ -58,7 +58,7 @@ class TagsCommand extends Command { } } else if (cmd === "list") { if (!this.channel.permissionsOf(this.client.user.id).has("embedLinks")) return "I don't have the `Embed Links` permission!"; - const tagList = await database.getTags(this.channel.guild.id); + const tagList = await database.getTags(this.guild.id); const embeds = []; const groups = Object.keys(tagList).map((item, index) => { return index % 15 === 0 ? Object.keys(tagList).slice(index, index + 15) : null; @@ -76,7 +76,7 @@ class TagsCommand extends Command { description: value.join("\n"), author: { name: this.author.username, - icon_url: this.author.avatarURL + iconURL: this.author.avatarURL } }] }); @@ -87,10 +87,10 @@ class TagsCommand extends Command { } else { let getResult; if (cmd === "random") { - const tagList = await database.getTags(this.channel.guild.id); + const tagList = await database.getTags(this.guild.id); getResult = tagList[random(Object.keys(tagList))]; } else { - getResult = await database.getTag(this.channel.guild.id, this.type === "classic" ? cmd : tagName); + getResult = await database.getTag(this.guild.id, this.type === "classic" ? cmd : tagName); } if (!getResult) return "This tag doesn't exist!"; this.success = true; diff --git a/docs/custom-commands.md b/docs/custom-commands.md index 324666e..1b8b1e7 100644 --- a/docs/custom-commands.md +++ b/docs/custom-commands.md @@ -44,24 +44,25 @@ The default command name is the same as the filename that you save it as, exclud The parameters available to your command consist of the following: -- `this.client`: An instance of an Eris [`Client`](https://abal.moe/Eris/docs/Client), useful for getting info or performing lower-level communication with the Discord API. +- `this.client`: An instance of an Oceanic [`Client`](https://docs.oceanic.ws/dev/classes/Client.Client.html), useful for getting info or performing lower-level communication with the Discord API. - `this.origOptions`: The raw options object provided to the command by the command handler. - `this.type`: The type of message that activated the command. Can be "classic" (a regular message) or "application" (slash/context menu commands). -- `this.channel`: An Eris [`TextChannel`](https://abal.moe/Eris/docs/TextChannel) object of the channel that the command was run in, useful for getting info about a server and how to respond to a message. -- `this.author`: An Eris [`User`](https://abal.moe/Eris/docs/User) object of the user who ran the command, or a [`Member`](https://abal.moe/Eris/docs/Member) object identical to `this.member` if run in a server as a slash command. -- `this.member`: An Eris [`Member`](https://abal.moe/Eris/docs/Member) object of the server member who ran the command. When running the command outside of a server, this parameter is undefined when run as a "classic" command or a [`User`](https://abal.moe/Eris/docs/User) object identical to `this.author` when run as a slash command. +- `this.channel`: An Oceanic [`TextChannel`](https://docs.oceanic.ws/dev/classes/TextChannel.TextChannel.html) object of the channel that the command was run in, useful for getting info about a server and how to respond to a message. +- `this.guild`: An Oceanic [`Guild`](https://docs.oceanic.ws/dev/classes/Guild.Guild.html) object of the guild that the command was run in. This is undefined in DMs. +- `this.author`: An Oceanic [`User`](https://docs.oceanic.ws/dev/classes/User.User.html) object of the user who ran the command, or a [`Member`](https://docs.oceanic.ws/dev/classes/Member.Member.html) object identical to `this.member` if run in a server as a slash command. +- `this.member`: An Oceanic [`Member`](https://docs.oceanic.ws/dev/classes/Member.Member.html) object of the server member who ran the command. When running the command outside of a server, this parameter is undefined when run as a "classic" command or a [`User`](https://docs.oceanic.ws/dev/classes/User.User.html) object identical to `this.author` when run as a slash command. - `this.options`: When run as a "classic" command, this is an object of special arguments (e.g. `--argument=true`) passed to the command. These arguments are stored in a key/value format, so following the previous example, `this.options.argument` would return true. When run as a slash command, this is an object of every argument passed to the command. Some options are only available depending on the context/original message type, which can be checked with `this.type`. The options only available with "classic" messages are listed below: -- `this.message`: An Eris [`Message`](https://abal.moe/Eris/docs/Message) object of the message that the command was run from, useful for interaction. +- `this.message`: An Oceanic [`Message`](https://docs.oceanic.ws/dev/classes/Message.Message.html) object of the message that the command was run from, useful for interaction. - `this.args`: An array of text arguments passed to the command. - `this.content`: A string of the raw content of the command message, excluding the prefix and command name. - `this.reference`: An object that's useful if you ever decide to reply to a user inside the command. You can use [`Object.assign`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) to combine your message content with this parameter. The options only available with application (slash and context menu) commands are listed below: -- `this.interaction`: An Eris [`CommandInteraction`](https://abal.moe/Eris/docs/CommandInteraction) object of the incoming slash command data. +- `this.interaction`: An Oceanic [`CommandInteraction`](https://docs.oceanic.ws/dev/classes/CommandInteraction.CommandInteraction.html) object of the incoming slash command data. - `this.optionsArray`: A raw array of command options. Should rarely be used. - `this.success`: A boolean value that causes the bot to respond with a normal message when `true`, or an "ephemeral" message (a message that's only visible to the person who ran the command) when `false`. diff --git a/events/interactionCreate.js b/events/interactionCreate.js index d76098b..0a2ba80 100644 --- a/events/interactionCreate.js +++ b/events/interactionCreate.js @@ -25,7 +25,7 @@ export default async (client, interaction) => { // eslint-disable-next-line no-unused-vars const commandClass = new cmd(client, { type: "application", interaction }); const result = await commandClass.run(); - const replyMethod = interaction.acknowledged ? "editOriginalMessage" : "createMessage"; + const replyMethod = interaction.acknowledged ? "editOriginal" : "createMessage"; if (typeof result === "string") { await interaction[replyMethod]({ content: result, @@ -35,9 +35,9 @@ export default async (client, interaction) => { await interaction[replyMethod](Object.assign(result, { flags: result.flags ?? (commandClass.success ? 0 : 64) })); - } else if (typeof result === "object" && result.file) { + } else if (typeof result === "object" && result.contents) { const fileSize = 8388119; - if (result.file.length > fileSize) { + if (result.contents.length > fileSize) { if (process.env.TEMPDIR && process.env.TEMPDIR !== "") { await upload(client, result, interaction, true); } else { @@ -47,11 +47,11 @@ export default async (client, interaction) => { }); } } else { - await interaction[replyMethod](result.text ? result.text : {}, result); + await interaction[replyMethod](result.text ? result.text : { files: [result] }); } } } catch (error) { - const replyMethod = interaction.acknowledged ? "editOriginalMessage" : "createMessage"; + const replyMethod = interaction.acknowledged ? "editOriginal" : "createMessage"; if (error.toString().includes("Request entity too large")) { await interaction[replyMethod]({ content: "The resulting file was too large to upload. Try again with a smaller image if possible.", flags: 64 }); } else if (error.toString().includes("Job ended prematurely")) { @@ -63,11 +63,16 @@ export default async (client, interaction) => { try { let err = error; if (error?.constructor?.name == "Promise") err = await error; - await interaction[replyMethod]("Uh oh! I ran into an error while running this command. Please report the content of the attached file at the following link or on the esmBot Support server: ", { - file: `Message: ${clean(err)}\n\nStack Trace: ${clean(err.stack)}`, - name: "error.txt" + await interaction[replyMethod]({ + content: "Uh oh! I ran into an error while running this command. Please report the content of the attached file at the following link or on the esmBot Support server: ", + files: [{ + contents: `Message: ${clean(err)}\n\nStack Trace: ${clean(err.stack)}`, + name: "error.txt" + }] }); - } catch { /* silently ignore */ } + } catch (e) { + logger.error(`While attempting to send the previous error message, another error occurred: ${e.stack || e}`); + } } } }; diff --git a/events/messageCreate.js b/events/messageCreate.js index 92626ac..aae1ed5 100644 --- a/events/messageCreate.js +++ b/events/messageCreate.js @@ -2,7 +2,7 @@ import database from "../utils/database.js"; import { log, error as _error } from "../utils/logger.js"; import { prefixCache, aliases, disabledCache, disabledCmdCache, commands } from "../utils/collections.js"; import parseCommand from "../utils/parseCommand.js"; -import { clean } from "../utils/misc.js"; +import { clean, cleanMessage } from "../utils/misc.js"; import { upload } from "../utils/tempimages.js"; // run when someone sends a message @@ -11,28 +11,28 @@ export default async (client, message) => { if (message.author.bot) return; // don't run command if bot can't send messages - if (message.channel.guild && !message.channel.permissionsOf(client.user.id).has("sendMessages")) return; + if (message.guildID && !message.channel.permissionsOf(client.user.id.toString()).has("SEND_MESSAGES")) return; let prefixCandidate; let guildDB; - if (message.channel.guild) { - const cachedPrefix = prefixCache.get(message.channel.guild.id); + if (message.guildID) { + const cachedPrefix = prefixCache.get(message.guildID); if (cachedPrefix) { prefixCandidate = cachedPrefix; } else { - guildDB = await database.getGuild(message.channel.guild.id); + guildDB = await database.getGuild(message.guildID); if (!guildDB) { - guildDB = await database.fixGuild(message.channel.guild); + guildDB = await database.fixGuild(message.guildID); } prefixCandidate = guildDB.prefix; - prefixCache.set(message.channel.guild.id, guildDB.prefix); + prefixCache.set(message.guildID, guildDB.prefix); } } let prefix; let isMention = false; - if (message.channel.guild) { - const user = message.channel.guild.members.get(client.user.id); + if (message.guildID) { + const user = message.guild.members.get(client.user.id); if (message.content.startsWith(user.mention)) { prefix = `${user.mention} `; isMention = true; @@ -50,8 +50,8 @@ export default async (client, message) => { if (!message.content.startsWith(prefix)) return; // separate commands and args - const replace = isMention ? `@${(message.channel.guild ? message.channel.guild.members.get(client.user.id).nick : client.user.username) ?? client.user.username} ` : prefix; - const content = message.cleanContent.substring(replace.length).trim(); + const replace = isMention ? `@${(message.guild ? message.guild.members.get(client.user.id).nick : client.user.username) ?? client.user.username} ` : prefix; + const content = cleanMessage(message).substring(replace.length).trim(); const rawContent = message.content.substring(prefix.length).trim(); const preArgs = content.split(/\s+/g); preArgs.shift(); @@ -60,22 +60,22 @@ export default async (client, message) => { const aliased = aliases.get(command); // don't run if message is in a disabled channel - if (message.channel.guild) { - const disabled = disabledCache.get(message.channel.guild.id); + if (message.guildID) { + const disabled = disabledCache.get(message.guildID); if (disabled) { - if (disabled.includes(message.channel.id) && command != "channel") return; + if (disabled.includes(message.channelID) && command != "channel") return; } else { - guildDB = await database.getGuild(message.channel.guild.id); - disabledCache.set(message.channel.guild.id, guildDB.disabled); - if (guildDB.disabled.includes(message.channel.id) && command !== "channel") return; + guildDB = await database.getGuild(message.guildID); + disabledCache.set(message.guildID, guildDB.disabled); + if (guildDB.disabled.includes(message.channelID) && command !== "channel") return; } - const disabledCmds = disabledCmdCache.get(message.channel.guild.id); + const disabledCmds = disabledCmdCache.get(message.guildID); if (disabledCmds) { if (disabledCmds.includes(aliased ?? command)) return; } else { - guildDB = await database.getGuild(message.channel.guild.id); - disabledCmdCache.set(message.channel.guild.id, guildDB.disabled_commands ?? guildDB.disabledCommands); + guildDB = await database.getGuild(message.guildID); + disabledCmdCache.set(message.guildID, guildDB.disabled_commands ?? guildDB.disabledCommands); if ((guildDB.disabled_commands ?? guildDB.disabledCommands).includes(aliased ?? command)) return; } } @@ -85,15 +85,15 @@ export default async (client, message) => { if (!cmd) return; // block certain commands from running in DMs - if (!cmd.directAllowed && !message.channel.guild) return; + if (!cmd.directAllowed && !message.guildID) return; // actually run the command log("log", `${message.author.username} (${message.author.id}) ran classic command ${command}`); const reference = { messageReference: { - channelID: message.channel.id, + channelID: message.channelID, messageID: message.id, - guildID: message.channel.guild ? message.channel.guild.id : undefined, + guildID: message.guildID ?? undefined, failIfNotExists: false }, allowedMentions: { @@ -110,15 +110,15 @@ export default async (client, message) => { if ((endTime - startTime) >= 180000) reference.allowedMentions.repliedUser = true; if (typeof result === "string") { reference.allowedMentions.repliedUser = true; - await client.createMessage(message.channel.id, Object.assign({ + await client.rest.channels.createMessage(message.channelID, Object.assign({ content: result }, reference)); } else if (typeof result === "object" && result.embeds) { - await client.createMessage(message.channel.id, Object.assign(result, reference)); - } else if (typeof result === "object" && result.file) { + await client.rest.channels.createMessage(message.channelID, Object.assign(result, reference)); + } else if (typeof result === "object" && result.contents) { let fileSize = 8388119; - if (message.channel.guild) { - switch (message.channel.guild.premiumTier) { + if (message.guildID) { + switch (message.guild.premiumTier) { case 2: fileSize = 52428308; break; @@ -127,42 +127,44 @@ export default async (client, message) => { break; } } - if (result.file.length > fileSize) { + if (result.contents.length > fileSize) { if (process.env.TEMPDIR && process.env.TEMPDIR !== "") { await upload(client, result, message); } else { - await client.createMessage(message.channel.id, "The resulting image was more than 8MB in size, so I can't upload it."); + await client.rest.channels.createMessage(message.channelID, "The resulting image was more than 8MB in size, so I can't upload it."); } } else { - await client.createMessage(message.channel.id, Object.assign({ - content: result.text ? result.text : undefined - }, reference), result); + await client.rest.channels.createMessage(message.channelID, Object.assign({ + content: result.text ? result.text : undefined, + files: [result] + }, reference)); } } } catch (error) { if (error.toString().includes("Request entity too large")) { - await client.createMessage(message.channel.id, Object.assign({ + await client.rest.channels.createMessage(message.channelID, Object.assign({ content: "The resulting file was too large to upload. Try again with a smaller image if possible." }, reference)); } else if (error.toString().includes("Job ended prematurely")) { - await client.createMessage(message.channel.id, Object.assign({ + await client.rest.channels.createMessage(message.channelID, Object.assign({ content: "Something happened to the image servers before I could receive the image. Try running your command again." }, reference)); } else if (error.toString().includes("Timed out")) { - await client.createMessage(message.channel.id, Object.assign({ + await client.rest.channels.createMessage(message.channelID, Object.assign({ content: "The request timed out before I could download that image. Try uploading your image somewhere else or reducing its size." }, reference)); } else { - _error(`Error occurred with command message ${message.cleanContent}: ${error.stack || error}`); + _error(`Error occurred with command message ${message.content}: ${error.stack || error}`); try { let err = error; if (error?.constructor?.name == "Promise") err = await error; - await client.createMessage(message.channel.id, Object.assign({ - content: "Uh oh! I ran into an error while running this command. Please report the content of the attached file at the following link or on the esmBot Support server: " - }, reference), [{ - file: `Message: ${clean(err)}\n\nStack Trace: ${clean(err.stack)}`, + await client.rest.channels.createMessage(message.channelID, Object.assign({ + content: "Uh oh! I ran into an error while running this command. Please report the content of the attached file at the following link or on the esmBot Support server: ", + files: [{ + contents: `Message: ${clean(err)}\n\nStack Trace: ${clean(err.stack)}`, name: "error.txt" - }]); + }] + }, reference)); } catch (e) { _error(`While attempting to send the previous error message, another error occurred: ${e.stack || e}`); } diff --git a/events/voiceChannelLeave.js b/events/voiceChannelLeave.js index 3b143b2..a59659b 100644 --- a/events/voiceChannelLeave.js +++ b/events/voiceChannelLeave.js @@ -6,21 +6,25 @@ const isWaiting = new Map(); export default async (client, member, oldChannel) => { if (!oldChannel) return; - const connection = players.get(oldChannel.guild.id); + const connection = players.get(oldChannel.guildID); if (oldChannel.id === connection?.voiceChannel.id) { if (oldChannel.voiceMembers.filter((i) => i.id !== client.user.id && !i.bot).length === 0) { if (isWaiting.has(oldChannel.id)) return; isWaiting.set(oldChannel.id, true); connection.player.setPaused(true); - const waitMessage = await client.createMessage(connection.originalChannel.id, "🔊 Waiting 10 seconds for someone to return..."); + const waitMessage = await client.rest.channels.createMessage(connection.originalChannel.id, { + content: "🔊 Waiting 10 seconds for someone to return..." + }); const awaitRejoin = new AwaitRejoin(oldChannel, true, member.id); awaitRejoin.on("end", async (rejoined, newMember) => { isWaiting.delete(oldChannel.id); if (rejoined) { connection.player.setPaused(false); if (member.id !== newMember.id) { - players.set(connection.voiceChannel.guild.id, { player: connection.player, type: connection.type, host: newMember.id, voiceChannel: connection.voiceChannel, originalChannel: connection.originalChannel, loop: connection.loop, shuffle: connection.shuffle, playMessage: connection.playMessage }); - waitMessage.edit(`🔊 ${newMember.mention} is the new voice channel host.`); + players.set(connection.voiceChannel.guildID, { player: connection.player, type: connection.type, host: newMember.id, voiceChannel: connection.voiceChannel, originalChannel: connection.originalChannel, loop: connection.loop, shuffle: connection.shuffle, playMessage: connection.playMessage }); + waitMessage.edit({ + content: `🔊 ${newMember.mention} is the new voice channel host.` + }); } else { try { await waitMessage.delete(); @@ -35,20 +39,24 @@ export default async (client, member, oldChannel) => { // no-op } try { - connection.player.node.leaveChannel(connection.originalChannel.guild.id); + connection.player.node.leaveChannel(connection.originalChannel.guildID); } catch { // no-op } - players.delete(connection.originalChannel.guild.id); - queues.delete(connection.originalChannel.guild.id); - skipVotes.delete(connection.originalChannel.guild.id); - client.createMessage(connection.originalChannel.id, `🔊 The voice channel session in \`${connection.originalChannel.name}\` has ended.`); + players.delete(connection.originalChannel.guildID); + queues.delete(connection.originalChannel.guildID); + skipVotes.delete(connection.originalChannel.guildID); + client.rest.channels.createMessage(connection.originalChannel.id, { + content: `🔊 The voice channel session in \`${connection.originalChannel.name}\` has ended.` + }); } }); } else if (member.id === connection.host) { if (isWaiting.has(oldChannel.id)) return; isWaiting.set(oldChannel.id, true); - const waitMessage = await client.createMessage(connection.originalChannel.id, "🔊 Waiting 10 seconds for the host to return..."); + const waitMessage = await client.rest.channels.createMessage(connection.originalChannel.id, { + content: "🔊 Waiting 10 seconds for the host to return..." + }); const awaitRejoin = new AwaitRejoin(oldChannel, false, member.id); awaitRejoin.on("end", async (rejoined) => { isWaiting.delete(oldChannel.id); @@ -67,32 +75,38 @@ export default async (client, member, oldChannel) => { // no-op } try { - connection.player.node.leaveChannel(connection.originalChannel.guild.id); + connection.player.node.leaveChannel(connection.originalChannel.guildID); } catch { // no-op } - players.delete(connection.originalChannel.guild.id); - queues.delete(connection.originalChannel.guild.id); - skipVotes.delete(connection.originalChannel.guild.id); - client.createMessage(connection.originalChannel.id, `🔊 The voice channel session in \`${connection.originalChannel.name}\` has ended.`); + players.delete(connection.originalChannel.guildID); + queues.delete(connection.originalChannel.guildID); + skipVotes.delete(connection.originalChannel.guildID); + client.rest.channels.createMessage(connection.originalChannel.id, { + content: `🔊 The voice channel session in \`${connection.originalChannel.name}\` has ended.` + }); } else { const randomMember = random(members); - players.set(connection.voiceChannel.guild.id, { player: connection.player, type: connection.type, host: randomMember.id, voiceChannel: connection.voiceChannel, originalChannel: connection.originalChannel, loop: connection.loop, shuffle: connection.shuffle, playMessage: connection.playMessage }); - waitMessage.edit(`🔊 ${randomMember.mention} is the new voice channel host.`); + players.set(connection.voiceChannel.guildID, { player: connection.player, type: connection.type, host: randomMember.id, voiceChannel: connection.voiceChannel, originalChannel: connection.originalChannel, loop: connection.loop, shuffle: connection.shuffle, playMessage: connection.playMessage }); + waitMessage.edit({ + content: `🔊 ${randomMember.mention} is the new voice channel host.` + }); } } }); } else if (member.id === client.user.id) { isWaiting.delete(oldChannel.id); try { - connection.player.node.leaveChannel(connection.originalChannel.guild.id); + connection.player.node.leaveChannel(connection.originalChannel.guildID); } catch { // no-op } - players.delete(connection.originalChannel.guild.id); - queues.delete(connection.originalChannel.guild.id); - skipVotes.delete(connection.originalChannel.guild.id); - await client.createMessage(connection.originalChannel.id, `🔊 The voice channel session in \`${connection.originalChannel.name}\` has ended.`); + players.delete(connection.originalChannel.guildID); + queues.delete(connection.originalChannel.guildID); + skipVotes.delete(connection.originalChannel.guildID); + await client.rest.channels.createMessage(connection.originalChannel.id, { + content: `🔊 The voice channel session in \`${connection.originalChannel.name}\` has ended.` + }); } } }; diff --git a/package.json b/package.json index 887e228..eddd8d7 100644 --- a/package.json +++ b/package.json @@ -31,12 +31,12 @@ "cmake-js": "^6.3.2", "dotenv": "^16.0.2", "emoji-regex": "^10.1.0", - "eris": "github:esmBot/eris#dev", "file-type": "^17.1.6", "format-duration": "^2.0.0", "jsqr": "^1.4.0", "node-addon-api": "^5.0.0", "node-emoji": "^1.11.0", + "oceanic.js": "1.1.1-dev.51a0d21", "qrcode": "^1.5.1", "sharp": "^0.30.7", "shoukaku": "github:Deivu/shoukaku", @@ -45,9 +45,9 @@ "winston-daily-rotate-file": "^4.7.1" }, "devDependencies": { - "@babel/core": "^7.19.0", - "@babel/eslint-parser": "^7.18.9", - "@babel/eslint-plugin": "^7.18.10", + "@babel/core": "^7.19.1", + "@babel/eslint-parser": "^7.19.1", + "@babel/eslint-plugin": "^7.19.1", "@babel/plugin-proposal-class-properties": "^7.18.6", "eslint": "^8.23.1", "eslint-plugin-unicorn": "^42.0.0" @@ -59,7 +59,7 @@ "pm2": "^5.2.0", "postgres": "^3.2.4", "uuid": "^8.3.2", - "ws": "^8.8.1", + "ws": "^8.9.0", "zlib-sync": "^0.1.7" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 55bc05b..86efe28 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,9 +1,9 @@ lockfileVersion: 5.4 specifiers: - '@babel/core': ^7.19.0 - '@babel/eslint-parser': ^7.18.9 - '@babel/eslint-plugin': ^7.18.10 + '@babel/core': ^7.19.1 + '@babel/eslint-parser': ^7.19.1 + '@babel/eslint-plugin': ^7.19.1 '@babel/plugin-proposal-class-properties': ^7.18.6 '@top-gg/sdk': ^3.1.3 better-sqlite3: ^7.6.2 @@ -11,7 +11,6 @@ specifiers: cmake-js: ^6.3.2 dotenv: ^16.0.2 emoji-regex: ^10.1.0 - eris: github:esmBot/eris#dev erlpack: github:abalabahaha/erlpack eslint: ^8.23.1 eslint-plugin-unicorn: ^42.0.0 @@ -20,6 +19,7 @@ specifiers: jsqr: ^1.4.0 node-addon-api: ^5.0.0 node-emoji: ^1.11.0 + oceanic.js: 1.1.1-dev.51a0d21 pm2: ^5.2.0 postgres: ^3.2.4 qrcode: ^1.5.1 @@ -29,7 +29,7 @@ specifiers: uuid: ^8.3.2 winston: ^3.8.2 winston-daily-rotate-file: ^4.7.1 - ws: ^8.8.1 + ws: ^8.9.0 zlib-sync: ^0.1.7 dependencies: @@ -37,12 +37,12 @@ dependencies: cmake-js: 6.3.2 dotenv: 16.0.2 emoji-regex: 10.1.0 - eris: github.com/esmBot/eris/fbc637e7f92963d7f9e57c86223e995269e70de0_bufferutil@4.0.6 file-type: 17.1.6 format-duration: 2.0.0 jsqr: 1.4.0 node-addon-api: 5.0.0 node-emoji: 1.11.0 + oceanic.js: 1.1.1-dev.51a0d21_bufferutil@4.0.6 qrcode: 1.5.1 sharp: 0.30.7 shoukaku: github.com/Deivu/shoukaku/7822080092a13ea4cc71ab7d9f891f5cb933683b_bufferutil@4.0.6 @@ -57,14 +57,14 @@ optionalDependencies: pm2: 5.2.0_bufferutil@4.0.6 postgres: 3.2.4 uuid: 8.3.2 - ws: 8.8.1_bufferutil@4.0.6 + ws: 8.9.0_bufferutil@4.0.6 zlib-sync: 0.1.7 devDependencies: - '@babel/core': 7.19.0 - '@babel/eslint-parser': 7.18.9_eia2ig3m3pjccex4igkch6uffy - '@babel/eslint-plugin': 7.18.10_lp3qrsx55lt6xwfnux3kkcfwiu - '@babel/plugin-proposal-class-properties': 7.18.6_@babel+core@7.19.0 + '@babel/core': 7.19.1 + '@babel/eslint-parser': 7.19.1_zdglor7vg7osicr5spasq6cc5a + '@babel/eslint-plugin': 7.19.1_64ks3oho3y6ldxyvuvb3gc4oge + '@babel/plugin-proposal-class-properties': 7.18.6_@babel+core@7.19.1 eslint: 8.23.1 eslint-plugin-unicorn: 42.0.0_eslint@8.23.1 @@ -85,24 +85,24 @@ packages: '@babel/highlight': 7.18.6 dev: true - /@babel/compat-data/7.19.0: - resolution: {integrity: sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==} + /@babel/compat-data/7.19.1: + resolution: {integrity: sha512-72a9ghR0gnESIa7jBN53U32FOVCEoztyIlKaNoU05zRhEecduGK9L9c3ww7Mp06JiR+0ls0GBPFJQwwtjn9ksg==} engines: {node: '>=6.9.0'} dev: true - /@babel/core/7.19.0: - resolution: {integrity: sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==} + /@babel/core/7.19.1: + resolution: {integrity: sha512-1H8VgqXme4UXCRv7/Wa1bq7RVymKOzC7znjyFM8KiEzwFqcKUKYNoQef4GhdklgNvoBXyW4gYhuBNCM5o1zImw==} engines: {node: '>=6.9.0'} dependencies: '@ampproject/remapping': 2.2.0 '@babel/code-frame': 7.18.6 '@babel/generator': 7.19.0 - '@babel/helper-compilation-targets': 7.19.0_@babel+core@7.19.0 + '@babel/helper-compilation-targets': 7.19.1_@babel+core@7.19.1 '@babel/helper-module-transforms': 7.19.0 '@babel/helpers': 7.19.0 - '@babel/parser': 7.19.0 + '@babel/parser': 7.19.1 '@babel/template': 7.18.10 - '@babel/traverse': 7.19.0 + '@babel/traverse': 7.19.1 '@babel/types': 7.19.0 convert-source-map: 1.8.0 debug: 4.3.4 @@ -113,28 +113,28 @@ packages: - supports-color dev: true - /@babel/eslint-parser/7.18.9_eia2ig3m3pjccex4igkch6uffy: - resolution: {integrity: sha512-KzSGpMBggz4fKbRbWLNyPVTuQr6cmCcBhOyXTw/fieOVaw5oYAwcAj4a7UKcDYCPxQq+CG1NCDZH9e2JTXquiQ==} + /@babel/eslint-parser/7.19.1_zdglor7vg7osicr5spasq6cc5a: + resolution: {integrity: sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ==} engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} peerDependencies: '@babel/core': '>=7.11.0' eslint: ^7.5.0 || ^8.0.0 dependencies: - '@babel/core': 7.19.0 + '@babel/core': 7.19.1 + '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 eslint: 8.23.1 - eslint-scope: 5.1.1 eslint-visitor-keys: 2.1.0 semver: 6.3.0 dev: true - /@babel/eslint-plugin/7.18.10_lp3qrsx55lt6xwfnux3kkcfwiu: - resolution: {integrity: sha512-iV1OZj/7eg4wZIcsVEkXS3MUWdhmpLsu2h+9Zr2ppywKWdCRs6VfjxbRzmHHYeurTizrrnaJ9ZkbO8KOv4lauQ==} + /@babel/eslint-plugin/7.19.1_64ks3oho3y6ldxyvuvb3gc4oge: + resolution: {integrity: sha512-ElGPkQPapKMa3zVqXHkZYzuL7I5LbRw9UWBUArgWsdWDDb9XcACqOpBib5tRPA9XvbVZYrFUkoQPbiJ4BFvu4w==} engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} peerDependencies: '@babel/eslint-parser': '>=7.11.0' eslint: '>=7.5.0' dependencies: - '@babel/eslint-parser': 7.18.9_eia2ig3m3pjccex4igkch6uffy + '@babel/eslint-parser': 7.19.1_zdglor7vg7osicr5spasq6cc5a eslint: 8.23.1 eslint-rule-composer: 0.3.0 dev: true @@ -155,32 +155,32 @@ packages: '@babel/types': 7.19.0 dev: true - /@babel/helper-compilation-targets/7.19.0_@babel+core@7.19.0: - resolution: {integrity: sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==} + /@babel/helper-compilation-targets/7.19.1_@babel+core@7.19.1: + resolution: {integrity: sha512-LlLkkqhCMyz2lkQPvJNdIYU7O5YjWRgC2R4omjCTpZd8u8KMQzZvX4qce+/BluN1rcQiV7BoGUpmQ0LeHerbhg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/compat-data': 7.19.0 - '@babel/core': 7.19.0 + '@babel/compat-data': 7.19.1 + '@babel/core': 7.19.1 '@babel/helper-validator-option': 7.18.6 - browserslist: 4.21.3 + browserslist: 4.21.4 semver: 6.3.0 dev: true - /@babel/helper-create-class-features-plugin/7.19.0_@babel+core@7.19.0: + /@babel/helper-create-class-features-plugin/7.19.0_@babel+core@7.19.1: resolution: {integrity: sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.19.0 + '@babel/core': 7.19.1 '@babel/helper-annotate-as-pure': 7.18.6 '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-function-name': 7.19.0 '@babel/helper-member-expression-to-functions': 7.18.9 '@babel/helper-optimise-call-expression': 7.18.6 - '@babel/helper-replace-supers': 7.18.9 + '@babel/helper-replace-supers': 7.19.1 '@babel/helper-split-export-declaration': 7.18.6 transitivePeerDependencies: - supports-color @@ -228,9 +228,9 @@ packages: '@babel/helper-module-imports': 7.18.6 '@babel/helper-simple-access': 7.18.6 '@babel/helper-split-export-declaration': 7.18.6 - '@babel/helper-validator-identifier': 7.18.6 + '@babel/helper-validator-identifier': 7.19.1 '@babel/template': 7.18.10 - '@babel/traverse': 7.19.0 + '@babel/traverse': 7.19.1 '@babel/types': 7.19.0 transitivePeerDependencies: - supports-color @@ -248,14 +248,14 @@ packages: engines: {node: '>=6.9.0'} dev: true - /@babel/helper-replace-supers/7.18.9: - resolution: {integrity: sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==} + /@babel/helper-replace-supers/7.19.1: + resolution: {integrity: sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw==} engines: {node: '>=6.9.0'} dependencies: '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-member-expression-to-functions': 7.18.9 '@babel/helper-optimise-call-expression': 7.18.6 - '@babel/traverse': 7.19.0 + '@babel/traverse': 7.19.1 '@babel/types': 7.19.0 transitivePeerDependencies: - supports-color @@ -280,8 +280,8 @@ packages: engines: {node: '>=6.9.0'} dev: true - /@babel/helper-validator-identifier/7.18.6: - resolution: {integrity: sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==} + /@babel/helper-validator-identifier/7.19.1: + resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} engines: {node: '>=6.9.0'} dev: true @@ -295,7 +295,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.18.10 - '@babel/traverse': 7.19.0 + '@babel/traverse': 7.19.1 '@babel/types': 7.19.0 transitivePeerDependencies: - supports-color @@ -305,27 +305,27 @@ packages: resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-validator-identifier': 7.18.6 + '@babel/helper-validator-identifier': 7.19.1 chalk: 2.4.2 js-tokens: 4.0.0 dev: true - /@babel/parser/7.19.0: - resolution: {integrity: sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==} + /@babel/parser/7.19.1: + resolution: {integrity: sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==} engines: {node: '>=6.0.0'} hasBin: true dependencies: '@babel/types': 7.19.0 dev: true - /@babel/plugin-proposal-class-properties/7.18.6_@babel+core@7.19.0: + /@babel/plugin-proposal-class-properties/7.18.6_@babel+core@7.19.1: resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.19.0 - '@babel/helper-create-class-features-plugin': 7.19.0_@babel+core@7.19.0 + '@babel/core': 7.19.1 + '@babel/helper-create-class-features-plugin': 7.19.0_@babel+core@7.19.1 '@babel/helper-plugin-utils': 7.19.0 transitivePeerDependencies: - supports-color @@ -336,12 +336,12 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.18.6 - '@babel/parser': 7.19.0 + '@babel/parser': 7.19.1 '@babel/types': 7.19.0 dev: true - /@babel/traverse/7.19.0: - resolution: {integrity: sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==} + /@babel/traverse/7.19.1: + resolution: {integrity: sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA==} engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.18.6 @@ -350,7 +350,7 @@ packages: '@babel/helper-function-name': 7.19.0 '@babel/helper-hoist-variables': 7.18.6 '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.19.0 + '@babel/parser': 7.19.1 '@babel/types': 7.19.0 debug: 4.3.4 globals: 11.12.0 @@ -363,7 +363,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/helper-string-parser': 7.18.10 - '@babel/helper-validator-identifier': 7.18.6 + '@babel/helper-validator-identifier': 7.19.1 to-fast-properties: 2.0.0 dev: true @@ -380,6 +380,26 @@ packages: kuler: 2.0.0 dev: false + /@discordjs/voice/0.11.0_bufferutil@4.0.6: + resolution: {integrity: sha512-6+9cj1dxzBJm7WJ9qyG2XZZQ8rcLl6x2caW0C0OxuTtMLAaEDntpb6lqMTFiBg/rDc4Rd59g1w0gJmib33CuHw==} + engines: {node: '>=16.9.0'} + requiresBuild: true + dependencies: + '@types/ws': 8.5.3 + discord-api-types: 0.36.3 + prism-media: 1.3.4 + tslib: 2.4.0 + ws: 8.9.0_bufferutil@4.0.6 + transitivePeerDependencies: + - '@discordjs/opus' + - bufferutil + - ffmpeg-static + - node-opus + - opusscript + - utf-8-validate + dev: false + optional: true + /@eslint/eslintrc/1.3.2: resolution: {integrity: sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -397,8 +417,8 @@ packages: - supports-color dev: true - /@humanwhocodes/config-array/0.10.4: - resolution: {integrity: sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==} + /@humanwhocodes/config-array/0.10.5: + resolution: {integrity: sha512-XVVDtp+dVvRxMoxSiSfasYaG02VEe1qH5cKgMQJWhol6HwzbcqoCMJi8dAGoYAO57jhUyhI6cWuRiTcRaDaYug==} engines: {node: '>=10.10.0'} dependencies: '@humanwhocodes/object-schema': 1.2.1 @@ -459,6 +479,12 @@ packages: '@jridgewell/sourcemap-codec': 1.4.14 dev: true + /@nicolo-ribaudo/eslint-scope-5-internals/5.1.1-v1: + resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} + dependencies: + eslint-scope: 5.1.1 + dev: true + /@nodelib/fs.scandir/2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -563,7 +589,7 @@ packages: axios: 0.21.4_debug@4.3.4 debug: 4.3.4 eventemitter2: 6.4.9 - ws: 7.4.6_bufferutil@4.0.6 + ws: 7.5.9_bufferutil@4.0.6 transitivePeerDependencies: - bufferutil - supports-color @@ -599,10 +625,22 @@ packages: - encoding dev: false + /@types/node/18.7.19: + resolution: {integrity: sha512-Sq1itGUKUX1ap7GgZlrzdBydjbsJL/NSQt/4wkAxUJ7/OS5c2WkoN6WSpWc2Yc5wtKMZOUA0VCs/j2XJadN3HA==} + dev: false + optional: true + /@types/normalize-package-data/2.4.1: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} dev: true + /@types/ws/8.5.3: + resolution: {integrity: sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==} + dependencies: + '@types/node': 18.7.19 + dev: false + optional: true + /acorn-jsx/5.3.2_acorn@8.8.0: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -748,7 +786,7 @@ packages: /axios/0.21.4_debug@4.3.4: resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} dependencies: - follow-redirects: 1.15.1_debug@4.3.4 + follow-redirects: 1.15.2_debug@4.3.4 transitivePeerDependencies: - debug dev: false @@ -834,15 +872,15 @@ packages: dependencies: fill-range: 7.0.1 - /browserslist/4.21.3: - resolution: {integrity: sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==} + /browserslist/4.21.4: + resolution: {integrity: sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001397 - electron-to-chromium: 1.4.247 + caniuse-lite: 1.0.30001410 + electron-to-chromium: 1.4.259 node-releases: 2.0.6 - update-browserslist-db: 1.0.8_browserslist@4.21.3 + update-browserslist-db: 1.0.9_browserslist@4.21.4 dev: true /buffer-from/1.1.2: @@ -904,8 +942,8 @@ packages: engines: {node: '>=6'} dev: false - /caniuse-lite/1.0.30001397: - resolution: {integrity: sha512-SW9N2TbCdLf0eiNDRrrQXx2sOkaakNZbCjgNpPyMJJbiOrU5QzMIrXOVMRM1myBXTD5iTkdrtU/EguCrBocHlA==} + /caniuse-lite/1.0.30001410: + resolution: {integrity: sha512-QoblBnuE+rG0lc3Ur9ltP5q47lbguipa/ncNMyyGuqPk44FxbScWAeEO+k5fSQ8WekdAK4mWqNs1rADDAiN5xQ==} dev: true /chainsaw/0.1.0: @@ -1211,6 +1249,11 @@ packages: path-type: 4.0.0 dev: true + /discord-api-types/0.36.3: + resolution: {integrity: sha512-bz/NDyG0KBo/tY14vSkrwQ/n3HKPf87a0WFW/1M9+tXYK+vp5Z5EksawfCWo2zkAc6o7CClc0eff1Pjrqznlwg==} + dev: false + optional: true + /doctrine/3.0.0: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} @@ -1226,11 +1269,11 @@ packages: /duplexer2/0.1.4: resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==} dependencies: - readable-stream: 2.3.7 + readable-stream: 2.1.5 dev: false - /electron-to-chromium/1.4.247: - resolution: {integrity: sha512-FLs6R4FQE+1JHM0hh3sfdxnYjKvJpHZyhQDjc2qFq/xFvmmRt/TATNToZhrcGUFzpF2XjeiuozrA8lI0PZmYYw==} + /electron-to-chromium/1.4.259: + resolution: {integrity: sha512-dzbPZG0PKsqiSxfZovjBZn5InX4OoSITSsJ5S/U0QRrFaKsQtHx352zbyqtiDpNpX5lnPCAeBS6D+QpWipqDRw==} dev: true /emitter-listener/1.1.2: @@ -1310,7 +1353,7 @@ packages: peerDependencies: eslint: '>=8.8.0' dependencies: - '@babel/helper-validator-identifier': 7.18.6 + '@babel/helper-validator-identifier': 7.19.1 ci-info: 3.4.0 clean-regexp: 1.0.0 eslint: 8.23.1 @@ -1374,7 +1417,7 @@ packages: hasBin: true dependencies: '@eslint/eslintrc': 1.3.2 - '@humanwhocodes/config-array': 0.10.4 + '@humanwhocodes/config-array': 0.10.5 '@humanwhocodes/gitignore-to-minimatch': 1.0.2 '@humanwhocodes/module-importer': 1.0.1 ajv: 6.12.6 @@ -1591,8 +1634,8 @@ packages: resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} dev: false - /follow-redirects/1.15.1_debug@4.3.4: - resolution: {integrity: sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==} + /follow-redirects/1.15.2_debug@4.3.4: + resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} engines: {node: '>=4.0'} peerDependencies: debug: '*' @@ -2122,7 +2165,7 @@ packages: '@colors/colors': 1.5.0 fecha: 4.2.3 ms: 2.1.3 - safe-stable-stringify: 2.3.1 + safe-stable-stringify: 2.4.0 triple-beam: 1.3.0 dev: false @@ -2341,6 +2384,23 @@ packages: engines: {node: '>= 6'} dev: false + /oceanic.js/1.1.1-dev.51a0d21_bufferutil@4.0.6: + resolution: {integrity: sha512-Ks/SuYCY9inHSU0iHAWBUwy73den1T4DDs8HbyYMXDE36o3RYjQx5w54u5gZ5pjoEBg7/Ik1hQbJmfC0kH8F9g==} + engines: {node: '>=16.16.0'} + dependencies: + undici: 5.10.0 + ws: 8.9.0_bufferutil@4.0.6 + optionalDependencies: + '@discordjs/voice': 0.11.0_bufferutil@4.0.6 + transitivePeerDependencies: + - '@discordjs/opus' + - bufferutil + - ffmpeg-static + - node-opus + - opusscript + - utf-8-validate + dev: false + /once/1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: @@ -2657,6 +2717,25 @@ packages: engines: {node: '>= 0.8.0'} dev: true + /prism-media/1.3.4: + resolution: {integrity: sha512-eW7LXORkTCQznZs+eqe9VjGOrLBxcBPXgNyHXMTSRVhphvd/RrxgIR7WaWt4fkLuhshcdT5KHL88LAfcvS3f5g==} + peerDependencies: + '@discordjs/opus': ^0.8.0 + ffmpeg-static: ^5.0.2 || ^4.2.7 || ^3.0.0 || ^2.4.0 + node-opus: ^0.3.3 + opusscript: ^0.0.8 + peerDependenciesMeta: + '@discordjs/opus': + optional: true + ffmpeg-static: + optional: true + node-opus: + optional: true + opusscript: + optional: true + dev: false + optional: true + /process-nextick-args/1.0.7: resolution: {integrity: sha512-yN0WQmuCX63LP/TMvAg31nvT6m4vDqJEiiv2CAZqWOGNWutc9DfDk1NPYYmKUFmaVM2UwDowH4u5AHWYP/jxKw==} dev: false @@ -2922,8 +3001,8 @@ packages: regexp-tree: 0.1.24 dev: true - /safe-stable-stringify/2.3.1: - resolution: {integrity: sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg==} + /safe-stable-stringify/2.4.0: + resolution: {integrity: sha512-eehKHKpab6E741ud7ZIMcXhKcP6TSIezPkNZhy5U8xC6+VvrRdUA2tMgxGxaGl4cz7c2Ew5+mg5+wNB16KQqrA==} engines: {node: '>=10'} dev: false @@ -3378,13 +3457,13 @@ packages: setimmediate: 1.0.5 dev: false - /update-browserslist-db/1.0.8_browserslist@4.21.3: - resolution: {integrity: sha512-GHg7C4M7oJSJYW/ED/5QOJ7nL/E0lwTOBGsOorA7jqHr8ExUhPfwAotIAmdSw/LWv3SMLSNpzTAgeLG9zaZKTA==} + /update-browserslist-db/1.0.9_browserslist@4.21.4: + resolution: {integrity: sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' dependencies: - browserslist: 4.21.3 + browserslist: 4.21.4 escalade: 3.1.1 picocolors: 1.0.0 dev: true @@ -3514,7 +3593,7 @@ packages: logform: 2.4.2 one-time: 1.0.0 readable-stream: 3.6.0 - safe-stable-stringify: 2.3.1 + safe-stable-stringify: 2.4.0 stack-trace: 0.0.10 triple-beam: 1.3.0 winston-transport: 4.5.0 @@ -3560,8 +3639,24 @@ packages: dev: false optional: true - /ws/8.8.1_bufferutil@4.0.6: - resolution: {integrity: sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==} + /ws/7.5.9_bufferutil@4.0.6: + resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dependencies: + bufferutil: 4.0.6 + dev: false + optional: true + + /ws/8.9.0_bufferutil@4.0.6: + resolution: {integrity: sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -3664,7 +3759,7 @@ packages: requiresBuild: true dependencies: undici: 5.10.0 - ws: 8.8.1_bufferutil@4.0.6 + ws: 8.9.0_bufferutil@4.0.6 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -3680,16 +3775,3 @@ packages: nan: 2.16.0 dev: false optional: true - - github.com/esmBot/eris/fbc637e7f92963d7f9e57c86223e995269e70de0_bufferutil@4.0.6: - resolution: {tarball: https://codeload.github.com/esmBot/eris/tar.gz/fbc637e7f92963d7f9e57c86223e995269e70de0} - id: github.com/esmBot/eris/fbc637e7f92963d7f9e57c86223e995269e70de0 - name: eris - version: 0.17.2-dev - engines: {node: '>=10.4.0'} - dependencies: - ws: 8.8.1_bufferutil@4.0.6 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - dev: false diff --git a/utils/database/postgresql.js b/utils/database/postgresql.js index 4c8b696..c44e4c8 100644 --- a/utils/database/postgresql.js +++ b/utils/database/postgresql.js @@ -118,16 +118,16 @@ export async function enableCommand(guild, command) { } export async function disableChannel(channel) { - const guildDB = await this.getGuild(channel.guild.id); - await sql`UPDATE guilds SET disabled_commands = ${[...guildDB.disabled, channel.id]} WHERE guild_id = ${channel.guild.id}`; - disabledCache.set(channel.guild.id, [...guildDB.disabled, channel.id]); + const guildDB = await this.getGuild(channel.guildID); + await sql`UPDATE guilds SET disabled_commands = ${[...guildDB.disabled, channel.id]} WHERE guild_id = ${channel.guildID}`; + disabledCache.set(channel.guildID, [...guildDB.disabled, channel.id]); } export async function enableChannel(channel) { - const guildDB = await this.getGuild(channel.guild.id); + const guildDB = await this.getGuild(channel.guildID); const newDisabled = guildDB.disabled.filter(item => item !== channel.id); - await sql`UPDATE guilds SET disabled_commands = ${newDisabled} WHERE guild_id = ${channel.guild.id}`; - disabledCache.set(channel.guild.id, newDisabled); + await sql`UPDATE guilds SET disabled_commands = ${newDisabled} WHERE guild_id = ${channel.guildID}`; + disabledCache.set(channel.guildID, newDisabled); } export async function getCounts() { diff --git a/utils/database/sqlite.js b/utils/database/sqlite.js index 9d24417..7621455 100644 --- a/utils/database/sqlite.js +++ b/utils/database/sqlite.js @@ -106,16 +106,16 @@ export async function enableCommand(guild, command) { } export async function disableChannel(channel) { - const guildDB = await this.getGuild(channel.guild.id); - connection.prepare("UPDATE guilds SET disabled = ? WHERE guild_id = ?").run(JSON.stringify([...JSON.parse(guildDB.disabled), channel.id]), channel.guild.id); - collections.disabledCache.set(channel.guild.id, [...JSON.parse(guildDB.disabled), channel.id]); + const guildDB = await this.getGuild(channel.guildID); + connection.prepare("UPDATE guilds SET disabled = ? WHERE guild_id = ?").run(JSON.stringify([...JSON.parse(guildDB.disabled), channel.id]), channel.guildID); + collections.disabledCache.set(channel.guildID, [...JSON.parse(guildDB.disabled), channel.id]); } export async function enableChannel(channel) { - const guildDB = await this.getGuild(channel.guild.id); + const guildDB = await this.getGuild(channel.guildID); const newDisabled = JSON.parse(guildDB.disabled).filter(item => item !== channel.id); - connection.prepare("UPDATE guilds SET disabled = ? WHERE guild_id = ?").run(JSON.stringify(newDisabled), channel.guild.id); - collections.disabledCache.set(channel.guild.id, newDisabled); + connection.prepare("UPDATE guilds SET disabled = ? WHERE guild_id = ?").run(JSON.stringify(newDisabled), channel.guildID); + collections.disabledCache.set(channel.guildID, newDisabled); } export async function getTag(guild, tag) { diff --git a/utils/handler.js b/utils/handler.js index 0321478..e842aa8 100644 --- a/utils/handler.js +++ b/utils/handler.js @@ -122,9 +122,9 @@ export async function send(bot) { log("info", "Sending application command data to Discord..."); let cmdArray = commandArray.main; if (process.env.ADMIN_SERVER && process.env.ADMIN_SERVER !== "") { - await bot.bulkEditGuildCommands(process.env.ADMIN_SERVER, commandArray.private); + await bot.application.bulkEditGuildCommands(process.env.ADMIN_SERVER, commandArray.private); } else { cmdArray = [...commandArray.main, ...commandArray.private]; } - await bot.bulkEditCommands(cmdArray); + await bot.application.bulkEditGlobalCommands(cmdArray); } \ No newline at end of file diff --git a/utils/imagedetect.js b/utils/imagedetect.js index 4857a79..2dd042b 100644 --- a/utils/imagedetect.js +++ b/utils/imagedetect.js @@ -131,8 +131,8 @@ const checkImages = async (message, extraReturnTypes, video, sticker) => { } } // then check the attachments - } else if (message.attachments.length !== 0 && message.attachments[0].width) { - type = await getImage(message.attachments[0].proxy_url, message.attachments[0].url, video); + } else if (message.attachments.size !== 0 && message.attachments.first().width) { + type = await getImage(message.attachments.first().proxyURL, message.attachments.first().url, video); } } // if the return value exists then return it @@ -147,7 +147,7 @@ export default async (client, cmdMessage, interaction, options, extraReturnTypes if (options) { if (options.image) { const attachment = interaction.data.resolved.attachments.get(options.image); - const result = await getImage(attachment.proxyUrl, attachment.url, video, attachment.contentType); + const result = await getImage(attachment.proxyURL, attachment.url, video, attachment.contentType); if (result !== false) return result; } else if (options.link) { const result = await getImage(options.link, options.link, video, extraReturnTypes, false, null, true); @@ -171,7 +171,8 @@ export default async (client, cmdMessage, interaction, options, extraReturnTypes if (!singleMessage) { // if there aren't any replies or interaction attachments then iterate over the last few messages in the channel try { - const messages = await client.getMessages((interaction ? interaction : cmdMessage).channel.id); + const channel = (interaction ? interaction : cmdMessage).channel ?? await client.rest.channels.get((interaction ? interaction : cmdMessage).channelID); + const messages = await channel.getMessages(); // iterate over each message for (const message of messages) { const result = await checkImages(message, extraReturnTypes, video, sticker); @@ -180,7 +181,7 @@ export default async (client, cmdMessage, interaction, options, extraReturnTypes } else { return result; } - } + } } catch { // no-op } diff --git a/utils/misc.js b/utils/misc.js index 4bac238..8c2d595 100644 --- a/utils/misc.js +++ b/utils/misc.js @@ -52,11 +52,12 @@ export function textEncode(string) { } // set activity (a.k.a. the gamer code) -export function activityChanger(bot) { +export async function activityChanger(bot) { if (!broadcast) { - bot.editStatus("dnd", { + await bot.editStatus("dnd", [{ + type: "GAME", name: random(messages) + (types.classic ? ` | @${bot.user.username} help` : ""), - }); + }]); } setTimeout(() => activityChanger(bot), 900000); } @@ -68,16 +69,18 @@ export function checkBroadcast(bot) { } export function startBroadcast(bot, message) { - bot.editStatus("dnd", { + bot.editStatus("dnd", [{ + type: "GAME", name: message + (types.classic ? ` | @${bot.user.username} help` : ""), - }); + }]); broadcast = true; } export function endBroadcast(bot) { - bot.editStatus("dnd", { + bot.editStatus("dnd", [{ + type: "GAME", name: random(messages) + (types.classic ? ` | @${bot.user.username} help` : ""), - }); + }]); broadcast = false; } @@ -107,4 +110,47 @@ export function getServers(bot) { resolve(bot.guilds.size); } }); +} + +// copied from eris +export function cleanMessage(message) { + let cleanContent = message.content && message.content.replace(//g, "$1") || ""; + + let authorName = message.author.username; + if (message.guildID) { + const member = message.guild.members.get(message.author.id); + if (member && member.nick) { + authorName = member.nick; + } + } + cleanContent = cleanContent.replace(new RegExp(`<@!?${message.author.id}>`, "g"), `@\u200b${authorName}`); + + if (message.mentions) { + for (const mention of message.mentions.members) { + if (message.guildID) { + const member = message.guild.members.get(mention.id); + if (member && member.nick) { + cleanContent = cleanContent.replace(new RegExp(`<@!?${mention.id}>`, "g"), `@\u200b${member.nick}`); + } + } + cleanContent = cleanContent.replace(new RegExp(`<@!?${mention.id}>`, "g"), `@\u200b${mention.username}`); + } + + if (message.guildID && message.mentions.roles) { + for (const roleID of message.mentions.roles) { + const role = message.guild.roles.get(roleID); + const roleName = role ? role.name : "deleted-role"; + cleanContent = cleanContent.replace(new RegExp(`<@&${roleID}>`, "g"), `@\u200b${roleName}`); + } + } + + for (const id of message.mentions.channels) { + const channel = message.client.getChannel(id); + if (channel && channel.name && channel.mention) { + cleanContent = cleanContent.replace(channel.mention, `#${channel.name}`); + } + } + } + + return cleanContent.replace(/@everyone/g, "@\u200beveryone").replace(/@here/g, "@\u200bhere"); } \ No newline at end of file diff --git a/utils/pagination/awaitinteractions.js b/utils/pagination/awaitinteractions.js index 39087d6..b416dfb 100644 --- a/utils/pagination/awaitinteractions.js +++ b/utils/pagination/awaitinteractions.js @@ -1,4 +1,4 @@ -// eris doesn't come with a method to wait for interactions by default, so we make our own +// oceanic doesn't come with a method to wait for interactions by default, so we make our own import { EventEmitter } from "events"; class InteractionCollector extends EventEmitter { diff --git a/utils/pagination/pagination.js b/utils/pagination/pagination.js index c73dad0..aa9f842 100644 --- a/utils/pagination/pagination.js +++ b/utils/pagination/pagination.js @@ -1,12 +1,12 @@ import InteractionCollector from "./awaitinteractions.js"; -import { ComponentInteraction } from "eris"; +import { ComponentInteraction } from "oceanic.js"; export default async (client, info, pages, timeout = 120000) => { const options = info.type === "classic" ? { messageReference: { - channelID: info.channel.id, + channelID: info.message.channelID, messageID: info.message.id, - guildID: info.channel.guild ? info.channel.guild.id : undefined, + guildID: info.message.guildID, failIfNotExists: false }, allowedMentions: { @@ -26,7 +26,7 @@ export default async (client, info, pages, timeout = 120000) => { name: "◀" }, style: 1, - custom_id: "back" + customID: "back" }, { type: 2, @@ -36,7 +36,7 @@ export default async (client, info, pages, timeout = 120000) => { name: "â–ļ" }, style: 1, - custom_id: "forward" + customID: "forward" }, { type: 2, @@ -46,7 +46,7 @@ export default async (client, info, pages, timeout = 120000) => { name: "đŸ”ĸ" }, style: 1, - custom_id: "jump" + customID: "jump" }, { type: 2, @@ -56,24 +56,24 @@ export default async (client, info, pages, timeout = 120000) => { name: "🗑" }, style: 4, - custom_id: "delete" + customID: "delete" } ] }] }; let currentPage; if (info.type === "classic") { - currentPage = await client.createMessage(info.message.channel.id, Object.assign(pages[page], options, pages.length > 1 ? components : {})); + currentPage = await client.rest.channels.createMessage(info.message.channelID, Object.assign(pages[page], options, pages.length > 1 ? components : {})); } else { - await info.interaction[info.interaction.acknowledged ? "editOriginalMessage" : "createMessage"](Object.assign(pages[page], pages.length > 1 ? components : {})); - currentPage = await info.interaction.getOriginalMessage(); + await info.interaction[info.interaction.acknowledged ? "editOriginal" : "createMessage"](Object.assign(pages[page], pages.length > 1 ? components : {})); + currentPage = await info.interaction.getOriginal(); } if (pages.length > 1) { const interactionCollector = new InteractionCollector(client, currentPage, ComponentInteraction, timeout); interactionCollector.on("interaction", async (interaction) => { if ((interaction.member ?? interaction.user).id === info.author.id) { - switch (interaction.data.custom_id) { + switch (interaction.data.customID) { case "back": await interaction.deferUpdate(); page = page > 0 ? --page : pages.length - 1; @@ -99,7 +99,7 @@ export default async (client, info, pages, timeout = 120000) => { type: 1, components: [{ type: 3, - custom_id: "seekDropdown", + customID: "seekDropdown", placeholder: "Page Number", options: [] }] @@ -114,11 +114,11 @@ export default async (client, info, pages, timeout = 120000) => { } var promise; if (info.type === "classic") { - promise = client.createMessage(info.message.channel.id, Object.assign({ content: "What page do you want to jump to?" }, { + promise = client.rest.channels.createMessage(info.message.channelID, Object.assign({ content: "What page do you want to jump to?" }, { messageReference: { - channelID: currentPage.channel.id, + channelID: currentPage.channelID, messageID: currentPage.id, - guildID: currentPage.channel.guild ? currentPage.channel.guild.id : undefined, + guildID: currentPage.guildID, failIfNotExists: false }, allowedMentions: { @@ -132,9 +132,9 @@ export default async (client, info, pages, timeout = 120000) => { const dropdownCollector = new InteractionCollector(client, askMessage, ComponentInteraction, timeout); let ended = false; dropdownCollector.on("interaction", async (response) => { - if (response.data.custom_id !== "seekDropdown") return; + if (response.data.customID !== "seekDropdown") return; try { - if (askMessage.channel.messages ? askMessage.channel.messages.has(askMessage.id) : await client.getMessage(askMessage.channel.id, askMessage.id).catch(() => undefined)) await askMessage.delete(); + await askMessage.delete(); } catch { // no-op } @@ -146,7 +146,7 @@ export default async (client, info, pages, timeout = 120000) => { dropdownCollector.once("end", async () => { if (ended) return; try { - if (askMessage.channel.messages ? askMessage.channel.messages.has(askMessage.id) : await client.getMessage(askMessage.channel.id, askMessage.id).catch(() => undefined)) await askMessage.delete(); + await askMessage.delete(); } catch { // no-op } @@ -159,7 +159,11 @@ export default async (client, info, pages, timeout = 120000) => { case "delete": await interaction.deferUpdate(); interactionCollector.emit("end", true); - if (currentPage.channel.messages ? currentPage.channel.messages.has(currentPage.id) : await client.getMessage(currentPage.channel.id, currentPage.id).catch(() => undefined)) await currentPage.delete(); + try { + await currentPage.delete(); + } catch { + // no-op + } return; default: break; @@ -172,8 +176,10 @@ export default async (client, info, pages, timeout = 120000) => { for (const index of components.components[0].components.keys()) { components.components[0].components[index].disabled = true; } - if (currentPage.channel.messages ? currentPage.channel.messages.has(currentPage.id) : await client.getMessage(currentPage.channel.id, currentPage.id).catch(() => undefined)) { + try { await currentPage.edit(components); + } catch { + // no-op } } }); diff --git a/utils/soundplayer.js b/utils/soundplayer.js index 85cda7c..f108981 100644 --- a/utils/soundplayer.js +++ b/utils/soundplayer.js @@ -32,7 +32,7 @@ export async function checkStatus() { } export function connect(client) { - manager = new Shoukaku(new Connectors.Eris(client), nodes, { moveOnDisconnect: true, resume: true, reconnectInterval: 500, reconnectTries: 1 }); + manager = new Shoukaku(new Connectors.OceanicJS(client), nodes, { moveOnDisconnect: true, resume: true, reconnectInterval: 500, reconnectTries: 1 }); client.emit("ready"); // workaround manager.on("error", (node, error) => { logger.error(`An error occurred on Lavalink node ${node}: ${error}`); @@ -66,7 +66,7 @@ export async function play(client, sound, options, music = false) { if (!options.channel.guild.permissionsOf(client.user.id).has("voiceConnect")) return { content: "I can't join this voice channel!", flags: 64 }; const voiceChannel = options.channel.guild.channels.get(options.member.voiceState.channelID); if (!voiceChannel.permissionsOf(client.user.id).has("voiceConnect")) return { content: "I don't have permission to join this voice channel!", flags: 64 }; - if (!music && manager.players.has(options.channel.guild.id)) return { content: "I can't play a sound effect while other audio is playing!", flags: 64 }; + if (!music && manager.players.has(options.channel.guildID)) return { content: "I can't play a sound effect while other audio is playing!", flags: 64 }; let node = manager.getNode(); if (!node) { const status = await checkStatus(); @@ -87,17 +87,17 @@ export async function play(client, sound, options, music = false) { logger.error(e); return { content: "🔊 Hmmm, seems that all of the audio servers are down. Try again in a bit.", flags: 64 }; } - const oldQueue = queues.get(voiceChannel.guild.id); + const oldQueue = queues.get(voiceChannel.guildID); if (!response.tracks || response.tracks.length === 0) return { content: "I couldn't find that song!", flags: 64 }; if (music) { const sortedTracks = response.tracks.map((val) => { return val.track; }); const playlistTracks = response.playlistInfo.selectedTrack ? sortedTracks : [sortedTracks[0]]; - queues.set(voiceChannel.guild.id, oldQueue ? [...oldQueue, ...playlistTracks] : playlistTracks); + queues.set(voiceChannel.guildID, oldQueue ? [...oldQueue, ...playlistTracks] : playlistTracks); } - const playerMeta = players.get(options.channel.guild.id); + const playerMeta = players.get(options.channel.guildID); let player; - if (node.players.has(voiceChannel.guild.id)) { - player = node.players.get(voiceChannel.guild.id); + if (node.players.has(voiceChannel.guildID)) { + player = node.players.get(voiceChannel.guildID); } else if (playerMeta?.player) { const storedState = playerMeta?.player?.connection.state; if (storedState && storedState === 1) { @@ -105,7 +105,7 @@ export async function play(client, sound, options, music = false) { } } const connection = player ?? await node.joinChannel({ - guildId: voiceChannel.guild.id, + guildId: voiceChannel.guildID, channelId: voiceChannel.id, shardId: voiceChannel.guild.shard.id, deaf: true @@ -120,19 +120,19 @@ export async function play(client, sound, options, music = false) { } export async function nextSong(client, options, connection, track, info, music, voiceChannel, host, loop = false, shuffle = false, lastTrack = null) { - skipVotes.delete(voiceChannel.guild.id); + skipVotes.delete(voiceChannel.guildID); const parts = Math.floor((0 / info.length) * 10); let playingMessage; - if (music && lastTrack === track && players.has(voiceChannel.guild.id)) { - playingMessage = players.get(voiceChannel.guild.id).playMessage; + if (music && lastTrack === track && players.has(voiceChannel.guildID)) { + playingMessage = players.get(voiceChannel.guildID).playMessage; } else { try { - const content = !music ? "🔊 Playing sound..." : { + const content = !music ? { content: "🔊 Playing sound..." } : { embeds: [{ color: 16711680, author: { name: "Now Playing", - icon_url: client.user.avatarURL + iconURL: client.user.avatarURL }, fields: [{ name: "ℹī¸ Title", @@ -157,7 +157,7 @@ export async function nextSong(client, options, connection, track, info, music, }] }; if (options.type === "classic") { - playingMessage = await client.createMessage(options.channel.id, content); + playingMessage = await client.rest.channels.createMessage(options.channel.id, content); } else { await options.interaction[options.interaction.acknowledged ? "editOriginalMessage" : "createMessage"](content); playingMessage = await options.interaction.getOriginalMessage(); @@ -171,30 +171,30 @@ export async function nextSong(client, options, connection, track, info, music, connection.removeAllListeners("end"); connection.setVolume(0.70); connection.playTrack({ track }); - players.set(voiceChannel.guild.id, { player: connection, type: music ? "music" : "sound", host: host, voiceChannel: voiceChannel, originalChannel: options.channel, loop, shuffle, playMessage: playingMessage }); + players.set(voiceChannel.guildID, { player: connection, type: music ? "music" : "sound", host: host, voiceChannel: voiceChannel, originalChannel: options.channel, loop, shuffle, playMessage: playingMessage }); connection.once("exception", async (exception) => { try { if (playingMessage.channel.messages.has(playingMessage.id)) await playingMessage.delete(); - const playMessage = players.get(voiceChannel.guild.id).playMessage; + const playMessage = players.get(voiceChannel.guildID).playMessage; if (playMessage.channel.messages.has(playMessage.id)) await playMessage.delete(); } catch { // no-op } try { - connection.node.leaveChannel(voiceChannel.guild.id); + connection.node.leaveChannel(voiceChannel.guildID); } catch { // no-op } connection.removeAllListeners("stuck"); connection.removeAllListeners("end"); - players.delete(voiceChannel.guild.id); - queues.delete(voiceChannel.guild.id); + players.delete(voiceChannel.guildID); + queues.delete(voiceChannel.guildID); logger.error(exception.error); const content = `🔊 Looks like there was an error regarding sound playback:\n\`\`\`${exception.type}: ${exception.error}\`\`\``; if (options.type === "classic") { - await client.createMessage(options.channel.id, content); + await client.rest.channels.createMessage(options.channel.id, { content }); } else { - await options.interaction.createMessage(content); + await options.interaction.createMessage({ content }); } }); connection.on("stuck", () => { @@ -204,11 +204,11 @@ export async function nextSong(client, options, connection, track, info, music, }); connection.on("end", async (data) => { if (data.reason === "REPLACED") return; - let queue = queues.get(voiceChannel.guild.id); - const player = players.get(voiceChannel.guild.id); + let queue = queues.get(voiceChannel.guildID); + const player = players.get(voiceChannel.guildID); if (player && process.env.STAYVC === "true") { player.type = "idle"; - players.set(voiceChannel.guild.id, player); + players.set(voiceChannel.guildID, player); } let newQueue; if (player?.shuffle) { @@ -225,7 +225,7 @@ export async function nextSong(client, options, connection, track, info, music, } else { newQueue = queue ? queue.slice(1) : []; } - queues.set(voiceChannel.guild.id, newQueue); + queues.set(voiceChannel.guildID, newQueue); if (newQueue.length !== 0) { const newTrack = await connection.node.rest.decode(newQueue[0]); nextSong(client, options, connection, newQueue[0], newTrack, music, voiceChannel, host, player.loop, player.shuffle, track); @@ -239,15 +239,15 @@ export async function nextSong(client, options, connection, track, info, music, } } else if (process.env.STAYVC !== "true") { await setTimeout(400); - connection.node.leaveChannel(voiceChannel.guild.id); - players.delete(voiceChannel.guild.id); - queues.delete(voiceChannel.guild.id); - skipVotes.delete(voiceChannel.guild.id); + connection.node.leaveChannel(voiceChannel.guildID); + players.delete(voiceChannel.guildID); + queues.delete(voiceChannel.guildID); + skipVotes.delete(voiceChannel.guildID); const content = `🔊 The voice channel session in \`${voiceChannel.name}\` has ended.`; if (options.type === "classic") { - await client.createMessage(options.channel.id, content); + await client.rest.channels.createMessage(options.channel.id, { content }); } else { - await options.interaction.createMessage(content); + await options.interaction.createMessage({ content }); } } if (options.type === "classic") { diff --git a/utils/tempimages.js b/utils/tempimages.js index 9d744ab..22b5cf3 100644 --- a/utils/tempimages.js +++ b/utils/tempimages.js @@ -23,11 +23,11 @@ export async function upload(client, result, context, interaction = false) { if (interaction) { await context[context.acknowledged ? "editOriginalMessage" : "createMessage"](payload); } else { - await client.createMessage(context.channel.id, Object.assign(payload, { + await client.rest.channels.createMessage(context.channel.id, Object.assign(payload, { messageReference: { channelID: context.channel.id, messageID: context.id, - guildID: context.channel.guild ? context.channel.guild.id : undefined, + guildID: context.channel.guildID ?? undefined, failIfNotExists: false }, allowedMentions: {