From be71357ff98d36923ac38f9f0ccd434bf5efedf6 Mon Sep 17 00:00:00 2001
From: Dark <7890309+DarkView@users.noreply.github.com>
Date: Wed, 30 Jun 2021 18:43:42 +0200
Subject: [PATCH] Upgrade DJS, fix bugs

---
 backend/package-lock.json                     | 79 +++++++++++++++----
 backend/package.json                          |  2 +-
 .../BotControl/commands/DisallowServerCmd.ts  |  4 +-
 .../BotControl/commands/LeaveServerCmd.ts     |  8 +-
 .../BotControl/commands/ReloadServerCmd.ts    |  6 +-
 .../commands/ArchiveChannelCmd.ts             |  2 +-
 .../plugins/ModActions/commands/MassBanCmd.ts |  6 +-
 .../ModActions/commands/MassUnbanCmd.ts       |  7 +-
 .../ModActions/commands/MassmuteCmd.ts        |  4 +-
 .../plugins/NameHistory/commands/NamesCmd.ts  |  3 +-
 .../commands/PostButtonRolesCmd.ts            |  2 +-
 .../src/plugins/Utility/commands/AboutCmd.ts  | 45 ++++++-----
 .../src/plugins/Utility/commands/CleanCmd.ts  |  2 +-
 .../plugins/Utility/commands/ContextCmd.ts    |  4 +-
 .../src/plugins/Utility/commands/InfoCmd.ts   |  2 +-
 .../src/plugins/Utility/commands/VcmoveCmd.ts | 10 +--
 backend/src/plugins/Utility/search.ts         |  3 +-
 17 files changed, 123 insertions(+), 66 deletions(-)

diff --git a/backend/package-lock.json b/backend/package-lock.json
index 4809cb21..6a2cfff2 100644
--- a/backend/package-lock.json
+++ b/backend/package-lock.json
@@ -14,7 +14,7 @@
         "cors": "^2.8.5",
         "cross-env": "^5.2.0",
         "deep-diff": "^1.0.2",
-        "discord.js": "^13.0.0-dev.edab5af.1624996138",
+        "discord.js": "^13.0.0-dev.64f093f.1625054868",
         "dotenv": "^4.0.0",
         "emoji-regex": "^8.0.0",
         "erlpack": "github:discord/erlpack",
@@ -161,6 +161,24 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/@discordjs/builders": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.1.1.tgz",
+      "integrity": "sha512-9eBC22bX2HBsob5ixMwZ6quy/vewU5GHuSJhpmSZ3cDGg8XPnrYdzbwI54U+V9kQBTa7M+aMu1lYVqMEPojj8A==",
+      "dependencies": {
+        "discord-api-types": "^0.18.1",
+        "tslib": "^2.3.0"
+      },
+      "engines": {
+        "node": ">=14.0.0",
+        "npm": ">=7.0.0"
+      }
+    },
+    "node_modules/@discordjs/builders/node_modules/tslib": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
+      "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
+    },
     "node_modules/@discordjs/collection": {
       "version": "0.1.6",
       "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz",
@@ -2133,11 +2151,20 @@
         "node": ">=8"
       }
     },
