From 50776c56d41f9118b49e4bf459062ed8b1b31487 Mon Sep 17 00:00:00 2001 From: seeyebe Date: Sun, 7 Dec 2025 17:26:09 +0200 Subject: [PATCH 1/2] feat: resolve members on demand for mass actions --- .../plugins/ModActions/commands/massban/actualMassBanCmd.ts | 4 ++-- .../ModActions/commands/massmute/actualMassMuteCmd.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/src/plugins/ModActions/commands/massban/actualMassBanCmd.ts b/backend/src/plugins/ModActions/commands/massban/actualMassBanCmd.ts index bdaf59c83..fc41bb99d 100644 --- a/backend/src/plugins/ModActions/commands/massban/actualMassBanCmd.ts +++ b/backend/src/plugins/ModActions/commands/massban/actualMassBanCmd.ts @@ -11,7 +11,7 @@ import { isContextInteraction, sendContextResponse, } from "../../../../pluginUtils.js"; -import { DAYS, MINUTES, SECONDS, noop } from "../../../../utils.js"; +import { DAYS, MINUTES, SECONDS, noop, resolveMember } from "../../../../utils.js"; import { CasesPlugin } from "../../../Cases/CasesPlugin.js"; import { LogsPlugin } from "../../../Logs/LogsPlugin.js"; import { handleAttachmentLinkDetectionAndGetRestriction } from "../../functions/attachmentLinkReaction.js"; @@ -45,7 +45,7 @@ export async function actualMassBanCmd( // Verify we can act on each of the users specified for (const userId of userIds) { - const member = pluginData.guild.members.cache.get(userId as Snowflake); // TODO: Get members on demand? + const member = await resolveMember(pluginData.client, pluginData.guild, userId); if (member && !canActOn(pluginData, author, member)) { pluginData.state.common.sendErrorMessage(context, "Cannot massban one or more users: insufficient permissions"); return; diff --git a/backend/src/plugins/ModActions/commands/massmute/actualMassMuteCmd.ts b/backend/src/plugins/ModActions/commands/massmute/actualMassMuteCmd.ts index cb3b313ee..ea5453585 100644 --- a/backend/src/plugins/ModActions/commands/massmute/actualMassMuteCmd.ts +++ b/backend/src/plugins/ModActions/commands/massmute/actualMassMuteCmd.ts @@ -1,9 +1,9 @@ -import { Attachment, ChatInputCommandInteraction, GuildMember, Message, Snowflake } from "discord.js"; +import { Attachment, ChatInputCommandInteraction, GuildMember, Message } from "discord.js"; import { GuildPluginData } from "vety"; import { LogType } from "../../../../data/LogType.js"; import { logger } from "../../../../logger.js"; import { canActOn, deleteContextResponse, isContextInteraction, sendContextResponse } from "../../../../pluginUtils.js"; -import { noop } from "../../../../utils.js"; +import { noop, resolveMember } from "../../../../utils.js"; import { LogsPlugin } from "../../../Logs/LogsPlugin.js"; import { MutesPlugin } from "../../../Mutes/MutesPlugin.js"; import { handleAttachmentLinkDetectionAndGetRestriction } from "../../functions/attachmentLinkReaction.js"; @@ -36,7 +36,7 @@ export async function actualMassMuteCmd( // Verify we can act upon all users for (const userId of userIds) { - const member = pluginData.guild.members.cache.get(userId as Snowflake); + const member = await resolveMember(pluginData.client, pluginData.guild, userId); if (member && !canActOn(pluginData, author, member)) { pluginData.state.common.sendErrorMessage(context, "Cannot massmute one or more users: insufficient permissions"); return; From a259e7bbbbd9c2fb54a0063a224ae7fb4ad8f0f8 Mon Sep 17 00:00:00 2001 From: seeyebe Date: Sun, 7 Dec 2025 17:59:09 +0200 Subject: [PATCH 2/2] feat: batch member fetch for mass actions --- .../ModActions/commands/massban/actualMassBanCmd.ts | 9 ++++++++- .../ModActions/commands/massmute/actualMassMuteCmd.ts | 11 +++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/backend/src/plugins/ModActions/commands/massban/actualMassBanCmd.ts b/backend/src/plugins/ModActions/commands/massban/actualMassBanCmd.ts index fc41bb99d..de75a5f65 100644 --- a/backend/src/plugins/ModActions/commands/massban/actualMassBanCmd.ts +++ b/backend/src/plugins/ModActions/commands/massban/actualMassBanCmd.ts @@ -44,8 +44,15 @@ export async function actualMassBanCmd( const banReasonWithAttachments = formatReasonWithAttachments(reason, attachments); // Verify we can act on each of the users specified + let fetchedMembers: Map | null = null; + try { + fetchedMembers = await pluginData.guild.members.fetch({ user: userIds as Snowflake[] }); + } catch { + // If bulk fetch fails, fall back to cache-only checks + } + for (const userId of userIds) { - const member = await resolveMember(pluginData.client, pluginData.guild, userId); + const member = fetchedMembers?.get(userId) ?? pluginData.guild.members.cache.get(userId as Snowflake); if (member && !canActOn(pluginData, author, member)) { pluginData.state.common.sendErrorMessage(context, "Cannot massban one or more users: insufficient permissions"); return; diff --git a/backend/src/plugins/ModActions/commands/massmute/actualMassMuteCmd.ts b/backend/src/plugins/ModActions/commands/massmute/actualMassMuteCmd.ts index ea5453585..8e9ccf06e 100644 --- a/backend/src/plugins/ModActions/commands/massmute/actualMassMuteCmd.ts +++ b/backend/src/plugins/ModActions/commands/massmute/actualMassMuteCmd.ts @@ -1,4 +1,4 @@ -import { Attachment, ChatInputCommandInteraction, GuildMember, Message } from "discord.js"; +import { Attachment, ChatInputCommandInteraction, GuildMember, Message, Snowflake } from "discord.js"; import { GuildPluginData } from "vety"; import { LogType } from "../../../../data/LogType.js"; import { logger } from "../../../../logger.js"; @@ -35,8 +35,15 @@ export async function actualMassMuteCmd( const muteReasonWithAttachments = formatReasonWithAttachments(reason, attachments); // Verify we can act upon all users + let fetchedMembers: Map | null = null; + try { + fetchedMembers = await pluginData.guild.members.fetch({ user: userIds as Snowflake[] }); + } catch { + // If bulk fetch fails, fall back to cache-only checks + } + for (const userId of userIds) { - const member = await resolveMember(pluginData.client, pluginData.guild, userId); + const member = fetchedMembers?.get(userId) ?? pluginData.guild.members.cache.get(userId as Snowflake); if (member && !canActOn(pluginData, author, member)) { pluginData.state.common.sendErrorMessage(context, "Cannot massmute one or more users: insufficient permissions"); return;