From 2821252a5a4b88847981792adb19d956c0429fc4 Mon Sep 17 00:00:00 2001 From: metal Date: Sat, 4 Sep 2021 09:37:58 +0000 Subject: [PATCH 01/31] check if "channel" exists --- .../Utility/functions/getInviteInfoEmbed.ts | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/backend/src/plugins/Utility/functions/getInviteInfoEmbed.ts b/backend/src/plugins/Utility/functions/getInviteInfoEmbed.ts index a95de14b..4a7215ed 100644 --- a/backend/src/plugins/Utility/functions/getInviteInfoEmbed.ts +++ b/backend/src/plugins/Utility/functions/getInviteInfoEmbed.ts @@ -65,32 +65,33 @@ export async function getInviteInfoEmbed( `), inline: true, }); + if (invite.channel) { + const channelName = + invite.channel.type === ChannelTypeStrings.VOICE ? `🔉 ${invite.channel.name}` : `#${invite.channel.name}`; - const channelName = - invite.channel.type === ChannelTypeStrings.VOICE ? `🔉 ${invite.channel.name}` : `#${invite.channel.name}`; + const channelCreatedAtTimestamp = snowflakeToTimestamp(invite.channel.id); + const channelCreatedAt = moment.utc(channelCreatedAtTimestamp, "x"); + const channelAge = humanizeDuration(Date.now() - channelCreatedAtTimestamp, { + largest: 2, + round: true, + }); - const channelCreatedAtTimestamp = snowflakeToTimestamp(invite.channel.id); - const channelCreatedAt = moment.utc(channelCreatedAtTimestamp, "x"); - const channelAge = humanizeDuration(Date.now() - channelCreatedAtTimestamp, { - largest: 2, - round: true, - }); - - let channelInfo = trimLines(` + let channelInfo = trimLines(` Name: **${channelName}** ID: \`${invite.channel.id}\` Created: **${channelAge} ago** `); - if (invite.channel.type !== ChannelTypeStrings.VOICE) { - channelInfo += `\nMention: <#${invite.channel.id}>`; - } + if (invite.channel.type !== ChannelTypeStrings.VOICE) { + channelInfo += `\nMention: <#${invite.channel.id}>`; + } - embed.fields.push({ - name: preEmbedPadding + "Channel information", - value: channelInfo, - inline: true, - }); + embed.fields.push({ + name: preEmbedPadding + "Channel information", + value: channelInfo, + inline: true, + }); + } if (invite.inviter) { embed.fields.push({ From 5ae5e7bc1da51fb0a9c2a45074f82cdc23422f0d Mon Sep 17 00:00:00 2001 From: Dragory <2606411+Dragory@users.noreply.github.com> Date: Sat, 4 Sep 2021 19:02:14 +0300 Subject: [PATCH 02/31] Upgrade to Knub v30.0.0-beta.43 --- backend/package-lock.json | 14 +++++++------- backend/package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/backend/package-lock.json b/backend/package-lock.json index ab298c68..e1970c3f 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -24,7 +24,7 @@ "humanize-duration": "^3.15.0", "io-ts": "^2.0.0", "js-yaml": "^3.13.1", - "knub": "^30.0.0-beta.42", + "knub": "^30.0.0-beta.43", "knub-command-manager": "^9.1.0", "last-commit-log": "^2.1.0", "lodash.chunk": "^4.2.0", @@ -3043,9 +3043,9 @@ } }, "node_modules/knub": { - "version": "30.0.0-beta.42", - "resolved": "https://registry.npmjs.org/knub/-/knub-30.0.0-beta.42.tgz", - "integrity": "sha512-y7nqQh1bzQniYwEftdv6S8Jp2qBvT5a7vn+3JeA0s0ADXobI+/rRVznpq8o0x2m0+E+EeKxo1Ch8F8Hy+VMX6w==", + "version": "30.0.0-beta.43", + "resolved": "https://registry.npmjs.org/knub/-/knub-30.0.0-beta.43.tgz", + "integrity": "sha512-Cmmy2+vnIWLoQhEGhXMykdJoBnB4ofli1HLWOeYCK4OuZrASh6hFvkbliLUuMet3yaHLFQkmK5Gw06ndw67OcA==", "dependencies": { "discord-api-types": "^0.22.0", "discord.js": "^13.0.1", @@ -8290,9 +8290,9 @@ } }, "knub": { - "version": "30.0.0-beta.42", - "resolved": "https://registry.npmjs.org/knub/-/knub-30.0.0-beta.42.tgz", - "integrity": "sha512-y7nqQh1bzQniYwEftdv6S8Jp2qBvT5a7vn+3JeA0s0ADXobI+/rRVznpq8o0x2m0+E+EeKxo1Ch8F8Hy+VMX6w==", + "version": "30.0.0-beta.43", + "resolved": "https://registry.npmjs.org/knub/-/knub-30.0.0-beta.43.tgz", + "integrity": "sha512-Cmmy2+vnIWLoQhEGhXMykdJoBnB4ofli1HLWOeYCK4OuZrASh6hFvkbliLUuMet3yaHLFQkmK5Gw06ndw67OcA==", "requires": { "discord-api-types": "^0.22.0", "discord.js": "^13.0.1", diff --git a/backend/package.json b/backend/package.json index 5ef83427..5ae1c006 100644 --- a/backend/package.json +++ b/backend/package.json @@ -39,7 +39,7 @@ "humanize-duration": "^3.15.0", "io-ts": "^2.0.0", "js-yaml": "^3.13.1", - "knub": "^30.0.0-beta.42", + "knub": "^30.0.0-beta.43", "knub-command-manager": "^9.1.0", "last-commit-log": "^2.1.0", "lodash.chunk": "^4.2.0", From 0d1bfefce0904da3160fd67de5183790da6b6721 Mon Sep 17 00:00:00 2001 From: Dragory <2606411+Dragory@users.noreply.github.com> Date: Sat, 4 Sep 2021 19:05:47 +0300 Subject: [PATCH 03/31] Optimize/tweak message saving --- backend/src/data/GuildSavedMessages.ts | 3 -- .../MessageSaver/events/SaveMessagesEvts.ts | 35 +++++++++---------- backend/src/plugins/MessageSaver/types.ts | 1 - 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/backend/src/data/GuildSavedMessages.ts b/backend/src/data/GuildSavedMessages.ts index 0e7db243..462df642 100644 --- a/backend/src/data/GuildSavedMessages.ts +++ b/backend/src/data/GuildSavedMessages.ts @@ -226,9 +226,6 @@ export class GuildSavedMessages extends BaseGuildRepository { } async createFromMsg(msg: Message, overrides = {}) { - const existingSavedMsg = await this.find(msg.id); - if (existingSavedMsg) return; - // FIXME: Hotfix if (!msg.channel) { return; diff --git a/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts b/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts index 386549e6..42a6b982 100644 --- a/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts +++ b/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts @@ -29,17 +29,20 @@ export const MessageCreateEvt = messageSaverEvt({ return; } - meta.pluginData.state.queue.add(async () => { - if (recentlyCreatedMessages.includes(meta.args.message.id)) { - console.warn( - `Tried to save duplicate message from messageCreate event: ${meta.args.message.guildId} / ${meta.args.message.channelId} / ${meta.args.message.id}`, - ); - return; - } - recentlyCreatedMessages.push(meta.args.message.id); + // Don't save the bot's own messages + if (meta.args.message.author.id === meta.pluginData.client.user?.id) { + return; + } - await meta.pluginData.state.savedMessages.createFromMsg(meta.args.message); - }); + if (recentlyCreatedMessages.includes(meta.args.message.id)) { + console.warn( + `Tried to save duplicate message from messageCreate event: ${meta.args.message.guildId} / ${meta.args.message.channelId} / ${meta.args.message.id}`, + ); + return; + } + recentlyCreatedMessages.push(meta.args.message.id); + + await meta.pluginData.state.savedMessages.createFromMsg(meta.args.message); }, }); @@ -57,9 +60,7 @@ export const MessageUpdateEvt = messageSaverEvt({ return; } - meta.pluginData.state.queue.add(async () => { - await meta.pluginData.state.savedMessages.saveEditFromMsg(meta.args.newMessage as Message); - }); + await meta.pluginData.state.savedMessages.saveEditFromMsg(meta.args.newMessage as Message); }, }); @@ -74,9 +75,7 @@ export const MessageDeleteEvt = messageSaverEvt({ return; } - meta.pluginData.state.queue.add(async () => { - await meta.pluginData.state.savedMessages.markAsDeleted(msg.id); - }); + await meta.pluginData.state.savedMessages.markAsDeleted(msg.id); }, }); @@ -87,8 +86,6 @@ export const MessageDeleteBulkEvt = messageSaverEvt({ async listener(meta) { const ids = meta.args.messages.map(m => m.id); - meta.pluginData.state.queue.add(async () => { - await meta.pluginData.state.savedMessages.markBulkAsDeleted(ids); - }); + await meta.pluginData.state.savedMessages.markBulkAsDeleted(ids); }, }); diff --git a/backend/src/plugins/MessageSaver/types.ts b/backend/src/plugins/MessageSaver/types.ts index f8b481f7..28495da3 100644 --- a/backend/src/plugins/MessageSaver/types.ts +++ b/backend/src/plugins/MessageSaver/types.ts @@ -12,7 +12,6 @@ export interface MessageSaverPluginType extends BasePluginType { config: TConfigSchema; state: { savedMessages: GuildSavedMessages; - queue: Queue; }; } From b8b4e93dc14de58397f45a47c3097fd295c3c3ea Mon Sep 17 00:00:00 2001 From: Dragory <2606411+Dragory@users.noreply.github.com> Date: Sat, 4 Sep 2021 19:07:14 +0300 Subject: [PATCH 04/31] Fix user cache issue with welcome message pings --- .../plugins/WelcomeMessage/events/SendWelcomeMessageEvt.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/src/plugins/WelcomeMessage/events/SendWelcomeMessageEvt.ts b/backend/src/plugins/WelcomeMessage/events/SendWelcomeMessageEvt.ts index 750c6c29..772f27a9 100644 --- a/backend/src/plugins/WelcomeMessage/events/SendWelcomeMessageEvt.ts +++ b/backend/src/plugins/WelcomeMessage/events/SendWelcomeMessageEvt.ts @@ -68,7 +68,9 @@ export const SendWelcomeMessageEvt = welcomeMessageEvt({ if (!channel || !(channel instanceof TextChannel)) return; try { - await createChunkedMessage(channel, formatted); + await createChunkedMessage(channel, formatted, { + parse: ["users"], + }); } catch { pluginData.getPlugin(LogsPlugin).logBotAlert({ body: `Failed send a welcome message for ${verboseUserMention(member.user)} to ${verboseChannelMention( From 3385841702c2aa2e837b5eefc0b0a3e903c7cb3b Mon Sep 17 00:00:00 2001 From: metal Date: Sat, 4 Sep 2021 17:09:49 +0100 Subject: [PATCH 05/31] Persist fix (#263) --- backend/src/plugins/Persist/events/StoreDataEvt.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/plugins/Persist/events/StoreDataEvt.ts b/backend/src/plugins/Persist/events/StoreDataEvt.ts index aad0c48e..45dbda4b 100644 --- a/backend/src/plugins/Persist/events/StoreDataEvt.ts +++ b/backend/src/plugins/Persist/events/StoreDataEvt.ts @@ -16,7 +16,7 @@ export const StoreDataEvt = persistEvt({ const persistedRoles = config.persisted_roles; if (persistedRoles.length && member.roles) { - const rolesToPersist = intersection(persistedRoles, member.roles); + const rolesToPersist = intersection(persistedRoles, [...member.roles.cache.keys()]); if (rolesToPersist.length) { persist = true; persistData.roles = rolesToPersist; From f2f246ee84f60215c2cbd4e8f41d69c20f18c522 Mon Sep 17 00:00:00 2001 From: metal Date: Sat, 4 Sep 2021 17:11:10 +0100 Subject: [PATCH 06/31] Custom Events fixes (#255) --- .../src/plugins/CustomEvents/CustomEventsPlugin.ts | 2 +- .../plugins/CustomEvents/actions/addRoleAction.ts | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/backend/src/plugins/CustomEvents/CustomEventsPlugin.ts b/backend/src/plugins/CustomEvents/CustomEventsPlugin.ts index 009bf5a6..391ee191 100644 --- a/backend/src/plugins/CustomEvents/CustomEventsPlugin.ts +++ b/backend/src/plugins/CustomEvents/CustomEventsPlugin.ts @@ -51,7 +51,7 @@ export const CustomEventsPlugin = zeppelinGuildPlugin()( } const values = createTypedTemplateSafeValueContainer({ - ...args, + ...safeArgs, msg: messageToTemplateSafeMessage(message), }); diff --git a/backend/src/plugins/CustomEvents/actions/addRoleAction.ts b/backend/src/plugins/CustomEvents/actions/addRoleAction.ts index 4fb21bf1..6b83770a 100644 --- a/backend/src/plugins/CustomEvents/actions/addRoleAction.ts +++ b/backend/src/plugins/CustomEvents/actions/addRoleAction.ts @@ -28,9 +28,11 @@ export async function addRoleAction( if (event.trigger.type === "command" && !canActOn(pluginData, eventData.msg.member, target)) { throw new ActionError("Missing permissions"); } - - const rolesToAdd = Array.isArray(action.role) ? action.role : [action.role]; - await target.edit({ - roles: Array.from(new Set([...target.roles.cache.values(), ...rolesToAdd])) as Snowflake[], - }); + const rolesToAdd = (Array.isArray(action.role) ? action.role : [action.role]).filter( + id => !target.roles.cache.has(id), + ); + if (rolesToAdd.length === 0) { + throw new ActionError("Target already has the role(s) specified"); + } + await target.roles.add(rolesToAdd); } From 6cddcb907404f9bd00e5decc88a45a0b33e8b323 Mon Sep 17 00:00:00 2001 From: metal Date: Sat, 4 Sep 2021 17:12:37 +0100 Subject: [PATCH 07/31] Bot-specific for bot users in !userinfo (#260) --- .../plugins/Utility/functions/getUserInfoEmbed.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/backend/src/plugins/Utility/functions/getUserInfoEmbed.ts b/backend/src/plugins/Utility/functions/getUserInfoEmbed.ts index dde541d7..d4e74637 100644 --- a/backend/src/plugins/Utility/functions/getUserInfoEmbed.ts +++ b/backend/src/plugins/Utility/functions/getUserInfoEmbed.ts @@ -36,7 +36,7 @@ export async function getUserInfoEmbed( const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin); embed.author = { - name: `User: ${user.tag}`, + name: `${user.bot ? "Bot" : "User"}: ${user.tag}`, }; const avatarURL = user.displayAvatarURL(); @@ -54,7 +54,7 @@ export async function getUserInfoEmbed( if (compact) { embed.fields.push({ - name: preEmbedPadding + "User information", + name: preEmbedPadding + `${user.bot ? "Bot" : "User"} information`, value: trimLines(` Profile: <@!${user.id}> Created: **${accountAge} ago** (\`${prettyCreatedAt}\`) @@ -70,11 +70,12 @@ export async function getUserInfoEmbed( largest: 2, round: true, }); - embed.fields[0].value += `\nJoined: **${joinAge} ago** (\`${prettyJoinedAt}\`)`; + + embed.fields[0].value += `\n${user.bot ? "Added" : "Joined"}: **${joinAge} ago** (\`${prettyJoinedAt}\`)`; } else { embed.fields.push({ name: preEmbedPadding + "!! NOTE !!", - value: "User is not on the server", + value: `${user.bot ? "Bot" : "User"} is not on the server`, }); } @@ -82,7 +83,7 @@ export async function getUserInfoEmbed( } embed.fields.push({ - name: preEmbedPadding + "User information", + name: preEmbedPadding + `${user.bot ? "Bot" : "User"} information`, value: trimLines(` Name: **${user.tag}** ID: \`${user.id}\` @@ -107,7 +108,7 @@ export async function getUserInfoEmbed( embed.fields.push({ name: preEmbedPadding + "Member information", value: trimLines(` - Joined: **${joinAge} ago** (\`${prettyJoinedAt}\`) + ${user.bot ? "Added" : "Joined"}: **${joinAge} ago** (\`${prettyJoinedAt}\`) ${roles.length > 0 ? "Roles: " + roles.map(r => `<@&${r.id}>`).join(", ") : ""} `), }); @@ -126,7 +127,7 @@ export async function getUserInfoEmbed( } else { embed.fields.push({ name: preEmbedPadding + "Member information", - value: "⚠ User is not on the server", + value: `⚠ ${user.bot ? "Bot" : "User"} is not on the server`, }); } const cases = (await pluginData.state.cases.getByUserId(user.id)).filter(c => !c.is_hidden); From d5da50c0ed07a63506a9494d19079e8d90b8fa20 Mon Sep 17 00:00:00 2001 From: metal Date: Sat, 4 Sep 2021 17:13:29 +0100 Subject: [PATCH 08/31] Fix customEvents channel perms overwrites (#253) --- .../actions/setChannelPermissionOverrides.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/backend/src/plugins/CustomEvents/actions/setChannelPermissionOverrides.ts b/backend/src/plugins/CustomEvents/actions/setChannelPermissionOverrides.ts index 6c345f05..6b9e9b1b 100644 --- a/backend/src/plugins/CustomEvents/actions/setChannelPermissionOverrides.ts +++ b/backend/src/plugins/CustomEvents/actions/setChannelPermissionOverrides.ts @@ -1,4 +1,4 @@ -import { Permissions, Snowflake, TextChannel } from "discord.js"; +import { Permissions, Snowflake, TextChannel, PermissionString } from "discord.js"; import * as t from "io-ts"; import { GuildPluginData } from "knub"; import { ActionError } from "../ActionError"; @@ -32,10 +32,17 @@ export async function setChannelPermissionOverridesAction( } for (const override of action.overrides) { - channel.permissionOverwrites.create( - override.id as Snowflake, - new Permissions(BigInt(override.allow)).remove(BigInt(override.deny)).serialize(), - ); + const allow = new Permissions(BigInt(override.allow)).serialize(); + const deny = new Permissions(BigInt(override.deny)).serialize(); + const perms: Partial> = {}; + for (const key in allow) { + if (allow[key]) { + perms[key] = true; + } else if (deny[key]) { + perms[key] = false; + } + } + channel.permissionOverwrites.create(override.id as Snowflake, perms); /* await channel.permissionOverwrites overwritePermissions( From e73d6d4e1c68d278397c2c9d812004b6da971d5b Mon Sep 17 00:00:00 2001 From: metal Date: Sat, 4 Sep 2021 17:14:33 +0100 Subject: [PATCH 09/31] Add template functions: strlen, round (#265) --- backend/src/templateFormatter.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/backend/src/templateFormatter.ts b/backend/src/templateFormatter.ts index 7b61af1e..2ed902d9 100644 --- a/backend/src/templateFormatter.ts +++ b/backend/src/templateFormatter.ts @@ -388,6 +388,10 @@ const baseValues = { ucfirst(arg) { return baseValues.upperFirst(arg); }, + strlen(arg) { + if (typeof arg !== "string") return 0; + return [...arg].length; + }, rand(from, to, seed = null) { if (isNaN(from)) return 0; @@ -406,6 +410,10 @@ const baseValues = { return Math.round(randValue * (to - from) + from); }, + round(arg, decimals = 0) { + if (isNaN(arg)) return 0; + return decimals === 0 ? Math.round(arg) : arg.toFixed(decimals); + }, add(...args) { return args.reduce((result, arg) => { if (isNaN(arg)) return result; From 2d777a03dbed1e768a04c23a0cfa9a0d26adbee2 Mon Sep 17 00:00:00 2001 From: metal Date: Sat, 4 Sep 2021 17:15:16 +0100 Subject: [PATCH 10/31] Logs - role change compare only role IDs instead of a collection (#264) --- .../plugins/Automod/events/RunAutomodOnMemberUpdate.ts | 4 ++-- backend/src/plugins/Logs/events/LogsUserUpdateEvts.ts | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/backend/src/plugins/Automod/events/RunAutomodOnMemberUpdate.ts b/backend/src/plugins/Automod/events/RunAutomodOnMemberUpdate.ts index a3636118..cf4563ca 100644 --- a/backend/src/plugins/Automod/events/RunAutomodOnMemberUpdate.ts +++ b/backend/src/plugins/Automod/events/RunAutomodOnMemberUpdate.ts @@ -14,8 +14,8 @@ export const RunAutomodOnMemberUpdate = typedGuildEventListener Date: Sat, 4 Sep 2021 17:16:44 +0100 Subject: [PATCH 11/31] Fix max stickers and premium tier in !server (#258) --- .../Utility/functions/getServerInfoEmbed.ts | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/backend/src/plugins/Utility/functions/getServerInfoEmbed.ts b/backend/src/plugins/Utility/functions/getServerInfoEmbed.ts index a0922399..91728e04 100644 --- a/backend/src/plugins/Utility/functions/getServerInfoEmbed.ts +++ b/backend/src/plugins/Utility/functions/getServerInfoEmbed.ts @@ -1,4 +1,4 @@ -import { MessageEmbedOptions, Snowflake } from "discord.js"; +import { MessageEmbedOptions, PremiumTier, Snowflake } from "discord.js"; import humanizeDuration from "humanize-duration"; import { GuildPluginData } from "knub"; import moment from "moment-timezone"; @@ -19,6 +19,13 @@ import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin"; import { UtilityPluginType } from "../types"; import { getGuildPreview } from "./getGuildPreview"; +const PremiumTiers: Record = { + NONE: 0, + TIER_1: 1, + TIER_2: 2, + TIER_3: 3, +}; + export async function getServerInfoEmbed( pluginData: GuildPluginData, serverId: string, @@ -179,20 +186,22 @@ export async function getServerInfoEmbed( } if (restGuild) { + const premiumTierValue = PremiumTiers[restGuild.premiumTier]; + const maxEmojis = { 0: 50, 1: 100, 2: 150, 3: 250, - }[restGuild.premiumTier] || 50; + }[premiumTierValue] ?? 50; const maxStickers = { 0: 0, 1: 15, 2: 30, 3: 60, - }[restGuild.premiumTier] || 0; + }[premiumTierValue] ?? 0; otherStats.push(`Emojis: **${restGuild.emojis.cache.size}** / ${maxEmojis * 2}`); otherStats.push(`Stickers: **${restGuild.stickers.cache.size}** / ${maxStickers}`); @@ -202,7 +211,9 @@ export async function getServerInfoEmbed( } if (thisServer) { - otherStats.push(`Boosts: **${thisServer.premiumSubscriptionCount ?? 0}** (level ${thisServer.premiumTier})`); + otherStats.push( + `Boosts: **${thisServer.premiumSubscriptionCount ?? 0}** (level ${PremiumTiers[thisServer.premiumTier]})`, + ); } embed.fields.push({ From 6a45ce67faf3bd599e9b2cbe528b7d7598b24556 Mon Sep 17 00:00:00 2001 From: Hiroyuki Date: Sat, 4 Sep 2021 12:18:33 -0400 Subject: [PATCH 12/31] feat(automod): MIME type trigger (#247) --- backend/src/plugins/Automod/AutomodPlugin.ts | 15 ++++ .../Automod/triggers/availableTriggers.ts | 3 + .../plugins/Automod/triggers/matchMimeType.ts | 79 +++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 backend/src/plugins/Automod/triggers/matchMimeType.ts diff --git a/backend/src/plugins/Automod/AutomodPlugin.ts b/backend/src/plugins/Automod/AutomodPlugin.ts index 80d160e3..60f55296 100644 --- a/backend/src/plugins/Automod/AutomodPlugin.ts +++ b/backend/src/plugins/Automod/AutomodPlugin.ts @@ -114,6 +114,21 @@ const configPreprocessor: ConfigPreprocessorFn = options => { ]); } } + + if (triggerObj[triggerName].match_mime_type) { + const white = triggerObj[triggerName].match_mime_type.whitelist_enabled; + const black = triggerObj[triggerName].match_mime_type.blacklist_enabled; + + if (white && black) { + throw new StrictValidationError([ + `Cannot have both blacklist and whitelist enabled at rule <${rule.name}/match_mime_type>`, + ]); + } else if (!white && !black) { + throw new StrictValidationError([ + `Must have either blacklist or whitelist enabled at rule <${rule.name}/match_mime_type>`, + ]); + } + } } } } diff --git a/backend/src/plugins/Automod/triggers/availableTriggers.ts b/backend/src/plugins/Automod/triggers/availableTriggers.ts index e62e811d..22c63cd9 100644 --- a/backend/src/plugins/Automod/triggers/availableTriggers.ts +++ b/backend/src/plugins/Automod/triggers/availableTriggers.ts @@ -11,6 +11,7 @@ import { KickTrigger } from "./kick"; import { LineSpamTrigger } from "./lineSpam"; import { LinkSpamTrigger } from "./linkSpam"; import { MatchAttachmentTypeTrigger } from "./matchAttachmentType"; +import { MatchMimeTypeTrigger } from "./matchMimeType"; import { MatchInvitesTrigger } from "./matchInvites"; import { MatchLinksTrigger } from "./matchLinks"; import { MatchRegexTrigger } from "./matchRegex"; @@ -37,6 +38,7 @@ export const availableTriggers: Record match_invites: MatchInvitesTrigger, match_links: MatchLinksTrigger, match_attachment_type: MatchAttachmentTypeTrigger, + match_mime_type: MatchMimeTypeTrigger, member_join: MemberJoinTrigger, role_added: RoleAddedTrigger, role_removed: RoleRemovedTrigger, @@ -72,6 +74,7 @@ export const AvailableTriggers = t.type({ match_invites: MatchInvitesTrigger.configType, match_links: MatchLinksTrigger.configType, match_attachment_type: MatchAttachmentTypeTrigger.configType, + match_mime_type: MatchMimeTypeTrigger.configType, member_join: MemberJoinTrigger.configType, member_leave: MemberLeaveTrigger.configType, role_added: RoleAddedTrigger.configType, diff --git a/backend/src/plugins/Automod/triggers/matchMimeType.ts b/backend/src/plugins/Automod/triggers/matchMimeType.ts new file mode 100644 index 00000000..f38bb8fa --- /dev/null +++ b/backend/src/plugins/Automod/triggers/matchMimeType.ts @@ -0,0 +1,79 @@ +import { automodTrigger } from "../helpers"; +import * as t from "io-ts"; +import { asSingleLine, messageSummary, verboseChannelMention } from "../../../utils"; +import { GuildChannel, Util } from "discord.js"; + +interface MatchResultType { + matchedType: string; + mode: "blacklist" | "whitelist"; +} + +export const MatchMimeTypeTrigger = automodTrigger()({ + configType: t.type({ + mime_type_blacklist: t.array(t.string), + blacklist_enabled: t.boolean, + mime_type_whitelist: t.array(t.string), + whitelist_enabled: t.boolean, + }), + + defaultConfig: { + mime_type_blacklist: [], + blacklist_enabled: false, + mime_type_whitelist: [], + whitelist_enabled: false, + }, + + async match({ context, triggerConfig: trigger }) { + if (!context.message) return; + + const { attachments } = context.message.data; + if (!attachments) return null; + + for (const attachment of attachments) { + const { contentType } = attachment; + + const blacklist = trigger.blacklist_enabled + ? (trigger.mime_type_blacklist ?? []).map(_t => _t.toLowerCase()) + : null; + + if (contentType && blacklist?.includes(contentType)) { + return { + extra: { + matchedType: contentType, + mode: "blacklist", + }, + }; + } + + const whitelist = trigger.whitelist_enabled + ? (trigger.mime_type_whitelist ?? []).map(_t => _t.toLowerCase()) + : null; + + if (whitelist && (!contentType || !whitelist.includes(contentType))) { + return { + extra: { + matchedType: contentType || "", + mode: "whitelist", + }, + }; + } + + return null; + } + }, + + renderMatchInformation({ pluginData, contexts, matchResult }) { + const { message } = contexts[0]; + const channel = pluginData.guild.channels.resolve(message!.channel_id); + const prettyChannel = verboseChannelMention(channel as GuildChannel); + const { matchedType, mode } = matchResult.extra; + + return ( + asSingleLine(` + Matched MIME type \`${Util.escapeInlineCode(matchedType)}\` + (${mode === "blacklist" ? "blacklisted" : "not in whitelist"}) + in message (\`${message!.id}\`) in ${prettyChannel} + `) + messageSummary(message!) + ); + }, +}); From a19de26ff1e73ef0950612111ed26f633afeb098 Mon Sep 17 00:00:00 2001 From: metal Date: Sat, 4 Sep 2021 17:20:50 +0100 Subject: [PATCH 13/31] Re-enable starboard + fixes (#262) --- .../Starboard/events/StarboardReactionAddEvt.ts | 3 --- .../events/StarboardReactionRemoveEvts.ts | 6 ------ .../util/removeMessageFromStarboard.ts | 17 +++++++++++++++-- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/backend/src/plugins/Starboard/events/StarboardReactionAddEvt.ts b/backend/src/plugins/Starboard/events/StarboardReactionAddEvt.ts index 22c5761c..99dbbaa0 100644 --- a/backend/src/plugins/Starboard/events/StarboardReactionAddEvt.ts +++ b/backend/src/plugins/Starboard/events/StarboardReactionAddEvt.ts @@ -9,9 +9,6 @@ export const StarboardReactionAddEvt = starboardEvt({ event: "messageReactionAdd", async listener(meta) { - // FIXME: Temporarily disabled - return; - const pluginData = meta.pluginData; let msg = meta.args.reaction.message as Message; diff --git a/backend/src/plugins/Starboard/events/StarboardReactionRemoveEvts.ts b/backend/src/plugins/Starboard/events/StarboardReactionRemoveEvts.ts index d2cc72da..203c4bde 100644 --- a/backend/src/plugins/Starboard/events/StarboardReactionRemoveEvts.ts +++ b/backend/src/plugins/Starboard/events/StarboardReactionRemoveEvts.ts @@ -5,9 +5,6 @@ export const StarboardReactionRemoveEvt = starboardEvt({ event: "messageReactionRemove", async listener(meta) { - // FIXME: Temporarily disabled - return; - const boardLock = await meta.pluginData.locks.acquire(allStarboardsLock()); await meta.pluginData.state.starboardReactions.deleteStarboardReaction( meta.args.reaction.message.id, @@ -21,9 +18,6 @@ export const StarboardReactionRemoveAllEvt = starboardEvt({ event: "messageReactionRemoveAll", async listener(meta) { - // FIXME: Temporarily disabled - return; - const boardLock = await meta.pluginData.locks.acquire(allStarboardsLock()); await meta.pluginData.state.starboardReactions.deleteAllStarboardReactionsForMessageId(meta.args.message.id); boardLock.unlock(); diff --git a/backend/src/plugins/Starboard/util/removeMessageFromStarboard.ts b/backend/src/plugins/Starboard/util/removeMessageFromStarboard.ts index 1a331358..f4635371 100644 --- a/backend/src/plugins/Starboard/util/removeMessageFromStarboard.ts +++ b/backend/src/plugins/Starboard/util/removeMessageFromStarboard.ts @@ -1,6 +1,19 @@ +import { GuildPluginData } from "knub"; import { StarboardMessage } from "../../../data/entities/StarboardMessage"; import { noop } from "../../../utils"; +import { StarboardPluginType } from "../types"; -export async function removeMessageFromStarboard(pluginData, msg: StarboardMessage) { - await pluginData.client.deleteMessage(msg.starboard_channel_id, msg.starboard_message_id).catch(noop); +export async function removeMessageFromStarboard( + pluginData: GuildPluginData, + msg: StarboardMessage, +) { + // fixes stuck entries on starboard_reactions table after messages being deleted, probably should add a cleanup script for this as well, i.e. DELETE FROM starboard_reactions WHERE message_id NOT IN (SELECT id FROM starboard_messages) + await pluginData.state.starboardReactions.deleteAllStarboardReactionsForMessageId(msg.message_id).catch(noop); + + // this code is now Almeida-certified and no longer ugly :ok_hand: :cake: + const channel = pluginData.client.channels.cache.find(c => c.id === msg.starboard_channel_id); + if (!channel?.isText()) return; + const message = await channel.messages.fetch(msg.starboard_message_id).catch(noop); + if (!message?.deletable) return; + await message.delete().catch(noop); } From 86143e7031ff609bdbcdaa280953aa7e64fe10ed Mon Sep 17 00:00:00 2001 From: Almeida Date: Sat, 4 Sep 2021 17:23:31 +0100 Subject: [PATCH 14/31] Don't match video embed descriptions (#256) --- .../Automod/functions/matchMultipleTextTypesOnMessage.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/plugins/Automod/functions/matchMultipleTextTypesOnMessage.ts b/backend/src/plugins/Automod/functions/matchMultipleTextTypesOnMessage.ts index 10188f7e..08492589 100644 --- a/backend/src/plugins/Automod/functions/matchMultipleTextTypesOnMessage.ts +++ b/backend/src/plugins/Automod/functions/matchMultipleTextTypesOnMessage.ts @@ -1,4 +1,4 @@ -import { Constants } from "discord.js"; +import { Constants, MessageEmbed } from "discord.js"; import { GuildPluginData } from "knub"; import { SavedMessage } from "../../../data/entities/SavedMessage"; import { resolveMember } from "../../../utils"; @@ -32,9 +32,9 @@ export async function* matchMultipleTextTypesOnMessage( yield ["message", msg.data.content]; } - if (trigger.match_embeds && msg.data.embeds && msg.data.embeds.length) { - const copiedEmbed = JSON.parse(JSON.stringify(msg.data.embeds[0])); - if (copiedEmbed.type === "video") { + if (trigger.match_embeds && msg.data.embeds?.length) { + const copiedEmbed: MessageEmbed = JSON.parse(JSON.stringify(msg.data.embeds[0])); + if (copiedEmbed.video) { copiedEmbed.description = ""; // The description is not rendered, hence it doesn't need to be matched } yield ["embed", JSON.stringify(copiedEmbed)]; From 60515ad7887809f0335a319662ed1f7adbcb0e1c Mon Sep 17 00:00:00 2001 From: metal Date: Sat, 4 Sep 2021 17:36:15 +0100 Subject: [PATCH 15/31] Update invite detection regex (#259) --- backend/src/utils.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/backend/src/utils.ts b/backend/src/utils.ts index 8a7f7c55..6e40d666 100644 --- a/backend/src/utils.ts +++ b/backend/src/utils.ts @@ -743,10 +743,11 @@ export function isNotNull(value): value is Exclude { // discordapp.com/invite/ // discord.gg/invite/ // discord.gg/ -const quickInviteDetection = /(?:discord.com|discordapp.com)\/invite\/([a-z0-9\-]+)|discord.gg\/(?:\S+\/)?([a-z0-9\-]+)/gi; +// discord.com/friend-invite/ +const quickInviteDetection = /discord(?:app)?\.com\/(?:friend-)?invite\/([a-z0-9\-]+)|discord\.gg\/(?:\S+\/)?([a-z0-9\-]+)/gi; const isInviteHostRegex = /(?:^|\.)(?:discord.gg|discord.com|discordapp.com)$/i; -const longInvitePathRegex = /^\/invite\/([a-z0-9\-]+)$/i; +const longInvitePathRegex = /^\/(?:friend-)?invite\/([a-z0-9\-]+)$/i; export function getInviteCodesInString(str: string): string[] { const inviteCodes: string[] = []; @@ -778,6 +779,8 @@ export function getInviteCodesInString(str: string): string[] { // discord.com/invite/[/anything] // discordapp.com/invite/[/anything] + // discord.com/friend-invite/[/anything] + // discordapp.com/friend-invite/[/anything] const longInviteMatch = url.pathname.match(longInvitePathRegex); if (longInviteMatch) { return longInviteMatch[1]; From 98f7c27dd4b8b857404aa578679d94900b4e1c1f Mon Sep 17 00:00:00 2001 From: Almeida Date: Sat, 4 Sep 2021 17:37:02 +0100 Subject: [PATCH 16/31] Add use_inline_reply option to the Automod reply action (#269) --- backend/src/plugins/Automod/actions/reply.ts | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/backend/src/plugins/Automod/actions/reply.ts b/backend/src/plugins/Automod/actions/reply.ts index d40681e3..70527f0b 100644 --- a/backend/src/plugins/Automod/actions/reply.ts +++ b/backend/src/plugins/Automod/actions/reply.ts @@ -1,7 +1,6 @@ import { MessageOptions, Permissions, Snowflake, TextChannel, ThreadChannel, User } from "discord.js"; import * as t from "io-ts"; import { userToTemplateSafeUser } from "../../../utils/templateSafeObjects"; -import { LogType } from "../../../data/LogType"; import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter"; import { convertDelayStringToMS, @@ -25,6 +24,7 @@ export const ReplyAction = automodAction({ t.type({ text: tMessageContent, auto_delete: tNullable(t.union([tDelayString, t.number])), + use_inline_reply: tNullable(t.boolean), }), ]), @@ -51,7 +51,7 @@ export const ReplyAction = automodAction({ const users = unique(Array.from(new Set(_contexts.map(c => c.user).filter(Boolean)))) as User[]; const user = users[0]; - const renderReplyText = async str => + const renderReplyText = async (str: string) => renderTemplate( str, new TemplateSafeValueContainer({ @@ -94,16 +94,26 @@ export const ReplyAction = automodAction({ } const messageContent = validateAndParseMessageContent(formatted); - const replyMsg = await channel.send({ + + const messageOpts: MessageOptions = { ...messageContent, allowedMentions: { users: [user.id], }, - }); + }; + + if (typeof actionConfig !== "string" && actionConfig.use_inline_reply) { + messageOpts.reply = { + failIfNotExists: false, + messageReference: _contexts[0].message!.id, + }; + } + + const replyMsg = await channel.send(messageOpts); if (typeof actionConfig === "object" && actionConfig.auto_delete) { const delay = convertDelayStringToMS(String(actionConfig.auto_delete))!; - setTimeout(() => replyMsg.delete().catch(noop), delay); + setTimeout(() => !replyMsg.deleted && replyMsg.delete().catch(noop), delay); } } } From b3e2e0cffb90f2789ebed6ee0dff06f71436fa19 Mon Sep 17 00:00:00 2001 From: Almeida Date: Sat, 4 Sep 2021 17:37:49 +0100 Subject: [PATCH 17/31] Add archive_thread action to automod (#271) --- .../plugins/Automod/actions/archiveThread.ts | 20 +++++++++++++++++++ .../Automod/actions/availableActions.ts | 3 +++ 2 files changed, 23 insertions(+) create mode 100644 backend/src/plugins/Automod/actions/archiveThread.ts diff --git a/backend/src/plugins/Automod/actions/archiveThread.ts b/backend/src/plugins/Automod/actions/archiveThread.ts new file mode 100644 index 00000000..7c7aa218 --- /dev/null +++ b/backend/src/plugins/Automod/actions/archiveThread.ts @@ -0,0 +1,20 @@ +import { ThreadChannel } from "discord.js"; +import * as t from "io-ts"; +import { noop } from "../../../utils"; +import { automodAction } from "../helpers"; + +export const ArchiveThreadAction = automodAction({ + configType: t.type({}), + defaultConfig: {}, + + async apply({ pluginData, contexts }) { + const threads = contexts + .filter(c => c.message?.channel_id) + .map(c => pluginData.guild.channels.cache.get(c.message!.channel_id)) + .filter((c): c is ThreadChannel => c?.isThread() ?? false); + + for (const thread of threads) { + await thread.setArchived().catch(noop); + } + }, +}); diff --git a/backend/src/plugins/Automod/actions/availableActions.ts b/backend/src/plugins/Automod/actions/availableActions.ts index fbdcf8f9..76b2a60e 100644 --- a/backend/src/plugins/Automod/actions/availableActions.ts +++ b/backend/src/plugins/Automod/actions/availableActions.ts @@ -3,6 +3,7 @@ import { AutomodActionBlueprint } from "../helpers"; import { AddRolesAction } from "./addRoles"; import { AddToCounterAction } from "./addToCounter"; import { AlertAction } from "./alert"; +import { ArchiveThreadAction } from "./archiveThread"; import { BanAction } from "./ban"; import { ChangeNicknameAction } from "./changeNickname"; import { CleanAction } from "./clean"; @@ -32,6 +33,7 @@ export const availableActions: Record> = { add_to_counter: AddToCounterAction, set_counter: SetCounterAction, set_slowmode: SetSlowmodeAction, + archive_thread: ArchiveThreadAction, }; export const AvailableActions = t.type({ @@ -50,4 +52,5 @@ export const AvailableActions = t.type({ add_to_counter: AddToCounterAction.configType, set_counter: SetCounterAction.configType, set_slowmode: SetSlowmodeAction.configType, + archive_thread: ArchiveThreadAction.configType, }); From 6e5dd2c31f13bf0f0a80681060d31372bb4464c3 Mon Sep 17 00:00:00 2001 From: Jonathan <54381371+axisiscool@users.noreply.github.com> Date: Sat, 4 Sep 2021 12:45:10 -0400 Subject: [PATCH 18/31] Fix typo in !removerole (#228) --- backend/src/plugins/Roles/commands/RemoveRoleCmd.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/plugins/Roles/commands/RemoveRoleCmd.ts b/backend/src/plugins/Roles/commands/RemoveRoleCmd.ts index d6e36356..63a843c8 100644 --- a/backend/src/plugins/Roles/commands/RemoveRoleCmd.ts +++ b/backend/src/plugins/Roles/commands/RemoveRoleCmd.ts @@ -63,7 +63,7 @@ export const RemoveRoleCmd = rolesCmd({ sendSuccessMessage( pluginData, msg.channel, - `Removed role **${role.name}** removed from ${verboseUserMention(args.member.user)}!`, + `Removed role **${role.name}** from ${verboseUserMention(args.member.user)}!`, ); }, }); From 200e8ba89d2f2d6e6d7d0310dafeb4d132f26297 Mon Sep 17 00:00:00 2001 From: Dragory <2606411+Dragory@users.noreply.github.com> Date: Sat, 4 Sep 2021 19:49:04 +0300 Subject: [PATCH 19/31] Remove leftover piece of code --- backend/src/plugins/MessageSaver/MessageSaverPlugin.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts b/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts index 0f316ad2..c8a603e1 100644 --- a/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts +++ b/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts @@ -45,6 +45,5 @@ export const MessageSaverPlugin = zeppelinGuildPlugin()( beforeLoad(pluginData) { const { state, guild } = pluginData; state.savedMessages = GuildSavedMessages.getGuildInstance(guild.id); - state.queue = new Queue(); }, }); From 6486dd7ca817802cbe3327fedac5498037268319 Mon Sep 17 00:00:00 2001 From: Dragory <2606411+Dragory@users.noreply.github.com> Date: Sat, 4 Sep 2021 19:57:59 +0300 Subject: [PATCH 20/31] Update update scripts and process files --- process-api.json | 3 ++- process-bot.json | 3 ++- update-backend-hotfix.sh | 16 ++++++++++++++++ update-backend.sh | 25 +++++++++++++++++++++++++ update-dashboard.sh | 15 +++++++++++++++ update.sh | 11 ++--------- 6 files changed, 62 insertions(+), 11 deletions(-) create mode 100755 update-backend-hotfix.sh create mode 100755 update-backend.sh create mode 100755 update-dashboard.sh diff --git a/process-api.json b/process-api.json index 99b5a8a3..2feaf75f 100644 --- a/process-api.json +++ b/process-api.json @@ -5,7 +5,8 @@ "cwd": "./backend", "script": "npm", "args": "run start-api-prod", - "log_date_format": "YYYY-MM-DD HH:mm:ss" + "log_date_format": "YYYY-MM-DD HH:mm:ss.SSS", + "exp_backoff_restart_delay": 2500 } ] } diff --git a/process-bot.json b/process-bot.json index 9c552b90..b8667e2d 100644 --- a/process-bot.json +++ b/process-bot.json @@ -5,7 +5,8 @@ "cwd": "./backend", "script": "npm", "args": "run start-bot-prod", - "log_date_format": "YYYY-MM-DD HH:mm:ss" + "log_date_format": "YYYY-MM-DD HH:mm:ss.SSS", + "exp_backoff_restart_delay": 2500 } ] } diff --git a/update-backend-hotfix.sh b/update-backend-hotfix.sh new file mode 100755 index 00000000..e692d7a9 --- /dev/null +++ b/update-backend-hotfix.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Load nvm +. ~/.nvm/nvm.sh + +# Run hotfix update +cd backend +nvm use +git pull +npm run build + +# Restart processes +cd .. +nvm use +pm2 restart process-bot.json +pm2 restart process-api.json diff --git a/update-backend.sh b/update-backend.sh new file mode 100755 index 00000000..4da51186 --- /dev/null +++ b/update-backend.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Load nvm +. ~/.nvm/nvm.sh + +# Stop current processes +nvm use +pm2 delete process-bot.json +pm2 delete process-api.json + +# Run update +nvm use +git pull +npm ci + +cd backend +npm ci +npm run build +npm run migrate-prod + +# Start processes again +cd .. +nvm use +pm2 start process-bot.json +pm2 start process-api.json diff --git a/update-dashboard.sh b/update-dashboard.sh new file mode 100755 index 00000000..7a336905 --- /dev/null +++ b/update-dashboard.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +TARGET_DIR=/var/www/zeppelin.gg + +# Load nvm +. ~/.nvm/nvm.sh + +# Update dashboard +cd dashboard +git pull +nvm use +npm ci +npm run build +rm -r "$TARGET_DIR/*" +cp -R dist/* "$TARGET_DIR" diff --git a/update.sh b/update.sh index 5e910c60..bf615aa5 100755 --- a/update.sh +++ b/update.sh @@ -1,11 +1,4 @@ #!/bin/bash -# Load nvm -. ~/.nvm/nvm.sh - -# Run update -nvm use -git pull -npm ci -npm run build -pm2 restart process.json +. ./update-backend.sh +. ./update-dashboard.sh From a396779cd5b0c7bd6d8bb153c8a99be696a1bafa Mon Sep 17 00:00:00 2001 From: Dragory <2606411+Dragory@users.noreply.github.com> Date: Sat, 4 Sep 2021 20:16:44 +0300 Subject: [PATCH 21/31] Add debug code for duplicate message saving --- .../MessageSaver/MessageSaverPlugin.ts | 3 +++ .../MessageSaver/events/SaveMessagesEvts.ts | 27 ++++++++++++------- backend/src/plugins/MessageSaver/types.ts | 1 + 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts b/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts index c8a603e1..724f0a15 100644 --- a/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts +++ b/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts @@ -21,6 +21,8 @@ const defaultOptions: PluginOptions = { ], }; +let debugId = 0; + export const MessageSaverPlugin = zeppelinGuildPlugin()({ name: "message_saver", showInDocs: false, @@ -45,5 +47,6 @@ export const MessageSaverPlugin = zeppelinGuildPlugin()( beforeLoad(pluginData) { const { state, guild } = pluginData; state.savedMessages = GuildSavedMessages.getGuildInstance(guild.id); + state.debugId = ++debugId; }, }); diff --git a/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts b/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts index 42a6b982..a2549820 100644 --- a/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts +++ b/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts @@ -1,14 +1,21 @@ import { Constants, Message, MessageType, Snowflake } from "discord.js"; import { messageSaverEvt } from "../types"; import { SECONDS } from "../../../utils"; +import moment from "moment-timezone"; -const recentlyCreatedMessages: Snowflake[] = []; +const recentlyCreatedMessages: Map = new Map(); const recentlyCreatedMessagesToKeep = 100; setInterval(() => { - const toDelete = recentlyCreatedMessages.length - recentlyCreatedMessagesToKeep; - if (toDelete > 0) { - recentlyCreatedMessages.splice(0, toDelete); + let toDelete = recentlyCreatedMessages.size - recentlyCreatedMessagesToKeep; + for (const key of recentlyCreatedMessages.keys()) { + if (toDelete === 0) { + break; + } + + recentlyCreatedMessages.delete(key); + + toDelete--; } }, 60 * SECONDS); @@ -34,13 +41,15 @@ export const MessageCreateEvt = messageSaverEvt({ return; } - if (recentlyCreatedMessages.includes(meta.args.message.id)) { - console.warn( - `Tried to save duplicate message from messageCreate event: ${meta.args.message.guildId} / ${meta.args.message.channelId} / ${meta.args.message.id}`, - ); + // FIXME: Remove debug code + if (recentlyCreatedMessages.has(meta.args.message.id)) { + const context = `${meta.pluginData.state.debugId} / ${meta.args.message.guildId} / ${meta.args.message.channelId} / ${meta.args.message.id}`; + const timestamp = moment(recentlyCreatedMessages.get(meta.args.message.id)!).format("HH:mm:ss.SSS"); + // tslint:disable-next-line:no-console + console.warn(`Tried to save duplicate message from messageCreate event: ${context} / saved at: ${timestamp}`); return; } - recentlyCreatedMessages.push(meta.args.message.id); + recentlyCreatedMessages.set(meta.args.message.id, Date.now()); await meta.pluginData.state.savedMessages.createFromMsg(meta.args.message); }, diff --git a/backend/src/plugins/MessageSaver/types.ts b/backend/src/plugins/MessageSaver/types.ts index 28495da3..694a0b0a 100644 --- a/backend/src/plugins/MessageSaver/types.ts +++ b/backend/src/plugins/MessageSaver/types.ts @@ -12,6 +12,7 @@ export interface MessageSaverPluginType extends BasePluginType { config: TConfigSchema; state: { savedMessages: GuildSavedMessages; + debugId: number; }; } From 633cf70f09144f870111ebd13f1f9fdadcee668e Mon Sep 17 00:00:00 2001 From: Dragory <2606411+Dragory@users.noreply.github.com> Date: Sat, 4 Sep 2021 20:24:30 +0300 Subject: [PATCH 22/31] Tweaks to debug code --- .../plugins/MessageSaver/events/SaveMessagesEvts.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts b/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts index a2549820..219607d7 100644 --- a/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts +++ b/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts @@ -3,7 +3,7 @@ import { messageSaverEvt } from "../types"; import { SECONDS } from "../../../utils"; import moment from "moment-timezone"; -const recentlyCreatedMessages: Map = new Map(); +const recentlyCreatedMessages: Map = new Map(); const recentlyCreatedMessagesToKeep = 100; setInterval(() => { @@ -43,13 +43,15 @@ export const MessageCreateEvt = messageSaverEvt({ // FIXME: Remove debug code if (recentlyCreatedMessages.has(meta.args.message.id)) { - const context = `${meta.pluginData.state.debugId} / ${meta.args.message.guildId} / ${meta.args.message.channelId} / ${meta.args.message.id}`; - const timestamp = moment(recentlyCreatedMessages.get(meta.args.message.id)!).format("HH:mm:ss.SSS"); + const ourDebugId = meta.pluginData.state.debugId; + const oldDebugId = recentlyCreatedMessages.get(meta.args.message.id)![0]; + const context = `${ourDebugId} : ${oldDebugId} / ${meta.args.message.guildId} / ${meta.args.message.channelId} / ${meta.args.message.id}`; + const timestamp = moment(recentlyCreatedMessages.get(meta.args.message.id)![1]).format("HH:mm:ss.SSS"); // tslint:disable-next-line:no-console console.warn(`Tried to save duplicate message from messageCreate event: ${context} / saved at: ${timestamp}`); return; } - recentlyCreatedMessages.set(meta.args.message.id, Date.now()); + recentlyCreatedMessages.set(meta.args.message.id, [meta.pluginData.state.debugId, Date.now()]); await meta.pluginData.state.savedMessages.createFromMsg(meta.args.message); }, From 8d84e8cb14001aeafa1b6a38cc3d09569731e40b Mon Sep 17 00:00:00 2001 From: Dragory <2606411+Dragory@users.noreply.github.com> Date: Sat, 4 Sep 2021 20:29:30 +0300 Subject: [PATCH 23/31] One more debug code tweak --- backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts b/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts index 219607d7..56b7e680 100644 --- a/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts +++ b/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts @@ -45,7 +45,7 @@ export const MessageCreateEvt = messageSaverEvt({ if (recentlyCreatedMessages.has(meta.args.message.id)) { const ourDebugId = meta.pluginData.state.debugId; const oldDebugId = recentlyCreatedMessages.get(meta.args.message.id)![0]; - const context = `${ourDebugId} : ${oldDebugId} / ${meta.args.message.guildId} / ${meta.args.message.channelId} / ${meta.args.message.id}`; + const context = `${ourDebugId} : ${oldDebugId} / ${meta.pluginData.guild.id} : ${meta.args.message.guildId} / ${meta.args.message.channelId} / ${meta.args.message.id}`; const timestamp = moment(recentlyCreatedMessages.get(meta.args.message.id)![1]).format("HH:mm:ss.SSS"); // tslint:disable-next-line:no-console console.warn(`Tried to save duplicate message from messageCreate event: ${context} / saved at: ${timestamp}`); From e5fd91eac9afe2f900eb68389f8f35ffd70c2e60 Mon Sep 17 00:00:00 2001 From: Dragory <2606411+Dragory@users.noreply.github.com> Date: Sat, 4 Sep 2021 20:49:05 +0300 Subject: [PATCH 24/31] More debug --- .../src/plugins/MessageSaver/MessageSaverPlugin.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts b/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts index 724f0a15..3d8bc9e4 100644 --- a/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts +++ b/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts @@ -22,6 +22,7 @@ const defaultOptions: PluginOptions = { }; let debugId = 0; +const debugGuilds = ["877581055920603238", "348468156597010432", "134286179121102848"]; export const MessageSaverPlugin = zeppelinGuildPlugin()({ name: "message_saver", @@ -48,5 +49,15 @@ export const MessageSaverPlugin = zeppelinGuildPlugin()( const { state, guild } = pluginData; state.savedMessages = GuildSavedMessages.getGuildInstance(guild.id); state.debugId = ++debugId; + + if (debugGuilds.includes(pluginData.guild.id)) { + console.log(`MessageSaverPlugin::beforeLoad (${state.debugId}): ${pluginData.guild.id}`); + } + }, + + beforeUnload(pluginData) { + if (debugGuilds.includes(pluginData.guild.id)) { + console.log(`MessageSaverPlugin::beforeUnload (${pluginData.state.debugId}): ${pluginData.guild.id}`); + } }, }); From 2190523866f8b067d136732169f3d299f9794f53 Mon Sep 17 00:00:00 2001 From: Dragory <2606411+Dragory@users.noreply.github.com> Date: Sat, 4 Sep 2021 20:49:25 +0300 Subject: [PATCH 25/31] Fix missing await --- .../ReactionRoles/util/applyReactionRoleReactionsToMessage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/plugins/ReactionRoles/util/applyReactionRoleReactionsToMessage.ts b/backend/src/plugins/ReactionRoles/util/applyReactionRoleReactionsToMessage.ts index 86c81a29..0c6334e9 100644 --- a/backend/src/plugins/ReactionRoles/util/applyReactionRoleReactionsToMessage.ts +++ b/backend/src/plugins/ReactionRoles/util/applyReactionRoleReactionsToMessage.ts @@ -25,7 +25,7 @@ export async function applyReactionRoleReactionsToMessage( let targetMessage; try { - targetMessage = channel.messages.fetch(messageId, { force: true }); + targetMessage = await channel.messages.fetch(messageId, { force: true }); } catch (e) { if (isDiscordAPIError(e)) { if (e.code === 10008) { From b550ce0c8e12db80d148c02566f719ea770de6d2 Mon Sep 17 00:00:00 2001 From: Dragory <2606411+Dragory@users.noreply.github.com> Date: Sat, 4 Sep 2021 20:53:32 +0300 Subject: [PATCH 26/31] More+ debug --- .../src/plugins/MessageSaver/events/SaveMessagesEvts.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts b/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts index 56b7e680..3e1e91a6 100644 --- a/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts +++ b/backend/src/plugins/MessageSaver/events/SaveMessagesEvts.ts @@ -3,7 +3,7 @@ import { messageSaverEvt } from "../types"; import { SECONDS } from "../../../utils"; import moment from "moment-timezone"; -const recentlyCreatedMessages: Map = new Map(); +const recentlyCreatedMessages: Map = new Map(); const recentlyCreatedMessagesToKeep = 100; setInterval(() => { @@ -45,13 +45,14 @@ export const MessageCreateEvt = messageSaverEvt({ if (recentlyCreatedMessages.has(meta.args.message.id)) { const ourDebugId = meta.pluginData.state.debugId; const oldDebugId = recentlyCreatedMessages.get(meta.args.message.id)![0]; - const context = `${ourDebugId} : ${oldDebugId} / ${meta.pluginData.guild.id} : ${meta.args.message.guildId} / ${meta.args.message.channelId} / ${meta.args.message.id}`; + const oldGuildId = recentlyCreatedMessages.get(meta.args.message.id)![2]; + const context = `${ourDebugId} : ${oldDebugId} / ${meta.pluginData.guild.id} : ${oldGuildId} : ${meta.args.message.guildId} / ${meta.args.message.channelId} / ${meta.args.message.id}`; const timestamp = moment(recentlyCreatedMessages.get(meta.args.message.id)![1]).format("HH:mm:ss.SSS"); // tslint:disable-next-line:no-console console.warn(`Tried to save duplicate message from messageCreate event: ${context} / saved at: ${timestamp}`); return; } - recentlyCreatedMessages.set(meta.args.message.id, [meta.pluginData.state.debugId, Date.now()]); + recentlyCreatedMessages.set(meta.args.message.id, [meta.pluginData.state.debugId, Date.now(), meta.pluginData.guild.id]); await meta.pluginData.state.savedMessages.createFromMsg(meta.args.message); }, From 5e13938f60a5b64c9234d7938d666c1345183688 Mon Sep 17 00:00:00 2001 From: Dragory <2606411+Dragory@users.noreply.github.com> Date: Sat, 4 Sep 2021 21:02:55 +0300 Subject: [PATCH 27/31] More++ debug --- backend/src/index.ts | 16 ++++++++++++++++ .../plugins/MessageSaver/MessageSaverPlugin.ts | 6 ++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/backend/src/index.ts b/backend/src/index.ts index 2ab3417c..108a3cbe 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -300,6 +300,22 @@ connect().then(async () => { startUptimeCounter(); }); + const debugGuilds = ["877581055920603238", "348468156597010432", "134286179121102848"]; + bot.on("guildLoaded", guildId => { + if (!debugGuilds.includes(guildId)) { + return; + } + + console.log(`[!! DEBUG !!] LOADED GUILD ${guildId}`); + }); + bot.on("guildUnloaded", guildId => { + if (!debugGuilds.includes(guildId)) { + return; + } + + console.log(`[!! DEBUG !!] UNLOADED GUILD ${guildId}`); + }); + bot.initialize(); logger.info("Bot Initialized"); logger.info("Logging in..."); diff --git a/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts b/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts index 3d8bc9e4..202f03dd 100644 --- a/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts +++ b/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts @@ -51,13 +51,15 @@ export const MessageSaverPlugin = zeppelinGuildPlugin()( state.debugId = ++debugId; if (debugGuilds.includes(pluginData.guild.id)) { - console.log(`MessageSaverPlugin::beforeLoad (${state.debugId}): ${pluginData.guild.id}`); + console.log(`[!! DEBUG !!] MessageSaverPlugin::beforeLoad (${state.debugId}): ${pluginData.guild.id}`); } }, beforeUnload(pluginData) { if (debugGuilds.includes(pluginData.guild.id)) { - console.log(`MessageSaverPlugin::beforeUnload (${pluginData.state.debugId}): ${pluginData.guild.id}`); + console.log( + `[!! DEBUG !!] MessageSaverPlugin::beforeUnload (${pluginData.state.debugId}): ${pluginData.guild.id}`, + ); } }, }); From 0b6e61bf25db59c6341a40b307a17ff1d7783c22 Mon Sep 17 00:00:00 2001 From: Dragory <2606411+Dragory@users.noreply.github.com> Date: Sat, 4 Sep 2021 21:23:53 +0300 Subject: [PATCH 28/31] Upgrade to Knub v30.0.0-beta.44 --- backend/package-lock.json | 14 +++++++------- backend/package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/backend/package-lock.json b/backend/package-lock.json index e1970c3f..8ed1eff1 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -24,7 +24,7 @@ "humanize-duration": "^3.15.0", "io-ts": "^2.0.0", "js-yaml": "^3.13.1", - "knub": "^30.0.0-beta.43", + "knub": "^30.0.0-beta.44", "knub-command-manager": "^9.1.0", "last-commit-log": "^2.1.0", "lodash.chunk": "^4.2.0", @@ -3043,9 +3043,9 @@ } }, "node_modules/knub": { - "version": "30.0.0-beta.43", - "resolved": "https://registry.npmjs.org/knub/-/knub-30.0.0-beta.43.tgz", - "integrity": "sha512-Cmmy2+vnIWLoQhEGhXMykdJoBnB4ofli1HLWOeYCK4OuZrASh6hFvkbliLUuMet3yaHLFQkmK5Gw06ndw67OcA==", + "version": "30.0.0-beta.44", + "resolved": "https://registry.npmjs.org/knub/-/knub-30.0.0-beta.44.tgz", + "integrity": "sha512-VkddBzz43A2ZBEGI0V8YjPuRzzbMxZ9TAyswYm+lwsnMTVygvn2E/cWVz6BEWcbUj0rU/uCEUHsMD4M8NfXVqg==", "dependencies": { "discord-api-types": "^0.22.0", "discord.js": "^13.0.1", @@ -8290,9 +8290,9 @@ } }, "knub": { - "version": "30.0.0-beta.43", - "resolved": "https://registry.npmjs.org/knub/-/knub-30.0.0-beta.43.tgz", - "integrity": "sha512-Cmmy2+vnIWLoQhEGhXMykdJoBnB4ofli1HLWOeYCK4OuZrASh6hFvkbliLUuMet3yaHLFQkmK5Gw06ndw67OcA==", + "version": "30.0.0-beta.44", + "resolved": "https://registry.npmjs.org/knub/-/knub-30.0.0-beta.44.tgz", + "integrity": "sha512-VkddBzz43A2ZBEGI0V8YjPuRzzbMxZ9TAyswYm+lwsnMTVygvn2E/cWVz6BEWcbUj0rU/uCEUHsMD4M8NfXVqg==", "requires": { "discord-api-types": "^0.22.0", "discord.js": "^13.0.1", diff --git a/backend/package.json b/backend/package.json index 5ae1c006..74f02a5c 100644 --- a/backend/package.json +++ b/backend/package.json @@ -39,7 +39,7 @@ "humanize-duration": "^3.15.0", "io-ts": "^2.0.0", "js-yaml": "^3.13.1", - "knub": "^30.0.0-beta.43", + "knub": "^30.0.0-beta.44", "knub-command-manager": "^9.1.0", "last-commit-log": "^2.1.0", "lodash.chunk": "^4.2.0", From e95987a766a0bdb78555767982595b417543b605 Mon Sep 17 00:00:00 2001 From: Dragory <2606411+Dragory@users.noreply.github.com> Date: Sat, 4 Sep 2021 22:11:08 +0300 Subject: [PATCH 29/31] Fix rare crash if isOwner() is called before the global config is loaded --- backend/src/pluginUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/pluginUtils.ts b/backend/src/pluginUtils.ts index 14dcf85e..309914f1 100644 --- a/backend/src/pluginUtils.ts +++ b/backend/src/pluginUtils.ts @@ -232,7 +232,7 @@ export function getBaseUrl(pluginData: AnyPluginData) { export function isOwner(pluginData: AnyPluginData, userId: string) { const knub = pluginData.getKnubInstance() as TZeppelinKnub; - const owners = knub.getGlobalConfig().owners; + const owners = knub.getGlobalConfig()?.owners; if (!owners) { return false; } From 05c2434efcaa1772bbfa677f8ce3f5d6a2c807a6 Mon Sep 17 00:00:00 2001 From: Dragory <2606411+Dragory@users.noreply.github.com> Date: Sat, 4 Sep 2021 22:11:38 +0300 Subject: [PATCH 30/31] Add command to monitor plugin load performance --- .../plugins/BotControl/BotControlPlugin.ts | 3 +++ .../BotControl/commands/PerformanceCmd.ts | 23 +++++++++++++++++++ backend/src/plugins/BotControl/types.ts | 1 + 3 files changed, 27 insertions(+) create mode 100644 backend/src/plugins/BotControl/commands/PerformanceCmd.ts diff --git a/backend/src/plugins/BotControl/BotControlPlugin.ts b/backend/src/plugins/BotControl/BotControlPlugin.ts index dd53d72c..6770b8ef 100644 --- a/backend/src/plugins/BotControl/BotControlPlugin.ts +++ b/backend/src/plugins/BotControl/BotControlPlugin.ts @@ -18,11 +18,13 @@ import { ReloadServerCmd } from "./commands/ReloadServerCmd"; import { RemoveDashboardUserCmd } from "./commands/RemoveDashboardUserCmd"; import { ServersCmd } from "./commands/ServersCmd"; import { BotControlPluginType, ConfigSchema } from "./types"; +import { PerformanceCmd } from "./commands/PerformanceCmd"; const defaultOptions = { config: { can_use: false, can_eligible: false, + can_performance: false, update_cmd: null, }, }; @@ -45,6 +47,7 @@ export const BotControlPlugin = zeppelinGlobalPlugin()({ ListDashboardUsersCmd, ListDashboardPermsCmd, EligibleCmd, + PerformanceCmd, ], async afterLoad(pluginData) { diff --git a/backend/src/plugins/BotControl/commands/PerformanceCmd.ts b/backend/src/plugins/BotControl/commands/PerformanceCmd.ts new file mode 100644 index 00000000..6e4c857a --- /dev/null +++ b/backend/src/plugins/BotControl/commands/PerformanceCmd.ts @@ -0,0 +1,23 @@ +import { TextChannel } from "discord.js"; +import { commandTypeHelpers as ct } from "../../../commandTypes"; +import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { createChunkedMessage, formatNumber, resolveInvite, sorter, verboseUserMention } from "../../../utils"; +import { botControlCmd } from "../types"; + +export const PerformanceCmd = botControlCmd({ + trigger: ["performance"], + permission: "can_performance", + + signature: {}, + + async run({ pluginData, message: msg, args }) { + const stats = pluginData.getKnubInstance().getPluginPerformanceStats(); + const averageLoadTimeEntries = Object.entries(stats.averageLoadTimes); + averageLoadTimeEntries.sort(sorter(v => v[1].time, "DESC")); + const lines = averageLoadTimeEntries.map( + ([pluginName, { time }]) => `${pluginName}: **${formatNumber(Math.round(time))}ms**`, + ); + const fullStats = `Average plugin load times:\n\n${lines.join("\n")}`; + createChunkedMessage(msg.channel as TextChannel, fullStats); + }, +}); diff --git a/backend/src/plugins/BotControl/types.ts b/backend/src/plugins/BotControl/types.ts index 1acac3a4..44e57cf8 100644 --- a/backend/src/plugins/BotControl/types.ts +++ b/backend/src/plugins/BotControl/types.ts @@ -9,6 +9,7 @@ import { tNullable } from "../../utils"; export const ConfigSchema = t.type({ can_use: t.boolean, can_eligible: t.boolean, + can_performance: t.boolean, update_cmd: tNullable(t.string), }); export type TConfigSchema = t.TypeOf; From 2b8f75b91b6cffe984d6b6309b07d15cf135eec0 Mon Sep 17 00:00:00 2001 From: Dragory <2606411+Dragory@users.noreply.github.com> Date: Sat, 4 Sep 2021 22:15:27 +0300 Subject: [PATCH 31/31] Upgrade to Knub v30.0.0-beta.45 --- backend/package-lock.json | 14 +++++++------- backend/package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/backend/package-lock.json b/backend/package-lock.json index 8ed1eff1..79e1da28 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -24,7 +24,7 @@ "humanize-duration": "^3.15.0", "io-ts": "^2.0.0", "js-yaml": "^3.13.1", - "knub": "^30.0.0-beta.44", + "knub": "^30.0.0-beta.45", "knub-command-manager": "^9.1.0", "last-commit-log": "^2.1.0", "lodash.chunk": "^4.2.0", @@ -3043,9 +3043,9 @@ } }, "node_modules/knub": { - "version": "30.0.0-beta.44", - "resolved": "https://registry.npmjs.org/knub/-/knub-30.0.0-beta.44.tgz", - "integrity": "sha512-VkddBzz43A2ZBEGI0V8YjPuRzzbMxZ9TAyswYm+lwsnMTVygvn2E/cWVz6BEWcbUj0rU/uCEUHsMD4M8NfXVqg==", + "version": "30.0.0-beta.45", + "resolved": "https://registry.npmjs.org/knub/-/knub-30.0.0-beta.45.tgz", + "integrity": "sha512-r1jtHBYthOn8zjgyILh418/Qnw8f/cUMzz5aky7+T5HLFV0BAiBzeg5TOb0UFMkn8ewIPSy8GTG1x/CIAv3s8Q==", "dependencies": { "discord-api-types": "^0.22.0", "discord.js": "^13.0.1", @@ -8290,9 +8290,9 @@ } }, "knub": { - "version": "30.0.0-beta.44", - "resolved": "https://registry.npmjs.org/knub/-/knub-30.0.0-beta.44.tgz", - "integrity": "sha512-VkddBzz43A2ZBEGI0V8YjPuRzzbMxZ9TAyswYm+lwsnMTVygvn2E/cWVz6BEWcbUj0rU/uCEUHsMD4M8NfXVqg==", + "version": "30.0.0-beta.45", + "resolved": "https://registry.npmjs.org/knub/-/knub-30.0.0-beta.45.tgz", + "integrity": "sha512-r1jtHBYthOn8zjgyILh418/Qnw8f/cUMzz5aky7+T5HLFV0BAiBzeg5TOb0UFMkn8ewIPSy8GTG1x/CIAv3s8Q==", "requires": { "discord-api-types": "^0.22.0", "discord.js": "^13.0.1", diff --git a/backend/package.json b/backend/package.json index 74f02a5c..685637b7 100644 --- a/backend/package.json +++ b/backend/package.json @@ -39,7 +39,7 @@ "humanize-duration": "^3.15.0", "io-ts": "^2.0.0", "js-yaml": "^3.13.1", - "knub": "^30.0.0-beta.44", + "knub": "^30.0.0-beta.45", "knub-command-manager": "^9.1.0", "last-commit-log": "^2.1.0", "lodash.chunk": "^4.2.0",