+    "node_modules/discord-api-types": {
+      "version": "0.18.1",
+      "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.18.1.tgz",
+      "integrity": "sha512-hNC38R9ZF4uaujaZQtQfm5CdQO58uhdkoHQAVvMfIL0LgOSZeW575W8H6upngQOuoxWd8tiRII3LLJm9zuQKYg==",
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/discord.js": {
-      "version": "13.0.0-dev.edab5af.1624996138",
-      "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.0.0-dev.edab5af.1624996138.tgz",
-      "integrity": "sha512-WGbizyvt23aorgHH4dP4vDB/v7NT2szQOdLaeypzjiP89e3yvtVOPDpoFdm03PPzG65n4K005/qfN4yBVVbysw==",
+      "version": "13.0.0-dev.64f093f.1625054868",
+      "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.0.0-dev.64f093f.1625054868.tgz",
+      "integrity": "sha512-CgpgvpcALYmEhgGETAxFHMqt+XmuTbcSYIN+kLyzualzHNQ2RageW3tslgLgSnBdID60AMvXN/nzMuEn/J6rAA==",
       "dependencies": {
+        "@discordjs/builders": "^0.1.1",
         "@discordjs/collection": "^0.1.6",
         "@discordjs/form-data": "^3.0.1",
         "@sapphire/async-queue": "^1.1.4",
@@ -2145,7 +2172,7 @@
         "abort-controller": "^3.0.0",
         "discord-api-types": "^0.19.0-next.f393ba520d7d6d2aacaca7b3ca5d355fab614f6e",
         "node-fetch": "^2.6.1",
-        "ws": "^7.5.0"
+        "ws": "^7.5.1"
       },
       "engines": {
         "node": ">=14.0.0",
@@ -6134,9 +6161,9 @@
       }
     },
     "node_modules/ws": {
-      "version": "7.5.0",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.0.tgz",
-      "integrity": "sha512-6ezXvzOZupqKj4jUqbQ9tXuJNo+BR2gU8fFRk3XCP3e0G6WT414u5ELe6Y0vtp7kmSJ3F7YWObSNr1ESsgi4vw==",
+      "version": "7.5.1",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.1.tgz",
+      "integrity": "sha512-2c6faOUH/nhoQN6abwMloF7Iyl0ZS2E9HGtsiLrWn0zOOMWlhtDmdf/uihDt6jnuCxgtwGBNy6Onsoy2s2O2Ow==",
       "engines": {
         "node": ">=8.3.0"
       },
@@ -6410,6 +6437,22 @@
         }
       }
     },
+    "@discordjs/builders": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.1.1.tgz",
+      "integrity": "sha512-9eBC22bX2HBsob5ixMwZ6quy/vewU5GHuSJhpmSZ3cDGg8XPnrYdzbwI54U+V9kQBTa7M+aMu1lYVqMEPojj8A==",
+      "requires": {
+        "discord-api-types": "^0.18.1",
+        "tslib": "^2.3.0"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
+          "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
+        }
+      }
+    },
     "@discordjs/collection": {
       "version": "0.1.6",
       "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz",
@@ -7986,11 +8029,17 @@
         "path-type": "^4.0.0"
       }
     },
+    "discord-api-types": {
+      "version": "0.18.1",
+      "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.18.1.tgz",
+      "integrity": "sha512-hNC38R9ZF4uaujaZQtQfm5CdQO58uhdkoHQAVvMfIL0LgOSZeW575W8H6upngQOuoxWd8tiRII3LLJm9zuQKYg=="
+    },
     "discord.js": {
-      "version": "13.0.0-dev.edab5af.1624996138",
-      "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.0.0-dev.edab5af.1624996138.tgz",
-      "integrity": "sha512-WGbizyvt23aorgHH4dP4vDB/v7NT2szQOdLaeypzjiP89e3yvtVOPDpoFdm03PPzG65n4K005/qfN4yBVVbysw==",
+      "version": "13.0.0-dev.64f093f.1625054868",
+      "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.0.0-dev.64f093f.1625054868.tgz",
+      "integrity": "sha512-CgpgvpcALYmEhgGETAxFHMqt+XmuTbcSYIN+kLyzualzHNQ2RageW3tslgLgSnBdID60AMvXN/nzMuEn/J6rAA==",
       "requires": {
+        "@discordjs/builders": "^0.1.1",
         "@discordjs/collection": "^0.1.6",
         "@discordjs/form-data": "^3.0.1",
         "@sapphire/async-queue": "^1.1.4",
@@ -7998,7 +8047,7 @@
         "abort-controller": "^3.0.0",
         "discord-api-types": "^0.19.0-next.f393ba520d7d6d2aacaca7b3ca5d355fab614f6e",
         "node-fetch": "^2.6.1",
-        "ws": "^7.5.0"
+        "ws": "^7.5.1"
       },
       "dependencies": {
         "discord-api-types": {
@@ -11132,9 +11181,9 @@
       }
     },
     "ws": {
-      "version": "7.5.0",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.0.tgz",
-      "integrity": "sha512-6ezXvzOZupqKj4jUqbQ9tXuJNo+BR2gU8fFRk3XCP3e0G6WT414u5ELe6Y0vtp7kmSJ3F7YWObSNr1ESsgi4vw==",
+      "version": "7.5.1",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.1.tgz",
+      "integrity": "sha512-2c6faOUH/nhoQN6abwMloF7Iyl0ZS2E9HGtsiLrWn0zOOMWlhtDmdf/uihDt6jnuCxgtwGBNy6Onsoy2s2O2Ow==",
       "requires": {}
     },
     "xdg-basedir": {
diff --git a/backend/package.json b/backend/package.json
index 73213034..9cf5f4b3 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -29,7 +29,7 @@
     "cors": "^2.8.5",
     "cross-env": "^5.2.0",
     "deep-diff": "^1.0.2",
-    "discord.js": "^13.0.0-dev.edab5af.1624996138",
+    "discord.js": "^13.0.0-dev.64f093f.1625054868",
     "dotenv": "^4.0.0",
     "emoji-regex": "^8.0.0",
     "erlpack": "github:discord/erlpack",
diff --git a/backend/src/plugins/BotControl/commands/DisallowServerCmd.ts b/backend/src/plugins/BotControl/commands/DisallowServerCmd.ts
index 9dfd9599..1a9cf64a 100644
--- a/backend/src/plugins/BotControl/commands/DisallowServerCmd.ts
+++ b/backend/src/plugins/BotControl/commands/DisallowServerCmd.ts
@@ -1,4 +1,4 @@
-import { TextChannel } from "discord.js";
+import { Snowflake, TextChannel } from "discord.js";
 import { commandTypeHelpers as ct } from "../../../commandTypes";
 import { isOwnerPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
 import { noop } from "../../../utils";
@@ -24,7 +24,7 @@ export const DisallowServerCmd = botControlCmd({
 
     await pluginData.state.allowedGuilds.remove(args.guildId);
     await pluginData.client.guilds.cache
-      .get(args.guildId)
+      .get(args.guildId as Snowflake)
       ?.leave()
       .catch(noop);
     sendSuccessMessage(pluginData, msg.channel as TextChannel, "Server removed!");
diff --git a/backend/src/plugins/BotControl/commands/LeaveServerCmd.ts b/backend/src/plugins/BotControl/commands/LeaveServerCmd.ts
index 8352548a..b502c08f 100644
--- a/backend/src/plugins/BotControl/commands/LeaveServerCmd.ts
+++ b/backend/src/plugins/BotControl/commands/LeaveServerCmd.ts
@@ -1,4 +1,4 @@
-import { TextChannel } from "discord.js";
+import { Snowflake, TextChannel } from "discord.js";
 import { commandTypeHelpers as ct } from "../../../commandTypes";
 import { isOwnerPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
 import { botControlCmd } from "../types";
@@ -15,16 +15,16 @@ export const LeaveServerCmd = botControlCmd({
   },
 
   async run({ pluginData, message: msg, args }) {
-    if (!pluginData.client.guilds.cache.has(args.guildId)) {
+    if (!pluginData.client.guilds.cache.has(args.guildId as Snowflake)) {
       sendErrorMessage(pluginData, msg.channel as TextChannel, "I am not in that guild");
       return;
     }
 
-    const guildToLeave = await pluginData.client.guilds.fetch(args.guildId)!;
+    const guildToLeave = await pluginData.client.guilds.fetch(args.guildId as Snowflake)!;
     const guildName = guildToLeave.name;
 
     try {
-      await pluginData.client.guilds.cache.get(args.guildId)?.leave();
+      await pluginData.client.guilds.cache.get(args.guildId as Snowflake)?.leave();
     } catch (e) {
       sendErrorMessage(pluginData, msg.channel as TextChannel, `Failed to leave guild: ${e.message}`);
       return;
diff --git a/backend/src/plugins/BotControl/commands/ReloadServerCmd.ts b/backend/src/plugins/BotControl/commands/ReloadServerCmd.ts
index 0166cba1..fb652b65 100644
--- a/backend/src/plugins/BotControl/commands/ReloadServerCmd.ts
+++ b/backend/src/plugins/BotControl/commands/ReloadServerCmd.ts
@@ -1,4 +1,4 @@
-import { TextChannel } from "discord.js";
+import { Snowflake, TextChannel } from "discord.js";
 import { commandTypeHelpers as ct } from "../../../commandTypes";
 import { isOwnerPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
 import { botControlCmd } from "../types";
@@ -15,7 +15,7 @@ export const ReloadServerCmd = botControlCmd({
   },
 
   async run({ pluginData, message: msg, args }) {
-    if (!pluginData.client.guilds.cache.has(args.guildId)) {
+    if (!pluginData.client.guilds.cache.has(args.guildId as Snowflake)) {
       sendErrorMessage(pluginData, msg.channel as TextChannel, "I am not in that guild");
       return;
     }
@@ -27,7 +27,7 @@ export const ReloadServerCmd = botControlCmd({
       return;
     }
 
-    const guild = await pluginData.client.guilds.fetch(args.guildId);
+    const guild = await pluginData.client.guilds.fetch(args.guildId as Snowflake);
     sendSuccessMessage(pluginData, msg.channel as TextChannel, `Reloaded guild **${guild?.name || "???"}**`);
   },
 });
diff --git a/backend/src/plugins/ChannelArchiver/commands/ArchiveChannelCmd.ts b/backend/src/plugins/ChannelArchiver/commands/ArchiveChannelCmd.ts
index 5d84be22..84e26317 100644
--- a/backend/src/plugins/ChannelArchiver/commands/ArchiveChannelCmd.ts
+++ b/backend/src/plugins/ChannelArchiver/commands/ArchiveChannelCmd.ts
@@ -62,7 +62,7 @@ export const ArchiveChannelCmd = channelArchiverCmd({
       const messagesToFetch = Math.min(MAX_MESSAGES_PER_FETCH, maxMessagesToArchive - archivedMessages);
       const messages = (await args.channel.messages.fetch({
         limit: messagesToFetch,
-        before: previousId,
+        before: previousId as Snowflake,
       })) as Collection<Snowflake, Message>;
       if (messages.size === 0) break;
 
diff --git a/backend/src/plugins/ModActions/commands/MassBanCmd.ts b/backend/src/plugins/ModActions/commands/MassBanCmd.ts
index 8fb84b73..dc1e0855 100644
--- a/backend/src/plugins/ModActions/commands/MassBanCmd.ts
+++ b/backend/src/plugins/ModActions/commands/MassBanCmd.ts
@@ -1,4 +1,4 @@
-import { TextChannel } from "discord.js";
+import { Snowflake, TextChannel } from "discord.js";
 import { waitForReply } from "knub/dist/helpers";
 import { performance } from "perf_hooks";
 import { commandTypeHelpers as ct } from "../../../commandTypes";
@@ -42,7 +42,7 @@ export const MassbanCmd = modActionsCmd({
 
     // Verify we can act on each of the users specified
     for (const userId of args.userIds) {
-      const member = pluginData.guild.members.cache.get(userId); // TODO: Get members on demand?
+      const member = pluginData.guild.members.cache.get(userId as Snowflake); // TODO: Get members on demand?
       if (member && !canActOn(pluginData, msg.member, member)) {
         sendErrorMessage(pluginData, msg.channel, "Cannot massban one or more users: insufficient permissions");
         return;
@@ -91,7 +91,7 @@ export const MassbanCmd = modActionsCmd({
           ignoreEvent(pluginData, IgnoredEventType.Ban, userId, 120 * 1000);
           pluginData.state.serverLogs.ignoreLog(LogType.MEMBER_BAN, userId, 120 * 1000);
 
-          await pluginData.guild.bans.create(userId, {
+          await pluginData.guild.bans.create(userId as Snowflake, {
             days: 1,
             reason: banReason != null ? encodeURIComponent(banReason) : undefined,
           });
diff --git a/backend/src/plugins/ModActions/commands/MassUnbanCmd.ts b/backend/src/plugins/ModActions/commands/MassUnbanCmd.ts
index 6b41e3f4..1d6ec0c7 100644
--- a/backend/src/plugins/ModActions/commands/MassUnbanCmd.ts
+++ b/backend/src/plugins/ModActions/commands/MassUnbanCmd.ts
@@ -1,4 +1,4 @@
-import { TextChannel } from "discord.js";
+import { Snowflake, TextChannel } from "discord.js";
 import { waitForReply } from "knub/dist/helpers";
 import { commandTypeHelpers as ct } from "../../../commandTypes";
 import { CaseTypes } from "../../../data/CaseTypes";
@@ -60,7 +60,10 @@ export const MassunbanCmd = modActionsCmd({
       }
 
       try {
-        await pluginData.guild.bans.remove(userId, unbanReason != null ? encodeURIComponent(unbanReason) : undefined);
+        await pluginData.guild.bans.remove(
+          userId as Snowflake,
+          unbanReason != null ? encodeURIComponent(unbanReason) : undefined,
+        );
 
         await casesPlugin.createCase({
           userId,
diff --git a/backend/src/plugins/ModActions/commands/MassmuteCmd.ts b/backend/src/plugins/ModActions/commands/MassmuteCmd.ts
index 171270da..a2c1faf2 100644
--- a/backend/src/plugins/ModActions/commands/MassmuteCmd.ts
+++ b/backend/src/plugins/ModActions/commands/MassmuteCmd.ts
@@ -1,4 +1,4 @@
-import { TextChannel } from "discord.js";
+import { Snowflake, TextChannel } from "discord.js";
 import { waitForReply } from "knub/dist/helpers";
 import { commandTypeHelpers as ct } from "../../../commandTypes";
 import { LogType } from "../../../data/LogType";
@@ -43,7 +43,7 @@ export const MassmuteCmd = modActionsCmd({
 
     // Verify we can act upon all users
     for (const userId of args.userIds) {
-      const member = pluginData.guild.members.cache.get(userId);
+      const member = pluginData.guild.members.cache.get(userId as Snowflake);
       if (member && !canActOn(pluginData, msg.member, member)) {
         sendErrorMessage(pluginData, msg.channel, "Cannot massmute one or more users: insufficient permissions");
         return;
diff --git a/backend/src/plugins/NameHistory/commands/NamesCmd.ts b/backend/src/plugins/NameHistory/commands/NamesCmd.ts
index a6f722c7..f2a7348a 100644
--- a/backend/src/plugins/NameHistory/commands/NamesCmd.ts
+++ b/backend/src/plugins/NameHistory/commands/NamesCmd.ts
@@ -1,3 +1,4 @@
+import { Snowflake } from "discord.js";
 import { createChunkedMessage, disableCodeBlocks } from "knub/dist/helpers";
 import { commandTypeHelpers as ct } from "../../../commandTypes";
 import { NICKNAME_RETENTION_PERIOD } from "../../../data/cleanup/nicknames";
@@ -29,7 +30,7 @@ export const NamesCmd = nameHistoryCmd({
     );
     const usernameRows = usernames.map(r => `\`[${r.timestamp}]\` **${disableCodeBlocks(r.username)}**`);
 
-    const user = await pluginData.client.users.fetch(args.userId);
+    const user = await pluginData.client.users.fetch(args.userId as Snowflake);
     const currentUsername = user ? `${user.username}#${user.discriminator}` : args.userId;
 
     const nicknameDays = Math.round(NICKNAME_RETENTION_PERIOD / DAYS);
diff --git a/backend/src/plugins/ReactionRoles/commands/PostButtonRolesCmd.ts b/backend/src/plugins/ReactionRoles/commands/PostButtonRolesCmd.ts
index 84f809d8..aa74c553 100644
--- a/backend/src/plugins/ReactionRoles/commands/PostButtonRolesCmd.ts
+++ b/backend/src/plugins/ReactionRoles/commands/PostButtonRolesCmd.ts
@@ -52,7 +52,7 @@ export const PostButtonRolesCmd = reactionRolesCmd({
     const rows = splitButtonsIntoRows(buttons, Object.values(group.default_buttons)); // new MessageActionRow().addComponents(buttons);
 
     try {
-      const newMsg = await args.channel.send({ content: group.message, components: rows, split: false });
+      const newMsg = await args.channel.send({ content: group.message, components: rows });
 
       for (const btn of toInsert) {
         await pluginData.state.buttonRoles.add(
diff --git a/backend/src/plugins/Utility/commands/AboutCmd.ts b/backend/src/plugins/Utility/commands/AboutCmd.ts
index 546d51dc..dd788816 100644
--- a/backend/src/plugins/Utility/commands/AboutCmd.ts
+++ b/backend/src/plugins/Utility/commands/AboutCmd.ts
@@ -63,24 +63,26 @@ export const AboutCmd = utilityCmd({
     );
     loadedPlugins.sort();
 
-    const aboutContent: MessageOptions & { embed: EmbedWith<"title" | "fields"> } = {
-      embed: {
-        title: `About ${pluginData.client.user!.username}`,
-        fields: [
-          {
-            name: "Status",
-            value: basicInfoRows
-              .map(([label, value]) => {
-                return `${label}: **${value}**`;
-              })
-              .join("\n"),
-          },
-          {
-            name: `Loaded plugins on this server (${loadedPlugins.length})`,
-            value: loadedPlugins.join(", "),
-          },
-        ],
-      },
+    const aboutContent: MessageOptions = {
+      embeds: [
+        {
+          title: `About ${pluginData.client.user!.username}`,
+          fields: [
+            {
+              name: "Status",
+              value: basicInfoRows
+                .map(([label, value]) => {
+                  return `${label}: **${value}**`;
+                })
+                .join("\n"),
+            },
+            {
+              name: `Loaded plugins on this server (${loadedPlugins.length})`,
+              value: loadedPlugins.join(", "),
+            },
+          ],
+        },
+      ],
     };
 
     const supporters = await pluginData.state.supporters.getAll();
@@ -92,9 +94,10 @@ export const AboutCmd = utilityCmd({
     );
 
     if (supporters.length) {
-      aboutContent.embed.fields.push({
+      aboutContent.embeds![0].fields!.push({
         name: "Zeppelin supporters 🎉",
         value: supporters.map(s => `**${s.name}** ${s.amount ? `${s.amount}€/mo` : ""}`.trim()).join("\n"),
+        inline: false,
       });
     }
 
@@ -105,12 +108,12 @@ export const AboutCmd = utilityCmd({
     botRoles = botRoles.filter(r => r.color); // Filter to those with a color
     botRoles.sort(sorter("position", "DESC")); // Sort by position (highest first)
     if (botRoles.length) {
-      aboutContent.embed.color = botRoles[0].color;
+      aboutContent.embeds![0].color = botRoles[0].color;
     }
 
     // Use the bot avatar as the embed image
     if (pluginData.client.user!.avatarURL()) {
-      aboutContent.embed.thumbnail = { url: pluginData.client.user!.avatarURL()! };
+      aboutContent.embeds![0].thumbnail = { url: pluginData.client.user!.avatarURL()! };
     }
 
     msg.channel.send(aboutContent);
diff --git a/backend/src/plugins/Utility/commands/CleanCmd.ts b/backend/src/plugins/Utility/commands/CleanCmd.ts
index e953b7f2..e7024866 100644
--- a/backend/src/plugins/Utility/commands/CleanCmd.ts
+++ b/backend/src/plugins/Utility/commands/CleanCmd.ts
@@ -87,7 +87,7 @@ export const CleanCmd = utilityCmd({
       return;
     }
 
-    const targetChannel = args.channel ? pluginData.guild.channels.cache.get(args.channel) : msg.channel;
+    const targetChannel = args.channel ? pluginData.guild.channels.cache.get(args.channel as Snowflake) : msg.channel;
     if (!targetChannel || !(targetChannel instanceof TextChannel)) {
       sendErrorMessage(pluginData, msg.channel, `Invalid channel specified`);
       return;
diff --git a/backend/src/plugins/Utility/commands/ContextCmd.ts b/backend/src/plugins/Utility/commands/ContextCmd.ts
index e51ceeab..ceec4407 100644
--- a/backend/src/plugins/Utility/commands/ContextCmd.ts
+++ b/backend/src/plugins/Utility/commands/ContextCmd.ts
@@ -1,4 +1,4 @@
-import { TextChannel } from "discord.js";
+import { Snowflake, TextChannel } from "discord.js";
 import { commandTypeHelpers as ct } from "../../../commandTypes";
 import { sendErrorMessage } from "../../../pluginUtils";
 import { messageLink } from "../../../utils";
@@ -38,7 +38,7 @@ export const ContextCmd = utilityCmd({
     const previousMessage = (
       await (pluginData.guild.channels.cache.get(channel.id) as TextChannel).messages.fetch({
         limit: 1,
-        before: messageId,
+        before: messageId as Snowflake,
       })
     )[0];
     if (!previousMessage) {
diff --git a/backend/src/plugins/Utility/commands/InfoCmd.ts b/backend/src/plugins/Utility/commands/InfoCmd.ts
index 8ca414a5..9c4b55d3 100644
--- a/backend/src/plugins/Utility/commands/InfoCmd.ts
+++ b/backend/src/plugins/Utility/commands/InfoCmd.ts
@@ -58,7 +58,7 @@ export const InfoCmd = utilityCmd({
 
     // 2. Server
     if (userCfg.can_server) {
-      const guild = await pluginData.client.guilds.fetch(value).catch(noop);
+      const guild = await pluginData.client.guilds.fetch(value as Snowflake).catch(noop);
       if (guild) {
         const embed = await getServerInfoEmbed(pluginData, value, message.author.id);
         if (embed) {
diff --git a/backend/src/plugins/Utility/commands/VcmoveCmd.ts b/backend/src/plugins/Utility/commands/VcmoveCmd.ts
index 967db1f0..c7d68008 100644
--- a/backend/src/plugins/Utility/commands/VcmoveCmd.ts
+++ b/backend/src/plugins/Utility/commands/VcmoveCmd.ts
@@ -1,4 +1,4 @@
-import { VoiceChannel } from "discord.js";
+import { Snowflake, VoiceChannel } from "discord.js";
 import { commandTypeHelpers as ct } from "../../../commandTypes";
 import { LogType } from "../../../data/LogType";
 import { canActOn, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
@@ -21,7 +21,7 @@ export const VcmoveCmd = utilityCmd({
 
     if (isSnowflake(args.channel)) {
       // Snowflake -> resolve channel directly
-      const potentialChannel = pluginData.guild.channels.cache.get(args.channel);
+      const potentialChannel = pluginData.guild.channels.cache.get(args.channel as Snowflake);
       if (!potentialChannel || !(potentialChannel instanceof VoiceChannel)) {
         sendErrorMessage(pluginData, msg.channel, "Unknown or non-voice channel");
         return;
@@ -31,7 +31,7 @@ export const VcmoveCmd = utilityCmd({
     } else if (channelMentionRegex.test(args.channel)) {
       // Channel mention -> parse channel id and resolve channel from that
       const channelId = args.channel.match(channelMentionRegex)![1];
-      const potentialChannel = pluginData.guild.channels.cache.get(channelId);
+      const potentialChannel = pluginData.guild.channels.cache.get(channelId as Snowflake);
       if (!potentialChannel || !(potentialChannel instanceof VoiceChannel)) {
         sendErrorMessage(pluginData, msg.channel, "Unknown or non-voice channel");
         return;
@@ -104,7 +104,7 @@ export const VcmoveAllCmd = utilityCmd({
 
     if (isSnowflake(args.channel)) {
       // Snowflake -> resolve channel directly
-      const potentialChannel = pluginData.guild.channels.cache.get(args.channel);
+      const potentialChannel = pluginData.guild.channels.cache.get(args.channel as Snowflake);
       if (!potentialChannel || !(potentialChannel instanceof VoiceChannel)) {
         sendErrorMessage(pluginData, msg.channel, "Unknown or non-voice channel");
         return;
@@ -114,7 +114,7 @@ export const VcmoveAllCmd = utilityCmd({
     } else if (channelMentionRegex.test(args.channel)) {
       // Channel mention -> parse channel id and resolve channel from that
       const channelId = args.channel.match(channelMentionRegex)![1];
-      const potentialChannel = pluginData.guild.channels.cache.get(channelId);
+      const potentialChannel = pluginData.guild.channels.cache.get(channelId as Snowflake);
       if (!potentialChannel || !(potentialChannel instanceof VoiceChannel)) {
         sendErrorMessage(pluginData, msg.channel, "Unknown or non-voice channel");
         return;
diff --git a/backend/src/plugins/Utility/search.ts b/backend/src/plugins/Utility/search.ts
index d53c21ab..f535539d 100644
--- a/backend/src/plugins/Utility/search.ts
+++ b/backend/src/plugins/Utility/search.ts
@@ -5,6 +5,7 @@ import {
   MessageButton,
   MessageComponentInteraction,
   Permissions,
+  Snowflake,
   TextChannel,
   User,
 } from "discord.js";
@@ -316,7 +317,7 @@ async function performMemberSearch(
     const roleIds = args.role.split(",");
     matchingMembers = matchingMembers.filter(member => {
       for (const role of roleIds) {
-        if (!member.roles.cache.has(role)) return false;
+        if (!member.roles.cache.has(role as Snowflake)) return false;
       }
 
       return true;