diff --git a/backend/src/index.ts b/backend/src/index.ts index 2fe16c11..146b2297 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -203,7 +203,7 @@ if (env.DEBUG) { } logger.info("Connecting to database"); -connect().then(async (connection) => { +connect().then(async () => { const client = new Client({ partials: [Partials.User, Partials.Channel, Partials.GuildMember, Partials.Message, Partials.Reaction], @@ -315,9 +315,27 @@ connect().then(async (connection) => { if (row) { try { const loaded = loadYamlSafely(row.config); + + if (loaded.success_emoji || loaded.error_emoji) { + const deprecatedKeys = [] as string[]; + const exampleConfig = `plugins:\n common:\n config:\n success_emoji: "👍"\n error_emoji: "👎"`; + + if (loaded.success_emoji) { + deprecatedKeys.push("success_emoji"); + } + + if (loaded.error_emoji) { + deprecatedKeys.push("error_emoji"); + } + + logger.warn(`Deprecated config properties found in "${key}": ${deprecatedKeys.join(", ")}`); + logger.warn(`You can now configure those emojis in the "common" plugin config\n${exampleConfig}`); + } + // Remove deprecated properties some may still have in their config delete loaded.success_emoji; delete loaded.error_emoji; + return loaded; } catch (err) { logger.error(`Error while loading config "${key}": ${err.message}`); diff --git a/backend/src/pluginUtils.ts b/backend/src/pluginUtils.ts index 9736c9fe..7f394092 100644 --- a/backend/src/pluginUtils.ts +++ b/backend/src/pluginUtils.ts @@ -7,8 +7,6 @@ import { GuildMember, Message, MessageCreateOptions, - MessageMentionOptions, - ModalSubmitInteraction, PermissionsBitField, TextBasedChannel, User, @@ -23,10 +21,9 @@ import { PluginOverrideCriteria, helpers, } from "knub"; -import { logger } from "./logger"; import { isStaff } from "./staff"; import { TZeppelinKnub } from "./types"; -import { errorMessage, successMessage, tNullable } from "./utils"; +import { tNullable } from "./utils"; import { Tail } from "./utils/typeUtils"; import { StrictValidationError, parseIoTsSchema } from "./validatorUtils"; @@ -103,121 +100,50 @@ export function makeIoTsConfigParser>(schema: Schema) } export function isContextInteraction( - context: TextBasedChannel | User | ChatInputCommandInteraction, + context: TextBasedChannel | Message | User | ChatInputCommandInteraction, ): context is ChatInputCommandInteraction { return "commandId" in context && !!context.commandId; } -export function sendContextResponse( - context: TextBasedChannel | User | ChatInputCommandInteraction, +export function isContextMessage( + context: TextBasedChannel | Message | User | ChatInputCommandInteraction, +): context is Message { + return "content" in context || "embeds" in context; +} + +export async function getContextChannel( + context: TextBasedChannel | Message | User | ChatInputCommandInteraction, +): Promise { + if (isContextInteraction(context)) { + // context is ChatInputCommandInteraction + return context.channel!; + } else if ("username" in context) { + // context is User + return await (context as User).createDM(); + } else if ("send" in context) { + // context is TextBaseChannel + return context as TextBasedChannel; + } else { + // context is Message + return context.channel; + } +} + +export async function sendContextResponse( + context: TextBasedChannel | Message | User | ChatInputCommandInteraction, response: string | Omit, ): Promise { if (isContextInteraction(context)) { const options = { ...(typeof response === "string" ? { content: response } : response), fetchReply: true }; return (context.replied ? context.followUp(options) : context.reply(options)) as Promise; - } else { + } else if ("send" in context) { return context.send(response); + } else { + return (await getContextChannel(context)).send(response); } } -export async function sendSuccessMessage( - pluginData: AnyPluginData, - context: TextBasedChannel | User | ChatInputCommandInteraction, - body: string, - allowedMentions?: MessageMentionOptions, - responseInteraction?: ModalSubmitInteraction, - ephemeral = true, -): Promise { - const emoji = pluginData.fullConfig.success_emoji || undefined; - const formattedBody = successMessage(body, emoji); - const content: MessageCreateOptions = allowedMentions - ? { content: formattedBody, allowedMentions } - : { content: formattedBody }; - - if (responseInteraction) { - await responseInteraction - .editReply({ content: formattedBody, embeds: [], components: [] }) - .catch((err) => logger.error(`Interaction reply failed: ${err}`)); - - return; - } - - if (!isContextInteraction(context)) { - // noinspection TypeScriptValidateJSTypes - return context - .send({ ...content }) // Force line break - .catch((err) => { - const channelInfo = "guild" in context ? `${context.id} (${context.guild.id})` : context.id; - logger.warn(`Failed to send success message to ${channelInfo}): ${err.code} ${err.message}`); - - return undefined; - }); - } - - const replyMethod = context.replied ? "followUp" : "reply"; - - return context[replyMethod]({ - content: formattedBody, - embeds: [], - components: [], - fetchReply: true, - ephemeral, - }).catch((err) => { - logger.error(`Context reply failed: ${err}`); - - return undefined; - }) as Promise; -} - -export async function sendErrorMessage( - pluginData: AnyPluginData, - context: TextBasedChannel | User | ChatInputCommandInteraction, - body: string, - allowedMentions?: MessageMentionOptions, - responseInteraction?: ModalSubmitInteraction, - ephemeral = false, -): Promise { - const emoji = pluginData.fullConfig.error_emoji || undefined; - const formattedBody = errorMessage(body, emoji); - const content: MessageCreateOptions = allowedMentions - ? { content: formattedBody, allowedMentions } - : { content: formattedBody }; - - if (responseInteraction) { - await responseInteraction - .editReply({ content: formattedBody, embeds: [], components: [] }) - .catch((err) => logger.error(`Interaction reply failed: ${err}`)); - - return; - } - - if (!isContextInteraction(context)) { - // noinspection TypeScriptValidateJSTypes - return context - .send({ ...content }) // Force line break - .catch((err) => { - const channelInfo = "guild" in context ? `${context.id} (${context.guild.id})` : context.id; - logger.warn(`Failed to send error message to ${channelInfo}): ${err.code} ${err.message}`); - return undefined; - }); - } - - const replyMethod = context.replied ? "followUp" : "reply"; - - return context[replyMethod]({ - content: formattedBody, - embeds: [], - components: [], - fetchReply: true, - ephemeral, - }).catch((err) => { - logger.error(`Context reply failed: ${err}`); - - return undefined; - }) as Promise; -} - export function getBaseUrl(pluginData: AnyPluginData) { const knub = pluginData.getKnubInstance() as TZeppelinKnub; // @ts-expect-error diff --git a/backend/src/plugins/AutoReactions/commands/DisableAutoReactionsCmd.ts b/backend/src/plugins/AutoReactions/commands/DisableAutoReactionsCmd.ts index 20f749ea..ec3417d4 100644 --- a/backend/src/plugins/AutoReactions/commands/DisableAutoReactionsCmd.ts +++ b/backend/src/plugins/AutoReactions/commands/DisableAutoReactionsCmd.ts @@ -1,5 +1,5 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { autoReactionsCmd } from "../types"; export const DisableAutoReactionsCmd = autoReactionsCmd({ @@ -14,12 +14,12 @@ export const DisableAutoReactionsCmd = autoReactionsCmd({ async run({ message: msg, args, pluginData }) { const autoReaction = await pluginData.state.autoReactions.getForChannel(args.channelId); if (!autoReaction) { - sendErrorMessage(pluginData, msg.channel, `Auto-reactions aren't enabled in <#${args.channelId}>`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `Auto-reactions aren't enabled in <#${args.channelId}>`); return; } await pluginData.state.autoReactions.removeFromChannel(args.channelId); pluginData.state.cache.delete(args.channelId); - sendSuccessMessage(pluginData, msg.channel, `Auto-reactions disabled in <#${args.channelId}>`); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, `Auto-reactions disabled in <#${args.channelId}>`); }, }); diff --git a/backend/src/plugins/AutoReactions/commands/NewAutoReactionsCmd.ts b/backend/src/plugins/AutoReactions/commands/NewAutoReactionsCmd.ts index a64cb95c..250df4f0 100644 --- a/backend/src/plugins/AutoReactions/commands/NewAutoReactionsCmd.ts +++ b/backend/src/plugins/AutoReactions/commands/NewAutoReactionsCmd.ts @@ -1,10 +1,10 @@ import { PermissionsBitField } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { canUseEmoji, customEmojiRegex, isEmoji } from "../../../utils"; import { getMissingChannelPermissions } from "../../../utils/getMissingChannelPermissions"; import { missingPermissionError } from "../../../utils/missingPermissionError"; import { readChannelPermissions } from "../../../utils/readChannelPermissions"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { autoReactionsCmd } from "../types"; const requiredPermissions = readChannelPermissions | PermissionsBitField.Flags.AddReactions; @@ -25,17 +25,20 @@ export const NewAutoReactionsCmd = autoReactionsCmd({ const me = pluginData.guild.members.cache.get(pluginData.client.user!.id)!; const missingPermissions = getMissingChannelPermissions(me, args.channel, requiredPermissions); if (missingPermissions) { - sendErrorMessage( - pluginData, - msg.channel, - `Cannot set auto-reactions for that channel. ${missingPermissionError(missingPermissions)}`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage( + msg, + `Cannot set auto-reactions for that channel. ${missingPermissionError(missingPermissions)}`, + ); return; } for (const reaction of args.reactions) { if (!isEmoji(reaction)) { - sendErrorMessage(pluginData, msg.channel, "One or more of the specified reactions were invalid!"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, "One or more of the specified reactions were invalid!"); return; } @@ -45,7 +48,9 @@ export const NewAutoReactionsCmd = autoReactionsCmd({ if (customEmojiMatch) { // Custom emoji if (!canUseEmoji(pluginData.client, customEmojiMatch[2])) { - sendErrorMessage(pluginData, msg.channel, "I can only use regular emojis and custom emojis from this server"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, "I can only use regular emojis and custom emojis from this server"); return; } @@ -60,6 +65,6 @@ export const NewAutoReactionsCmd = autoReactionsCmd({ await pluginData.state.autoReactions.set(args.channel.id, finalReactions); pluginData.state.cache.delete(args.channel.id); - sendSuccessMessage(pluginData, msg.channel, `Auto-reactions set for <#${args.channel.id}>`); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, `Auto-reactions set for <#${args.channel.id}>`); }, }); diff --git a/backend/src/plugins/Automod/actions/ban.ts b/backend/src/plugins/Automod/actions/ban.ts index 9cd0fd86..1e63af61 100644 --- a/backend/src/plugins/Automod/actions/ban.ts +++ b/backend/src/plugins/Automod/actions/ban.ts @@ -42,6 +42,7 @@ export const BanAction = automodAction({ await modActions.banUserId( userId, reason, + reason, { contactMethods, caseArgs, diff --git a/backend/src/plugins/Automod/actions/kick.ts b/backend/src/plugins/Automod/actions/kick.ts index 9e6a792d..af95c803 100644 --- a/backend/src/plugins/Automod/actions/kick.ts +++ b/backend/src/plugins/Automod/actions/kick.ts @@ -37,7 +37,7 @@ export const KickAction = automodAction({ const modActions = pluginData.getPlugin(ModActionsPlugin); for (const member of membersToKick) { if (!member) continue; - await modActions.kickMember(member, reason, { contactMethods, caseArgs, isAutomodAction: true }); + await modActions.kickMember(member, reason, reason, { contactMethods, caseArgs, isAutomodAction: true }); } }, }); diff --git a/backend/src/plugins/Automod/actions/mute.ts b/backend/src/plugins/Automod/actions/mute.ts index 3219c712..0afed092 100644 --- a/backend/src/plugins/Automod/actions/mute.ts +++ b/backend/src/plugins/Automod/actions/mute.ts @@ -48,6 +48,7 @@ export const MuteAction = automodAction({ userId, duration, reason, + reason, { contactMethods, caseArgs, isAutomodAction: true }, rolesToRemove, rolesToRestore, diff --git a/backend/src/plugins/Automod/actions/warn.ts b/backend/src/plugins/Automod/actions/warn.ts index 59135cb2..ff79f64f 100644 --- a/backend/src/plugins/Automod/actions/warn.ts +++ b/backend/src/plugins/Automod/actions/warn.ts @@ -37,7 +37,7 @@ export const WarnAction = automodAction({ const modActions = pluginData.getPlugin(ModActionsPlugin); for (const member of membersToWarn) { if (!member) continue; - await modActions.warnMember(member, reason, { contactMethods, caseArgs, isAutomodAction: true }); + await modActions.warnMember(member, reason, reason, { contactMethods, caseArgs, isAutomodAction: true }); } }, }); diff --git a/backend/src/plugins/Automod/commands/AntiraidClearCmd.ts b/backend/src/plugins/Automod/commands/AntiraidClearCmd.ts index fd31d4b1..983a1f99 100644 --- a/backend/src/plugins/Automod/commands/AntiraidClearCmd.ts +++ b/backend/src/plugins/Automod/commands/AntiraidClearCmd.ts @@ -1,5 +1,5 @@ import { guildPluginMessageCommand } from "knub"; -import { sendSuccessMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { setAntiraidLevel } from "../functions/setAntiraidLevel"; import { AutomodPluginType } from "../types"; @@ -9,6 +9,6 @@ export const AntiraidClearCmd = guildPluginMessageCommand()({ async run({ pluginData, message }) { await setAntiraidLevel(pluginData, null, message.author); - sendSuccessMessage(pluginData, message.channel, "Anti-raid turned **off**"); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(message, "Anti-raid turned **off**"); }, }); diff --git a/backend/src/plugins/Automod/commands/SetAntiraidCmd.ts b/backend/src/plugins/Automod/commands/SetAntiraidCmd.ts index 159ff576..91cbacd6 100644 --- a/backend/src/plugins/Automod/commands/SetAntiraidCmd.ts +++ b/backend/src/plugins/Automod/commands/SetAntiraidCmd.ts @@ -1,6 +1,6 @@ import { guildPluginMessageCommand } from "knub"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { setAntiraidLevel } from "../functions/setAntiraidLevel"; import { AutomodPluginType } from "../types"; @@ -15,11 +15,11 @@ export const SetAntiraidCmd = guildPluginMessageCommand()({ async run({ pluginData, message, args }) { const config = pluginData.config.get(); if (!config.antiraid_levels.includes(args.level)) { - sendErrorMessage(pluginData, message.channel, "Unknown anti-raid level"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Unknown anti-raid level"); return; } await setAntiraidLevel(pluginData, args.level, message.author); - sendSuccessMessage(pluginData, message.channel, `Anti-raid level set to **${args.level}**`); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(message, `Anti-raid level set to **${args.level}**`); }, }); diff --git a/backend/src/plugins/BotControl/BotControlPlugin.ts b/backend/src/plugins/BotControl/BotControlPlugin.ts index 76478ca2..e7d573fc 100644 --- a/backend/src/plugins/BotControl/BotControlPlugin.ts +++ b/backend/src/plugins/BotControl/BotControlPlugin.ts @@ -3,7 +3,8 @@ import { AllowedGuilds } from "../../data/AllowedGuilds"; import { ApiPermissionAssignments } from "../../data/ApiPermissionAssignments"; import { Configs } from "../../data/Configs"; import { GuildArchives } from "../../data/GuildArchives"; -import { makeIoTsConfigParser, sendSuccessMessage } from "../../pluginUtils"; +import { makeIoTsConfigParser } from "../../pluginUtils"; +import { CommonPlugin } from "../Common/CommonPlugin"; import { zeppelinGlobalPlugin } from "../ZeppelinPluginBlueprint"; import { getActiveReload, resetActiveReload } from "./activeReload"; import { AddDashboardUserCmd } from "./commands/AddDashboardUserCmd"; @@ -77,7 +78,7 @@ export const BotControlPlugin = zeppelinGlobalPlugin()({ if (guild) { const channel = guild.channels.cache.get(channelId as Snowflake); if (channel instanceof TextChannel) { - sendSuccessMessage(pluginData, channel, "Global plugins reloaded!"); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(channel, "Global plugins reloaded!"); } } } diff --git a/backend/src/plugins/BotControl/commands/AddDashboardUserCmd.ts b/backend/src/plugins/BotControl/commands/AddDashboardUserCmd.ts index c1259594..1e88d679 100644 --- a/backend/src/plugins/BotControl/commands/AddDashboardUserCmd.ts +++ b/backend/src/plugins/BotControl/commands/AddDashboardUserCmd.ts @@ -1,7 +1,8 @@ import { ApiPermissions } from "@shared/apiPermissions"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { isStaffPreFilter } from "../../../pluginUtils"; import { renderUserUsername } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { botControlCmd } from "../types"; export const AddDashboardUserCmd = botControlCmd({ @@ -19,7 +20,7 @@ export const AddDashboardUserCmd = botControlCmd({ async run({ pluginData, message: msg, args }) { const guild = await pluginData.state.allowedGuilds.find(args.guildId); if (!guild) { - sendErrorMessage(pluginData, msg.channel, "Server is not using Zeppelin"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Server is not using Zeppelin"); return; } @@ -36,10 +37,11 @@ export const AddDashboardUserCmd = botControlCmd({ } const userNameList = args.users.map((user) => `<@!${user.id}> (**${renderUserUsername(user)}**, \`${user.id}\`)`); - sendSuccessMessage( - pluginData, - msg.channel, - `The following users were given dashboard access for **${guild.name}**:\n\n${userNameList}`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage( + msg, + `The following users were given dashboard access for **${guild.name}**:\n\n${userNameList}`, + ); }, }); diff --git a/backend/src/plugins/BotControl/commands/AddServerFromInviteCmd.ts b/backend/src/plugins/BotControl/commands/AddServerFromInviteCmd.ts index cbf53bf4..97944c1d 100644 --- a/backend/src/plugins/BotControl/commands/AddServerFromInviteCmd.ts +++ b/backend/src/plugins/BotControl/commands/AddServerFromInviteCmd.ts @@ -1,8 +1,8 @@ import { ApiPermissions } from "@shared/apiPermissions"; import moment from "moment-timezone"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { DBDateFormat, isGuildInvite, resolveInvite } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { isEligible } from "../functions/isEligible"; import { botControlCmd } from "../types"; @@ -18,19 +18,21 @@ export const AddServerFromInviteCmd = botControlCmd({ async run({ pluginData, message: msg, args }) { const invite = await resolveInvite(pluginData.client, args.inviteCode, true); if (!invite || !isGuildInvite(invite)) { - sendErrorMessage(pluginData, msg.channel, "Could not resolve invite"); // :D + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Could not resolve invite"); // :D return; } const existing = await pluginData.state.allowedGuilds.find(invite.guild.id); if (existing) { - sendErrorMessage(pluginData, msg.channel, "Server is already allowed!"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Server is already allowed!"); return; } const { result, explanation } = await isEligible(pluginData, args.user, invite); if (!result) { - sendErrorMessage(pluginData, msg.channel, `Could not add server because it's not eligible: ${explanation}`); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `Could not add server because it's not eligible: ${explanation}`); return; } @@ -51,6 +53,8 @@ export const AddServerFromInviteCmd = botControlCmd({ ); } - sendSuccessMessage(pluginData, msg.channel, "Server was eligible and is now allowed to use Zeppelin!"); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(msg, "Server was eligible and is now allowed to use Zeppelin!"); }, }); diff --git a/backend/src/plugins/BotControl/commands/AllowServerCmd.ts b/backend/src/plugins/BotControl/commands/AllowServerCmd.ts index ce2c3b0c..36e2d17a 100644 --- a/backend/src/plugins/BotControl/commands/AllowServerCmd.ts +++ b/backend/src/plugins/BotControl/commands/AllowServerCmd.ts @@ -1,8 +1,9 @@ import { ApiPermissions } from "@shared/apiPermissions"; import moment from "moment-timezone"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { isStaffPreFilter } from "../../../pluginUtils"; import { DBDateFormat, isSnowflake } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { botControlCmd } from "../types"; export const AllowServerCmd = botControlCmd({ @@ -20,17 +21,17 @@ export const AllowServerCmd = botControlCmd({ async run({ pluginData, message: msg, args }) { const existing = await pluginData.state.allowedGuilds.find(args.guildId); if (existing) { - sendErrorMessage(pluginData, msg.channel, "Server is already allowed!"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Server is already allowed!"); return; } if (!isSnowflake(args.guildId)) { - sendErrorMessage(pluginData, msg.channel, "Invalid server ID!"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Invalid server ID!"); return; } if (args.userId && !isSnowflake(args.userId)) { - sendErrorMessage(pluginData, msg.channel, "Invalid user ID!"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Invalid user ID!"); return; } @@ -51,6 +52,6 @@ export const AllowServerCmd = botControlCmd({ ); } - sendSuccessMessage(pluginData, msg.channel, "Server is now allowed to use Zeppelin!"); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, "Server is now allowed to use Zeppelin!"); }, }); diff --git a/backend/src/plugins/BotControl/commands/ChannelToServerCmd.ts b/backend/src/plugins/BotControl/commands/ChannelToServerCmd.ts index 11d3a487..939077e2 100644 --- a/backend/src/plugins/BotControl/commands/ChannelToServerCmd.ts +++ b/backend/src/plugins/BotControl/commands/ChannelToServerCmd.ts @@ -1,5 +1,6 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { isStaffPreFilter, sendErrorMessage } from "../../../pluginUtils"; +import { isStaffPreFilter } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { botControlCmd } from "../types"; export const ChannelToServerCmd = botControlCmd({ @@ -16,7 +17,7 @@ export const ChannelToServerCmd = botControlCmd({ async run({ pluginData, message: msg, args }) { const channel = pluginData.client.channels.cache.get(args.channelId); if (!channel) { - sendErrorMessage(pluginData, msg.channel, "Channel not found in cache!"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Channel not found in cache!"); return; } diff --git a/backend/src/plugins/BotControl/commands/DisallowServerCmd.ts b/backend/src/plugins/BotControl/commands/DisallowServerCmd.ts index 06bc1b14..69ba0b4c 100644 --- a/backend/src/plugins/BotControl/commands/DisallowServerCmd.ts +++ b/backend/src/plugins/BotControl/commands/DisallowServerCmd.ts @@ -1,7 +1,8 @@ import { Snowflake } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { isStaffPreFilter } from "../../../pluginUtils"; import { noop } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { botControlCmd } from "../types"; export const DisallowServerCmd = botControlCmd({ @@ -18,7 +19,7 @@ export const DisallowServerCmd = botControlCmd({ async run({ pluginData, message: msg, args }) { const existing = await pluginData.state.allowedGuilds.find(args.guildId); if (!existing) { - sendErrorMessage(pluginData, msg.channel, "That server is not allowed in the first place!"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "That server is not allowed in the first place!"); return; } @@ -27,6 +28,6 @@ export const DisallowServerCmd = botControlCmd({ .get(args.guildId as Snowflake) ?.leave() .catch(noop); - sendSuccessMessage(pluginData, msg.channel, "Server removed!"); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, "Server removed!"); }, }); diff --git a/backend/src/plugins/BotControl/commands/EligibleCmd.ts b/backend/src/plugins/BotControl/commands/EligibleCmd.ts index face42a8..bbcd5c5d 100644 --- a/backend/src/plugins/BotControl/commands/EligibleCmd.ts +++ b/backend/src/plugins/BotControl/commands/EligibleCmd.ts @@ -1,6 +1,6 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { isGuildInvite, resolveInvite } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { isEligible } from "../functions/isEligible"; import { botControlCmd } from "../types"; @@ -16,17 +16,17 @@ export const EligibleCmd = botControlCmd({ async run({ pluginData, message: msg, args }) { const invite = await resolveInvite(pluginData.client, args.inviteCode, true); if (!invite || !isGuildInvite(invite)) { - sendErrorMessage(pluginData, msg.channel, "Could not resolve invite"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Could not resolve invite"); return; } const { result, explanation } = await isEligible(pluginData, args.user, invite); if (result) { - sendSuccessMessage(pluginData, msg.channel, `Server is eligible: ${explanation}`); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, `Server is eligible: ${explanation}`); return; } - sendErrorMessage(pluginData, msg.channel, `Server is **NOT** eligible: ${explanation}`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `Server is **NOT** eligible: ${explanation}`); }, }); diff --git a/backend/src/plugins/BotControl/commands/LeaveServerCmd.ts b/backend/src/plugins/BotControl/commands/LeaveServerCmd.ts index 14aaf833..0066a916 100644 --- a/backend/src/plugins/BotControl/commands/LeaveServerCmd.ts +++ b/backend/src/plugins/BotControl/commands/LeaveServerCmd.ts @@ -1,6 +1,7 @@ import { Snowflake } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { isStaffPreFilter } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { botControlCmd } from "../types"; export const LeaveServerCmd = botControlCmd({ @@ -16,7 +17,7 @@ export const LeaveServerCmd = botControlCmd({ async run({ pluginData, message: msg, args }) { if (!pluginData.client.guilds.cache.has(args.guildId as Snowflake)) { - sendErrorMessage(pluginData, msg.channel, "I am not in that guild"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "I am not in that guild"); return; } @@ -26,10 +27,10 @@ export const LeaveServerCmd = botControlCmd({ try { await pluginData.client.guilds.cache.get(args.guildId as Snowflake)?.leave(); } catch (e) { - sendErrorMessage(pluginData, msg.channel, `Failed to leave guild: ${e.message}`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `Failed to leave guild: ${e.message}`); return; } - sendSuccessMessage(pluginData, msg.channel, `Left guild **${guildName}**`); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, `Left guild **${guildName}**`); }, }); diff --git a/backend/src/plugins/BotControl/commands/ListDashboardPermsCmd.ts b/backend/src/plugins/BotControl/commands/ListDashboardPermsCmd.ts index 18c7d0d7..ecab5434 100644 --- a/backend/src/plugins/BotControl/commands/ListDashboardPermsCmd.ts +++ b/backend/src/plugins/BotControl/commands/ListDashboardPermsCmd.ts @@ -1,8 +1,8 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; import { AllowedGuild } from "../../../data/entities/AllowedGuild"; import { ApiPermissionAssignment } from "../../../data/entities/ApiPermissionAssignment"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { renderUserUsername, resolveUser } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { botControlCmd } from "../types"; export const ListDashboardPermsCmd = botControlCmd({ @@ -16,7 +16,7 @@ export const ListDashboardPermsCmd = botControlCmd({ async run({ pluginData, message: msg, args }) { if (!args.user && !args.guildId) { - sendErrorMessage(pluginData, msg.channel, "Must specify at least guildId, user, or both."); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Must specify at least guildId, user, or both."); return; } @@ -24,7 +24,7 @@ export const ListDashboardPermsCmd = botControlCmd({ if (args.guildId) { guild = await pluginData.state.allowedGuilds.find(args.guildId); if (!guild) { - sendErrorMessage(pluginData, msg.channel, "Server is not using Zeppelin"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Server is not using Zeppelin"); return; } } @@ -33,7 +33,7 @@ export const ListDashboardPermsCmd = botControlCmd({ if (args.user) { existingUserAssignment = await pluginData.state.apiPermissionAssignments.getByUserId(args.user.id); if (existingUserAssignment.length === 0) { - sendErrorMessage(pluginData, msg.channel, "The user has no assigned permissions."); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "The user has no assigned permissions."); return; } } @@ -54,11 +54,9 @@ export const ListDashboardPermsCmd = botControlCmd({ } if (finalMessage === "") { - sendErrorMessage( - pluginData, - msg.channel, - `The user ${userInfo} has no assigned permissions on the specified server.`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `The user ${userInfo} has no assigned permissions on the specified server.`); return; } // Else display all users that have permissions on the specified guild @@ -67,7 +65,9 @@ export const ListDashboardPermsCmd = botControlCmd({ const existingGuildAssignment = await pluginData.state.apiPermissionAssignments.getByGuildId(guild.id); if (existingGuildAssignment.length === 0) { - sendErrorMessage(pluginData, msg.channel, `The server ${guildInfo} has no assigned permissions.`); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `The server ${guildInfo} has no assigned permissions.`); return; } @@ -80,6 +80,6 @@ export const ListDashboardPermsCmd = botControlCmd({ } } - await sendSuccessMessage(pluginData, msg.channel, finalMessage.trim(), {}); + await pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, finalMessage.trim(), {}); }, }); diff --git a/backend/src/plugins/BotControl/commands/ListDashboardUsersCmd.ts b/backend/src/plugins/BotControl/commands/ListDashboardUsersCmd.ts index 36f1432f..f233e1f7 100644 --- a/backend/src/plugins/BotControl/commands/ListDashboardUsersCmd.ts +++ b/backend/src/plugins/BotControl/commands/ListDashboardUsersCmd.ts @@ -1,6 +1,6 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { renderUserUsername, resolveUser } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { botControlCmd } from "../types"; export const ListDashboardUsersCmd = botControlCmd({ @@ -14,7 +14,7 @@ export const ListDashboardUsersCmd = botControlCmd({ async run({ pluginData, message: msg, args }) { const guild = await pluginData.state.allowedGuilds.find(args.guildId); if (!guild) { - sendErrorMessage(pluginData, msg.channel, "Server is not using Zeppelin"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Server is not using Zeppelin"); return; } @@ -30,11 +30,12 @@ export const ListDashboardUsersCmd = botControlCmd({ `<@!${user.id}> (**${renderUserUsername(user)}**, \`${user.id}\`): ${permission.permissions.join(", ")}`, ); - sendSuccessMessage( - pluginData, - msg.channel, - `The following users have dashboard access for **${guild.name}**:\n\n${userNameList.join("\n")}`, - {}, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage( + msg, + `The following users have dashboard access for **${guild.name}**:\n\n${userNameList.join("\n")}`, + {}, + ); }, }); diff --git a/backend/src/plugins/BotControl/commands/RateLimitPerformanceCmd.ts b/backend/src/plugins/BotControl/commands/RateLimitPerformanceCmd.ts index 46d2a0e0..9ac5499d 100644 --- a/backend/src/plugins/BotControl/commands/RateLimitPerformanceCmd.ts +++ b/backend/src/plugins/BotControl/commands/RateLimitPerformanceCmd.ts @@ -1,7 +1,8 @@ import moment from "moment-timezone"; import { GuildArchives } from "../../../data/GuildArchives"; -import { getBaseUrl, sendSuccessMessage } from "../../../pluginUtils"; +import { getBaseUrl } from "../../../pluginUtils"; import { getRateLimitStats } from "../../../rateLimitStats"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { botControlCmd } from "../types"; export const RateLimitPerformanceCmd = botControlCmd({ @@ -13,7 +14,7 @@ export const RateLimitPerformanceCmd = botControlCmd({ async run({ pluginData, message: msg }) { const logItems = getRateLimitStats(); if (logItems.length === 0) { - sendSuccessMessage(pluginData, msg.channel, `No rate limits hit`); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, `No rate limits hit`); return; } diff --git a/backend/src/plugins/BotControl/commands/ReloadGlobalPluginsCmd.ts b/backend/src/plugins/BotControl/commands/ReloadGlobalPluginsCmd.ts index 4f59f8a2..ea51dc00 100644 --- a/backend/src/plugins/BotControl/commands/ReloadGlobalPluginsCmd.ts +++ b/backend/src/plugins/BotControl/commands/ReloadGlobalPluginsCmd.ts @@ -1,4 +1,5 @@ -import { isStaffPreFilter, sendErrorMessage } from "../../../pluginUtils"; +import { isStaffPreFilter } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { getActiveReload, setActiveReload } from "../activeReload"; import { botControlCmd } from "../types"; @@ -14,7 +15,7 @@ export const ReloadGlobalPluginsCmd = botControlCmd({ const guildId = "guild" in message.channel ? message.channel.guild.id : null; if (!guildId) { - sendErrorMessage(pluginData, message.channel, "This command can only be used in a server"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "This command can only be used in a server"); return; } diff --git a/backend/src/plugins/BotControl/commands/ReloadServerCmd.ts b/backend/src/plugins/BotControl/commands/ReloadServerCmd.ts index 0440129b..8481682e 100644 --- a/backend/src/plugins/BotControl/commands/ReloadServerCmd.ts +++ b/backend/src/plugins/BotControl/commands/ReloadServerCmd.ts @@ -1,6 +1,7 @@ import { Snowflake } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { isStaffPreFilter } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { botControlCmd } from "../types"; export const ReloadServerCmd = botControlCmd({ @@ -16,18 +17,18 @@ export const ReloadServerCmd = botControlCmd({ async run({ pluginData, message: msg, args }) { if (!pluginData.client.guilds.cache.has(args.guildId as Snowflake)) { - sendErrorMessage(pluginData, msg.channel, "I am not in that guild"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "I am not in that guild"); return; } try { await pluginData.getKnubInstance().reloadGuild(args.guildId); } catch (e) { - sendErrorMessage(pluginData, msg.channel, `Failed to reload guild: ${e.message}`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `Failed to reload guild: ${e.message}`); return; } const guild = await pluginData.client.guilds.fetch(args.guildId as Snowflake); - sendSuccessMessage(pluginData, msg.channel, `Reloaded guild **${guild?.name || "???"}**`); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, `Reloaded guild **${guild?.name || "???"}**`); }, }); diff --git a/backend/src/plugins/BotControl/commands/RemoveDashboardUserCmd.ts b/backend/src/plugins/BotControl/commands/RemoveDashboardUserCmd.ts index 3a90683c..350891a9 100644 --- a/backend/src/plugins/BotControl/commands/RemoveDashboardUserCmd.ts +++ b/backend/src/plugins/BotControl/commands/RemoveDashboardUserCmd.ts @@ -1,6 +1,7 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { isStaffPreFilter, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { isStaffPreFilter } from "../../../pluginUtils"; import { renderUserUsername } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { botControlCmd } from "../types"; export const RemoveDashboardUserCmd = botControlCmd({ @@ -18,7 +19,7 @@ export const RemoveDashboardUserCmd = botControlCmd({ async run({ pluginData, message: msg, args }) { const guild = await pluginData.state.allowedGuilds.find(args.guildId); if (!guild) { - sendErrorMessage(pluginData, msg.channel, "Server is not using Zeppelin"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Server is not using Zeppelin"); return; } @@ -35,10 +36,11 @@ export const RemoveDashboardUserCmd = botControlCmd({ } const userNameList = args.users.map((user) => `<@!${user.id}> (**${renderUserUsername(user)}**, \`${user.id}\`)`); - sendSuccessMessage( - pluginData, - msg.channel, - `The following users were removed from the dashboard for **${guild.name}**:\n\n${userNameList}`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage( + msg, + `The following users were removed from the dashboard for **${guild.name}**:\n\n${userNameList}`, + ); }, }); diff --git a/backend/src/plugins/ChannelArchiver/commands/ArchiveChannelCmd.ts b/backend/src/plugins/ChannelArchiver/commands/ArchiveChannelCmd.ts index 3fc1b72b..ad9a8f85 100644 --- a/backend/src/plugins/ChannelArchiver/commands/ArchiveChannelCmd.ts +++ b/backend/src/plugins/ChannelArchiver/commands/ArchiveChannelCmd.ts @@ -1,8 +1,9 @@ import { Snowflake } from "discord.js"; import moment from "moment-timezone"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { isOwner, sendErrorMessage } from "../../../pluginUtils"; +import { isOwner } from "../../../pluginUtils"; import { SECONDS, confirm, noop, renderUsername } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin"; import { rehostAttachment } from "../rehostAttachment"; import { channelArchiverCmd } from "../types"; @@ -32,12 +33,12 @@ export const ArchiveChannelCmd = channelArchiverCmd({ async run({ message: msg, args, pluginData }) { if (!args["attachment-channel"]) { - const confirmed = await confirm(msg.channel, msg.author.id, { + const confirmed = await confirm(msg, msg.author.id, { content: "No `-attachment-channel` specified. Continue? Attachments will not be available in the log if their message is deleted.", }); if (!confirmed) { - sendErrorMessage(pluginData, msg.channel, "Canceled"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Canceled"); return; } } diff --git a/backend/src/plugins/Common/CommonPlugin.ts b/backend/src/plugins/Common/CommonPlugin.ts new file mode 100644 index 00000000..a8935907 --- /dev/null +++ b/backend/src/plugins/Common/CommonPlugin.ts @@ -0,0 +1,146 @@ +import { + ChatInputCommandInteraction, + Message, + MessageCreateOptions, + MessageMentionOptions, + ModalSubmitInteraction, + TextBasedChannel, + User, +} from "discord.js"; +import { PluginOptions } from "knub"; +import { logger } from "../../logger"; +import { isContextInteraction, makeIoTsConfigParser, sendContextResponse } from "../../pluginUtils"; +import { errorMessage, successMessage } from "../../utils"; +import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint"; +import { getErrorEmoji, getSuccessEmoji } from "./functions/getEmoji"; +import { CommonPluginType, ConfigSchema } from "./types"; + +const defaultOptions: PluginOptions = { + config: { + success_emoji: "✅", + error_emoji: "❌", + }, +}; + +export const CommonPlugin = zeppelinGuildPlugin()({ + name: "common", + showInDocs: false, + info: { + prettyName: "Common", + }, + + dependencies: () => [], + configParser: makeIoTsConfigParser(ConfigSchema), + defaultOptions, + public: { + getSuccessEmoji(pluginData) { + return () => getSuccessEmoji(pluginData); + }, + + getErrorEmoji(pluginData) { + return () => getErrorEmoji(pluginData); + }, + + sendSuccessMessage(pluginData) { + return async ( + context: TextBasedChannel | Message | User | ChatInputCommandInteraction, + body: string, + allowedMentions?: MessageMentionOptions, + responseInteraction?: ModalSubmitInteraction, + ephemeral = true, + ): Promise => { + const emoji = getSuccessEmoji(pluginData); + const formattedBody = successMessage(body, emoji); + const content: MessageCreateOptions = allowedMentions + ? { content: formattedBody, allowedMentions } + : { content: formattedBody }; + + if (responseInteraction) { + await responseInteraction + .editReply({ content: formattedBody, embeds: [], components: [] }) + .catch((err) => logger.error(`Interaction reply failed: ${err}`)); + + return; + } + + if (!isContextInteraction(context)) { + // noinspection TypeScriptValidateJSTypes + return sendContextResponse(context, { ...content }) // Force line break + .catch((err) => { + const channelInfo = + "guild" in context && context.guild ? `${context.id} (${context.guild.id})` : context.id; + + logger.warn(`Failed to send success message to ${channelInfo}): ${err.code} ${err.message}`); + + return undefined; + }); + } + + const replyMethod = context.replied ? "followUp" : "reply"; + + return context[replyMethod]({ + content: formattedBody, + embeds: [], + components: [], + fetchReply: true, + ephemeral, + }).catch((err) => { + logger.error(`Context reply failed: ${err}`); + + return undefined; + }) as Promise; + }; + }, + + sendErrorMessage(pluginData) { + return async ( + context: TextBasedChannel | Message | User | ChatInputCommandInteraction, + body: string, + allowedMentions?: MessageMentionOptions, + responseInteraction?: ModalSubmitInteraction, + ephemeral = false, + ): Promise => { + const emoji = getErrorEmoji(pluginData); + const formattedBody = errorMessage(body, emoji); + const content: MessageCreateOptions = allowedMentions + ? { content: formattedBody, allowedMentions } + : { content: formattedBody }; + + if (responseInteraction) { + await responseInteraction + .editReply({ content: formattedBody, embeds: [], components: [] }) + .catch((err) => logger.error(`Interaction reply failed: ${err}`)); + + return; + } + + if (!isContextInteraction(context)) { + // noinspection TypeScriptValidateJSTypes + return sendContextResponse(context, { ...content }) // Force line break + .catch((err) => { + const channelInfo = + "guild" in context && context.guild ? `${context.id} (${context.guild.id})` : context.id; + + logger.warn(`Failed to send error message to ${channelInfo}): ${err.code} ${err.message}`); + + return undefined; + }); + } + + const replyMethod = context.replied ? "followUp" : "reply"; + + return context[replyMethod]({ + content: formattedBody, + embeds: [], + components: [], + fetchReply: true, + ephemeral, + }).catch((err) => { + logger.error(`Context reply failed: ${err}`); + + return undefined; + }) as Promise; + }; + }, + }, +}); diff --git a/backend/src/plugins/Common/functions/getEmoji.ts b/backend/src/plugins/Common/functions/getEmoji.ts new file mode 100644 index 00000000..c1910250 --- /dev/null +++ b/backend/src/plugins/Common/functions/getEmoji.ts @@ -0,0 +1,10 @@ +import { GuildPluginData } from "knub"; +import { CommonPluginType } from "../types"; + +export function getSuccessEmoji(pluginData: GuildPluginData) { + return pluginData.config.get().success_emoji ?? "✅"; +} + +export function getErrorEmoji(pluginData: GuildPluginData) { + return pluginData.config.get().error_emoji ?? "❌"; +} diff --git a/backend/src/plugins/Common/types.ts b/backend/src/plugins/Common/types.ts new file mode 100644 index 00000000..d0c8df85 --- /dev/null +++ b/backend/src/plugins/Common/types.ts @@ -0,0 +1,13 @@ +import * as t from "io-ts"; +import { BasePluginType } from "knub"; + +export const ConfigSchema = t.type({ + success_emoji: t.string, + error_emoji: t.string, +}); + +export type TConfigSchema = t.TypeOf; + +export interface CommonPluginType extends BasePluginType { + config: TConfigSchema; +} diff --git a/backend/src/plugins/ContextMenus/actions/ban.ts b/backend/src/plugins/ContextMenus/actions/ban.ts index f2b391cc..9848f5d5 100644 --- a/backend/src/plugins/ContextMenus/actions/ban.ts +++ b/backend/src/plugins/ContextMenus/actions/ban.ts @@ -55,7 +55,7 @@ async function banAction( }; const durationMs = duration ? convertDelayStringToMS(duration)! : undefined; - const result = await modactions.banUserId(target, reason, { caseArgs }, durationMs); + const result = await modactions.banUserId(target, reason, reason, { caseArgs }, durationMs); if (result.status === "failed") { await interactionToReply .editReply({ content: "Error: Failed to ban user", embeds: [], components: [] }) diff --git a/backend/src/plugins/ContextMenus/actions/mute.ts b/backend/src/plugins/ContextMenus/actions/mute.ts index 58457cb0..5959f6d7 100644 --- a/backend/src/plugins/ContextMenus/actions/mute.ts +++ b/backend/src/plugins/ContextMenus/actions/mute.ts @@ -68,7 +68,7 @@ async function muteAction( const durationMs = duration ? convertDelayStringToMS(duration)! : undefined; try { - const result = await mutes.muteUser(target, durationMs, reason, { caseArgs }); + const result = await mutes.muteUser(target, durationMs, reason, reason, { caseArgs }); const messageResultText = result.notifyResult.text ? ` (${result.notifyResult.text})` : ""; const muteMessage = `Muted **${result.case.user_name}** ${ diff --git a/backend/src/plugins/ContextMenus/actions/warn.ts b/backend/src/plugins/ContextMenus/actions/warn.ts index 6fbd40f3..b467ed61 100644 --- a/backend/src/plugins/ContextMenus/actions/warn.ts +++ b/backend/src/plugins/ContextMenus/actions/warn.ts @@ -60,7 +60,7 @@ async function warnAction( modId: executingMember.id, }; - const result = await modactions.warnMember(targetMember, reason, { caseArgs }); + const result = await modactions.warnMember(targetMember, reason, reason, { caseArgs }); if (result.status === "failed") { await interactionToReply .editReply({ content: "Error: Failed to warn user", embeds: [], components: [] }) diff --git a/backend/src/plugins/Counters/commands/AddCounterCmd.ts b/backend/src/plugins/Counters/commands/AddCounterCmd.ts index a71418df..0eb68f2b 100644 --- a/backend/src/plugins/Counters/commands/AddCounterCmd.ts +++ b/backend/src/plugins/Counters/commands/AddCounterCmd.ts @@ -2,8 +2,8 @@ import { Snowflake, TextChannel } from "discord.js"; import { guildPluginMessageCommand } from "knub"; import { waitForReply } from "knub/helpers"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage } from "../../../pluginUtils"; import { UnknownUser, resolveUser } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { changeCounterValue } from "../functions/changeCounterValue"; import { CountersPluginType } from "../types"; @@ -45,22 +45,22 @@ export const AddCounterCmd = guildPluginMessageCommand()({ const counter = config.counters[args.counterName]; const counterId = pluginData.state.counterIds[args.counterName]; if (!counter || !counterId) { - sendErrorMessage(pluginData, message.channel, `Unknown counter: ${args.counterName}`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, `Unknown counter: ${args.counterName}`); return; } if (counter.can_edit === false) { - sendErrorMessage(pluginData, message.channel, `Missing permissions to edit this counter's value`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, `Missing permissions to edit this counter's value`); return; } if (args.channel && !counter.per_channel) { - sendErrorMessage(pluginData, message.channel, `This counter is not per-channel`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, `This counter is not per-channel`); return; } if (args.user && !counter.per_user) { - sendErrorMessage(pluginData, message.channel, `This counter is not per-user`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, `This counter is not per-user`); return; } @@ -69,13 +69,13 @@ export const AddCounterCmd = guildPluginMessageCommand()({ message.channel.send(`Which channel's counter value would you like to add to?`); const reply = await waitForReply(pluginData.client, message.channel, message.author.id); if (!reply || !reply.content) { - sendErrorMessage(pluginData, message.channel, "Cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Cancelling"); return; } const potentialChannel = pluginData.guild.channels.resolve(reply.content as Snowflake); if (!potentialChannel || !(potentialChannel instanceof TextChannel)) { - sendErrorMessage(pluginData, message.channel, "Channel is not a text channel, cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Channel is not a text channel, cancelling"); return; } @@ -87,13 +87,13 @@ export const AddCounterCmd = guildPluginMessageCommand()({ message.channel.send(`Which user's counter value would you like to add to?`); const reply = await waitForReply(pluginData.client, message.channel, message.author.id); if (!reply || !reply.content) { - sendErrorMessage(pluginData, message.channel, "Cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Cancelling"); return; } const potentialUser = await resolveUser(pluginData.client, reply.content); if (!potentialUser || potentialUser instanceof UnknownUser) { - sendErrorMessage(pluginData, message.channel, "Unknown user, cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Unknown user, cancelling"); return; } @@ -105,13 +105,13 @@ export const AddCounterCmd = guildPluginMessageCommand()({ message.channel.send("How much would you like to add to the counter's value?"); const reply = await waitForReply(pluginData.client, message.channel, message.author.id); if (!reply || !reply.content) { - sendErrorMessage(pluginData, message.channel, "Cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Cancelling"); return; } const potentialAmount = parseInt(reply.content, 10); if (!potentialAmount) { - sendErrorMessage(pluginData, message.channel, "Not a number, cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Not a number, cancelling"); return; } diff --git a/backend/src/plugins/Counters/commands/CountersListCmd.ts b/backend/src/plugins/Counters/commands/CountersListCmd.ts index 84a0a272..db83812e 100644 --- a/backend/src/plugins/Counters/commands/CountersListCmd.ts +++ b/backend/src/plugins/Counters/commands/CountersListCmd.ts @@ -1,7 +1,7 @@ import { guildPluginMessageCommand } from "knub"; -import { sendErrorMessage } from "../../../pluginUtils"; import { trimMultilineString, ucfirst } from "../../../utils"; import { getGuildPrefix } from "../../../utils/getGuildPrefix"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { CountersPluginType } from "../types"; export const CountersListCmd = guildPluginMessageCommand()({ @@ -15,7 +15,7 @@ export const CountersListCmd = guildPluginMessageCommand()({ const countersToShow = Array.from(Object.values(config.counters)).filter((c) => c.can_view !== false); if (!countersToShow.length) { - sendErrorMessage(pluginData, message.channel, "No counters are configured for this server"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "No counters are configured for this server"); return; } diff --git a/backend/src/plugins/Counters/commands/ResetAllCounterValuesCmd.ts b/backend/src/plugins/Counters/commands/ResetAllCounterValuesCmd.ts index 3a44ecaa..e413cf21 100644 --- a/backend/src/plugins/Counters/commands/ResetAllCounterValuesCmd.ts +++ b/backend/src/plugins/Counters/commands/ResetAllCounterValuesCmd.ts @@ -1,7 +1,7 @@ import { guildPluginMessageCommand } from "knub"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { confirm, noop, trimMultilineString } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { resetAllCounterValues } from "../functions/resetAllCounterValues"; import { CountersPluginType } from "../types"; @@ -18,17 +18,19 @@ export const ResetAllCounterValuesCmd = guildPluginMessageCommand()({ const counter = config.counters[args.counterName]; const counterId = pluginData.state.counterIds[args.counterName]; if (!counter || !counterId) { - sendErrorMessage(pluginData, message.channel, `Unknown counter: ${args.counterName}`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, `Unknown counter: ${args.counterName}`); return; } if (counter.can_edit === false) { - sendErrorMessage(pluginData, message.channel, `Missing permissions to reset this counter's value`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, `Missing permissions to reset this counter's value`); return; } if (args.channel && !counter.per_channel) { - sendErrorMessage(pluginData, message.channel, `This counter is not per-channel`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, `This counter is not per-channel`); return; } if (args.user && !counter.per_user) { - sendErrorMessage(pluginData, message.channel, `This counter is not per-user`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, `This counter is not per-user`); return; } @@ -64,13 +64,13 @@ export const ResetCounterCmd = guildPluginMessageCommand()({ message.channel.send(`Which channel's counter value would you like to reset?`); const reply = await waitForReply(pluginData.client, message.channel, message.author.id); if (!reply || !reply.content) { - sendErrorMessage(pluginData, message.channel, "Cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Cancelling"); return; } const potentialChannel = pluginData.guild.channels.resolve(reply.content as Snowflake); if (!potentialChannel || !(potentialChannel instanceof TextChannel)) { - sendErrorMessage(pluginData, message.channel, "Channel is not a text channel, cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Channel is not a text channel, cancelling"); return; } @@ -82,13 +82,13 @@ export const ResetCounterCmd = guildPluginMessageCommand()({ message.channel.send(`Which user's counter value would you like to reset?`); const reply = await waitForReply(pluginData.client, message.channel, message.author.id); if (!reply || !reply.content) { - sendErrorMessage(pluginData, message.channel, "Cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Cancelling"); return; } const potentialUser = await resolveUser(pluginData.client, reply.content); if (!potentialUser || potentialUser instanceof UnknownUser) { - sendErrorMessage(pluginData, message.channel, "Unknown user, cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Unknown user, cancelling"); return; } diff --git a/backend/src/plugins/Counters/commands/SetCounterCmd.ts b/backend/src/plugins/Counters/commands/SetCounterCmd.ts index ba6fbc3a..3cc62c54 100644 --- a/backend/src/plugins/Counters/commands/SetCounterCmd.ts +++ b/backend/src/plugins/Counters/commands/SetCounterCmd.ts @@ -2,8 +2,8 @@ import { Snowflake, TextChannel } from "discord.js"; import { guildPluginMessageCommand } from "knub"; import { waitForReply } from "knub/helpers"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage } from "../../../pluginUtils"; import { UnknownUser, resolveUser } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { setCounterValue } from "../functions/setCounterValue"; import { CountersPluginType } from "../types"; @@ -45,22 +45,22 @@ export const SetCounterCmd = guildPluginMessageCommand()({ const counter = config.counters[args.counterName]; const counterId = pluginData.state.counterIds[args.counterName]; if (!counter || !counterId) { - sendErrorMessage(pluginData, message.channel, `Unknown counter: ${args.counterName}`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, `Unknown counter: ${args.counterName}`); return; } if (counter.can_edit === false) { - sendErrorMessage(pluginData, message.channel, `Missing permissions to edit this counter's value`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, `Missing permissions to edit this counter's value`); return; } if (args.channel && !counter.per_channel) { - sendErrorMessage(pluginData, message.channel, `This counter is not per-channel`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, `This counter is not per-channel`); return; } if (args.user && !counter.per_user) { - sendErrorMessage(pluginData, message.channel, `This counter is not per-user`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, `This counter is not per-user`); return; } @@ -69,13 +69,13 @@ export const SetCounterCmd = guildPluginMessageCommand()({ message.channel.send(`Which channel's counter value would you like to change?`); const reply = await waitForReply(pluginData.client, message.channel, message.author.id); if (!reply || !reply.content) { - sendErrorMessage(pluginData, message.channel, "Cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Cancelling"); return; } const potentialChannel = pluginData.guild.channels.resolve(reply.content as Snowflake); if (!potentialChannel || !(potentialChannel instanceof TextChannel)) { - sendErrorMessage(pluginData, message.channel, "Channel is not a text channel, cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Channel is not a text channel, cancelling"); return; } @@ -87,13 +87,13 @@ export const SetCounterCmd = guildPluginMessageCommand()({ message.channel.send(`Which user's counter value would you like to change?`); const reply = await waitForReply(pluginData.client, message.channel, message.author.id); if (!reply || !reply.content) { - sendErrorMessage(pluginData, message.channel, "Cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Cancelling"); return; } const potentialUser = await resolveUser(pluginData.client, reply.content); if (!potentialUser || potentialUser instanceof UnknownUser) { - sendErrorMessage(pluginData, message.channel, "Unknown user, cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Unknown user, cancelling"); return; } @@ -105,13 +105,13 @@ export const SetCounterCmd = guildPluginMessageCommand()({ message.channel.send("What would you like to set the counter's value to?"); const reply = await waitForReply(pluginData.client, message.channel, message.author.id); if (!reply || !reply.content) { - sendErrorMessage(pluginData, message.channel, "Cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Cancelling"); return; } const potentialValue = parseInt(reply.content, 10); if (Number.isNaN(potentialValue)) { - sendErrorMessage(pluginData, message.channel, "Not a number, cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Not a number, cancelling"); return; } @@ -119,7 +119,7 @@ export const SetCounterCmd = guildPluginMessageCommand()({ } if (value < 0) { - sendErrorMessage(pluginData, message.channel, "Cannot set counter value below 0"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Cannot set counter value below 0"); return; } diff --git a/backend/src/plugins/Counters/commands/ViewCounterCmd.ts b/backend/src/plugins/Counters/commands/ViewCounterCmd.ts index d2715c0c..1c037e69 100644 --- a/backend/src/plugins/Counters/commands/ViewCounterCmd.ts +++ b/backend/src/plugins/Counters/commands/ViewCounterCmd.ts @@ -2,8 +2,8 @@ import { Snowflake } from "discord.js"; import { guildPluginMessageCommand } from "knub"; import { waitForReply } from "knub/helpers"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage } from "../../../pluginUtils"; import { resolveUser, UnknownUser } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { CountersPluginType } from "../types"; export const ViewCounterCmd = guildPluginMessageCommand()({ @@ -39,22 +39,22 @@ export const ViewCounterCmd = guildPluginMessageCommand()({ const counter = config.counters[args.counterName]; const counterId = pluginData.state.counterIds[args.counterName]; if (!counter || !counterId) { - sendErrorMessage(pluginData, message.channel, `Unknown counter: ${args.counterName}`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, `Unknown counter: ${args.counterName}`); return; } if (counter.can_view === false) { - sendErrorMessage(pluginData, message.channel, `Missing permissions to view this counter's value`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, `Missing permissions to view this counter's value`); return; } if (args.channel && !counter.per_channel) { - sendErrorMessage(pluginData, message.channel, `This counter is not per-channel`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, `This counter is not per-channel`); return; } if (args.user && !counter.per_user) { - sendErrorMessage(pluginData, message.channel, `This counter is not per-user`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, `This counter is not per-user`); return; } @@ -63,13 +63,13 @@ export const ViewCounterCmd = guildPluginMessageCommand()({ message.channel.send(`Which channel's counter value would you like to view?`); const reply = await waitForReply(pluginData.client, message.channel, message.author.id); if (!reply || !reply.content) { - sendErrorMessage(pluginData, message.channel, "Cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Cancelling"); return; } const potentialChannel = pluginData.guild.channels.resolve(reply.content as Snowflake); if (!potentialChannel?.isTextBased()) { - sendErrorMessage(pluginData, message.channel, "Channel is not a text channel, cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Channel is not a text channel, cancelling"); return; } @@ -81,13 +81,13 @@ export const ViewCounterCmd = guildPluginMessageCommand()({ message.channel.send(`Which user's counter value would you like to view?`); const reply = await waitForReply(pluginData.client, message.channel, message.author.id); if (!reply || !reply.content) { - sendErrorMessage(pluginData, message.channel, "Cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Cancelling"); return; } const potentialUser = await resolveUser(pluginData.client, reply.content); if (!potentialUser || potentialUser instanceof UnknownUser) { - sendErrorMessage(pluginData, message.channel, "Unknown user, cancelling"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Unknown user, cancelling"); return; } diff --git a/backend/src/plugins/CustomEvents/functions/runEvent.ts b/backend/src/plugins/CustomEvents/functions/runEvent.ts index 8e38b9ab..5ea3ceca 100644 --- a/backend/src/plugins/CustomEvents/functions/runEvent.ts +++ b/backend/src/plugins/CustomEvents/functions/runEvent.ts @@ -1,7 +1,7 @@ import { Message } from "discord.js"; import { GuildPluginData } from "knub"; -import { sendErrorMessage } from "../../../pluginUtils"; import { TemplateSafeValueContainer } from "../../../templateFormatter"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { ActionError } from "../ActionError"; import { addRoleAction } from "../actions/addRoleAction"; import { createCaseAction } from "../actions/createCaseAction"; @@ -39,7 +39,7 @@ export async function runEvent( } catch (e) { if (e instanceof ActionError) { if (event.trigger.type === "command") { - sendErrorMessage(pluginData, (eventData.msg as Message).channel, e.message); + pluginData.getPlugin(CommonPlugin).sendErrorMessage((eventData.msg as Message).channel, e.message); } else { // TODO: Where to log action errors from other kinds of triggers? } diff --git a/backend/src/plugins/LocateUser/commands/FollowCmd.ts b/backend/src/plugins/LocateUser/commands/FollowCmd.ts index 1011f771..a214241b 100644 --- a/backend/src/plugins/LocateUser/commands/FollowCmd.ts +++ b/backend/src/plugins/LocateUser/commands/FollowCmd.ts @@ -2,8 +2,8 @@ import humanizeDuration from "humanize-duration"; import moment from "moment-timezone"; import { commandTypeHelpers as ct } from "../../../commandTypes"; import { registerExpiringVCAlert } from "../../../data/loops/expiringVCAlertsLoop"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { MINUTES, SECONDS } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { locateUserCmd } from "../types"; export const FollowCmd = locateUserCmd({ @@ -27,7 +27,9 @@ export const FollowCmd = locateUserCmd({ const active = args.active || false; if (time < 30 * SECONDS) { - sendErrorMessage(pluginData, msg.channel, "Sorry, but the minimum duration for an alert is 30 seconds!"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, "Sorry, but the minimum duration for an alert is 30 seconds!"); return; } @@ -46,19 +48,23 @@ export const FollowCmd = locateUserCmd({ } if (active) { - sendSuccessMessage( - pluginData, - msg.channel, - `Every time <@${args.member.id}> joins or switches VC in the next ${humanizeDuration( - time, - )} i will notify and move you.\nPlease make sure to be in a voice channel, otherwise i cannot move you!`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage( + msg, + `Every time <@${args.member.id}> joins or switches VC in the next ${humanizeDuration( + time, + )} i will notify and move you.\nPlease make sure to be in a voice channel, otherwise i cannot move you!`, + ); } else { - sendSuccessMessage( - pluginData, - msg.channel, - `Every time <@${args.member.id}> joins or switches VC in the next ${humanizeDuration(time)} i will notify you`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage( + msg, + `Every time <@${args.member.id}> joins or switches VC in the next ${humanizeDuration( + time, + )} i will notify you`, + ); } }, }); diff --git a/backend/src/plugins/LocateUser/commands/ListFollowCmd.ts b/backend/src/plugins/LocateUser/commands/ListFollowCmd.ts index d598d8a9..271b401d 100644 --- a/backend/src/plugins/LocateUser/commands/ListFollowCmd.ts +++ b/backend/src/plugins/LocateUser/commands/ListFollowCmd.ts @@ -1,7 +1,7 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; import { clearExpiringVCAlert } from "../../../data/loops/expiringVCAlertsLoop"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { createChunkedMessage, sorter } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { locateUserCmd } from "../types"; export const ListFollowCmd = locateUserCmd({ @@ -13,7 +13,7 @@ export const ListFollowCmd = locateUserCmd({ async run({ message: msg, pluginData }) { const alerts = await pluginData.state.alerts.getAlertsByRequestorId(msg.member.id); if (alerts.length === 0) { - sendErrorMessage(pluginData, msg.channel, "You have no active alerts!"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "You have no active alerts!"); return; } @@ -46,7 +46,7 @@ export const DeleteFollowCmd = locateUserCmd({ alerts.sort(sorter("expires_at")); if (args.num > alerts.length || args.num <= 0) { - sendErrorMessage(pluginData, msg.channel, "Unknown alert!"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Unknown alert!"); return; } @@ -54,6 +54,6 @@ export const DeleteFollowCmd = locateUserCmd({ clearExpiringVCAlert(toDelete); await pluginData.state.alerts.delete(toDelete.id); - sendSuccessMessage(pluginData, msg.channel, "Alert deleted"); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, "Alert deleted"); }, }); diff --git a/backend/src/plugins/LocateUser/utils/moveMember.ts b/backend/src/plugins/LocateUser/utils/moveMember.ts index 8d044d59..f6dbd96b 100644 --- a/backend/src/plugins/LocateUser/utils/moveMember.ts +++ b/backend/src/plugins/LocateUser/utils/moveMember.ts @@ -1,6 +1,6 @@ import { GuildMember, GuildTextBasedChannel, Snowflake } from "discord.js"; import { GuildPluginData } from "knub"; -import { sendErrorMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { LocateUserPluginType } from "../types"; export async function moveMember( @@ -16,10 +16,14 @@ export async function moveMember( channel: target.voice.channelId, }); } catch { - sendErrorMessage(pluginData, errorChannel, "Failed to move you. Are you in a voice channel?"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(errorChannel, "Failed to move you. Are you in a voice channel?"); return; } } else { - sendErrorMessage(pluginData, errorChannel, "Failed to move you. Are you in a voice channel?"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(errorChannel, "Failed to move you. Are you in a voice channel?"); } } diff --git a/backend/src/plugins/LocateUser/utils/sendWhere.ts b/backend/src/plugins/LocateUser/utils/sendWhere.ts index 7faaad80..8d40e99c 100644 --- a/backend/src/plugins/LocateUser/utils/sendWhere.ts +++ b/backend/src/plugins/LocateUser/utils/sendWhere.ts @@ -1,7 +1,7 @@ import { GuildMember, GuildTextBasedChannel, Invite, VoiceChannel } from "discord.js"; import { GuildPluginData } from "knub"; import { getInviteLink } from "knub/helpers"; -import { sendErrorMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { LocateUserPluginType } from "../types"; import { createOrReuseInvite } from "./createOrReuseInvite"; @@ -22,7 +22,7 @@ export async function sendWhere( try { invite = await createOrReuseInvite(voice); } catch { - sendErrorMessage(pluginData, channel, "Cannot create an invite to that channel!"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(channel, "Cannot create an invite to that channel!"); return; } channel.send({ diff --git a/backend/src/plugins/MessageSaver/commands/SaveMessagesToDB.ts b/backend/src/plugins/MessageSaver/commands/SaveMessagesToDB.ts index 3d2456e8..6b9211f1 100644 --- a/backend/src/plugins/MessageSaver/commands/SaveMessagesToDB.ts +++ b/backend/src/plugins/MessageSaver/commands/SaveMessagesToDB.ts @@ -1,5 +1,5 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendSuccessMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { saveMessagesToDB } from "../saveMessagesToDB"; import { messageSaverCmd } from "../types"; @@ -18,13 +18,14 @@ export const SaveMessagesToDBCmd = messageSaverCmd({ const { savedCount, failed } = await saveMessagesToDB(pluginData, args.channel, args.ids.trim().split(" ")); if (failed.length) { - sendSuccessMessage( - pluginData, - msg.channel, - `Saved ${savedCount} messages. The following messages could not be saved: ${failed.join(", ")}`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage( + msg, + `Saved ${savedCount} messages. The following messages could not be saved: ${failed.join(", ")}`, + ); } else { - sendSuccessMessage(pluginData, msg.channel, `Saved ${savedCount} messages!`); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, `Saved ${savedCount} messages!`); } }, }); diff --git a/backend/src/plugins/MessageSaver/commands/SavePinsToDB.ts b/backend/src/plugins/MessageSaver/commands/SavePinsToDB.ts index e81c73fe..92c5393d 100644 --- a/backend/src/plugins/MessageSaver/commands/SavePinsToDB.ts +++ b/backend/src/plugins/MessageSaver/commands/SavePinsToDB.ts @@ -1,5 +1,5 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendSuccessMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { saveMessagesToDB } from "../saveMessagesToDB"; import { messageSaverCmd } from "../types"; @@ -19,13 +19,14 @@ export const SavePinsToDBCmd = messageSaverCmd({ const { savedCount, failed } = await saveMessagesToDB(pluginData, args.channel, [...pins.keys()]); if (failed.length) { - sendSuccessMessage( - pluginData, - msg.channel, - `Saved ${savedCount} messages. The following messages could not be saved: ${failed.join(", ")}`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage( + msg, + `Saved ${savedCount} messages. The following messages could not be saved: ${failed.join(", ")}`, + ); } else { - sendSuccessMessage(pluginData, msg.channel, `Saved ${savedCount} messages!`); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, `Saved ${savedCount} messages!`); } }, }); diff --git a/backend/src/plugins/ModActions/ModActionsPlugin.ts b/backend/src/plugins/ModActions/ModActionsPlugin.ts index d9b08381..12eb729e 100644 --- a/backend/src/plugins/ModActions/ModActionsPlugin.ts +++ b/backend/src/plugins/ModActions/ModActionsPlugin.ts @@ -72,6 +72,7 @@ import { onModActionsEvent } from "./functions/onModActionsEvent"; import { updateCase } from "./functions/updateCase"; import { warnMember } from "./functions/warnMember"; import { + AttachmentLinkReactionType, BanOptions, ConfigSchema, KickOptions, @@ -100,6 +101,8 @@ const defaultOptions = { warn_notify_message: "The user already has **{priorWarnings}** warnings!\n Please check their prior cases and assess whether or not to warn anyways.\n Proceed with the warning?", ban_delete_message_days: 1, + attachment_link_reaction: "warn" as AttachmentLinkReactionType, + attachment_storing_channel: null, can_note: false, can_warn: false, @@ -217,26 +220,32 @@ export const ModActionsPlugin = zeppelinGuildPlugin()({ public: { warnMember(pluginData) { - return (member: GuildMember, reason: string, warnOptions?: WarnOptions) => { - return warnMember(pluginData, member, reason, warnOptions); + return (member: GuildMember, reason: string, reasonWithAttachments: string, warnOptions?: WarnOptions) => { + return warnMember(pluginData, member, reason, reasonWithAttachments, warnOptions); }; }, kickMember(pluginData) { - return (member: GuildMember, reason: string, kickOptions?: KickOptions) => { - kickMember(pluginData, member, reason, kickOptions); + return (member: GuildMember, reason: string, reasonWithAttachments: string, kickOptions?: KickOptions) => { + kickMember(pluginData, member, reason, reasonWithAttachments, kickOptions); }; }, banUserId(pluginData) { - return (userId: string, reason?: string, banOptions?: BanOptions, banTime?: number) => { - return banUserId(pluginData, userId, reason, banOptions, banTime); + return ( + userId: string, + reason?: string, + reasonWithAttachments?: string, + banOptions?: BanOptions, + banTime?: number, + ) => { + return banUserId(pluginData, userId, reason, reasonWithAttachments, banOptions, banTime); }; }, updateCase(pluginData) { return (msg: Message, caseNumber: number | null, note: string) => { - updateCase(pluginData, msg.channel, msg.author, caseNumber ?? undefined, note, [...msg.attachments.values()]); + updateCase(pluginData, msg, msg.author, caseNumber ?? undefined, note, [...msg.attachments.values()]); }; }, diff --git a/backend/src/plugins/ModActions/commands/addcase/AddCaseMsgCmd.ts b/backend/src/plugins/ModActions/commands/addcase/AddCaseMsgCmd.ts index 41c2a380..beb4cc3d 100644 --- a/backend/src/plugins/ModActions/commands/addcase/AddCaseMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/addcase/AddCaseMsgCmd.ts @@ -1,7 +1,8 @@ import { commandTypeHelpers as ct } from "../../../../commandTypes"; import { CaseTypes } from "../../../../data/CaseTypes"; -import { hasPermission, sendErrorMessage } from "../../../../pluginUtils"; +import { hasPermission } from "../../../../pluginUtils"; import { resolveUser } from "../../../../utils"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualAddCaseCmd } from "../../functions/actualCommands/actualAddCaseCmd"; import { modActionsMsgCmd } from "../../types"; @@ -27,7 +28,7 @@ export const AddCaseMsgCmd = modActionsMsgCmd({ async run({ pluginData, message: msg, args }) { const user = await resolveUser(pluginData.client, args.user); if (!user.id) { - sendErrorMessage(pluginData, msg.channel, `User not found`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `User not found`); return; } @@ -35,7 +36,7 @@ export const AddCaseMsgCmd = modActionsMsgCmd({ let mod = msg.member; if (args.mod) { if (!(await hasPermission(pluginData, "can_act_as_other", { message: msg }))) { - sendErrorMessage(pluginData, msg.channel, "You don't have permission to use -mod"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "You don't have permission to use -mod"); return; } @@ -45,13 +46,13 @@ export const AddCaseMsgCmd = modActionsMsgCmd({ // Verify the case type is valid const type: string = args.type[0].toUpperCase() + args.type.slice(1).toLowerCase(); if (!CaseTypes[type]) { - sendErrorMessage(pluginData, msg.channel, "Cannot add case: invalid case type"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Cannot add case: invalid case type"); return; } actualAddCaseCmd( pluginData, - msg.channel, + msg, msg.member, mod, [...msg.attachments.values()], diff --git a/backend/src/plugins/ModActions/commands/addcase/AddCaseSlashCmd.ts b/backend/src/plugins/ModActions/commands/addcase/AddCaseSlashCmd.ts index b5fbfc5f..c83a6b42 100644 --- a/backend/src/plugins/ModActions/commands/addcase/AddCaseSlashCmd.ts +++ b/backend/src/plugins/ModActions/commands/addcase/AddCaseSlashCmd.ts @@ -1,7 +1,8 @@ import { slashOptions } from "knub"; import { CaseTypes } from "../../../../data/CaseTypes"; -import { hasPermission, sendErrorMessage } from "../../../../pluginUtils"; +import { hasPermission } from "../../../../pluginUtils"; import { generateAttachmentSlashOptions, retrieveMultipleOptions } from "../../../../utils/multipleSlashOptions"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualAddCaseCmd } from "../../functions/actualCommands/actualAddCaseCmd"; import { NUMBER_ATTACHMENTS_CASE_CREATION } from "../constants"; @@ -44,7 +45,9 @@ export const AddCaseSlashCmd = { if (options.mod) { if (!canActAsOther) { - sendErrorMessage(pluginData, interaction, "You don't have permission to act as another moderator"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "You don't have permission to act as another moderator"); return; } diff --git a/backend/src/plugins/ModActions/commands/ban/BanMsgCmd.ts b/backend/src/plugins/ModActions/commands/ban/BanMsgCmd.ts index efea59d7..10b4344c 100644 --- a/backend/src/plugins/ModActions/commands/ban/BanMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/ban/BanMsgCmd.ts @@ -1,6 +1,7 @@ import { commandTypeHelpers as ct } from "../../../../commandTypes"; -import { hasPermission, sendErrorMessage } from "../../../../pluginUtils"; +import { hasPermission } from "../../../../pluginUtils"; import { UserNotificationMethod, resolveUser } from "../../../../utils"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualBanCmd } from "../../functions/actualCommands/actualBanCmd"; import { readContactMethodsFromArgs } from "../../functions/readContactMethodsFromArgs"; import { modActionsMsgCmd } from "../../types"; @@ -37,7 +38,7 @@ export const BanMsgCmd = modActionsMsgCmd({ const user = await resolveUser(pluginData.client, args.user); if (!user.id) { - sendErrorMessage(pluginData, msg.channel, `User not found`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `User not found`); return; } @@ -45,7 +46,7 @@ export const BanMsgCmd = modActionsMsgCmd({ let mod = msg.member; if (args.mod) { if (!(await hasPermission(pluginData, "can_act_as_other", { message: msg }))) { - sendErrorMessage(pluginData, msg.channel, "You don't have permission to use -mod"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "You don't have permission to use -mod"); return; } @@ -56,13 +57,13 @@ export const BanMsgCmd = modActionsMsgCmd({ try { contactMethods = readContactMethodsFromArgs(args) ?? undefined; } catch (e) { - sendErrorMessage(pluginData, msg.channel, e.message); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, e.message); return; } actualBanCmd( pluginData, - msg.channel, + msg, user, args["time"] ? args["time"] : null, args.reason || "", diff --git a/backend/src/plugins/ModActions/commands/ban/BanSlashCmd.ts b/backend/src/plugins/ModActions/commands/ban/BanSlashCmd.ts index acd19a43..dd86a546 100644 --- a/backend/src/plugins/ModActions/commands/ban/BanSlashCmd.ts +++ b/backend/src/plugins/ModActions/commands/ban/BanSlashCmd.ts @@ -1,8 +1,9 @@ import { ChannelType } from "discord.js"; import { slashOptions } from "knub"; -import { hasPermission, sendErrorMessage } from "../../../../pluginUtils"; +import { hasPermission } from "../../../../pluginUtils"; import { UserNotificationMethod, convertDelayStringToMS } from "../../../../utils"; import { generateAttachmentSlashOptions, retrieveMultipleOptions } from "../../../../utils/multipleSlashOptions"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualBanCmd } from "../../functions/actualCommands/actualBanCmd"; import { readContactMethodsFromArgs } from "../../functions/readContactMethodsFromArgs"; import { NUMBER_ATTACHMENTS_CASE_CREATION } from "../constants"; @@ -49,7 +50,9 @@ export const BanSlashCmd = { const attachments = retrieveMultipleOptions(NUMBER_ATTACHMENTS_CASE_CREATION, options, "attachment"); if ((!options.reason || options.reason.trim() === "") && attachments.length < 1) { - sendErrorMessage(pluginData, interaction, "Text or attachment required", undefined, undefined, true); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "Text or attachment required", undefined, undefined, true); return; } @@ -62,7 +65,9 @@ export const BanSlashCmd = { if (options.mod) { if (!canActAsOther) { - sendErrorMessage(pluginData, interaction, "You don't have permission to act as another moderator"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "You don't have permission to act as another moderator"); return; } @@ -73,13 +78,13 @@ export const BanSlashCmd = { try { contactMethods = readContactMethodsFromArgs(options) ?? undefined; } catch (e) { - sendErrorMessage(pluginData, interaction, e.message); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(interaction, e.message); return; } const convertedTime = options.time ? convertDelayStringToMS(options.time) : null; if (options.time && !convertedTime) { - sendErrorMessage(pluginData, interaction, `Could not convert ${options.time} to a delay`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(interaction, `Could not convert ${options.time} to a delay`); return; } diff --git a/backend/src/plugins/ModActions/commands/case/CaseMsgCmd.ts b/backend/src/plugins/ModActions/commands/case/CaseMsgCmd.ts index 6521e327..914cec0f 100644 --- a/backend/src/plugins/ModActions/commands/case/CaseMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/case/CaseMsgCmd.ts @@ -14,6 +14,6 @@ export const CaseMsgCmd = modActionsMsgCmd({ ], async run({ pluginData, message: msg, args }) { - actualCaseCmd(pluginData, msg.channel, msg.author.id, args.caseNumber); + actualCaseCmd(pluginData, msg, msg.author.id, args.caseNumber); }, }); diff --git a/backend/src/plugins/ModActions/commands/cases/CasesModMsgCmd.ts b/backend/src/plugins/ModActions/commands/cases/CasesModMsgCmd.ts index b9e496b7..717ea531 100644 --- a/backend/src/plugins/ModActions/commands/cases/CasesModMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/cases/CasesModMsgCmd.ts @@ -29,7 +29,7 @@ export const CasesModMsgCmd = modActionsMsgCmd({ async run({ pluginData, message: msg, args }) { return actualCasesCmd( pluginData, - msg.channel, + msg, args.mod, null, msg.author, diff --git a/backend/src/plugins/ModActions/commands/cases/CasesUserMsgCmd.ts b/backend/src/plugins/ModActions/commands/cases/CasesUserMsgCmd.ts index 765524df..dd50a5de 100644 --- a/backend/src/plugins/ModActions/commands/cases/CasesUserMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/cases/CasesUserMsgCmd.ts @@ -1,6 +1,6 @@ import { commandTypeHelpers as ct } from "../../../../commandTypes"; -import { sendErrorMessage } from "../../../../pluginUtils"; import { resolveUser } from "../../../../utils"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualCasesCmd } from "../../functions/actualCommands/actualCasesCmd"; import { modActionsMsgCmd } from "../../types"; @@ -33,13 +33,13 @@ export const CasesUserMsgCmd = modActionsMsgCmd({ async run({ pluginData, message: msg, args }) { const user = await resolveUser(pluginData.client, args.user); if (!user.id) { - sendErrorMessage(pluginData, msg.channel, `User not found`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `User not found`); return; } return actualCasesCmd( pluginData, - msg.channel, + msg, args.mod, user, msg.author, diff --git a/backend/src/plugins/ModActions/commands/deletecase/DeleteCaseMsgCmd.ts b/backend/src/plugins/ModActions/commands/deletecase/DeleteCaseMsgCmd.ts index 70dbc92f..b4c96a68 100644 --- a/backend/src/plugins/ModActions/commands/deletecase/DeleteCaseMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/deletecase/DeleteCaseMsgCmd.ts @@ -18,6 +18,6 @@ export const DeleteCaseMsgCmd = modActionsMsgCmd({ }, async run({ pluginData, message, args }) { - actualDeleteCaseCmd(pluginData, message.channel, message.member, args.caseNumber, args.force); + actualDeleteCaseCmd(pluginData, message, message.member, args.caseNumber, args.force); }, }); diff --git a/backend/src/plugins/ModActions/commands/forceban/ForceBanMsgCmd.ts b/backend/src/plugins/ModActions/commands/forceban/ForceBanMsgCmd.ts index ee0e4fa7..e15f3c13 100644 --- a/backend/src/plugins/ModActions/commands/forceban/ForceBanMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/forceban/ForceBanMsgCmd.ts @@ -1,6 +1,7 @@ import { commandTypeHelpers as ct } from "../../../../commandTypes"; -import { canActOn, hasPermission, sendErrorMessage } from "../../../../pluginUtils"; +import { canActOn, hasPermission } from "../../../../pluginUtils"; import { resolveMember, resolveUser } from "../../../../utils"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualForceBanCmd } from "../../functions/actualCommands/actualForceBanCmd"; import { isBanned } from "../../functions/isBanned"; import { modActionsMsgCmd } from "../../types"; @@ -26,21 +27,21 @@ export const ForceBanMsgCmd = modActionsMsgCmd({ async run({ pluginData, message: msg, args }) { const user = await resolveUser(pluginData.client, args.user); if (!user.id) { - sendErrorMessage(pluginData, msg.channel, `User not found`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `User not found`); return; } // If the user exists as a guild member, make sure we can act on them first const member = await resolveMember(pluginData.client, pluginData.guild, user.id); if (member && !canActOn(pluginData, msg.member, member)) { - sendErrorMessage(pluginData, msg.channel, "Cannot forceban this user: insufficient permissions"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Cannot forceban this user: insufficient permissions"); return; } // Make sure the user isn't already banned const banned = await isBanned(pluginData, user.id); if (banned) { - sendErrorMessage(pluginData, msg.channel, `User is already banned`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `User is already banned`); return; } @@ -48,13 +49,13 @@ export const ForceBanMsgCmd = modActionsMsgCmd({ let mod = msg.member; if (args.mod) { if (!(await hasPermission(pluginData, "can_act_as_other", { message: msg }))) { - sendErrorMessage(pluginData, msg.channel, "You don't have permission to use -mod"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "You don't have permission to use -mod"); return; } mod = args.mod; } - actualForceBanCmd(pluginData, msg.channel, msg.author.id, user, args.reason, [...msg.attachments.values()], mod); + actualForceBanCmd(pluginData, msg, msg.author.id, user, args.reason, [...msg.attachments.values()], mod); }, }); diff --git a/backend/src/plugins/ModActions/commands/forceban/ForceBanSlashCmd.ts b/backend/src/plugins/ModActions/commands/forceban/ForceBanSlashCmd.ts index c1722fcc..c246982e 100644 --- a/backend/src/plugins/ModActions/commands/forceban/ForceBanSlashCmd.ts +++ b/backend/src/plugins/ModActions/commands/forceban/ForceBanSlashCmd.ts @@ -1,7 +1,8 @@ import { slashOptions } from "knub"; -import { hasPermission, sendErrorMessage } from "../../../../pluginUtils"; +import { hasPermission } from "../../../../pluginUtils"; import { convertDelayStringToMS } from "../../../../utils"; import { generateAttachmentSlashOptions, retrieveMultipleOptions } from "../../../../utils/multipleSlashOptions"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualForceBanCmd } from "../../functions/actualCommands/actualForceBanCmd"; import { NUMBER_ATTACHMENTS_CASE_CREATION } from "../constants"; @@ -26,7 +27,9 @@ export const ForceBanSlashCmd = { const attachments = retrieveMultipleOptions(NUMBER_ATTACHMENTS_CASE_CREATION, options, "attachment"); if ((!options.reason || options.reason.trim() === "") && attachments.length < 1) { - sendErrorMessage(pluginData, interaction, "Text or attachment required", undefined, undefined, true); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "Text or attachment required", undefined, undefined, true); return; } @@ -39,7 +42,9 @@ export const ForceBanSlashCmd = { if (options.mod) { if (!canActAsOther) { - sendErrorMessage(pluginData, interaction, "You don't have permission to act as another moderator"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "You don't have permission to act as another moderator"); return; } @@ -48,7 +53,7 @@ export const ForceBanSlashCmd = { const convertedTime = options.time ? convertDelayStringToMS(options.time) : null; if (options.time && !convertedTime) { - sendErrorMessage(pluginData, interaction, `Could not convert ${options.time} to a delay`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(interaction, `Could not convert ${options.time} to a delay`); return; } diff --git a/backend/src/plugins/ModActions/commands/forcemute/ForceMuteMsgCmd.ts b/backend/src/plugins/ModActions/commands/forcemute/ForceMuteMsgCmd.ts index 9ecbae61..9c2a9cbb 100644 --- a/backend/src/plugins/ModActions/commands/forcemute/ForceMuteMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/forcemute/ForceMuteMsgCmd.ts @@ -1,6 +1,7 @@ import { commandTypeHelpers as ct } from "../../../../commandTypes"; -import { canActOn, hasPermission, sendErrorMessage } from "../../../../pluginUtils"; +import { canActOn, hasPermission } from "../../../../pluginUtils"; import { resolveMember, resolveUser } from "../../../../utils"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualMuteCmd } from "../../functions/actualCommands/actualMuteCmd"; import { readContactMethodsFromArgs } from "../../functions/readContactMethodsFromArgs"; import { modActionsMsgCmd } from "../../types"; @@ -35,7 +36,7 @@ export const ForceMuteMsgCmd = modActionsMsgCmd({ async run({ pluginData, message: msg, args }) { const user = await resolveUser(pluginData.client, args.user); if (!user.id) { - sendErrorMessage(pluginData, msg.channel, `User not found`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `User not found`); return; } @@ -43,7 +44,7 @@ export const ForceMuteMsgCmd = modActionsMsgCmd({ // Make sure we're allowed to mute this user if (memberToMute && !canActOn(pluginData, msg.member, memberToMute)) { - sendErrorMessage(pluginData, msg.channel, "Cannot mute: insufficient permissions"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Cannot mute: insufficient permissions"); return; } @@ -53,7 +54,7 @@ export const ForceMuteMsgCmd = modActionsMsgCmd({ if (args.mod) { if (!(await hasPermission(pluginData, "can_act_as_other", { message: msg }))) { - sendErrorMessage(pluginData, msg.channel, "You don't have permission to use -mod"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "You don't have permission to use -mod"); return; } @@ -65,13 +66,13 @@ export const ForceMuteMsgCmd = modActionsMsgCmd({ try { contactMethods = readContactMethodsFromArgs(args); } catch (e) { - sendErrorMessage(pluginData, msg.channel, e.message); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, e.message); return; } actualMuteCmd( pluginData, - msg.channel, + msg, user, [...msg.attachments.values()], mod, diff --git a/backend/src/plugins/ModActions/commands/forcemute/ForceMuteSlashCmd.ts b/backend/src/plugins/ModActions/commands/forcemute/ForceMuteSlashCmd.ts index b32cde4f..6d6c2fb9 100644 --- a/backend/src/plugins/ModActions/commands/forcemute/ForceMuteSlashCmd.ts +++ b/backend/src/plugins/ModActions/commands/forcemute/ForceMuteSlashCmd.ts @@ -1,8 +1,9 @@ import { ChannelType } from "discord.js"; import { slashOptions } from "knub"; -import { hasPermission, sendErrorMessage } from "../../../../pluginUtils"; +import { hasPermission } from "../../../../pluginUtils"; import { UserNotificationMethod, convertDelayStringToMS } from "../../../../utils"; import { generateAttachmentSlashOptions, retrieveMultipleOptions } from "../../../../utils/multipleSlashOptions"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualMuteCmd } from "../../functions/actualCommands/actualMuteCmd"; import { readContactMethodsFromArgs } from "../../functions/readContactMethodsFromArgs"; import { NUMBER_ATTACHMENTS_CASE_CREATION } from "../constants"; @@ -44,7 +45,9 @@ export const ForceMuteSlashCmd = { const attachments = retrieveMultipleOptions(NUMBER_ATTACHMENTS_CASE_CREATION, options, "attachment"); if ((!options.reason || options.reason.trim() === "") && attachments.length < 1) { - sendErrorMessage(pluginData, interaction, "Text or attachment required", undefined, undefined, true); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "Text or attachment required", undefined, undefined, true); return; } @@ -58,7 +61,9 @@ export const ForceMuteSlashCmd = { if (options.mod) { if (!canActAsOther) { - sendErrorMessage(pluginData, interaction, "You don't have permission to act as another moderator"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "You don't have permission to act as another moderator"); return; } @@ -68,7 +73,7 @@ export const ForceMuteSlashCmd = { const convertedTime = options.time ? convertDelayStringToMS(options.time) : null; if (options.time && !convertedTime) { - sendErrorMessage(pluginData, interaction, `Could not convert ${options.time} to a delay`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(interaction, `Could not convert ${options.time} to a delay`); return; } @@ -76,7 +81,7 @@ export const ForceMuteSlashCmd = { try { contactMethods = readContactMethodsFromArgs(options) ?? undefined; } catch (e) { - sendErrorMessage(pluginData, interaction, e.message); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(interaction, e.message); return; } diff --git a/backend/src/plugins/ModActions/commands/forceunmute/ForceUnmuteMsgCmd.ts b/backend/src/plugins/ModActions/commands/forceunmute/ForceUnmuteMsgCmd.ts index c1b97351..f9351d8f 100644 --- a/backend/src/plugins/ModActions/commands/forceunmute/ForceUnmuteMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/forceunmute/ForceUnmuteMsgCmd.ts @@ -1,6 +1,7 @@ import { commandTypeHelpers as ct } from "../../../../commandTypes"; -import { canActOn, hasPermission, sendErrorMessage } from "../../../../pluginUtils"; +import { canActOn, hasPermission } from "../../../../pluginUtils"; import { resolveMember, resolveUser } from "../../../../utils"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualUnmuteCmd } from "../../functions/actualCommands/actualUnmuteCmd"; import { modActionsMsgCmd } from "../../types"; @@ -32,13 +33,13 @@ export const ForceUnmuteMsgCmd = modActionsMsgCmd({ async run({ pluginData, message: msg, args }) { const user = await resolveUser(pluginData.client, args.user); if (!user.id) { - sendErrorMessage(pluginData, msg.channel, `User not found`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `User not found`); return; } // Check if they're muted in the first place if (!(await pluginData.state.mutes.isMuted(user.id))) { - sendErrorMessage(pluginData, msg.channel, "Cannot unmute: member is not muted"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Cannot unmute: member is not muted"); return; } @@ -47,7 +48,7 @@ export const ForceUnmuteMsgCmd = modActionsMsgCmd({ // Make sure we're allowed to unmute this member if (memberToUnmute && !canActOn(pluginData, msg.member, memberToUnmute)) { - sendErrorMessage(pluginData, msg.channel, "Cannot unmute: insufficient permissions"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Cannot unmute: insufficient permissions"); return; } @@ -57,7 +58,7 @@ export const ForceUnmuteMsgCmd = modActionsMsgCmd({ if (args.mod) { if (!(await hasPermission(pluginData, "can_act_as_other", { message: msg }))) { - sendErrorMessage(pluginData, msg.channel, "You don't have permission to use -mod"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "You don't have permission to use -mod"); return; } @@ -67,7 +68,7 @@ export const ForceUnmuteMsgCmd = modActionsMsgCmd({ actualUnmuteCmd( pluginData, - msg.channel, + msg, user, [...msg.attachments.values()], mod, diff --git a/backend/src/plugins/ModActions/commands/forceunmute/ForceUnmuteSlashCmd.ts b/backend/src/plugins/ModActions/commands/forceunmute/ForceUnmuteSlashCmd.ts index 107151a8..3c68a64e 100644 --- a/backend/src/plugins/ModActions/commands/forceunmute/ForceUnmuteSlashCmd.ts +++ b/backend/src/plugins/ModActions/commands/forceunmute/ForceUnmuteSlashCmd.ts @@ -1,7 +1,8 @@ import { slashOptions } from "knub"; -import { hasPermission, sendErrorMessage } from "../../../../pluginUtils"; +import { hasPermission } from "../../../../pluginUtils"; import { convertDelayStringToMS } from "../../../../utils"; import { generateAttachmentSlashOptions, retrieveMultipleOptions } from "../../../../utils/multipleSlashOptions"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualUnmuteCmd } from "../../functions/actualCommands/actualUnmuteCmd"; import { NUMBER_ATTACHMENTS_CASE_CREATION } from "../constants"; @@ -27,7 +28,9 @@ export const ForceUnmuteSlashCmd = { const attachments = retrieveMultipleOptions(NUMBER_ATTACHMENTS_CASE_CREATION, options, "attachment"); if ((!options.reason || options.reason.trim() === "") && attachments.length < 1) { - sendErrorMessage(pluginData, interaction, "Text or attachment required", undefined, undefined, true); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "Text or attachment required", undefined, undefined, true); return; } @@ -41,7 +44,9 @@ export const ForceUnmuteSlashCmd = { if (options.mod) { if (!canActAsOther) { - sendErrorMessage(pluginData, interaction, "You don't have permission to act as another moderator"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "You don't have permission to act as another moderator"); return; } @@ -51,7 +56,7 @@ export const ForceUnmuteSlashCmd = { const convertedTime = options.time ? convertDelayStringToMS(options.time) : null; if (options.time && !convertedTime) { - sendErrorMessage(pluginData, interaction, `Could not convert ${options.time} to a delay`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(interaction, `Could not convert ${options.time} to a delay`); return; } diff --git a/backend/src/plugins/ModActions/commands/hidecase/HideCaseMsgCmd.ts b/backend/src/plugins/ModActions/commands/hidecase/HideCaseMsgCmd.ts index e7701d4a..3d160d5f 100644 --- a/backend/src/plugins/ModActions/commands/hidecase/HideCaseMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/hidecase/HideCaseMsgCmd.ts @@ -14,6 +14,6 @@ export const HideCaseMsgCmd = modActionsMsgCmd({ ], async run({ pluginData, message: msg, args }) { - actualHideCaseCmd(pluginData, msg.channel, args.caseNum); + actualHideCaseCmd(pluginData, msg, args.caseNum); }, }); diff --git a/backend/src/plugins/ModActions/commands/kick/KickMsgCmd.ts b/backend/src/plugins/ModActions/commands/kick/KickMsgCmd.ts index bab6064d..fb2754e0 100644 --- a/backend/src/plugins/ModActions/commands/kick/KickMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/kick/KickMsgCmd.ts @@ -1,7 +1,7 @@ import { hasPermission } from "knub/helpers"; import { commandTypeHelpers as ct } from "../../../../commandTypes"; -import { sendErrorMessage } from "../../../../pluginUtils"; import { resolveUser } from "../../../../utils"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualKickCmd } from "../../functions/actualCommands/actualKickCmd"; import { readContactMethodsFromArgs } from "../../functions/readContactMethodsFromArgs"; import { modActionsMsgCmd } from "../../types"; @@ -30,7 +30,7 @@ export const KickMsgCmd = modActionsMsgCmd({ async run({ pluginData, message: msg, args }) { const user = await resolveUser(pluginData.client, args.user); if (!user.id) { - sendErrorMessage(pluginData, msg.channel, `User not found`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `User not found`); return; } @@ -38,7 +38,7 @@ export const KickMsgCmd = modActionsMsgCmd({ let mod = msg.member; if (args.mod) { if (!(await hasPermission(await pluginData.config.getForMessage(msg), "can_act_as_other"))) { - sendErrorMessage(pluginData, msg.channel, "You don't have permission to use -mod"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "You don't have permission to use -mod"); return; } @@ -49,13 +49,13 @@ export const KickMsgCmd = modActionsMsgCmd({ try { contactMethods = readContactMethodsFromArgs(args); } catch (e) { - sendErrorMessage(pluginData, msg.channel, e.message); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, e.message); return; } actualKickCmd( pluginData, - msg.channel, + msg, msg.member, user, args.reason, diff --git a/backend/src/plugins/ModActions/commands/kick/KickSlashCmd.ts b/backend/src/plugins/ModActions/commands/kick/KickSlashCmd.ts index 46041006..961445ec 100644 --- a/backend/src/plugins/ModActions/commands/kick/KickSlashCmd.ts +++ b/backend/src/plugins/ModActions/commands/kick/KickSlashCmd.ts @@ -1,8 +1,9 @@ import { ChannelType } from "discord.js"; import { slashOptions } from "knub"; -import { hasPermission, sendErrorMessage } from "../../../../pluginUtils"; +import { hasPermission } from "../../../../pluginUtils"; import { UserNotificationMethod } from "../../../../utils"; import { generateAttachmentSlashOptions, retrieveMultipleOptions } from "../../../../utils/multipleSlashOptions"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualKickCmd } from "../../functions/actualCommands/actualKickCmd"; import { readContactMethodsFromArgs } from "../../functions/readContactMethodsFromArgs"; import { NUMBER_ATTACHMENTS_CASE_CREATION } from "../constants"; @@ -48,7 +49,9 @@ export const KickSlashCmd = { const attachments = retrieveMultipleOptions(NUMBER_ATTACHMENTS_CASE_CREATION, options, "attachment"); if ((!options.reason || options.reason.trim() === "") && attachments.length < 1) { - sendErrorMessage(pluginData, interaction, "Text or attachment required", undefined, undefined, true); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "Text or attachment required", undefined, undefined, true); return; } @@ -61,7 +64,9 @@ export const KickSlashCmd = { if (options.mod) { if (!canActAsOther) { - sendErrorMessage(pluginData, interaction, "You don't have permission to act as another moderator"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "You don't have permission to act as another moderator"); return; } @@ -72,7 +77,7 @@ export const KickSlashCmd = { try { contactMethods = readContactMethodsFromArgs(options) ?? undefined; } catch (e) { - sendErrorMessage(pluginData, interaction, e.message); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(interaction, e.message); return; } diff --git a/backend/src/plugins/ModActions/commands/massban/MassBanMsgCmd.ts b/backend/src/plugins/ModActions/commands/massban/MassBanMsgCmd.ts index 222dbacc..d607224a 100644 --- a/backend/src/plugins/ModActions/commands/massban/MassBanMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/massban/MassBanMsgCmd.ts @@ -14,6 +14,6 @@ export const MassBanMsgCmd = modActionsMsgCmd({ ], async run({ pluginData, message: msg, args }) { - actualMassBanCmd(pluginData, msg.channel, args.userIds, msg.member); + actualMassBanCmd(pluginData, msg, args.userIds, msg.member); }, }); diff --git a/backend/src/plugins/ModActions/commands/massmute/MassMuteMsgCmd.ts b/backend/src/plugins/ModActions/commands/massmute/MassMuteMsgCmd.ts index 0d7793ce..a09a5f26 100644 --- a/backend/src/plugins/ModActions/commands/massmute/MassMuteMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/massmute/MassMuteMsgCmd.ts @@ -14,6 +14,6 @@ export const MassMuteMsgCmd = modActionsMsgCmd({ ], async run({ pluginData, message: msg, args }) { - actualMassMuteCmd(pluginData, msg.channel, args.userIds, msg.member); + actualMassMuteCmd(pluginData, msg, args.userIds, msg.member); }, }); diff --git a/backend/src/plugins/ModActions/commands/massunban/MassUnbanMsgCmd.ts b/backend/src/plugins/ModActions/commands/massunban/MassUnbanMsgCmd.ts index 8508b00e..72713ad5 100644 --- a/backend/src/plugins/ModActions/commands/massunban/MassUnbanMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/massunban/MassUnbanMsgCmd.ts @@ -14,6 +14,6 @@ export const MassUnbanMsgCmd = modActionsMsgCmd({ ], async run({ pluginData, message: msg, args }) { - actualMassBanCmd(pluginData, msg.channel, args.userIds, msg.member); + actualMassBanCmd(pluginData, msg, args.userIds, msg.member); }, }); diff --git a/backend/src/plugins/ModActions/commands/mute/MuteMsgCmd.ts b/backend/src/plugins/ModActions/commands/mute/MuteMsgCmd.ts index 16a5343f..469d7162 100644 --- a/backend/src/plugins/ModActions/commands/mute/MuteMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/mute/MuteMsgCmd.ts @@ -1,7 +1,8 @@ import { commandTypeHelpers as ct } from "../../../../commandTypes"; -import { canActOn, hasPermission, sendErrorMessage } from "../../../../pluginUtils"; +import { canActOn, hasPermission } from "../../../../pluginUtils"; import { resolveMember, resolveUser } from "../../../../utils"; import { waitForButtonConfirm } from "../../../../utils/waitForInteraction"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualMuteCmd } from "../../functions/actualCommands/actualMuteCmd"; import { isBanned } from "../../functions/isBanned"; import { readContactMethodsFromArgs } from "../../functions/readContactMethodsFromArgs"; @@ -37,7 +38,7 @@ export const MuteMsgCmd = modActionsMsgCmd({ async run({ pluginData, message: msg, args }) { const user = await resolveUser(pluginData.client, args.user); if (!user.id) { - sendErrorMessage(pluginData, msg.channel, `User not found`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `User not found`); return; } @@ -47,22 +48,20 @@ export const MuteMsgCmd = modActionsMsgCmd({ const _isBanned = await isBanned(pluginData, user.id); const prefix = pluginData.fullConfig.prefix; if (_isBanned) { - sendErrorMessage( - pluginData, - msg.channel, - `User is banned. Use \`${prefix}forcemute\` if you want to mute them anyway.`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `User is banned. Use \`${prefix}forcemute\` if you want to mute them anyway.`); return; } else { // Ask the mod if we should upgrade to a forcemute as the user is not on the server const reply = await waitForButtonConfirm( - msg.channel, + msg, { content: "User not found on the server, forcemute instead?" }, { confirmText: "Yes", cancelText: "No", restrictToId: msg.member.id }, ); if (!reply) { - sendErrorMessage(pluginData, msg.channel, "User not on server, mute cancelled by moderator"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "User not on server, mute cancelled by moderator"); return; } } @@ -70,7 +69,7 @@ export const MuteMsgCmd = modActionsMsgCmd({ // Make sure we're allowed to mute this member if (memberToMute && !canActOn(pluginData, msg.member, memberToMute)) { - sendErrorMessage(pluginData, msg.channel, "Cannot mute: insufficient permissions"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Cannot mute: insufficient permissions"); return; } @@ -80,7 +79,7 @@ export const MuteMsgCmd = modActionsMsgCmd({ if (args.mod) { if (!(await hasPermission(pluginData, "can_act_as_other", { message: msg }))) { - sendErrorMessage(pluginData, msg.channel, "You don't have permission to use -mod"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "You don't have permission to use -mod"); return; } @@ -92,13 +91,13 @@ export const MuteMsgCmd = modActionsMsgCmd({ try { contactMethods = readContactMethodsFromArgs(args); } catch (e) { - sendErrorMessage(pluginData, msg.channel, e.message); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, e.message); return; } actualMuteCmd( pluginData, - msg.channel, + msg, user, [...msg.attachments.values()], mod, diff --git a/backend/src/plugins/ModActions/commands/mute/MuteSlashCmd.ts b/backend/src/plugins/ModActions/commands/mute/MuteSlashCmd.ts index c17200fc..c84ce9ef 100644 --- a/backend/src/plugins/ModActions/commands/mute/MuteSlashCmd.ts +++ b/backend/src/plugins/ModActions/commands/mute/MuteSlashCmd.ts @@ -1,9 +1,10 @@ import { ChannelType } from "discord.js"; import { slashOptions } from "knub"; -import { canActOn, hasPermission, sendErrorMessage } from "../../../../pluginUtils"; +import { canActOn, hasPermission } from "../../../../pluginUtils"; import { UserNotificationMethod, convertDelayStringToMS, resolveMember } from "../../../../utils"; import { generateAttachmentSlashOptions, retrieveMultipleOptions } from "../../../../utils/multipleSlashOptions"; import { waitForButtonConfirm } from "../../../../utils/waitForInteraction"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualMuteCmd } from "../../functions/actualCommands/actualMuteCmd"; import { isBanned } from "../../functions/isBanned"; import { readContactMethodsFromArgs } from "../../functions/readContactMethodsFromArgs"; @@ -46,7 +47,9 @@ export const MuteSlashCmd = { const attachments = retrieveMultipleOptions(NUMBER_ATTACHMENTS_CASE_CREATION, options, "attachment"); if ((!options.reason || options.reason.trim() === "") && attachments.length < 1) { - sendErrorMessage(pluginData, interaction, "Text or attachment required", undefined, undefined, true); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "Text or attachment required", undefined, undefined, true); return; } @@ -57,11 +60,9 @@ export const MuteSlashCmd = { const _isBanned = await isBanned(pluginData, options.user.id); const prefix = pluginData.fullConfig.prefix; if (_isBanned) { - sendErrorMessage( - pluginData, - interaction, - `User is banned. Use \`${prefix}forcemute\` if you want to mute them anyway.`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, `User is banned. Use \`${prefix}forcemute\` if you want to mute them anyway.`); return; } else { // Ask the mod if we should upgrade to a forcemute as the user is not on the server @@ -72,7 +73,9 @@ export const MuteSlashCmd = { ); if (!reply) { - sendErrorMessage(pluginData, interaction, "User not on server, mute cancelled by moderator"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "User not on server, mute cancelled by moderator"); return; } } @@ -80,7 +83,7 @@ export const MuteSlashCmd = { // Make sure we're allowed to mute this member if (memberToMute && !canActOn(pluginData, interaction.member, memberToMute)) { - sendErrorMessage(pluginData, interaction, "Cannot mute: insufficient permissions"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(interaction, "Cannot mute: insufficient permissions"); return; } @@ -93,7 +96,9 @@ export const MuteSlashCmd = { if (options.mod) { if (!canActAsOther) { - sendErrorMessage(pluginData, interaction, "You don't have permission to act as another moderator"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "You don't have permission to act as another moderator"); return; } @@ -103,7 +108,7 @@ export const MuteSlashCmd = { const convertedTime = options.time ? convertDelayStringToMS(options.time) : null; if (options.time && !convertedTime) { - sendErrorMessage(pluginData, interaction, `Could not convert ${options.time} to a delay`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(interaction, `Could not convert ${options.time} to a delay`); return; } @@ -111,7 +116,7 @@ export const MuteSlashCmd = { try { contactMethods = readContactMethodsFromArgs(options) ?? undefined; } catch (e) { - sendErrorMessage(pluginData, interaction, e.message); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(interaction, e.message); return; } diff --git a/backend/src/plugins/ModActions/commands/note/NoteMsgCmd.ts b/backend/src/plugins/ModActions/commands/note/NoteMsgCmd.ts index 14336d89..9861702f 100644 --- a/backend/src/plugins/ModActions/commands/note/NoteMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/note/NoteMsgCmd.ts @@ -1,6 +1,6 @@ import { commandTypeHelpers as ct } from "../../../../commandTypes"; -import { sendErrorMessage } from "../../../../pluginUtils"; import { resolveUser } from "../../../../utils"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualNoteCmd } from "../../functions/actualCommands/actualNoteCmd"; import { modActionsMsgCmd } from "../../types"; @@ -17,15 +17,15 @@ export const NoteMsgCmd = modActionsMsgCmd({ async run({ pluginData, message: msg, args }) { const user = await resolveUser(pluginData.client, args.user); if (!user.id) { - sendErrorMessage(pluginData, msg.channel, `User not found`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `User not found`); return; } if (!args.note && msg.attachments.size === 0) { - sendErrorMessage(pluginData, msg.channel, "Text or attachment required"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Text or attachment required"); return; } - actualNoteCmd(pluginData, msg.channel, msg.author, [...msg.attachments.values()], user, args.note || ""); + actualNoteCmd(pluginData, msg, msg.author, [...msg.attachments.values()], user, args.note || ""); }, }); diff --git a/backend/src/plugins/ModActions/commands/note/NoteSlashCmd.ts b/backend/src/plugins/ModActions/commands/note/NoteSlashCmd.ts index 50fd2735..9647d861 100644 --- a/backend/src/plugins/ModActions/commands/note/NoteSlashCmd.ts +++ b/backend/src/plugins/ModActions/commands/note/NoteSlashCmd.ts @@ -1,6 +1,6 @@ import { slashOptions } from "knub"; -import { sendErrorMessage } from "../../../../pluginUtils"; import { generateAttachmentSlashOptions, retrieveMultipleOptions } from "../../../../utils/multipleSlashOptions"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualNoteCmd } from "../../functions/actualCommands/actualNoteCmd"; import { NUMBER_ATTACHMENTS_CASE_CREATION } from "../constants"; @@ -24,7 +24,9 @@ export const NoteSlashCmd = { const attachments = retrieveMultipleOptions(NUMBER_ATTACHMENTS_CASE_CREATION, options, "attachment"); if ((!options.note || options.note.trim() === "") && attachments.length < 1) { - sendErrorMessage(pluginData, interaction, "Text or attachment required", undefined, undefined, true); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "Text or attachment required", undefined, undefined, true); return; } diff --git a/backend/src/plugins/ModActions/commands/unban/UnbanMsgCmd.ts b/backend/src/plugins/ModActions/commands/unban/UnbanMsgCmd.ts index 1d9bd37d..531efc4a 100644 --- a/backend/src/plugins/ModActions/commands/unban/UnbanMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/unban/UnbanMsgCmd.ts @@ -1,6 +1,7 @@ import { commandTypeHelpers as ct } from "../../../../commandTypes"; -import { hasPermission, sendErrorMessage } from "../../../../pluginUtils"; +import { hasPermission } from "../../../../pluginUtils"; import { resolveUser } from "../../../../utils"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualUnbanCmd } from "../../functions/actualCommands/actualUnbanCmd"; import { modActionsMsgCmd } from "../../types"; @@ -25,7 +26,7 @@ export const UnbanMsgCmd = modActionsMsgCmd({ async run({ pluginData, message: msg, args }) { const user = await resolveUser(pluginData.client, args.user); if (!user.id) { - sendErrorMessage(pluginData, msg.channel, `User not found`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `User not found`); return; } @@ -33,13 +34,13 @@ export const UnbanMsgCmd = modActionsMsgCmd({ let mod = msg.member; if (args.mod) { if (!(await hasPermission(pluginData, "can_act_as_other", { message: msg, channelId: msg.channel.id }))) { - sendErrorMessage(pluginData, msg.channel, "You don't have permission to use -mod"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "You don't have permission to use -mod"); return; } mod = args.mod; } - actualUnbanCmd(pluginData, msg.channel, msg.author.id, user, args.reason, [...msg.attachments.values()], mod); + actualUnbanCmd(pluginData, msg, msg.author.id, user, args.reason, [...msg.attachments.values()], mod); }, }); diff --git a/backend/src/plugins/ModActions/commands/unban/UnbanSlashCmd.ts b/backend/src/plugins/ModActions/commands/unban/UnbanSlashCmd.ts index e85cfdfb..abc969de 100644 --- a/backend/src/plugins/ModActions/commands/unban/UnbanSlashCmd.ts +++ b/backend/src/plugins/ModActions/commands/unban/UnbanSlashCmd.ts @@ -1,6 +1,7 @@ import { slashOptions } from "knub"; -import { hasPermission, sendErrorMessage } from "../../../../pluginUtils"; +import { hasPermission } from "../../../../pluginUtils"; import { generateAttachmentSlashOptions, retrieveMultipleOptions } from "../../../../utils/multipleSlashOptions"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualUnbanCmd } from "../../functions/actualCommands/actualUnbanCmd"; import { NUMBER_ATTACHMENTS_CASE_CREATION } from "../constants"; @@ -25,7 +26,9 @@ export const UnbanSlashCmd = { const attachments = retrieveMultipleOptions(NUMBER_ATTACHMENTS_CASE_CREATION, options, "attachment"); if ((!options.reason || options.reason.trim() === "") && attachments.length < 1) { - sendErrorMessage(pluginData, interaction, "Text or attachment required", undefined, undefined, true); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "Text or attachment required", undefined, undefined, true); return; } @@ -38,7 +41,9 @@ export const UnbanSlashCmd = { if (options.mod) { if (!canActAsOther) { - sendErrorMessage(pluginData, interaction, "You don't have permission to act as another moderator"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "You don't have permission to act as another moderator"); return; } diff --git a/backend/src/plugins/ModActions/commands/unhidecase/UnhideCaseMsgCmd.ts b/backend/src/plugins/ModActions/commands/unhidecase/UnhideCaseMsgCmd.ts index 94c029a2..8e71c8e3 100644 --- a/backend/src/plugins/ModActions/commands/unhidecase/UnhideCaseMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/unhidecase/UnhideCaseMsgCmd.ts @@ -14,6 +14,6 @@ export const UnhideCaseMsgCmd = modActionsMsgCmd({ ], async run({ pluginData, message: msg, args }) { - actualHideCaseCmd(pluginData, msg.channel, args.caseNum); + actualHideCaseCmd(pluginData, msg, args.caseNum); }, }); diff --git a/backend/src/plugins/ModActions/commands/unmute/UnmuteMsgCmd.ts b/backend/src/plugins/ModActions/commands/unmute/UnmuteMsgCmd.ts index 8d7e111a..b917d83b 100644 --- a/backend/src/plugins/ModActions/commands/unmute/UnmuteMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/unmute/UnmuteMsgCmd.ts @@ -1,7 +1,8 @@ import { commandTypeHelpers as ct } from "../../../../commandTypes"; -import { canActOn, hasPermission, sendErrorMessage } from "../../../../pluginUtils"; +import { canActOn, hasPermission } from "../../../../pluginUtils"; import { resolveMember, resolveUser } from "../../../../utils"; import { waitForButtonConfirm } from "../../../../utils/waitForInteraction"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { MutesPlugin } from "../../../Mutes/MutesPlugin"; import { actualUnmuteCmd } from "../../functions/actualCommands/actualUnmuteCmd"; import { isBanned } from "../../functions/isBanned"; @@ -35,7 +36,7 @@ export const UnmuteMsgCmd = modActionsMsgCmd({ async run({ pluginData, message: msg, args }) { const user = await resolveUser(pluginData.client, args.user); if (!user.id) { - sendErrorMessage(pluginData, msg.channel, `User not found`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `User not found`); return; } @@ -49,7 +50,7 @@ export const UnmuteMsgCmd = modActionsMsgCmd({ !hasMuteRole && !memberToUnmute?.isCommunicationDisabled() ) { - sendErrorMessage(pluginData, msg.channel, "Cannot unmute: member is not muted"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Cannot unmute: member is not muted"); return; } @@ -57,22 +58,20 @@ export const UnmuteMsgCmd = modActionsMsgCmd({ const banned = await isBanned(pluginData, user.id); const prefix = pluginData.fullConfig.prefix; if (banned) { - sendErrorMessage( - pluginData, - msg.channel, - `User is banned. Use \`${prefix}forceunmute\` to unmute them anyway.`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `User is banned. Use \`${prefix}forceunmute\` to unmute them anyway.`); return; } else { // Ask the mod if we should upgrade to a forceunmute as the user is not on the server const reply = await waitForButtonConfirm( - msg.channel, + msg, { content: "User not on server, forceunmute instead?" }, { confirmText: "Yes", cancelText: "No", restrictToId: msg.member.id }, ); if (!reply) { - sendErrorMessage(pluginData, msg.channel, "User not on server, unmute cancelled by moderator"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "User not on server, unmute cancelled by moderator"); return; } } @@ -80,7 +79,7 @@ export const UnmuteMsgCmd = modActionsMsgCmd({ // Make sure we're allowed to unmute this member if (memberToUnmute && !canActOn(pluginData, msg.member, memberToUnmute)) { - sendErrorMessage(pluginData, msg.channel, "Cannot unmute: insufficient permissions"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Cannot unmute: insufficient permissions"); return; } @@ -90,7 +89,7 @@ export const UnmuteMsgCmd = modActionsMsgCmd({ if (args.mod) { if (!(await hasPermission(pluginData, "can_act_as_other", { message: msg }))) { - sendErrorMessage(pluginData, msg.channel, "You don't have permission to use -mod"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "You don't have permission to use -mod"); return; } @@ -100,7 +99,7 @@ export const UnmuteMsgCmd = modActionsMsgCmd({ actualUnmuteCmd( pluginData, - msg.channel, + msg, user, [...msg.attachments.values()], mod, diff --git a/backend/src/plugins/ModActions/commands/unmute/UnmuteSlashCmd.ts b/backend/src/plugins/ModActions/commands/unmute/UnmuteSlashCmd.ts index 04526be6..97163b2b 100644 --- a/backend/src/plugins/ModActions/commands/unmute/UnmuteSlashCmd.ts +++ b/backend/src/plugins/ModActions/commands/unmute/UnmuteSlashCmd.ts @@ -1,8 +1,9 @@ import { slashOptions } from "knub"; -import { canActOn, hasPermission, sendErrorMessage } from "../../../../pluginUtils"; +import { canActOn, hasPermission } from "../../../../pluginUtils"; import { convertDelayStringToMS, resolveMember } from "../../../../utils"; import { generateAttachmentSlashOptions, retrieveMultipleOptions } from "../../../../utils/multipleSlashOptions"; import { waitForButtonConfirm } from "../../../../utils/waitForInteraction"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { MutesPlugin } from "../../../Mutes/MutesPlugin"; import { actualUnmuteCmd } from "../../functions/actualCommands/actualUnmuteCmd"; import { isBanned } from "../../functions/isBanned"; @@ -30,7 +31,9 @@ export const UnmuteSlashCmd = { const attachments = retrieveMultipleOptions(NUMBER_ATTACHMENTS_CASE_CREATION, options, "attachment"); if ((!options.reason || options.reason.trim() === "") && attachments.length < 1) { - sendErrorMessage(pluginData, interaction, "Text or attachment required", undefined, undefined, true); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "Text or attachment required", undefined, undefined, true); return; } @@ -45,7 +48,7 @@ export const UnmuteSlashCmd = { !hasMuteRole && !memberToUnmute?.isCommunicationDisabled() ) { - sendErrorMessage(pluginData, interaction, "Cannot unmute: member is not muted"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(interaction, "Cannot unmute: member is not muted"); return; } @@ -53,11 +56,9 @@ export const UnmuteSlashCmd = { const banned = await isBanned(pluginData, options.user.id); const prefix = pluginData.fullConfig.prefix; if (banned) { - sendErrorMessage( - pluginData, - interaction, - `User is banned. Use \`${prefix}forceunmute\` to unmute them anyway.`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, `User is banned. Use \`${prefix}forceunmute\` to unmute them anyway.`); return; } else { // Ask the mod if we should upgrade to a forceunmute as the user is not on the server @@ -68,7 +69,9 @@ export const UnmuteSlashCmd = { ); if (!reply) { - sendErrorMessage(pluginData, interaction, "User not on server, unmute cancelled by moderator"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "User not on server, unmute cancelled by moderator"); return; } } @@ -76,7 +79,7 @@ export const UnmuteSlashCmd = { // Make sure we're allowed to unmute this member if (memberToUnmute && !canActOn(pluginData, interaction.member, memberToUnmute)) { - sendErrorMessage(pluginData, interaction, "Cannot unmute: insufficient permissions"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(interaction, "Cannot unmute: insufficient permissions"); return; } @@ -89,7 +92,9 @@ export const UnmuteSlashCmd = { if (options.mod) { if (!canActAsOther) { - sendErrorMessage(pluginData, interaction, "You don't have permission to act as another moderator"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "You don't have permission to act as another moderator"); return; } @@ -99,7 +104,7 @@ export const UnmuteSlashCmd = { const convertedTime = options.time ? convertDelayStringToMS(options.time) : null; if (options.time && !convertedTime) { - sendErrorMessage(pluginData, interaction, `Could not convert ${options.time} to a delay`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(interaction, `Could not convert ${options.time} to a delay`); return; } diff --git a/backend/src/plugins/ModActions/commands/update/UpdateMsgCmd.ts b/backend/src/plugins/ModActions/commands/update/UpdateMsgCmd.ts index 73c74f36..c0c186a9 100644 --- a/backend/src/plugins/ModActions/commands/update/UpdateMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/update/UpdateMsgCmd.ts @@ -19,6 +19,6 @@ export const UpdateMsgCmd = modActionsMsgCmd({ ], async run({ pluginData, message: msg, args }) { - await updateCase(pluginData, msg.channel, msg.author, args.caseNumber, args.note, [...msg.attachments.values()]); + await updateCase(pluginData, msg, msg.author, args.caseNumber, args.note, [...msg.attachments.values()]); }, }); diff --git a/backend/src/plugins/ModActions/commands/warn/WarnMsgCmd.ts b/backend/src/plugins/ModActions/commands/warn/WarnMsgCmd.ts index 4baeb3c1..cd8533b6 100644 --- a/backend/src/plugins/ModActions/commands/warn/WarnMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/warn/WarnMsgCmd.ts @@ -1,6 +1,7 @@ import { commandTypeHelpers as ct } from "../../../../commandTypes"; -import { canActOn, hasPermission, sendErrorMessage } from "../../../../pluginUtils"; +import { canActOn, hasPermission } from "../../../../pluginUtils"; import { errorMessage, resolveMember, resolveUser } from "../../../../utils"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualWarnCmd } from "../../functions/actualCommands/actualWarnCmd"; import { isBanned } from "../../functions/isBanned"; import { readContactMethodsFromArgs } from "../../functions/readContactMethodsFromArgs"; @@ -23,7 +24,7 @@ export const WarnMsgCmd = modActionsMsgCmd({ async run({ pluginData, message: msg, args }) { const user = await resolveUser(pluginData.client, args.user); if (!user.id) { - sendErrorMessage(pluginData, msg.channel, `User not found`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `User not found`); return; } @@ -32,9 +33,9 @@ export const WarnMsgCmd = modActionsMsgCmd({ if (!memberToWarn) { const _isBanned = await isBanned(pluginData, user.id); if (_isBanned) { - sendErrorMessage(pluginData, msg.channel, `User is banned`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `User is banned`); } else { - sendErrorMessage(pluginData, msg.channel, `User not found on the server`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `User not found on the server`); } return; @@ -42,7 +43,7 @@ export const WarnMsgCmd = modActionsMsgCmd({ // Make sure we're allowed to warn this member if (!canActOn(pluginData, msg.member, memberToWarn)) { - sendErrorMessage(pluginData, msg.channel, "Cannot warn: insufficient permissions"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Cannot warn: insufficient permissions"); return; } @@ -61,13 +62,13 @@ export const WarnMsgCmd = modActionsMsgCmd({ try { contactMethods = readContactMethodsFromArgs(args); } catch (e) { - sendErrorMessage(pluginData, msg.channel, e.message); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, e.message); return; } actualWarnCmd( pluginData, - msg.channel, + msg, msg.author.id, mod, memberToWarn, diff --git a/backend/src/plugins/ModActions/commands/warn/WarnSlashCmd.ts b/backend/src/plugins/ModActions/commands/warn/WarnSlashCmd.ts index 025f1981..c34e91e0 100644 --- a/backend/src/plugins/ModActions/commands/warn/WarnSlashCmd.ts +++ b/backend/src/plugins/ModActions/commands/warn/WarnSlashCmd.ts @@ -1,8 +1,9 @@ import { ChannelType } from "discord.js"; import { slashOptions } from "knub"; -import { canActOn, hasPermission, sendErrorMessage } from "../../../../pluginUtils"; +import { canActOn, hasPermission } from "../../../../pluginUtils"; import { UserNotificationMethod, resolveMember } from "../../../../utils"; import { generateAttachmentSlashOptions, retrieveMultipleOptions } from "../../../../utils/multipleSlashOptions"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { actualWarnCmd } from "../../functions/actualCommands/actualWarnCmd"; import { isBanned } from "../../functions/isBanned"; import { readContactMethodsFromArgs } from "../../functions/readContactMethodsFromArgs"; @@ -44,7 +45,9 @@ export const WarnSlashCmd = { const attachments = retrieveMultipleOptions(NUMBER_ATTACHMENTS_CASE_CREATION, options, "attachment"); if ((!options.reason || options.reason.trim() === "") && attachments.length < 1) { - sendErrorMessage(pluginData, interaction, "Text or attachment required", undefined, undefined, true); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "Text or attachment required", undefined, undefined, true); return; } @@ -54,9 +57,9 @@ export const WarnSlashCmd = { if (!memberToWarn) { const _isBanned = await isBanned(pluginData, options.user.id); if (_isBanned) { - sendErrorMessage(pluginData, interaction, `User is banned`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(interaction, `User is banned`); } else { - sendErrorMessage(pluginData, interaction, `User not found on the server`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(interaction, `User not found on the server`); } return; @@ -64,7 +67,7 @@ export const WarnSlashCmd = { // Make sure we're allowed to warn this member if (!canActOn(pluginData, interaction.member, memberToWarn)) { - sendErrorMessage(pluginData, interaction, "Cannot warn: insufficient permissions"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(interaction, "Cannot warn: insufficient permissions"); return; } @@ -76,7 +79,9 @@ export const WarnSlashCmd = { if (options.mod) { if (!canActAsOther) { - sendErrorMessage(pluginData, interaction, "You don't have permission to act as another moderator"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(interaction, "You don't have permission to act as another moderator"); return; } @@ -87,7 +92,7 @@ export const WarnSlashCmd = { try { contactMethods = readContactMethodsFromArgs(options) ?? undefined; } catch (e) { - sendErrorMessage(pluginData, interaction, e.message); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(interaction, e.message); return; } diff --git a/backend/src/plugins/ModActions/functions/actualCommands/actualAddCaseCmd.ts b/backend/src/plugins/ModActions/functions/actualCommands/actualAddCaseCmd.ts index 572d450c..25ce2fbb 100644 --- a/backend/src/plugins/ModActions/functions/actualCommands/actualAddCaseCmd.ts +++ b/backend/src/plugins/ModActions/functions/actualCommands/actualAddCaseCmd.ts @@ -1,17 +1,19 @@ -import { Attachment, ChatInputCommandInteraction, GuildMember, TextBasedChannel, User } from "discord.js"; +import { Attachment, ChatInputCommandInteraction, GuildMember, Message, User } from "discord.js"; import { GuildPluginData } from "knub"; import { CaseTypes } from "../../../../data/CaseTypes"; import { Case } from "../../../../data/entities/Case"; -import { canActOn, sendErrorMessage, sendSuccessMessage } from "../../../../pluginUtils"; +import { canActOn } from "../../../../pluginUtils"; import { UnknownUser, renderUserUsername, resolveMember } from "../../../../utils"; import { CasesPlugin } from "../../../Cases/CasesPlugin"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { LogsPlugin } from "../../../Logs/LogsPlugin"; import { ModActionsPluginType } from "../../types"; -import { formatReasonWithAttachments } from "../formatReasonWithAttachments"; +import { handleAttachmentLinkDetectionAndGetRestriction } from "../attachmentLinkReaction"; +import { formatReasonWithMessageLinkForAttachments } from "../formatReasonForAttachments"; export async function actualAddCaseCmd( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, author: GuildMember, mod: GuildMember, attachments: Array, @@ -19,14 +21,20 @@ export async function actualAddCaseCmd( type: keyof CaseTypes, reason: string, ) { - // If the user exists as a guild member, make sure we can act on them first - const member = await resolveMember(pluginData.client, pluginData.guild, user.id); - if (member && !canActOn(pluginData, author, member)) { - sendErrorMessage(pluginData, context, "Cannot add case on this user: insufficient permissions"); + if (await handleAttachmentLinkDetectionAndGetRestriction(pluginData, context, reason)) { return; } - const formattedReason = formatReasonWithAttachments(reason, attachments); + // If the user exists as a guild member, make sure we can act on them first + const member = await resolveMember(pluginData.client, pluginData.guild, user.id); + if (member && !canActOn(pluginData, author, member)) { + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(context, "Cannot add case on this user: insufficient permissions"); + return; + } + + const formattedReason = await formatReasonWithMessageLinkForAttachments(pluginData, reason, context, attachments); // Create the case const casesPlugin = pluginData.getPlugin(CasesPlugin); @@ -39,9 +47,11 @@ export async function actualAddCaseCmd( }); if (user) { - sendSuccessMessage(pluginData, context, `Case #${theCase.case_number} created for **${renderUserUsername(user)}**`); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(context, `Case #${theCase.case_number} created for **${renderUserUsername(user)}**`); } else { - sendSuccessMessage(pluginData, context, `Case #${theCase.case_number} created`); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(context, `Case #${theCase.case_number} created`); } // Log the action diff --git a/backend/src/plugins/ModActions/functions/actualCommands/actualBanCmd.ts b/backend/src/plugins/ModActions/functions/actualCommands/actualBanCmd.ts index 5b665884..fa9b7c94 100644 --- a/backend/src/plugins/ModActions/functions/actualCommands/actualBanCmd.ts +++ b/backend/src/plugins/ModActions/functions/actualCommands/actualBanCmd.ts @@ -1,23 +1,25 @@ -import { Attachment, ChatInputCommandInteraction, GuildMember, TextBasedChannel, User } from "discord.js"; +import { Attachment, ChatInputCommandInteraction, GuildMember, Message, User } from "discord.js"; import humanizeDuration from "humanize-duration"; import { GuildPluginData } from "knub"; import { getMemberLevel } from "knub/helpers"; import { CaseTypes } from "../../../../data/CaseTypes"; import { clearExpiringTempban, registerExpiringTempban } from "../../../../data/loops/expiringTempbansLoop"; -import { canActOn, isContextInteraction, sendErrorMessage, sendSuccessMessage } from "../../../../pluginUtils"; +import { canActOn, getContextChannel } from "../../../../pluginUtils"; import { UnknownUser, UserNotificationMethod, renderUserUsername, resolveMember } from "../../../../utils"; import { banLock } from "../../../../utils/lockNameHelpers"; import { waitForButtonConfirm } from "../../../../utils/waitForInteraction"; import { CasesPlugin } from "../../../Cases/CasesPlugin"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { LogsPlugin } from "../../../Logs/LogsPlugin"; import { ModActionsPluginType } from "../../types"; +import { handleAttachmentLinkDetectionAndGetRestriction } from "../attachmentLinkReaction"; import { banUserId } from "../banUserId"; -import { formatReasonWithAttachments } from "../formatReasonWithAttachments"; +import { formatReasonWithAttachments, formatReasonWithMessageLinkForAttachments } from "../formatReasonForAttachments"; import { isBanned } from "../isBanned"; export async function actualBanCmd( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, user: User | UnknownUser, time: number | null, reason: string, @@ -27,8 +29,13 @@ export async function actualBanCmd( contactMethods?: UserNotificationMethod[], deleteDays?: number, ) { + if (await handleAttachmentLinkDetectionAndGetRestriction(pluginData, context, reason)) { + return; + } + const memberToBan = await resolveMember(pluginData.client, pluginData.guild, user.id); - const formattedReason = formatReasonWithAttachments(reason, attachments); + const formattedReason = await formatReasonWithMessageLinkForAttachments(pluginData, reason, context, attachments); + const formattedReasonWithAttachments = formatReasonWithAttachments(reason, attachments); // acquire a lock because of the needed user-inputs below (if banned/not on server) const lock = await pluginData.locks.acquire(banLock(user)); @@ -47,7 +54,7 @@ export async function actualBanCmd( ); if (!reply) { - sendErrorMessage(pluginData, context, "User not on server, ban cancelled by moderator"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "User not on server, ban cancelled by moderator"); lock.unlock(); return; } else { @@ -57,7 +64,7 @@ export async function actualBanCmd( // Abort if trying to ban user indefinitely if they are already banned indefinitely if (!existingTempban && !time) { - sendErrorMessage(pluginData, context, `User is already banned indefinitely.`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, `User is already banned indefinitely.`); return; } @@ -69,7 +76,9 @@ export async function actualBanCmd( ); if (!reply) { - sendErrorMessage(pluginData, context, "User already banned, update cancelled by moderator"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(context, "User already banned, update cancelled by moderator"); lock.unlock(); return; } @@ -114,11 +123,12 @@ export async function actualBanCmd( }); } - sendSuccessMessage( - pluginData, - context, - `Ban updated to ${time ? "expire in " + humanizeDuration(time) + " from now" : "indefinite"}`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage( + context, + `Ban updated to ${time ? "expire in " + humanizeDuration(time) + " from now" : "indefinite"}`, + ); lock.unlock(); return; } @@ -127,24 +137,26 @@ export async function actualBanCmd( if (!forceban && !canActOn(pluginData, author, memberToBan!)) { const ourLevel = getMemberLevel(pluginData, author); const targetLevel = getMemberLevel(pluginData, memberToBan!); - sendErrorMessage( - pluginData, - context, - `Cannot ban: target permission level is equal or higher to yours, ${targetLevel} >= ${ourLevel}`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage( + context, + `Cannot ban: target permission level is equal or higher to yours, ${targetLevel} >= ${ourLevel}`, + ); lock.unlock(); return; } const matchingConfig = await pluginData.config.getMatchingConfig({ member: author, - channel: isContextInteraction(context) ? context.channel : context, + channel: await getContextChannel(context), }); const deleteMessageDays = deleteDays ?? matchingConfig.ban_delete_message_days; const banResult = await banUserId( pluginData, user.id, formattedReason, + formattedReasonWithAttachments, { contactMethods, caseArgs: { @@ -158,7 +170,7 @@ export async function actualBanCmd( ); if (banResult.status === "failed") { - sendErrorMessage(pluginData, context, `Failed to ban member: ${banResult.error}`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, `Failed to ban member: ${banResult.error}`); lock.unlock(); return; } @@ -178,5 +190,5 @@ export async function actualBanCmd( } lock.unlock(); - sendSuccessMessage(pluginData, context, response); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(context, response); } diff --git a/backend/src/plugins/ModActions/functions/actualCommands/actualCaseCmd.ts b/backend/src/plugins/ModActions/functions/actualCommands/actualCaseCmd.ts index 38ddf2bf..eabd8333 100644 --- a/backend/src/plugins/ModActions/functions/actualCommands/actualCaseCmd.ts +++ b/backend/src/plugins/ModActions/functions/actualCommands/actualCaseCmd.ts @@ -1,19 +1,20 @@ -import { ChatInputCommandInteraction, TextBasedChannel } from "discord.js"; +import { ChatInputCommandInteraction, Message } from "discord.js"; import { GuildPluginData } from "knub"; -import { sendContextResponse, sendErrorMessage } from "../../../../pluginUtils"; +import { sendContextResponse } from "../../../../pluginUtils"; import { CasesPlugin } from "../../../Cases/CasesPlugin"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { ModActionsPluginType } from "../../types"; export async function actualCaseCmd( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, authorId: string, caseNumber: number, ) { const theCase = await pluginData.state.cases.findByCaseNumber(caseNumber); if (!theCase) { - sendErrorMessage(pluginData, context, "Case not found"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "Case not found"); return; } diff --git a/backend/src/plugins/ModActions/functions/actualCommands/actualCasesCmd.ts b/backend/src/plugins/ModActions/functions/actualCommands/actualCasesCmd.ts index 22a16e93..a3707003 100644 --- a/backend/src/plugins/ModActions/functions/actualCommands/actualCasesCmd.ts +++ b/backend/src/plugins/ModActions/functions/actualCommands/actualCasesCmd.ts @@ -1,10 +1,10 @@ -import { APIEmbed, ChatInputCommandInteraction, TextBasedChannel, User } from "discord.js"; +import { APIEmbed, ChatInputCommandInteraction, Message, User } from "discord.js"; import { GuildPluginData } from "knub"; import { In } from "typeorm"; import { FindOptionsWhere } from "typeorm/find-options/FindOptionsWhere"; import { CaseTypes } from "../../../../data/CaseTypes"; import { Case } from "../../../../data/entities/Case"; -import { sendContextResponse, sendErrorMessage } from "../../../../pluginUtils"; +import { sendContextResponse } from "../../../../pluginUtils"; import { UnknownUser, chunkArray, @@ -18,6 +18,7 @@ import { createPaginatedMessage } from "../../../../utils/createPaginatedMessage import { getChunkedEmbedFields } from "../../../../utils/getChunkedEmbedFields"; import { getGuildPrefix } from "../../../../utils/getGuildPrefix"; import { CasesPlugin } from "../../../Cases/CasesPlugin"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { ModActionsPluginType } from "../../types"; const casesPerPage = 5; @@ -25,7 +26,7 @@ const maxExpandedCases = 8; async function sendExpandedCases( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, casesCount: number, cases: Case[], ) { @@ -45,7 +46,7 @@ async function sendExpandedCases( async function casesUserCmd( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, author: User, modId: string | null, user: User | UnknownUser, @@ -137,7 +138,7 @@ async function casesUserCmd( async function casesModCmd( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, author: User, modId: string | null, mod: User | UnknownUser, @@ -152,7 +153,7 @@ async function casesModCmd( const totalCases = await casesPlugin.getTotalCasesByMod(modId ?? author.id, caseFilters); if (totalCases === 0) { - sendErrorMessage(pluginData, context, `No cases by **${modName}**`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, `No cases by **${modName}**`); return; } @@ -211,7 +212,7 @@ async function casesModCmd( export async function actualCasesCmd( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, modId: string | null, user: User | UnknownUser | null, author: User, diff --git a/backend/src/plugins/ModActions/functions/actualCommands/actualDeleteCaseCmd.ts b/backend/src/plugins/ModActions/functions/actualCommands/actualDeleteCaseCmd.ts index 3fac80cf..66240913 100644 --- a/backend/src/plugins/ModActions/functions/actualCommands/actualDeleteCaseCmd.ts +++ b/backend/src/plugins/ModActions/functions/actualCommands/actualDeleteCaseCmd.ts @@ -1,21 +1,17 @@ -import { ChatInputCommandInteraction, GuildMember, TextBasedChannel } from "discord.js"; +import { ChatInputCommandInteraction, GuildMember, Message } from "discord.js"; import { GuildPluginData, helpers } from "knub"; import { Case } from "../../../../data/entities/Case"; -import { - isContextInteraction, - sendContextResponse, - sendErrorMessage, - sendSuccessMessage, -} from "../../../../pluginUtils"; +import { getContextChannel, sendContextResponse } from "../../../../pluginUtils"; import { SECONDS } from "../../../../utils"; import { CasesPlugin } from "../../../Cases/CasesPlugin"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { LogsPlugin } from "../../../Logs/LogsPlugin"; import { TimeAndDatePlugin } from "../../../TimeAndDate/TimeAndDatePlugin"; import { ModActionsPluginType } from "../../types"; export async function actualDeleteCaseCmd( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, author: GuildMember, caseNumbers: number[], force: boolean, @@ -35,7 +31,7 @@ export async function actualDeleteCaseCmd( } if (failed.length === caseNumbers.length) { - sendErrorMessage(pluginData, context, "None of the cases were found!"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "None of the cases were found!"); return; } @@ -50,7 +46,7 @@ export async function actualDeleteCaseCmd( const reply = await helpers.waitForReply( pluginData.client, - isContextInteraction(context) ? context.channel! : context, + await getContextChannel(context), author.id, 15 * SECONDS, ); @@ -87,9 +83,13 @@ export async function actualDeleteCaseCmd( : ""; const amt = validCases.length - cancelled; if (amt === 0) { - sendErrorMessage(pluginData, context, "All deletions were cancelled, no cases were deleted."); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(context, "All deletions were cancelled, no cases were deleted."); return; } - sendSuccessMessage(pluginData, context, `${amt} case${amt === 1 ? " was" : "s were"} deleted!${failedAddendum}`); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(context, `${amt} case${amt === 1 ? " was" : "s were"} deleted!${failedAddendum}`); } diff --git a/backend/src/plugins/ModActions/functions/actualCommands/actualForceBanCmd.ts b/backend/src/plugins/ModActions/functions/actualCommands/actualForceBanCmd.ts index 095e06a7..c093306f 100644 --- a/backend/src/plugins/ModActions/functions/actualCommands/actualForceBanCmd.ts +++ b/backend/src/plugins/ModActions/functions/actualCommands/actualForceBanCmd.ts @@ -1,25 +1,31 @@ -import { Attachment, ChatInputCommandInteraction, GuildMember, Snowflake, TextBasedChannel, User } from "discord.js"; +import { Attachment, ChatInputCommandInteraction, GuildMember, Message, Snowflake, User } from "discord.js"; import { GuildPluginData } from "knub"; import { CaseTypes } from "../../../../data/CaseTypes"; import { LogType } from "../../../../data/LogType"; -import { sendErrorMessage, sendSuccessMessage } from "../../../../pluginUtils"; import { DAYS, MINUTES, UnknownUser } from "../../../../utils"; import { CasesPlugin } from "../../../Cases/CasesPlugin"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { LogsPlugin } from "../../../Logs/LogsPlugin"; import { IgnoredEventType, ModActionsPluginType } from "../../types"; -import { formatReasonWithAttachments } from "../formatReasonWithAttachments"; +import { handleAttachmentLinkDetectionAndGetRestriction } from "../attachmentLinkReaction"; +import { formatReasonWithAttachments, formatReasonWithMessageLinkForAttachments } from "../formatReasonForAttachments"; import { ignoreEvent } from "../ignoreEvent"; export async function actualForceBanCmd( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, authorId: string, user: User | UnknownUser, reason: string, attachments: Array, mod: GuildMember, ) { - const formattedReason = formatReasonWithAttachments(reason, attachments); + if (await handleAttachmentLinkDetectionAndGetRestriction(pluginData, context, reason)) { + return; + } + + const formattedReason = await formatReasonWithMessageLinkForAttachments(pluginData, reason, context, attachments); + const formattedReasonWithAttachments = formatReasonWithAttachments(reason, attachments); ignoreEvent(pluginData, IgnoredEventType.Ban, user.id); pluginData.state.serverLogs.ignoreLog(LogType.MEMBER_BAN, user.id); @@ -28,10 +34,10 @@ export async function actualForceBanCmd( // FIXME: Use banUserId()? await pluginData.guild.bans.create(user.id as Snowflake, { deleteMessageSeconds: (1 * DAYS) / MINUTES, - reason: formattedReason ?? undefined, + reason: formattedReasonWithAttachments ?? undefined, }); } catch { - sendErrorMessage(pluginData, context, "Failed to forceban member"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "Failed to forceban member"); return; } @@ -46,7 +52,9 @@ export async function actualForceBanCmd( }); // Confirm the action - sendSuccessMessage(pluginData, context, `Member forcebanned (Case #${createdCase.case_number})`); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(context, `Member forcebanned (Case #${createdCase.case_number})`); // Log the action pluginData.getPlugin(LogsPlugin).logMemberForceban({ diff --git a/backend/src/plugins/ModActions/functions/actualCommands/actualHideCaseCmd.ts b/backend/src/plugins/ModActions/functions/actualCommands/actualHideCaseCmd.ts index d500ce5f..28527b4d 100644 --- a/backend/src/plugins/ModActions/functions/actualCommands/actualHideCaseCmd.ts +++ b/backend/src/plugins/ModActions/functions/actualCommands/actualHideCaseCmd.ts @@ -1,11 +1,11 @@ -import { ChatInputCommandInteraction, TextBasedChannel } from "discord.js"; +import { ChatInputCommandInteraction, Message } from "discord.js"; import { GuildPluginData } from "knub"; -import { sendErrorMessage, sendSuccessMessage } from "../../../../pluginUtils"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { ModActionsPluginType } from "../../types"; export async function actualHideCaseCmd( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, caseNumbers: number[], ) { const failed: number[] = []; @@ -21,7 +21,7 @@ export async function actualHideCaseCmd( } if (failed.length === caseNumbers.length) { - sendErrorMessage(pluginData, context, "None of the cases were found!"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "None of the cases were found!"); return; } const failedAddendum = @@ -30,9 +30,10 @@ export async function actualHideCaseCmd( : ""; const amt = caseNumbers.length - failed.length; - sendSuccessMessage( - pluginData, - context, - `${amt} case${amt === 1 ? " is" : "s are"} now hidden! Use \`unhidecase\` to unhide them.${failedAddendum}`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage( + context, + `${amt} case${amt === 1 ? " is" : "s are"} now hidden! Use \`unhidecase\` to unhide them.${failedAddendum}`, + ); } diff --git a/backend/src/plugins/ModActions/functions/actualCommands/actualKickCmd.ts b/backend/src/plugins/ModActions/functions/actualCommands/actualKickCmd.ts index e66383fe..9a85965b 100644 --- a/backend/src/plugins/ModActions/functions/actualCommands/actualKickCmd.ts +++ b/backend/src/plugins/ModActions/functions/actualCommands/actualKickCmd.ts @@ -1,7 +1,7 @@ -import { Attachment, ChatInputCommandInteraction, GuildMember, TextBasedChannel, User } from "discord.js"; +import { Attachment, ChatInputCommandInteraction, GuildMember, Message, User } from "discord.js"; import { GuildPluginData } from "knub"; import { LogType } from "../../../../data/LogType"; -import { canActOn, sendErrorMessage, sendSuccessMessage } from "../../../../pluginUtils"; +import { canActOn } from "../../../../pluginUtils"; import { DAYS, SECONDS, @@ -10,15 +10,17 @@ import { renderUserUsername, resolveMember, } from "../../../../utils"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { IgnoredEventType, ModActionsPluginType } from "../../types"; -import { formatReasonWithAttachments } from "../formatReasonWithAttachments"; +import { handleAttachmentLinkDetectionAndGetRestriction } from "../attachmentLinkReaction"; +import { formatReasonWithAttachments, formatReasonWithMessageLinkForAttachments } from "../formatReasonForAttachments"; import { ignoreEvent } from "../ignoreEvent"; import { isBanned } from "../isBanned"; import { kickMember } from "../kickMember"; export async function actualKickCmd( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, author: GuildMember, user: User | UnknownUser, reason: string, @@ -27,14 +29,18 @@ export async function actualKickCmd( contactMethods?: UserNotificationMethod[], clean?: boolean, ) { + if (await handleAttachmentLinkDetectionAndGetRestriction(pluginData, context, reason)) { + return; + } + const memberToKick = await resolveMember(pluginData.client, pluginData.guild, user.id); if (!memberToKick) { const banned = await isBanned(pluginData, user.id); if (banned) { - sendErrorMessage(pluginData, context, `User is banned`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, `User is banned`); } else { - sendErrorMessage(pluginData, context, `User not found on the server`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, `User not found on the server`); } return; @@ -42,13 +48,14 @@ export async function actualKickCmd( // Make sure we're allowed to kick this member if (!canActOn(pluginData, author, memberToKick)) { - sendErrorMessage(pluginData, context, "Cannot kick: insufficient permissions"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "Cannot kick: insufficient permissions"); return; } - const formattedReason = formatReasonWithAttachments(reason, attachments); + const formattedReason = await formatReasonWithMessageLinkForAttachments(pluginData, reason, context, attachments); + const formattedReasonWithAttachments = formatReasonWithAttachments(reason, attachments); - const kickResult = await kickMember(pluginData, memberToKick, formattedReason, { + const kickResult = await kickMember(pluginData, memberToKick, formattedReason, formattedReasonWithAttachments, { contactMethods, caseArgs: { modId: mod.id, @@ -63,7 +70,7 @@ export async function actualKickCmd( try { await memberToKick.ban({ deleteMessageSeconds: (1 * DAYS) / SECONDS, reason: "kick -clean" }); } catch { - sendErrorMessage(pluginData, context, "Failed to ban the user to clean messages (-clean)"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "Failed to ban the user to clean messages (-clean)"); } pluginData.state.serverLogs.ignoreLog(LogType.MEMBER_UNBAN, memberToKick.id); @@ -72,12 +79,14 @@ export async function actualKickCmd( try { await pluginData.guild.bans.remove(memberToKick.id, "kick -clean"); } catch { - sendErrorMessage(pluginData, context, "Failed to unban the user after banning them (-clean)"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(context, "Failed to unban the user after banning them (-clean)"); } } if (kickResult.status === "failed") { - sendErrorMessage(pluginData, context, `Failed to kick user`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, `Failed to kick user`); return; } @@ -85,5 +94,5 @@ export async function actualKickCmd( let response = `Kicked **${renderUserUsername(memberToKick.user)}** (Case #${kickResult.case.case_number})`; if (kickResult.notifyResult.text) response += ` (${kickResult.notifyResult.text})`; - sendSuccessMessage(pluginData, context, response); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(context, response); } diff --git a/backend/src/plugins/ModActions/functions/actualCommands/actualMassBanCmd.ts b/backend/src/plugins/ModActions/functions/actualCommands/actualMassBanCmd.ts index c0abc3a8..2b35c51a 100644 --- a/backend/src/plugins/ModActions/functions/actualCommands/actualMassBanCmd.ts +++ b/backend/src/plugins/ModActions/functions/actualCommands/actualMassBanCmd.ts @@ -1,55 +1,58 @@ -import { ChatInputCommandInteraction, GuildMember, Snowflake, TextBasedChannel } from "discord.js"; +import { ChatInputCommandInteraction, GuildMember, Message, Snowflake } from "discord.js"; import { GuildPluginData } from "knub"; import { waitForReply } from "knub/helpers"; import { CaseTypes } from "../../../../data/CaseTypes"; import { LogType } from "../../../../data/LogType"; import { humanizeDurationShort } from "../../../../humanizeDurationShort"; -import { - canActOn, - isContextInteraction, - sendContextResponse, - sendErrorMessage, - sendSuccessMessage, -} from "../../../../pluginUtils"; +import { canActOn, getContextChannel, isContextInteraction, sendContextResponse } from "../../../../pluginUtils"; import { DAYS, MINUTES, SECONDS, noop } from "../../../../utils"; import { CasesPlugin } from "../../../Cases/CasesPlugin"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { LogsPlugin } from "../../../Logs/LogsPlugin"; import { IgnoredEventType, ModActionsPluginType } from "../../types"; -import { formatReasonWithAttachments } from "../formatReasonWithAttachments"; +import { handleAttachmentLinkDetectionAndGetRestriction } from "../attachmentLinkReaction"; +import { formatReasonWithAttachments, formatReasonWithMessageLinkForAttachments } from "../formatReasonForAttachments"; import { ignoreEvent } from "../ignoreEvent"; export async function actualMassBanCmd( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, userIds: string[], author: GuildMember, ) { // Limit to 100 users at once (arbitrary?) if (userIds.length > 100) { - sendErrorMessage(pluginData, context, `Can only massban max 100 users at once`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, `Can only massban max 100 users at once`); return; } // Ask for ban reason (cleaner this way instead of trying to cram it into the args) sendContextResponse(context, "Ban reason? `cancel` to cancel"); - const banReasonReply = await waitForReply( - pluginData.client, - isContextInteraction(context) ? context.channel! : context, - author.id, - ); + const banReasonReply = await waitForReply(pluginData.client, await getContextChannel(context), author.id); if (!banReasonReply || !banReasonReply.content || banReasonReply.content.toLowerCase().trim() === "cancel") { - sendErrorMessage(pluginData, context, "Cancelled"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "Cancelled"); return; } - const banReason = formatReasonWithAttachments(banReasonReply.content, [...banReasonReply.attachments.values()]); + if (await handleAttachmentLinkDetectionAndGetRestriction(pluginData, context, banReasonReply.content)) { + return; + } + + const banReason = await formatReasonWithMessageLinkForAttachments(pluginData, banReasonReply.content, context, [ + ...banReasonReply.attachments.values(), + ]); + const banReasonWithAttachments = formatReasonWithAttachments(banReasonReply.content, [ + ...banReasonReply.attachments.values(), + ]); // 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? if (member && !canActOn(pluginData, author, member)) { - sendErrorMessage(pluginData, context, "Cannot massban one or more users: insufficient permissions"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(context, "Cannot massban one or more users: insufficient permissions"); return; } } @@ -87,7 +90,7 @@ export async function actualMassBanCmd( const casesPlugin = pluginData.getPlugin(CasesPlugin); const messageConfig = isContextInteraction(context) ? await pluginData.config.getForInteraction(context) - : await pluginData.config.getForChannel(context); + : await pluginData.config.getForChannel(await getContextChannel(context)); const deleteDays = messageConfig.ban_delete_message_days; for (const [i, userId] of userIds.entries()) { @@ -103,7 +106,7 @@ export async function actualMassBanCmd( await pluginData.guild.bans.create(userId as Snowflake, { deleteMessageSeconds: (deleteDays * DAYS) / SECONDS, - reason: banReason, + reason: banReasonWithAttachments, }); await casesPlugin.createCase({ @@ -134,7 +137,7 @@ export async function actualMassBanCmd( const successfulBanCount = userIds.length - failedBans.length; if (successfulBanCount === 0) { // All bans failed - don't create a log entry and notify the user - sendErrorMessage(pluginData, context, "All bans failed. Make sure the IDs are valid."); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "All bans failed. Make sure the IDs are valid."); } else { // Some or all bans were successful. Create a log entry for the mass ban and notify the user. pluginData.getPlugin(LogsPlugin).logMassBan({ @@ -144,19 +147,18 @@ export async function actualMassBanCmd( }); if (failedBans.length) { - sendSuccessMessage( - pluginData, - context, - `Banned ${successfulBanCount} users in ${formattedTimeTaken}, ${failedBans.length} failed: ${failedBans.join( - " ", - )}`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage( + context, + `Banned ${successfulBanCount} users in ${formattedTimeTaken}, ${ + failedBans.length + } failed: ${failedBans.join(" ")}`, + ); } else { - sendSuccessMessage( - pluginData, - context, - `Banned ${successfulBanCount} users successfully in ${formattedTimeTaken}`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(context, `Banned ${successfulBanCount} users successfully in ${formattedTimeTaken}`); } } }); diff --git a/backend/src/plugins/ModActions/functions/actualCommands/actualMassMuteCmd.ts b/backend/src/plugins/ModActions/functions/actualCommands/actualMassMuteCmd.ts index 8dd735ab..2d8086cb 100644 --- a/backend/src/plugins/ModActions/functions/actualCommands/actualMassMuteCmd.ts +++ b/backend/src/plugins/ModActions/functions/actualCommands/actualMassMuteCmd.ts @@ -1,49 +1,48 @@ -import { ChatInputCommandInteraction, GuildMember, Snowflake, TextBasedChannel } from "discord.js"; +import { ChatInputCommandInteraction, GuildMember, Message, Snowflake } from "discord.js"; import { GuildPluginData } from "knub"; import { waitForReply } from "knub/helpers"; import { LogType } from "../../../../data/LogType"; import { logger } from "../../../../logger"; -import { - canActOn, - isContextInteraction, - sendContextResponse, - sendErrorMessage, - sendSuccessMessage, -} from "../../../../pluginUtils"; +import { canActOn, getContextChannel, sendContextResponse } from "../../../../pluginUtils"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { LogsPlugin } from "../../../Logs/LogsPlugin"; import { MutesPlugin } from "../../../Mutes/MutesPlugin"; import { ModActionsPluginType } from "../../types"; -import { formatReasonWithAttachments } from "../formatReasonWithAttachments"; +import { handleAttachmentLinkDetectionAndGetRestriction } from "../attachmentLinkReaction"; +import { formatReasonWithAttachments, formatReasonWithMessageLinkForAttachments } from "../formatReasonForAttachments"; export async function actualMassMuteCmd( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, userIds: string[], author: GuildMember, ) { // Limit to 100 users at once (arbitrary?) if (userIds.length > 100) { - sendErrorMessage(pluginData, context, `Can only massmute max 100 users at once`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, `Can only massmute max 100 users at once`); return; } // Ask for mute reason sendContextResponse(context, "Mute reason? `cancel` to cancel"); - const muteReasonReceived = await waitForReply( - pluginData.client, - isContextInteraction(context) ? context.channel! : context, - author.id, - ); + const muteReasonReceived = await waitForReply(pluginData.client, await getContextChannel(context), author.id); if ( !muteReasonReceived || !muteReasonReceived.content || muteReasonReceived.content.toLowerCase().trim() === "cancel" ) { - sendErrorMessage(pluginData, context, "Cancelled"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "Cancelled"); return; } - const muteReason = formatReasonWithAttachments(muteReasonReceived.content, [ + if (await handleAttachmentLinkDetectionAndGetRestriction(pluginData, context, muteReasonReceived.content)) { + return; + } + + const muteReason = await formatReasonWithMessageLinkForAttachments(pluginData, muteReasonReceived.content, context, [ + ...muteReasonReceived.attachments.values(), + ]); + const muteReasonWithAttachments = formatReasonWithAttachments(muteReasonReceived.content, [ ...muteReasonReceived.attachments.values(), ]); @@ -51,7 +50,9 @@ export async function actualMassMuteCmd( for (const userId of userIds) { const member = pluginData.guild.members.cache.get(userId as Snowflake); if (member && !canActOn(pluginData, author, member)) { - sendErrorMessage(pluginData, context, "Cannot massmute one or more users: insufficient permissions"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(context, "Cannot massmute one or more users: insufficient permissions"); return; } } @@ -72,7 +73,7 @@ export async function actualMassMuteCmd( const mutesPlugin = pluginData.getPlugin(MutesPlugin); for (const userId of userIds) { try { - await mutesPlugin.muteUser(userId, 0, `Mass mute: ${muteReason}`, { + await mutesPlugin.muteUser(userId, 0, `Mass mute: ${muteReason}`, `Mass mute: ${muteReasonWithAttachments}`, { caseArgs: { modId, }, @@ -89,7 +90,7 @@ export async function actualMassMuteCmd( const successfulMuteCount = userIds.length - failedMutes.length; if (successfulMuteCount === 0) { // All mutes failed - sendErrorMessage(pluginData, context, "All mutes failed. Make sure the IDs are valid."); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "All mutes failed. Make sure the IDs are valid."); } else { // Success on all or some mutes pluginData.getPlugin(LogsPlugin).logMassMute({ @@ -98,13 +99,14 @@ export async function actualMassMuteCmd( }); if (failedMutes.length) { - sendSuccessMessage( - pluginData, - context, - `Muted ${successfulMuteCount} users, ${failedMutes.length} failed: ${failedMutes.join(" ")}`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage( + context, + `Muted ${successfulMuteCount} users, ${failedMutes.length} failed: ${failedMutes.join(" ")}`, + ); } else { - sendSuccessMessage(pluginData, context, `Muted ${successfulMuteCount} users successfully`); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(context, `Muted ${successfulMuteCount} users successfully`); } } } diff --git a/backend/src/plugins/ModActions/functions/actualCommands/actualMassUnbanCmd.ts b/backend/src/plugins/ModActions/functions/actualCommands/actualMassUnbanCmd.ts index cf829fd7..bfb57111 100644 --- a/backend/src/plugins/ModActions/functions/actualCommands/actualMassUnbanCmd.ts +++ b/backend/src/plugins/ModActions/functions/actualCommands/actualMassUnbanCmd.ts @@ -1,46 +1,45 @@ -import { ChatInputCommandInteraction, GuildMember, Snowflake, TextBasedChannel } from "discord.js"; +import { ChatInputCommandInteraction, GuildMember, Message, Snowflake } from "discord.js"; import { GuildPluginData } from "knub"; import { waitForReply } from "knub/helpers"; import { CaseTypes } from "../../../../data/CaseTypes"; import { LogType } from "../../../../data/LogType"; -import { - isContextInteraction, - sendContextResponse, - sendErrorMessage, - sendSuccessMessage, -} from "../../../../pluginUtils"; +import { getContextChannel, sendContextResponse } from "../../../../pluginUtils"; import { CasesPlugin } from "../../../Cases/CasesPlugin"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { LogsPlugin } from "../../../Logs/LogsPlugin"; import { IgnoredEventType, ModActionsPluginType } from "../../types"; -import { formatReasonWithAttachments } from "../formatReasonWithAttachments"; +import { handleAttachmentLinkDetectionAndGetRestriction } from "../attachmentLinkReaction"; +import { formatReasonWithMessageLinkForAttachments } from "../formatReasonForAttachments"; import { ignoreEvent } from "../ignoreEvent"; import { isBanned } from "../isBanned"; export async function actualMassUnbanCmd( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, userIds: string[], author: GuildMember, ) { // Limit to 100 users at once (arbitrary?) if (userIds.length > 100) { - sendErrorMessage(pluginData, context, `Can only mass-unban max 100 users at once`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, `Can only mass-unban max 100 users at once`); return; } // Ask for unban reason (cleaner this way instead of trying to cram it into the args) sendContextResponse(context, "Unban reason? `cancel` to cancel"); - const unbanReasonReply = await waitForReply( - pluginData.client, - isContextInteraction(context) ? context.channel! : context, - author.id, - ); + const unbanReasonReply = await waitForReply(pluginData.client, await getContextChannel(context), author.id); if (!unbanReasonReply || !unbanReasonReply.content || unbanReasonReply.content.toLowerCase().trim() === "cancel") { - sendErrorMessage(pluginData, context, "Cancelled"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "Cancelled"); return; } - const unbanReason = formatReasonWithAttachments(unbanReasonReply.content, [...unbanReasonReply.attachments.values()]); + if (await handleAttachmentLinkDetectionAndGetRestriction(pluginData, context, unbanReasonReply.content)) { + return; + } + + const unbanReason = await formatReasonWithMessageLinkForAttachments(pluginData, unbanReasonReply.content, context, [ + ...unbanReasonReply.attachments.values(), + ]); // Ignore automatic unban cases and logs for these users // We'll create our own cases below and post a single "mass unbanned" log instead @@ -83,7 +82,9 @@ export async function actualMassUnbanCmd( const successfulUnbanCount = userIds.length - failedUnbans.length; if (successfulUnbanCount === 0) { // All unbans failed - don't create a log entry and notify the user - sendErrorMessage(pluginData, context, "All unbans failed. Make sure the IDs are valid and banned."); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(context, "All unbans failed. Make sure the IDs are valid and banned."); } else { // Some or all unbans were successful. Create a log entry for the mass unban and notify the user. pluginData.getPlugin(LogsPlugin).logMassUnban({ @@ -110,13 +111,16 @@ export async function actualMassUnbanCmd( }); } - sendSuccessMessage( - pluginData, - context, - `Unbanned ${successfulUnbanCount} users, ${failedUnbans.length} failed:\n${failedMsg}`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage( + context, + `Unbanned ${successfulUnbanCount} users, ${failedUnbans.length} failed:\n${failedMsg}`, + ); } else { - sendSuccessMessage(pluginData, context, `Unbanned ${successfulUnbanCount} users successfully`); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(context, `Unbanned ${successfulUnbanCount} users successfully`); } } } diff --git a/backend/src/plugins/ModActions/functions/actualCommands/actualMuteCmd.ts b/backend/src/plugins/ModActions/functions/actualCommands/actualMuteCmd.ts index 487cf453..7a136a32 100644 --- a/backend/src/plugins/ModActions/functions/actualCommands/actualMuteCmd.ts +++ b/backend/src/plugins/ModActions/functions/actualCommands/actualMuteCmd.ts @@ -1,9 +1,8 @@ -import { Attachment, ChatInputCommandInteraction, GuildMember, TextBasedChannel, User } from "discord.js"; +import { Attachment, ChatInputCommandInteraction, GuildMember, Message, User } from "discord.js"; import humanizeDuration from "humanize-duration"; import { GuildPluginData } from "knub"; import { ERRORS, RecoverablePluginError } from "../../../../RecoverablePluginError"; import { logger } from "../../../../logger"; -import { sendErrorMessage, sendSuccessMessage } from "../../../../pluginUtils"; import { UnknownUser, UserNotificationMethod, @@ -11,10 +10,12 @@ import { isDiscordAPIError, renderUserUsername, } from "../../../../utils"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { MutesPlugin } from "../../../Mutes/MutesPlugin"; import { MuteResult } from "../../../Mutes/types"; import { ModActionsPluginType } from "../../types"; -import { formatReasonWithAttachments } from "../formatReasonWithAttachments"; +import { handleAttachmentLinkDetectionAndGetRestriction } from "../attachmentLinkReaction"; +import { formatReasonWithAttachments, formatReasonWithMessageLinkForAttachments } from "../formatReasonForAttachments"; /** * The actual function run by both !mute and !forcemute. @@ -22,23 +23,32 @@ import { formatReasonWithAttachments } from "../formatReasonWithAttachments"; */ export async function actualMuteCmd( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, user: User | UnknownUser, - attachments: Array, + attachments: Attachment[], mod: GuildMember, ppId?: string, time?: number, reason?: string, contactMethods?: UserNotificationMethod[], ) { + if (await handleAttachmentLinkDetectionAndGetRestriction(pluginData, context, reason)) { + return; + } + const timeUntilUnmute = time && humanizeDuration(time); - const formattedReason = reason ? formatReasonWithAttachments(reason, attachments) : undefined; + const formattedReason = + reason || attachments.length > 0 + ? await formatReasonWithMessageLinkForAttachments(pluginData, reason ?? "", context, attachments) + : undefined; + const formattedReasonWithAttachments = + reason || attachments.length > 0 ? formatReasonWithAttachments(reason ?? "", attachments) : undefined; let muteResult: MuteResult; const mutesPlugin = pluginData.getPlugin(MutesPlugin); try { - muteResult = await mutesPlugin.muteUser(user.id, time, formattedReason, { + muteResult = await mutesPlugin.muteUser(user.id, time, formattedReason, formattedReasonWithAttachments, { contactMethods, caseArgs: { modId: mod.id, @@ -47,9 +57,11 @@ export async function actualMuteCmd( }); } catch (e) { if (e instanceof RecoverablePluginError && e.code === ERRORS.NO_MUTE_ROLE_IN_CONFIG) { - sendErrorMessage(pluginData, context, "Could not mute the user: no mute role set in config"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(context, "Could not mute the user: no mute role set in config"); } else if (isDiscordAPIError(e) && e.code === 10007) { - sendErrorMessage(pluginData, context, "Could not mute the user: unknown member"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "Could not mute the user: unknown member"); } else { logger.error(`Failed to mute user ${user.id}: ${e.stack}`); if (user.id == null) { @@ -57,7 +69,7 @@ export async function actualMuteCmd( // tslint:disable-next-line:no-console console.trace("[DEBUG] Null user.id for mute"); } - sendErrorMessage(pluginData, context, "Could not mute the user"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "Could not mute the user"); } return; @@ -92,5 +104,5 @@ export async function actualMuteCmd( } if (muteResult.notifyResult.text) response += ` (${muteResult.notifyResult.text})`; - sendSuccessMessage(pluginData, context, response); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(context, response); } diff --git a/backend/src/plugins/ModActions/functions/actualCommands/actualNoteCmd.ts b/backend/src/plugins/ModActions/functions/actualCommands/actualNoteCmd.ts index 2a29e2df..7b2e4831 100644 --- a/backend/src/plugins/ModActions/functions/actualCommands/actualNoteCmd.ts +++ b/backend/src/plugins/ModActions/functions/actualCommands/actualNoteCmd.ts @@ -1,23 +1,28 @@ -import { Attachment, ChatInputCommandInteraction, TextBasedChannel, User } from "discord.js"; +import { Attachment, ChatInputCommandInteraction, Message, User } from "discord.js"; import { GuildPluginData } from "knub"; import { CaseTypes } from "../../../../data/CaseTypes"; -import { sendSuccessMessage } from "../../../../pluginUtils"; import { UnknownUser, renderUserUsername } from "../../../../utils"; import { CasesPlugin } from "../../../Cases/CasesPlugin"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { LogsPlugin } from "../../../Logs/LogsPlugin"; import { ModActionsPluginType } from "../../types"; -import { formatReasonWithAttachments } from "../formatReasonWithAttachments"; +import { handleAttachmentLinkDetectionAndGetRestriction } from "../attachmentLinkReaction"; +import { formatReasonWithMessageLinkForAttachments } from "../formatReasonForAttachments"; export async function actualNoteCmd( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, author: User, attachments: Array, user: User | UnknownUser, note: string, ) { + if (await handleAttachmentLinkDetectionAndGetRestriction(pluginData, context, note)) { + return; + } + const userName = renderUserUsername(user); - const reason = formatReasonWithAttachments(note, attachments); + const reason = await formatReasonWithMessageLinkForAttachments(pluginData, note, context, attachments); const casesPlugin = pluginData.getPlugin(CasesPlugin); const createdCase = await casesPlugin.createCase({ @@ -34,14 +39,15 @@ export async function actualNoteCmd( reason, }); - sendSuccessMessage( - pluginData, - context, - `Note added on **${userName}** (Case #${createdCase.case_number})`, - undefined, - undefined, - true, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage( + context, + `Note added on **${userName}** (Case #${createdCase.case_number})`, + undefined, + undefined, + true, + ); pluginData.state.events.emit("note", user.id, reason); } diff --git a/backend/src/plugins/ModActions/functions/actualCommands/actualUnbanCmd.ts b/backend/src/plugins/ModActions/functions/actualCommands/actualUnbanCmd.ts index 94df7d4f..85f9abba 100644 --- a/backend/src/plugins/ModActions/functions/actualCommands/actualUnbanCmd.ts +++ b/backend/src/plugins/ModActions/functions/actualCommands/actualUnbanCmd.ts @@ -1,33 +1,40 @@ -import { Attachment, ChatInputCommandInteraction, GuildMember, Snowflake, TextBasedChannel, User } from "discord.js"; +import { Attachment, ChatInputCommandInteraction, GuildMember, Message, Snowflake, User } from "discord.js"; import { GuildPluginData } from "knub"; import { CaseTypes } from "../../../../data/CaseTypes"; import { LogType } from "../../../../data/LogType"; import { clearExpiringTempban } from "../../../../data/loops/expiringTempbansLoop"; -import { sendErrorMessage, sendSuccessMessage } from "../../../../pluginUtils"; import { UnknownUser } from "../../../../utils"; import { CasesPlugin } from "../../../Cases/CasesPlugin"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { LogsPlugin } from "../../../Logs/LogsPlugin"; import { IgnoredEventType, ModActionsPluginType } from "../../types"; -import { formatReasonWithAttachments } from "../formatReasonWithAttachments"; +import { handleAttachmentLinkDetectionAndGetRestriction } from "../attachmentLinkReaction"; +import { formatReasonWithMessageLinkForAttachments } from "../formatReasonForAttachments"; import { ignoreEvent } from "../ignoreEvent"; export async function actualUnbanCmd( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, authorId: string, user: User | UnknownUser, reason: string, attachments: Array, mod: GuildMember, ) { + if (await handleAttachmentLinkDetectionAndGetRestriction(pluginData, context, reason)) { + return; + } + pluginData.state.serverLogs.ignoreLog(LogType.MEMBER_UNBAN, user.id); - const formattedReason = formatReasonWithAttachments(reason, attachments); + const formattedReason = await formatReasonWithMessageLinkForAttachments(pluginData, reason, context, attachments); try { ignoreEvent(pluginData, IgnoredEventType.Unban, user.id); await pluginData.guild.bans.remove(user.id as Snowflake, formattedReason ?? undefined); } catch { - sendErrorMessage(pluginData, context, "Failed to unban member; are you sure they're banned?"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(context, "Failed to unban member; are you sure they're banned?"); return; } @@ -49,7 +56,7 @@ export async function actualUnbanCmd( } // Confirm the action - sendSuccessMessage(pluginData, context, `Member unbanned (Case #${createdCase.case_number})`); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(context, `Member unbanned (Case #${createdCase.case_number})`); // Log the action pluginData.getPlugin(LogsPlugin).logMemberUnban({ diff --git a/backend/src/plugins/ModActions/functions/actualCommands/actualUnhideCaseCmd.ts b/backend/src/plugins/ModActions/functions/actualCommands/actualUnhideCaseCmd.ts index 3ec2cd9e..313261ee 100644 --- a/backend/src/plugins/ModActions/functions/actualCommands/actualUnhideCaseCmd.ts +++ b/backend/src/plugins/ModActions/functions/actualCommands/actualUnhideCaseCmd.ts @@ -1,11 +1,11 @@ -import { ChatInputCommandInteraction, TextBasedChannel } from "discord.js"; +import { ChatInputCommandInteraction, Message } from "discord.js"; import { GuildPluginData } from "knub"; -import { sendErrorMessage, sendSuccessMessage } from "../../../../pluginUtils"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { ModActionsPluginType } from "../../types"; export async function actualUnhideCaseCmd( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, caseNumbers: number[], ) { const failed: number[] = []; @@ -21,7 +21,7 @@ export async function actualUnhideCaseCmd( } if (failed.length === caseNumbers.length) { - sendErrorMessage(pluginData, context, "None of the cases were found!"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "None of the cases were found!"); return; } @@ -31,9 +31,7 @@ export async function actualUnhideCaseCmd( : ""; const amt = caseNumbers.length - failed.length; - sendSuccessMessage( - pluginData, - context, - `${amt} case${amt === 1 ? " is" : "s are"} no longer hidden!${failedAddendum}`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(context, `${amt} case${amt === 1 ? " is" : "s are"} no longer hidden!${failedAddendum}`); } diff --git a/backend/src/plugins/ModActions/functions/actualCommands/actualUnmuteCmd.ts b/backend/src/plugins/ModActions/functions/actualCommands/actualUnmuteCmd.ts index 96804c38..0f945a0f 100644 --- a/backend/src/plugins/ModActions/functions/actualCommands/actualUnmuteCmd.ts +++ b/backend/src/plugins/ModActions/functions/actualCommands/actualUnmuteCmd.ts @@ -1,15 +1,16 @@ -import { Attachment, ChatInputCommandInteraction, GuildMember, TextBasedChannel, User } from "discord.js"; +import { Attachment, ChatInputCommandInteraction, GuildMember, Message, User } from "discord.js"; import humanizeDuration from "humanize-duration"; import { GuildPluginData } from "knub"; -import { sendErrorMessage, sendSuccessMessage } from "../../../../pluginUtils"; import { UnknownUser, asSingleLine, renderUserUsername } from "../../../../utils"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { MutesPlugin } from "../../../Mutes/MutesPlugin"; import { ModActionsPluginType } from "../../types"; -import { formatReasonWithAttachments } from "../formatReasonWithAttachments"; +import { handleAttachmentLinkDetectionAndGetRestriction } from "../attachmentLinkReaction"; +import { formatReasonWithMessageLinkForAttachments } from "../formatReasonForAttachments"; export async function actualUnmuteCmd( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, user: User | UnknownUser, attachments: Array, mod: GuildMember, @@ -17,25 +18,31 @@ export async function actualUnmuteCmd( time?: number, reason?: string, ) { - const parsedReason = reason ? formatReasonWithAttachments(reason, attachments) : undefined; + if (await handleAttachmentLinkDetectionAndGetRestriction(pluginData, context, reason)) { + return; + } + + const formattedReason = + reason || attachments.length > 0 + ? await formatReasonWithMessageLinkForAttachments(pluginData, reason ?? "", context, attachments) + : undefined; const mutesPlugin = pluginData.getPlugin(MutesPlugin); const result = await mutesPlugin.unmuteUser(user.id, time, { modId: mod.id, ppId: ppId ?? undefined, - reason: parsedReason, + reason: formattedReason, }); if (!result) { - sendErrorMessage(pluginData, context, "User is not muted!"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "User is not muted!"); return; } // Confirm the action to the moderator if (time) { const timeUntilUnmute = time && humanizeDuration(time); - sendSuccessMessage( - pluginData, + pluginData.getPlugin(CommonPlugin).sendSuccessMessage( context, asSingleLine(` Unmuting **${renderUserUsername(user)}** @@ -43,8 +50,7 @@ export async function actualUnmuteCmd( `), ); } else { - sendSuccessMessage( - pluginData, + pluginData.getPlugin(CommonPlugin).sendSuccessMessage( context, asSingleLine(` Unmuted **${renderUserUsername(user)}** diff --git a/backend/src/plugins/ModActions/functions/actualCommands/actualWarnCmd.ts b/backend/src/plugins/ModActions/functions/actualCommands/actualWarnCmd.ts index 5748f72e..0349b6da 100644 --- a/backend/src/plugins/ModActions/functions/actualCommands/actualWarnCmd.ts +++ b/backend/src/plugins/ModActions/functions/actualCommands/actualWarnCmd.ts @@ -1,17 +1,18 @@ -import { Attachment, ChatInputCommandInteraction, GuildMember, TextBasedChannel } from "discord.js"; +import { Attachment, ChatInputCommandInteraction, GuildMember, Message } from "discord.js"; import { GuildPluginData } from "knub"; import { CaseTypes } from "../../../../data/CaseTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../../pluginUtils"; import { UserNotificationMethod, renderUserUsername } from "../../../../utils"; import { waitForButtonConfirm } from "../../../../utils/waitForInteraction"; import { CasesPlugin } from "../../../Cases/CasesPlugin"; +import { CommonPlugin } from "../../../Common/CommonPlugin"; import { ModActionsPluginType } from "../../types"; -import { formatReasonWithAttachments } from "../formatReasonWithAttachments"; +import { handleAttachmentLinkDetectionAndGetRestriction } from "../attachmentLinkReaction"; +import { formatReasonWithAttachments, formatReasonWithMessageLinkForAttachments } from "../formatReasonForAttachments"; import { warnMember } from "../warnMember"; export async function actualWarnCmd( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, authorId: string, mod: GuildMember, memberToWarn: GuildMember, @@ -19,8 +20,13 @@ export async function actualWarnCmd( attachments: Attachment[], contactMethods?: UserNotificationMethod[], ) { + if (await handleAttachmentLinkDetectionAndGetRestriction(pluginData, context, reason)) { + return; + } + const config = pluginData.config.get(); - const formattedReason = formatReasonWithAttachments(reason, attachments); + const formattedReason = await formatReasonWithMessageLinkForAttachments(pluginData, reason, context, attachments); + const formattedReasonWithAttachments = formatReasonWithAttachments(reason, attachments); const casesPlugin = pluginData.getPlugin(CasesPlugin); const priorWarnAmount = await casesPlugin.getCaseTypeAmountForUserId(memberToWarn.id, CaseTypes.Warn); @@ -31,12 +37,12 @@ export async function actualWarnCmd( { confirmText: "Yes", cancelText: "No", restrictToId: authorId }, ); if (!reply) { - sendErrorMessage(pluginData, context, "Warn cancelled by moderator"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "Warn cancelled by moderator"); return; } } - const warnResult = await warnMember(pluginData, memberToWarn, formattedReason, { + const warnResult = await warnMember(pluginData, memberToWarn, formattedReason, formattedReasonWithAttachments, { contactMethods, caseArgs: { modId: mod.id, @@ -47,15 +53,16 @@ export async function actualWarnCmd( }); if (warnResult.status === "failed") { - sendErrorMessage(pluginData, context, "Failed to warn user"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "Failed to warn user"); return; } const messageResultText = warnResult.notifyResult.text ? ` (${warnResult.notifyResult.text})` : ""; - sendSuccessMessage( - pluginData, - context, - `Warned **${renderUserUsername(memberToWarn.user)}** (Case #${warnResult.case.case_number})${messageResultText}`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage( + context, + `Warned **${renderUserUsername(memberToWarn.user)}** (Case #${warnResult.case.case_number})${messageResultText}`, + ); } diff --git a/backend/src/plugins/ModActions/functions/attachmentLinkReaction.ts b/backend/src/plugins/ModActions/functions/attachmentLinkReaction.ts new file mode 100644 index 00000000..868786ed --- /dev/null +++ b/backend/src/plugins/ModActions/functions/attachmentLinkReaction.ts @@ -0,0 +1,51 @@ +import { ChatInputCommandInteraction, Message, TextBasedChannel } from "discord.js"; +import { AnyPluginData, GuildPluginData } from "knub"; +import { CommonPlugin } from "../../Common/CommonPlugin"; +import { ModActionsPluginType } from "../types"; + +export function shouldReactToAttachmentLink(pluginData: GuildPluginData) { + const config = pluginData.config.get(); + + return !config.attachment_link_reaction || config.attachment_link_reaction !== "none"; +} + +export function attachmentLinkShouldRestrict(pluginData: GuildPluginData) { + return pluginData.config.get().attachment_link_reaction === "restrict"; +} + +export function detectAttachmentLink(reason: string | null | undefined) { + return reason && /https:\/\/(cdn|media)\.discordapp\.(com|net)\/(ephemeral-)?attachments/gu.test(reason); +} + +export function sendAttachmentLinkDetectionErrorMessage( + pluginData: AnyPluginData, + context: TextBasedChannel | Message | ChatInputCommandInteraction, + restricted = false, +) { + const emoji = pluginData.getPlugin(CommonPlugin).getErrorEmoji(); + + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage( + context, + "You manually added a Discord attachment link to the reason. This link will only work for a limited time.\n" + + "You should instead **re-upload** the attachment with the command, in the same message.\n\n" + + (restricted ? `${emoji} **Command canceled.** ${emoji}` : "").trim(), + ); +} + +export async function handleAttachmentLinkDetectionAndGetRestriction( + pluginData: GuildPluginData, + context: TextBasedChannel | Message | ChatInputCommandInteraction, + reason: string | null | undefined, +) { + if (!shouldReactToAttachmentLink(pluginData) || !detectAttachmentLink(reason)) { + return false; + } + + const restricted = attachmentLinkShouldRestrict(pluginData); + + sendAttachmentLinkDetectionErrorMessage(pluginData, context, restricted); + + return restricted; +} diff --git a/backend/src/plugins/ModActions/functions/banUserId.ts b/backend/src/plugins/ModActions/functions/banUserId.ts index d9d1454b..55cc0049 100644 --- a/backend/src/plugins/ModActions/functions/banUserId.ts +++ b/backend/src/plugins/ModActions/functions/banUserId.ts @@ -30,6 +30,7 @@ export async function banUserId( pluginData: GuildPluginData, userId: string, reason?: string, + reasonWithAttachments?: string, banOptions: BanOptions = {}, banTime?: number, ): Promise { @@ -45,7 +46,7 @@ export async function banUserId( // Attempt to message the user *before* banning them, as doing it after may not be possible const member = await resolveMember(pluginData.client, pluginData.guild, userId); let notifyResult: UserNotificationResult = { method: null, success: true }; - if (reason && member) { + if (reasonWithAttachments && member) { const contactMethods = banOptions?.contactMethods ? banOptions.contactMethods : getDefaultContactMethods(pluginData, "ban"); @@ -56,7 +57,7 @@ export async function banUserId( config.ban_message, new TemplateSafeValueContainer({ guildName: pluginData.guild.name, - reason, + reason: reasonWithAttachments, moderator: banOptions.caseArgs?.modId ? userToTemplateSafeUser(await resolveUser(pluginData.client, banOptions.caseArgs.modId)) : null, @@ -69,7 +70,7 @@ export async function banUserId( config.tempban_message, new TemplateSafeValueContainer({ guildName: pluginData.guild.name, - reason, + reason: reasonWithAttachments, moderator: banOptions.caseArgs?.modId ? userToTemplateSafeUser(await resolveUser(pluginData.client, banOptions.caseArgs.modId)) : null, diff --git a/backend/src/plugins/ModActions/functions/clearTempban.ts b/backend/src/plugins/ModActions/functions/clearTempban.ts index 25807df8..1b196db0 100644 --- a/backend/src/plugins/ModActions/functions/clearTempban.ts +++ b/backend/src/plugins/ModActions/functions/clearTempban.ts @@ -10,7 +10,6 @@ import { resolveUser } from "../../../utils"; import { CasesPlugin } from "../../Cases/CasesPlugin"; import { LogsPlugin } from "../../Logs/LogsPlugin"; import { IgnoredEventType, ModActionsPluginType } from "../types"; -import { formatReasonWithAttachments } from "./formatReasonWithAttachments"; import { ignoreEvent } from "./ignoreEvent"; import { isBanned } from "./isBanned"; @@ -21,11 +20,9 @@ export async function clearTempban(pluginData: GuildPluginData, + reason: string, + context: Message | ChatInputCommandInteraction, + attachments: Attachment[], +) { + if (isContextMessage(context)) { + return context.attachments.size > 0 ? ((reason || "") + " " + context.url).trim() : reason; + } + + if (attachments.length < 1) { + return reason; + } + + const attachmentChannelId = pluginData.config.get().attachment_storing_channel; + const channel = attachmentChannelId + ? (pluginData.guild.channels.cache.get(attachmentChannelId) as TextBasedChannel) ?? context.channel + : context.channel; + + const message = await channel!.send({ + content: `Storing ${attachments.length} attachment${attachments.length === 1 ? "" : "s"}`, + files: attachments.map((a) => a.url), + }); + + return ((reason || "") + " " + message.url).trim(); +} + +export function formatReasonWithAttachments(reason: string, attachments: Attachment[]) { + const attachmentUrls = attachments.map((a) => a.url); + return ((reason || "") + " " + attachmentUrls.join(" ")).trim(); +} diff --git a/backend/src/plugins/ModActions/functions/formatReasonWithAttachments.ts b/backend/src/plugins/ModActions/functions/formatReasonWithAttachments.ts deleted file mode 100644 index 3fd92ee8..00000000 --- a/backend/src/plugins/ModActions/functions/formatReasonWithAttachments.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Attachment } from "discord.js"; - -export function formatReasonWithAttachments(reason: string, attachments: Attachment[]) { - const attachmentUrls = attachments.map((a) => a.url); - return ((reason || "") + " " + attachmentUrls.join(" ")).trim(); -} diff --git a/backend/src/plugins/ModActions/functions/kickMember.ts b/backend/src/plugins/ModActions/functions/kickMember.ts index d54dfd15..22c6eb63 100644 --- a/backend/src/plugins/ModActions/functions/kickMember.ts +++ b/backend/src/plugins/ModActions/functions/kickMember.ts @@ -18,13 +18,14 @@ export async function kickMember( pluginData: GuildPluginData, member: GuildMember, reason?: string, + reasonWithAttachments?: string, kickOptions: KickOptions = {}, ): Promise { const config = pluginData.config.get(); // Attempt to message the user *before* kicking them, as doing it after may not be possible let notifyResult: UserNotificationResult = { method: null, success: true }; - if (reason && member) { + if (reasonWithAttachments && member) { const contactMethods = kickOptions?.contactMethods ? kickOptions.contactMethods : getDefaultContactMethods(pluginData, "kick"); @@ -35,7 +36,7 @@ export async function kickMember( config.kick_message, new TemplateSafeValueContainer({ guildName: pluginData.guild.name, - reason, + reason: reasonWithAttachments, moderator: kickOptions.caseArgs?.modId ? userToTemplateSafeUser(await resolveUser(pluginData.client, kickOptions.caseArgs.modId)) : null, diff --git a/backend/src/plugins/ModActions/functions/updateCase.ts b/backend/src/plugins/ModActions/functions/updateCase.ts index d715e263..78b5d6f4 100644 --- a/backend/src/plugins/ModActions/functions/updateCase.ts +++ b/backend/src/plugins/ModActions/functions/updateCase.ts @@ -1,19 +1,19 @@ -import { Attachment, ChatInputCommandInteraction, TextBasedChannel, User } from "discord.js"; +import { Attachment, ChatInputCommandInteraction, Message, User } from "discord.js"; import { GuildPluginData } from "knub"; import { CaseTypes } from "../../../data/CaseTypes"; import { Case } from "../../../data/entities/Case"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { CasesPlugin } from "../../Cases/CasesPlugin"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { LogsPlugin } from "../../Logs/LogsPlugin"; import { ModActionsPluginType } from "../types"; -import { formatReasonWithAttachments } from "./formatReasonWithAttachments"; +import { formatReasonWithMessageLinkForAttachments } from "./formatReasonForAttachments"; export async function updateCase( pluginData: GuildPluginData, - context: TextBasedChannel | ChatInputCommandInteraction, + context: Message | ChatInputCommandInteraction, author: User, caseNumber?: number, - note?: string, + note = "", attachments: Attachment[] = [], ) { let theCase: Case | null; @@ -24,16 +24,16 @@ export async function updateCase( } if (!theCase) { - sendErrorMessage(pluginData, context, "Case not found"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "Case not found"); return; } - if (!note && attachments.length === 0) { - sendErrorMessage(pluginData, context, "Text or attachment required"); + if (note.length === 0 && attachments.length === 0) { + pluginData.getPlugin(CommonPlugin).sendErrorMessage(context, "Text or attachment required"); return; } - const formattedNote = formatReasonWithAttachments(note ?? "", attachments); + const formattedNote = await formatReasonWithMessageLinkForAttachments(pluginData, note, context, attachments); const casesPlugin = pluginData.getPlugin(CasesPlugin); await casesPlugin.createCaseNote({ @@ -49,5 +49,5 @@ export async function updateCase( note: formattedNote, }); - sendSuccessMessage(pluginData, context, `Case \`#${theCase.case_number}\` updated`); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(context, `Case \`#${theCase.case_number}\` updated`); } diff --git a/backend/src/plugins/ModActions/functions/warnMember.ts b/backend/src/plugins/ModActions/functions/warnMember.ts index 8f58f915..004caf7f 100644 --- a/backend/src/plugins/ModActions/functions/warnMember.ts +++ b/backend/src/plugins/ModActions/functions/warnMember.ts @@ -1,7 +1,7 @@ import { GuildMember, Snowflake } from "discord.js"; import { GuildPluginData } from "knub"; import { CaseTypes } from "../../../data/CaseTypes"; -import { isContextInteraction } from "../../../pluginUtils"; +import { getContextChannel, isContextInteraction } from "../../../pluginUtils"; import { TemplateSafeValueContainer, renderTemplate } from "../../../templateFormatter"; import { UserNotificationResult, createUserNotificationError, notifyUser, resolveUser, ucfirst } from "../../../utils"; import { userToTemplateSafeUser } from "../../../utils/templateSafeObjects"; @@ -15,6 +15,7 @@ export async function warnMember( pluginData: GuildPluginData, member: GuildMember, reason: string, + reasonWithAttachments: string, warnOptions: WarnOptions = {}, ): Promise { const config = pluginData.config.get(); @@ -25,7 +26,7 @@ export async function warnMember( config.warn_message, new TemplateSafeValueContainer({ guildName: pluginData.guild.name, - reason, + reason: reasonWithAttachments, moderator: warnOptions.caseArgs?.modId ? userToTemplateSafeUser(await resolveUser(pluginData.client, warnOptions.caseArgs.modId)) : null, @@ -40,8 +41,10 @@ export async function warnMember( } if (!notifyResult.success) { - const contextIsChannel = warnOptions.retryPromptContext && !isContextInteraction(warnOptions.retryPromptContext); - const isValidChannel = contextIsChannel && pluginData.guild.channels.resolve(warnOptions.retryPromptContext!.id); + const contextIsNotInteraction = + warnOptions.retryPromptContext && !isContextInteraction(warnOptions.retryPromptContext); + const contextChannel = contextIsNotInteraction ? await getContextChannel(warnOptions.retryPromptContext!) : null; + const isValidChannel = contextIsNotInteraction && pluginData.guild.channels.resolve(contextChannel!.id); if (!warnOptions.retryPromptContext || !isValidChannel) { return { diff --git a/backend/src/plugins/ModActions/types.ts b/backend/src/plugins/ModActions/types.ts index 5a61c342..68a0acda 100644 --- a/backend/src/plugins/ModActions/types.ts +++ b/backend/src/plugins/ModActions/types.ts @@ -1,4 +1,4 @@ -import { ChatInputCommandInteraction, TextBasedChannel } from "discord.js"; +import { ChatInputCommandInteraction, Message } from "discord.js"; import { EventEmitter } from "events"; import * as t from "io-ts"; import { BasePluginType, guildPluginEventListener, guildPluginMessageCommand, guildPluginSlashGroup } from "knub"; @@ -11,6 +11,8 @@ import { Case } from "../../data/entities/Case"; import { UserNotificationMethod, UserNotificationResult, tNullable } from "../../utils"; import { CaseArgs } from "../Cases/types"; +export type AttachmentLinkReactionType = "none" | "warn" | "restrict" | null | undefined; + export const ConfigSchema = t.type({ dm_on_warn: t.boolean, dm_on_kick: t.boolean, @@ -29,6 +31,8 @@ export const ConfigSchema = t.type({ warn_notify_threshold: t.number, warn_notify_message: t.string, ban_delete_message_days: t.number, + attachment_link_reaction: tNullable(t.union([t.literal("none"), t.literal("warn"), t.literal("restrict")])), + attachment_storing_channel: tNullable(t.string), can_note: t.boolean, can_warn: t.boolean, can_mute: t.boolean, @@ -127,7 +131,7 @@ export type WarnMemberNotifyRetryCallback = () => boolean | Promise; export interface WarnOptions { caseArgs?: Partial | null; contactMethods?: UserNotificationMethod[] | null; - retryPromptContext?: TextBasedChannel | ChatInputCommandInteraction | null; + retryPromptContext?: Message | ChatInputCommandInteraction | null; isAutomodAction?: boolean; } diff --git a/backend/src/plugins/Mutes/commands/ClearBannedMutesCmd.ts b/backend/src/plugins/Mutes/commands/ClearBannedMutesCmd.ts index 29f9dc28..3884ae89 100644 --- a/backend/src/plugins/Mutes/commands/ClearBannedMutesCmd.ts +++ b/backend/src/plugins/Mutes/commands/ClearBannedMutesCmd.ts @@ -1,5 +1,5 @@ import { Snowflake } from "discord.js"; -import { sendSuccessMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { mutesCmd } from "../types"; export const ClearBannedMutesCmd = mutesCmd({ @@ -25,6 +25,6 @@ export const ClearBannedMutesCmd = mutesCmd({ } } - sendSuccessMessage(pluginData, msg.channel, `Cleared ${cleared} mutes from banned users!`); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, `Cleared ${cleared} mutes from banned users!`); }, }); diff --git a/backend/src/plugins/Mutes/commands/ClearMutesCmd.ts b/backend/src/plugins/Mutes/commands/ClearMutesCmd.ts index 3021a7a7..a71dc402 100644 --- a/backend/src/plugins/Mutes/commands/ClearMutesCmd.ts +++ b/backend/src/plugins/Mutes/commands/ClearMutesCmd.ts @@ -1,5 +1,5 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { mutesCmd } from "../types"; export const ClearMutesCmd = mutesCmd({ @@ -23,15 +23,18 @@ export const ClearMutesCmd = mutesCmd({ } if (failed.length !== args.userIds.length) { - sendSuccessMessage(pluginData, msg.channel, `**${args.userIds.length - failed.length} active mute(s) cleared**`); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(msg, `**${args.userIds.length - failed.length} active mute(s) cleared**`); } if (failed.length) { - sendErrorMessage( - pluginData, - msg.channel, - `**${failed.length}/${args.userIds.length} IDs failed**, they are not muted: ${failed.join(" ")}`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage( + msg, + `**${failed.length}/${args.userIds.length} IDs failed**, they are not muted: ${failed.join(" ")}`, + ); } }, }); diff --git a/backend/src/plugins/Mutes/commands/ClearMutesWithoutRoleCmd.ts b/backend/src/plugins/Mutes/commands/ClearMutesWithoutRoleCmd.ts index 0dbef291..1e52f6b3 100644 --- a/backend/src/plugins/Mutes/commands/ClearMutesWithoutRoleCmd.ts +++ b/backend/src/plugins/Mutes/commands/ClearMutesWithoutRoleCmd.ts @@ -1,6 +1,6 @@ import { Snowflake } from "discord.js"; -import { sendSuccessMessage } from "../../../pluginUtils"; import { resolveMember } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { mutesCmd } from "../types"; export const ClearMutesWithoutRoleCmd = mutesCmd({ @@ -26,6 +26,8 @@ export const ClearMutesWithoutRoleCmd = mutesCmd({ } } - sendSuccessMessage(pluginData, msg.channel, `Cleared ${cleared} mutes from members that don't have the mute role`); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(msg, `Cleared ${cleared} mutes from members that don't have the mute role`); }, }); diff --git a/backend/src/plugins/Mutes/functions/muteUser.ts b/backend/src/plugins/Mutes/functions/muteUser.ts index 575f96fb..2dd5a3d1 100644 --- a/backend/src/plugins/Mutes/functions/muteUser.ts +++ b/backend/src/plugins/Mutes/functions/muteUser.ts @@ -35,6 +35,7 @@ export async function muteUser( userId: string, muteTime?: number, reason?: string, + reasonWithAttachments?: string, muteOptions: MuteOptions = {}, removeRolesOnMuteOverride: boolean | string[] | null = null, restoreRolesOnMuteOverride: boolean | string[] | null = null, @@ -193,7 +194,7 @@ export async function muteUser( template, new TemplateSafeValueContainer({ guildName: pluginData.guild.name, - reason: reason || "None", + reason: reasonWithAttachments || "None", time: timeUntilUnmuteStr, moderator: muteOptions.caseArgs?.modId ? userToTemplateSafeUser(await resolveUser(pluginData.client, muteOptions.caseArgs.modId)) diff --git a/backend/src/plugins/NameHistory/commands/NamesCmd.ts b/backend/src/plugins/NameHistory/commands/NamesCmd.ts index 373f1671..d7ef50b0 100644 --- a/backend/src/plugins/NameHistory/commands/NamesCmd.ts +++ b/backend/src/plugins/NameHistory/commands/NamesCmd.ts @@ -4,8 +4,8 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; import { MAX_NICKNAME_ENTRIES_PER_USER } from "../../../data/GuildNicknameHistory"; import { MAX_USERNAME_ENTRIES_PER_USER } from "../../../data/UsernameHistory"; import { NICKNAME_RETENTION_PERIOD } from "../../../data/cleanup/nicknames"; -import { sendErrorMessage } from "../../../pluginUtils"; import { DAYS, renderUserUsername } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { nameHistoryCmd } from "../types"; export const NamesCmd = nameHistoryCmd({ @@ -21,7 +21,7 @@ export const NamesCmd = nameHistoryCmd({ const usernames = await pluginData.state.usernameHistory.getByUserId(args.userId); if (nicknames.length === 0 && usernames.length === 0) { - sendErrorMessage(pluginData, msg.channel, "No name history found"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "No name history found"); return; } diff --git a/backend/src/plugins/PingableRoles/commands/PingableRoleDisableCmd.ts b/backend/src/plugins/PingableRoles/commands/PingableRoleDisableCmd.ts index 41709ffc..00006cee 100644 --- a/backend/src/plugins/PingableRoles/commands/PingableRoleDisableCmd.ts +++ b/backend/src/plugins/PingableRoles/commands/PingableRoleDisableCmd.ts @@ -1,5 +1,5 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { pingableRolesCmd } from "../types"; export const PingableRoleDisableCmd = pingableRolesCmd({ @@ -14,17 +14,17 @@ export const PingableRoleDisableCmd = pingableRolesCmd({ async run({ message: msg, args, pluginData }) { const pingableRole = await pluginData.state.pingableRoles.getByChannelAndRoleId(args.channelId, args.role.id); if (!pingableRole) { - sendErrorMessage(pluginData, msg.channel, `**${args.role.name}** is not set as pingable in <#${args.channelId}>`); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `**${args.role.name}** is not set as pingable in <#${args.channelId}>`); return; } await pluginData.state.pingableRoles.delete(args.channelId, args.role.id); pluginData.state.cache.delete(args.channelId); - sendSuccessMessage( - pluginData, - msg.channel, - `**${args.role.name}** is no longer set as pingable in <#${args.channelId}>`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(msg, `**${args.role.name}** is no longer set as pingable in <#${args.channelId}>`); }, }); diff --git a/backend/src/plugins/PingableRoles/commands/PingableRoleEnableCmd.ts b/backend/src/plugins/PingableRoles/commands/PingableRoleEnableCmd.ts index 30077e09..7a93990f 100644 --- a/backend/src/plugins/PingableRoles/commands/PingableRoleEnableCmd.ts +++ b/backend/src/plugins/PingableRoles/commands/PingableRoleEnableCmd.ts @@ -1,5 +1,5 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { pingableRolesCmd } from "../types"; export const PingableRoleEnableCmd = pingableRolesCmd({ @@ -17,21 +17,17 @@ export const PingableRoleEnableCmd = pingableRolesCmd({ args.role.id, ); if (existingPingableRole) { - sendErrorMessage( - pluginData, - msg.channel, - `**${args.role.name}** is already set as pingable in <#${args.channelId}>`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `**${args.role.name}** is already set as pingable in <#${args.channelId}>`); return; } await pluginData.state.pingableRoles.add(args.channelId, args.role.id); pluginData.state.cache.delete(args.channelId); - sendSuccessMessage( - pluginData, - msg.channel, - `**${args.role.name}** has been set as pingable in <#${args.channelId}>`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(msg, `**${args.role.name}** has been set as pingable in <#${args.channelId}>`); }, }); diff --git a/backend/src/plugins/Post/commands/EditCmd.ts b/backend/src/plugins/Post/commands/EditCmd.ts index 47ae07d7..cd607aa6 100644 --- a/backend/src/plugins/Post/commands/EditCmd.ts +++ b/backend/src/plugins/Post/commands/EditCmd.ts @@ -1,5 +1,5 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { postCmd } from "../types"; import { formatContent } from "../util/formatContent"; @@ -15,18 +15,18 @@ export const EditCmd = postCmd({ async run({ message: msg, args, pluginData }) { const targetMessage = await args.message.channel.messages.fetch(args.message.messageId); if (!targetMessage) { - sendErrorMessage(pluginData, msg.channel, "Unknown message"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Unknown message"); return; } if (targetMessage.author.id !== pluginData.client.user!.id) { - sendErrorMessage(pluginData, msg.channel, "Message wasn't posted by me"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Message wasn't posted by me"); return; } targetMessage.channel.messages.edit(targetMessage.id, { content: formatContent(args.content), }); - sendSuccessMessage(pluginData, msg.channel, "Message edited"); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, "Message edited"); }, }); diff --git a/backend/src/plugins/Post/commands/EditEmbedCmd.ts b/backend/src/plugins/Post/commands/EditEmbedCmd.ts index 2ac364f1..7d42c040 100644 --- a/backend/src/plugins/Post/commands/EditEmbedCmd.ts +++ b/backend/src/plugins/Post/commands/EditEmbedCmd.ts @@ -1,9 +1,9 @@ import { APIEmbed } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { isValidEmbed, trimLines } from "../../../utils"; import { parseColor } from "../../../utils/parseColor"; import { rgbToInt } from "../../../utils/rgbToInt"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { postCmd } from "../types"; import { formatContent } from "../util/formatContent"; @@ -30,14 +30,14 @@ export const EditEmbedCmd = postCmd({ if (colorRgb) { color = rgbToInt(colorRgb); } else { - sendErrorMessage(pluginData, msg.channel, "Invalid color specified"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Invalid color specified"); return; } } const targetMessage = await args.message.channel.messages.fetch(args.message.messageId); if (!targetMessage) { - sendErrorMessage(pluginData, msg.channel, "Unknown message"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Unknown message"); return; } @@ -51,12 +51,12 @@ export const EditEmbedCmd = postCmd({ try { parsed = JSON.parse(content); } catch (e) { - sendErrorMessage(pluginData, msg.channel, `Syntax error in embed JSON: ${e.message}`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `Syntax error in embed JSON: ${e.message}`); return; } if (!isValidEmbed(parsed)) { - sendErrorMessage(pluginData, msg.channel, "Embed is not valid"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Embed is not valid"); return; } @@ -69,7 +69,7 @@ export const EditEmbedCmd = postCmd({ args.message.channel.messages.edit(targetMessage.id, { embeds: [embed], }); - await sendSuccessMessage(pluginData, msg.channel, "Embed edited"); + await pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, "Embed edited"); if (args.content) { const prefix = pluginData.fullConfig.prefix || "!"; diff --git a/backend/src/plugins/Post/commands/PostEmbedCmd.ts b/backend/src/plugins/Post/commands/PostEmbedCmd.ts index e605402b..a78abacb 100644 --- a/backend/src/plugins/Post/commands/PostEmbedCmd.ts +++ b/backend/src/plugins/Post/commands/PostEmbedCmd.ts @@ -1,9 +1,9 @@ import { APIEmbed } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage } from "../../../pluginUtils"; import { isValidEmbed, trimLines } from "../../../utils"; import { parseColor } from "../../../utils/parseColor"; import { rgbToInt } from "../../../utils/rgbToInt"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { postCmd } from "../types"; import { actualPostCmd } from "../util/actualPostCmd"; import { formatContent } from "../util/formatContent"; @@ -31,7 +31,7 @@ export const PostEmbedCmd = postCmd({ const content = args.content || args.maincontent; if (!args.title && !content) { - sendErrorMessage(pluginData, msg.channel, "Title or content required"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Title or content required"); return; } @@ -41,7 +41,7 @@ export const PostEmbedCmd = postCmd({ if (colorRgb) { color = rgbToInt(colorRgb); } else { - sendErrorMessage(pluginData, msg.channel, "Invalid color specified"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Invalid color specified"); return; } } @@ -56,12 +56,12 @@ export const PostEmbedCmd = postCmd({ try { parsed = JSON.parse(content); } catch (e) { - sendErrorMessage(pluginData, msg.channel, `Syntax error in embed JSON: ${e.message}`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `Syntax error in embed JSON: ${e.message}`); return; } if (!isValidEmbed(parsed)) { - sendErrorMessage(pluginData, msg.channel, "Embed is not valid"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Embed is not valid"); return; } diff --git a/backend/src/plugins/Post/commands/ScheduledPostsDeleteCmd.ts b/backend/src/plugins/Post/commands/ScheduledPostsDeleteCmd.ts index 78becae8..565135e6 100644 --- a/backend/src/plugins/Post/commands/ScheduledPostsDeleteCmd.ts +++ b/backend/src/plugins/Post/commands/ScheduledPostsDeleteCmd.ts @@ -1,7 +1,7 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; import { clearUpcomingScheduledPost } from "../../../data/loops/upcomingScheduledPostsLoop"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { sorter } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { postCmd } from "../types"; export const ScheduledPostsDeleteCmd = postCmd({ @@ -17,12 +17,12 @@ export const ScheduledPostsDeleteCmd = postCmd({ scheduledPosts.sort(sorter("post_at")); const post = scheduledPosts[args.num - 1]; if (!post) { - sendErrorMessage(pluginData, msg.channel, "Scheduled post not found"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Scheduled post not found"); return; } clearUpcomingScheduledPost(post); await pluginData.state.scheduledPosts.delete(post.id); - sendSuccessMessage(pluginData, msg.channel, "Scheduled post deleted!"); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, "Scheduled post deleted!"); }, }); diff --git a/backend/src/plugins/Post/commands/ScheduledPostsShowCmd.ts b/backend/src/plugins/Post/commands/ScheduledPostsShowCmd.ts index 990bfbae..2895cc68 100644 --- a/backend/src/plugins/Post/commands/ScheduledPostsShowCmd.ts +++ b/backend/src/plugins/Post/commands/ScheduledPostsShowCmd.ts @@ -1,6 +1,6 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage } from "../../../pluginUtils"; import { sorter } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { postCmd } from "../types"; import { postMessage } from "../util/postMessage"; @@ -17,7 +17,7 @@ export const ScheduledPostsShowCmd = postCmd({ scheduledPosts.sort(sorter("post_at")); const post = scheduledPosts[args.num - 1]; if (!post) { - sendErrorMessage(pluginData, msg.channel, "Scheduled post not found"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Scheduled post not found"); return; } diff --git a/backend/src/plugins/Post/util/actualPostCmd.ts b/backend/src/plugins/Post/util/actualPostCmd.ts index c73a672b..fb564499 100644 --- a/backend/src/plugins/Post/util/actualPostCmd.ts +++ b/backend/src/plugins/Post/util/actualPostCmd.ts @@ -3,8 +3,8 @@ import humanizeDuration from "humanize-duration"; import { GuildPluginData } from "knub"; import moment from "moment-timezone"; import { registerUpcomingScheduledPost } from "../../../data/loops/upcomingScheduledPostsLoop"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { DBDateFormat, MINUTES, StrictMessageContent, errorMessage } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { LogsPlugin } from "../../Logs/LogsPlugin"; import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin"; import { PostPluginType } from "../types"; @@ -40,11 +40,15 @@ export async function actualPostCmd( if (opts.repeat) { if (opts.repeat < MIN_REPEAT_TIME) { - sendErrorMessage(pluginData, msg.channel, `Minimum time for -repeat is ${humanizeDuration(MIN_REPEAT_TIME)}`); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `Minimum time for -repeat is ${humanizeDuration(MIN_REPEAT_TIME)}`); return; } if (opts.repeat > MAX_REPEAT_TIME) { - sendErrorMessage(pluginData, msg.channel, `Max time for -repeat is ${humanizeDuration(MAX_REPEAT_TIME)}`); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `Max time for -repeat is ${humanizeDuration(MAX_REPEAT_TIME)}`); return; } } @@ -55,7 +59,7 @@ export async function actualPostCmd( // Schedule the post to be posted later postAt = await parseScheduleTime(pluginData, msg.author.id, opts.schedule); if (!postAt) { - sendErrorMessage(pluginData, msg.channel, "Invalid schedule time"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Invalid schedule time"); return; } } else if (opts.repeat) { @@ -72,36 +76,41 @@ export async function actualPostCmd( // Invalid time if (!repeatUntil) { - sendErrorMessage(pluginData, msg.channel, "Invalid time specified for -repeat-until"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Invalid time specified for -repeat-until"); return; } if (repeatUntil.isBefore(moment.utc())) { - sendErrorMessage(pluginData, msg.channel, "You can't set -repeat-until in the past"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "You can't set -repeat-until in the past"); return; } if (repeatUntil.isAfter(MAX_REPEAT_UNTIL)) { - sendErrorMessage( - pluginData, - msg.channel, - "Unfortunately, -repeat-until can only be at most 100 years into the future. Maybe 99 years would be enough?", - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage( + msg, + "Unfortunately, -repeat-until can only be at most 100 years into the future. Maybe 99 years would be enough?", + ); return; } } else if (opts["repeat-times"]) { repeatTimes = opts["repeat-times"]; if (repeatTimes <= 0) { - sendErrorMessage(pluginData, msg.channel, "-repeat-times must be 1 or more"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "-repeat-times must be 1 or more"); return; } } if (repeatUntil && repeatTimes) { - sendErrorMessage(pluginData, msg.channel, "You can only use one of -repeat-until or -repeat-times at once"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, "You can only use one of -repeat-until or -repeat-times at once"); return; } if (opts.repeat && !repeatUntil && !repeatTimes) { - sendErrorMessage(pluginData, msg.channel, "You must specify -repeat-until or -repeat-times for repeated messages"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, "You must specify -repeat-until or -repeat-times for repeated messages"); return; } @@ -116,7 +125,7 @@ export async function actualPostCmd( // Save schedule/repeat information in DB if (postAt) { if (postAt < moment.utc()) { - sendErrorMessage(pluginData, msg.channel, "Post can't be scheduled to be posted in the past"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Post can't be scheduled to be posted in the past"); return; } @@ -192,6 +201,6 @@ export async function actualPostCmd( } if (targetChannel.id !== msg.channel.id || opts.schedule || opts.repeat) { - sendSuccessMessage(pluginData, msg.channel, successMessage); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, successMessage); } } diff --git a/backend/src/plugins/ReactionRoles/commands/ClearReactionRolesCmd.ts b/backend/src/plugins/ReactionRoles/commands/ClearReactionRolesCmd.ts index ff88b194..1dc632a7 100644 --- a/backend/src/plugins/ReactionRoles/commands/ClearReactionRolesCmd.ts +++ b/backend/src/plugins/ReactionRoles/commands/ClearReactionRolesCmd.ts @@ -1,7 +1,7 @@ import { Message } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { isDiscordAPIError } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { reactionRolesCmd } from "../types"; export const ClearReactionRolesCmd = reactionRolesCmd({ @@ -15,7 +15,7 @@ export const ClearReactionRolesCmd = reactionRolesCmd({ async run({ message: msg, args, pluginData }) { const existingReactionRoles = pluginData.state.reactionRoles.getForMessage(args.message.messageId); if (!existingReactionRoles) { - sendErrorMessage(pluginData, msg.channel, "Message doesn't have reaction roles on it"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Message doesn't have reaction roles on it"); return; } @@ -26,7 +26,7 @@ export const ClearReactionRolesCmd = reactionRolesCmd({ targetMessage = await args.message.channel.messages.fetch(args.message.messageId); } catch (err) { if (isDiscordAPIError(err) && err.code === 50001) { - sendErrorMessage(pluginData, msg.channel, "Missing access to the specified message"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Missing access to the specified message"); return; } @@ -35,6 +35,6 @@ export const ClearReactionRolesCmd = reactionRolesCmd({ await targetMessage.reactions.removeAll(); - sendSuccessMessage(pluginData, msg.channel, "Reaction roles cleared"); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, "Reaction roles cleared"); }, }); diff --git a/backend/src/plugins/ReactionRoles/commands/InitReactionRolesCmd.ts b/backend/src/plugins/ReactionRoles/commands/InitReactionRolesCmd.ts index fefc166e..26d49039 100644 --- a/backend/src/plugins/ReactionRoles/commands/InitReactionRolesCmd.ts +++ b/backend/src/plugins/ReactionRoles/commands/InitReactionRolesCmd.ts @@ -1,8 +1,8 @@ import { Snowflake } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { canUseEmoji, isDiscordAPIError, isValidEmoji, noop, trimPluginDescription } from "../../../utils"; import { canReadChannel } from "../../../utils/canReadChannel"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { TReactionRolePair, reactionRolesCmd } from "../types"; import { applyReactionRoleReactionsToMessage } from "../util/applyReactionRoleReactionsToMessage"; @@ -34,7 +34,9 @@ export const InitReactionRolesCmd = reactionRolesCmd({ async run({ message: msg, args, pluginData }) { if (!canReadChannel(args.message.channel, msg.member)) { - sendErrorMessage(pluginData, msg.channel, "You can't add reaction roles to channels you can't see yourself"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, "You can't add reaction roles to channels you can't see yourself"); return; } @@ -43,7 +45,7 @@ export const InitReactionRolesCmd = reactionRolesCmd({ targetMessage = await args.message.channel.messages.fetch(args.message.messageId); } catch (e) { if (isDiscordAPIError(e)) { - sendErrorMessage(pluginData, msg.channel, `Error ${e.code} while getting message: ${e.message}`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `Error ${e.code} while getting message: ${e.message}`); return; } @@ -71,30 +73,26 @@ export const InitReactionRolesCmd = reactionRolesCmd({ // Verify the specified emojis and roles are valid and usable for (const pair of emojiRolePairs) { if (pair[0] === CLEAR_ROLES_EMOJI) { - sendErrorMessage( - pluginData, - msg.channel, - `The emoji for clearing roles (${CLEAR_ROLES_EMOJI}) is reserved and cannot be used`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `The emoji for clearing roles (${CLEAR_ROLES_EMOJI}) is reserved and cannot be used`); return; } if (!isValidEmoji(pair[0])) { - sendErrorMessage(pluginData, msg.channel, `Invalid emoji: ${pair[0]}`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `Invalid emoji: ${pair[0]}`); return; } if (!canUseEmoji(pluginData.client, pair[0])) { - sendErrorMessage( - pluginData, - msg.channel, - "I can only use regular emojis and custom emojis from servers I'm on", - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, "I can only use regular emojis and custom emojis from servers I'm on"); return; } if (!pluginData.guild.roles.cache.has(pair[1] as Snowflake)) { - sendErrorMessage(pluginData, msg.channel, `Unknown role ${pair[1]}`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `Unknown role ${pair[1]}`); return; } } @@ -125,9 +123,11 @@ export const InitReactionRolesCmd = reactionRolesCmd({ ); if (errors?.length) { - sendErrorMessage(pluginData, msg.channel, `Errors while adding reaction roles:\n${errors.join("\n")}`); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `Errors while adding reaction roles:\n${errors.join("\n")}`); } else { - sendSuccessMessage(pluginData, msg.channel, "Reaction roles added"); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, "Reaction roles added"); } (await progressMessage).delete().catch(noop); diff --git a/backend/src/plugins/ReactionRoles/commands/RefreshReactionRolesCmd.ts b/backend/src/plugins/ReactionRoles/commands/RefreshReactionRolesCmd.ts index 3a55f6ba..6d26ff48 100644 --- a/backend/src/plugins/ReactionRoles/commands/RefreshReactionRolesCmd.ts +++ b/backend/src/plugins/ReactionRoles/commands/RefreshReactionRolesCmd.ts @@ -1,5 +1,5 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { reactionRolesCmd } from "../types"; import { refreshReactionRoles } from "../util/refreshReactionRoles"; @@ -13,12 +13,12 @@ export const RefreshReactionRolesCmd = reactionRolesCmd({ async run({ message: msg, args, pluginData }) { if (pluginData.state.pendingRefreshes.has(`${args.message.channel.id}-${args.message.messageId}`)) { - sendErrorMessage(pluginData, msg.channel, "Another refresh in progress"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Another refresh in progress"); return; } await refreshReactionRoles(pluginData, args.message.channel.id, args.message.messageId); - sendSuccessMessage(pluginData, msg.channel, "Reaction roles refreshed"); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, "Reaction roles refreshed"); }, }); diff --git a/backend/src/plugins/Reminders/commands/RemindCmd.ts b/backend/src/plugins/Reminders/commands/RemindCmd.ts index c4655771..88ceeaa3 100644 --- a/backend/src/plugins/Reminders/commands/RemindCmd.ts +++ b/backend/src/plugins/Reminders/commands/RemindCmd.ts @@ -2,8 +2,8 @@ import humanizeDuration from "humanize-duration"; import moment from "moment-timezone"; import { commandTypeHelpers as ct } from "../../../commandTypes"; import { registerUpcomingReminder } from "../../../data/loops/upcomingRemindersLoop"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { convertDelayStringToMS, messageLink } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin"; import { remindersCmd } from "../types"; @@ -38,7 +38,7 @@ export const RemindCmd = remindersCmd({ // "Delay string" i.e. e.g. "2h30m" const ms = convertDelayStringToMS(args.time); if (ms === null) { - sendErrorMessage(pluginData, msg.channel, "Invalid reminder time"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Invalid reminder time"); return; } @@ -46,7 +46,7 @@ export const RemindCmd = remindersCmd({ } if (!reminderTime.isValid() || reminderTime.isBefore(now)) { - sendErrorMessage(pluginData, msg.channel, "Invalid reminder time"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Invalid reminder time"); return; } @@ -67,10 +67,8 @@ export const RemindCmd = remindersCmd({ pluginData.getPlugin(TimeAndDatePlugin).getDateFormat("pretty_datetime"), ); - sendSuccessMessage( - pluginData, - msg.channel, - `I will remind you in **${timeUntilReminder}** at **${prettyReminderTime}**`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(msg, `I will remind you in **${timeUntilReminder}** at **${prettyReminderTime}**`); }, }); diff --git a/backend/src/plugins/Reminders/commands/RemindersCmd.ts b/backend/src/plugins/Reminders/commands/RemindersCmd.ts index ce914a34..7b2da150 100644 --- a/backend/src/plugins/Reminders/commands/RemindersCmd.ts +++ b/backend/src/plugins/Reminders/commands/RemindersCmd.ts @@ -1,7 +1,7 @@ import humanizeDuration from "humanize-duration"; import moment from "moment-timezone"; -import { sendErrorMessage } from "../../../pluginUtils"; import { createChunkedMessage, DBDateFormat, sorter } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin"; import { remindersCmd } from "../types"; @@ -12,7 +12,7 @@ export const RemindersCmd = remindersCmd({ async run({ message: msg, pluginData }) { const reminders = await pluginData.state.reminders.getRemindersByUserId(msg.author.id); if (reminders.length === 0) { - sendErrorMessage(pluginData, msg.channel, "No reminders"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "No reminders"); return; } diff --git a/backend/src/plugins/Reminders/commands/RemindersDeleteCmd.ts b/backend/src/plugins/Reminders/commands/RemindersDeleteCmd.ts index 25713a4f..5566a133 100644 --- a/backend/src/plugins/Reminders/commands/RemindersDeleteCmd.ts +++ b/backend/src/plugins/Reminders/commands/RemindersDeleteCmd.ts @@ -1,7 +1,7 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; import { clearUpcomingReminder } from "../../../data/loops/upcomingRemindersLoop"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { sorter } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { remindersCmd } from "../types"; export const RemindersDeleteCmd = remindersCmd({ @@ -17,7 +17,7 @@ export const RemindersDeleteCmd = remindersCmd({ reminders.sort(sorter("remind_at")); if (args.num > reminders.length || args.num <= 0) { - sendErrorMessage(pluginData, msg.channel, "Unknown reminder"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Unknown reminder"); return; } @@ -25,6 +25,6 @@ export const RemindersDeleteCmd = remindersCmd({ clearUpcomingReminder(toDelete); await pluginData.state.reminders.delete(toDelete.id); - sendSuccessMessage(pluginData, msg.channel, "Reminder deleted"); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, "Reminder deleted"); }, }); diff --git a/backend/src/plugins/RoleButtons/commands/resetButtons.ts b/backend/src/plugins/RoleButtons/commands/resetButtons.ts index cca8e643..edd99eb0 100644 --- a/backend/src/plugins/RoleButtons/commands/resetButtons.ts +++ b/backend/src/plugins/RoleButtons/commands/resetButtons.ts @@ -1,6 +1,6 @@ import { guildPluginMessageCommand } from "knub"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { applyAllRoleButtons } from "../functions/applyAllRoleButtons"; import { RoleButtonsPluginType } from "../types"; @@ -16,12 +16,14 @@ export const resetButtonsCmd = guildPluginMessageCommand( async run({ pluginData, args, message }) { const config = pluginData.config.get(); if (!config.buttons[args.name]) { - sendErrorMessage(pluginData, message.channel, `Can't find role buttons with the name "${args.name}"`); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(message, `Can't find role buttons with the name "${args.name}"`); return; } await pluginData.state.roleButtons.deleteRoleButtonItem(args.name); await applyAllRoleButtons(pluginData); - sendSuccessMessage(pluginData, message.channel, "Done!"); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(message, "Done!"); }, }); diff --git a/backend/src/plugins/Roles/commands/AddRoleCmd.ts b/backend/src/plugins/Roles/commands/AddRoleCmd.ts index ccd64325..a66ff365 100644 --- a/backend/src/plugins/Roles/commands/AddRoleCmd.ts +++ b/backend/src/plugins/Roles/commands/AddRoleCmd.ts @@ -1,7 +1,8 @@ import { GuildChannel } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { canActOn, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { canActOn } from "../../../pluginUtils"; import { resolveRoleId, verboseUserMention } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { LogsPlugin } from "../../Logs/LogsPlugin"; import { RoleManagerPlugin } from "../../RoleManager/RoleManagerPlugin"; import { rolesCmd } from "../types"; @@ -18,19 +19,21 @@ export const AddRoleCmd = rolesCmd({ async run({ message: msg, args, pluginData }) { if (!canActOn(pluginData, msg.member, args.member, true)) { - sendErrorMessage(pluginData, msg.channel, "Cannot add roles to this user: insufficient permissions"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, "Cannot add roles to this user: insufficient permissions"); return; } const roleId = await resolveRoleId(pluginData.client, pluginData.guild.id, args.role); if (!roleId) { - sendErrorMessage(pluginData, msg.channel, "Invalid role id"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Invalid role id"); return; } const config = await pluginData.config.getForMessage(msg); if (!config.assignable_roles.includes(roleId)) { - sendErrorMessage(pluginData, msg.channel, "You cannot assign that role"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "You cannot assign that role"); return; } @@ -40,12 +43,12 @@ export const AddRoleCmd = rolesCmd({ pluginData.getPlugin(LogsPlugin).logBotAlert({ body: `Unknown role configured for 'roles' plugin: ${roleId}`, }); - sendErrorMessage(pluginData, msg.channel, "You cannot assign that role"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "You cannot assign that role"); return; } if (args.member.roles.cache.has(roleId)) { - sendErrorMessage(pluginData, msg.channel, "Member already has that role"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Member already has that role"); return; } @@ -57,10 +60,8 @@ export const AddRoleCmd = rolesCmd({ roles: [role], }); - sendSuccessMessage( - pluginData, - msg.channel, - `Added role **${role.name}** to ${verboseUserMention(args.member.user)}!`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(msg, `Added role **${role.name}** to ${verboseUserMention(args.member.user)}!`); }, }); diff --git a/backend/src/plugins/Roles/commands/MassAddRoleCmd.ts b/backend/src/plugins/Roles/commands/MassAddRoleCmd.ts index 9030e45c..05db86ba 100644 --- a/backend/src/plugins/Roles/commands/MassAddRoleCmd.ts +++ b/backend/src/plugins/Roles/commands/MassAddRoleCmd.ts @@ -1,8 +1,9 @@ import { GuildMember } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; import { logger } from "../../../logger"; -import { canActOn, sendErrorMessage } from "../../../pluginUtils"; +import { canActOn } from "../../../pluginUtils"; import { resolveMember, resolveRoleId, successMessage } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { LogsPlugin } from "../../Logs/LogsPlugin"; import { RoleManagerPlugin } from "../../RoleManager/RoleManagerPlugin"; import { rolesCmd } from "../types"; @@ -29,24 +30,22 @@ export const MassAddRoleCmd = rolesCmd({ for (const member of members) { if (!canActOn(pluginData, msg.member, member, true)) { - sendErrorMessage( - pluginData, - msg.channel, - "Cannot add roles to 1 or more specified members: insufficient permissions", - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, "Cannot add roles to 1 or more specified members: insufficient permissions"); return; } } const roleId = await resolveRoleId(pluginData.client, pluginData.guild.id, args.role); if (!roleId) { - sendErrorMessage(pluginData, msg.channel, "Invalid role id"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Invalid role id"); return; } const config = await pluginData.config.getForMessage(msg); if (!config.assignable_roles.includes(roleId)) { - sendErrorMessage(pluginData, msg.channel, "You cannot assign that role"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "You cannot assign that role"); return; } @@ -55,7 +54,7 @@ export const MassAddRoleCmd = rolesCmd({ pluginData.getPlugin(LogsPlugin).logBotAlert({ body: `Unknown role configured for 'roles' plugin: ${roleId}`, }); - sendErrorMessage(pluginData, msg.channel, "You cannot assign that role"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "You cannot assign that role"); return; } diff --git a/backend/src/plugins/Roles/commands/MassRemoveRoleCmd.ts b/backend/src/plugins/Roles/commands/MassRemoveRoleCmd.ts index de4591b4..06a5337d 100644 --- a/backend/src/plugins/Roles/commands/MassRemoveRoleCmd.ts +++ b/backend/src/plugins/Roles/commands/MassRemoveRoleCmd.ts @@ -1,7 +1,8 @@ import { GuildMember } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { canActOn, sendErrorMessage } from "../../../pluginUtils"; +import { canActOn } from "../../../pluginUtils"; import { resolveMember, resolveRoleId, successMessage } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { LogsPlugin } from "../../Logs/LogsPlugin"; import { RoleManagerPlugin } from "../../RoleManager/RoleManagerPlugin"; import { rolesCmd } from "../types"; @@ -28,24 +29,22 @@ export const MassRemoveRoleCmd = rolesCmd({ for (const member of members) { if (!canActOn(pluginData, msg.member, member, true)) { - sendErrorMessage( - pluginData, - msg.channel, - "Cannot add roles to 1 or more specified members: insufficient permissions", - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, "Cannot add roles to 1 or more specified members: insufficient permissions"); return; } } const roleId = await resolveRoleId(pluginData.client, pluginData.guild.id, args.role); if (!roleId) { - sendErrorMessage(pluginData, msg.channel, "Invalid role id"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Invalid role id"); return; } const config = await pluginData.config.getForMessage(msg); if (!config.assignable_roles.includes(roleId)) { - sendErrorMessage(pluginData, msg.channel, "You cannot remove that role"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "You cannot remove that role"); return; } @@ -54,7 +53,7 @@ export const MassRemoveRoleCmd = rolesCmd({ pluginData.getPlugin(LogsPlugin).logBotAlert({ body: `Unknown role configured for 'roles' plugin: ${roleId}`, }); - sendErrorMessage(pluginData, msg.channel, "You cannot remove that role"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "You cannot remove that role"); return; } diff --git a/backend/src/plugins/Roles/commands/RemoveRoleCmd.ts b/backend/src/plugins/Roles/commands/RemoveRoleCmd.ts index 8cd6f306..e3dc979d 100644 --- a/backend/src/plugins/Roles/commands/RemoveRoleCmd.ts +++ b/backend/src/plugins/Roles/commands/RemoveRoleCmd.ts @@ -1,7 +1,8 @@ import { GuildChannel } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { canActOn, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { canActOn } from "../../../pluginUtils"; import { resolveRoleId, verboseUserMention } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { LogsPlugin } from "../../Logs/LogsPlugin"; import { RoleManagerPlugin } from "../../RoleManager/RoleManagerPlugin"; import { rolesCmd } from "../types"; @@ -18,19 +19,21 @@ export const RemoveRoleCmd = rolesCmd({ async run({ message: msg, args, pluginData }) { if (!canActOn(pluginData, msg.member, args.member, true)) { - sendErrorMessage(pluginData, msg.channel, "Cannot remove roles from this user: insufficient permissions"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, "Cannot remove roles from this user: insufficient permissions"); return; } const roleId = await resolveRoleId(pluginData.client, pluginData.guild.id, args.role); if (!roleId) { - sendErrorMessage(pluginData, msg.channel, "Invalid role id"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Invalid role id"); return; } const config = await pluginData.config.getForMessage(msg); if (!config.assignable_roles.includes(roleId)) { - sendErrorMessage(pluginData, msg.channel, "You cannot remove that role"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "You cannot remove that role"); return; } @@ -40,12 +43,12 @@ export const RemoveRoleCmd = rolesCmd({ pluginData.getPlugin(LogsPlugin).logBotAlert({ body: `Unknown role configured for 'roles' plugin: ${roleId}`, }); - sendErrorMessage(pluginData, msg.channel, "You cannot remove that role"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "You cannot remove that role"); return; } if (!args.member.roles.cache.has(roleId)) { - sendErrorMessage(pluginData, msg.channel, "Member doesn't have that role"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Member doesn't have that role"); return; } @@ -56,10 +59,8 @@ export const RemoveRoleCmd = rolesCmd({ roles: [role], }); - sendSuccessMessage( - pluginData, - msg.channel, - `Removed role **${role.name}** from ${verboseUserMention(args.member.user)}!`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(msg, `Removed role **${role.name}** from ${verboseUserMention(args.member.user)}!`); }, }); diff --git a/backend/src/plugins/SelfGrantableRoles/commands/RoleAddCmd.ts b/backend/src/plugins/SelfGrantableRoles/commands/RoleAddCmd.ts index ce8a3a73..006307ac 100644 --- a/backend/src/plugins/SelfGrantableRoles/commands/RoleAddCmd.ts +++ b/backend/src/plugins/SelfGrantableRoles/commands/RoleAddCmd.ts @@ -1,7 +1,7 @@ import { Role, Snowflake } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { memberRolesLock } from "../../../utils/lockNameHelpers"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { selfGrantableRolesCmd } from "../types"; import { findMatchingRoles } from "../util/findMatchingRoles"; import { getApplyingEntries } from "../util/getApplyingEntries"; @@ -39,12 +39,11 @@ export const RoleAddCmd = selfGrantableRolesCmd({ }, new Map()); if (!rolesToAdd.size) { - sendErrorMessage( - pluginData, - msg.channel, - `<@!${msg.author.id}> Unknown ${args.roleNames.length === 1 ? "role" : "roles"}`, - { users: [msg.author.id] }, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `<@!${msg.author.id}> Unknown ${args.roleNames.length === 1 ? "role" : "roles"}`, { + users: [msg.author.id], + }); lock.unlock(); return; } @@ -84,12 +83,11 @@ export const RoleAddCmd = selfGrantableRolesCmd({ roles: Array.from(newRoleIds) as Snowflake[], }); } catch { - sendErrorMessage( - pluginData, - msg.channel, - `<@!${msg.author.id}> Got an error while trying to grant you the roles`, - { users: [msg.author.id] }, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `<@!${msg.author.id}> Got an error while trying to grant you the roles`, { + users: [msg.author.id], + }); return; } @@ -120,7 +118,7 @@ export const RoleAddCmd = selfGrantableRolesCmd({ messageParts.push("couldn't recognize some of the roles"); } - sendSuccessMessage(pluginData, msg.channel, `<@!${msg.author.id}> ${messageParts.join("; ")}`, { + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, `<@!${msg.author.id}> ${messageParts.join("; ")}`, { users: [msg.author.id], }); diff --git a/backend/src/plugins/SelfGrantableRoles/commands/RoleRemoveCmd.ts b/backend/src/plugins/SelfGrantableRoles/commands/RoleRemoveCmd.ts index 007aa459..b688203f 100644 --- a/backend/src/plugins/SelfGrantableRoles/commands/RoleRemoveCmd.ts +++ b/backend/src/plugins/SelfGrantableRoles/commands/RoleRemoveCmd.ts @@ -1,7 +1,7 @@ import { Snowflake } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { memberRolesLock } from "../../../utils/lockNameHelpers"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { selfGrantableRolesCmd } from "../types"; import { findMatchingRoles } from "../util/findMatchingRoles"; import { getApplyingEntries } from "../util/getApplyingEntries"; @@ -46,36 +46,34 @@ export const RoleRemoveCmd = selfGrantableRolesCmd({ const removedRolesWord = rolesToRemove.length === 1 ? "role" : "roles"; if (rolesToRemove.length !== roleNames.length) { - sendSuccessMessage( - pluginData, - msg.channel, - `<@!${msg.author.id}> Removed ${removedRolesStr.join(", ")} ${removedRolesWord};` + - ` couldn't recognize the other roles you mentioned`, - { users: [msg.author.id] }, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage( + msg, + `<@!${msg.author.id}> Removed ${removedRolesStr.join(", ")} ${removedRolesWord};` + + ` couldn't recognize the other roles you mentioned`, + { users: [msg.author.id] }, + ); } else { - sendSuccessMessage( - pluginData, - msg.channel, - `<@!${msg.author.id}> Removed ${removedRolesStr.join(", ")} ${removedRolesWord}`, - { users: [msg.author.id] }, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(msg, `<@!${msg.author.id}> Removed ${removedRolesStr.join(", ")} ${removedRolesWord}`, { + users: [msg.author.id], + }); } } catch { - sendSuccessMessage( - pluginData, - msg.channel, - `<@!${msg.author.id}> Got an error while trying to remove the roles`, - { users: [msg.author.id] }, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(msg, `<@!${msg.author.id}> Got an error while trying to remove the roles`, { + users: [msg.author.id], + }); } } else { - sendErrorMessage( - pluginData, - msg.channel, - `<@!${msg.author.id}> Unknown ${args.roleNames.length === 1 ? "role" : "roles"}`, - { users: [msg.author.id] }, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `<@!${msg.author.id}> Unknown ${args.roleNames.length === 1 ? "role" : "roles"}`, { + users: [msg.author.id], + }); } lock.unlock(); diff --git a/backend/src/plugins/Slowmode/commands/SlowmodeClearCmd.ts b/backend/src/plugins/Slowmode/commands/SlowmodeClearCmd.ts index 246a048e..72082350 100644 --- a/backend/src/plugins/Slowmode/commands/SlowmodeClearCmd.ts +++ b/backend/src/plugins/Slowmode/commands/SlowmodeClearCmd.ts @@ -1,9 +1,9 @@ import { ChannelType, escapeInlineCode } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { asSingleLine, renderUserUsername } from "../../../utils"; import { getMissingChannelPermissions } from "../../../utils/getMissingChannelPermissions"; import { missingPermissionError } from "../../../utils/missingPermissionError"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { BOT_SLOWMODE_CLEAR_PERMISSIONS } from "../requiredPermissions"; import { slowmodeCmd } from "../types"; import { clearBotSlowmodeFromUserId } from "../util/clearBotSlowmodeFromUserId"; @@ -22,18 +22,16 @@ export const SlowmodeClearCmd = slowmodeCmd({ async run({ message: msg, args, pluginData }) { const channelSlowmode = await pluginData.state.slowmodes.getChannelSlowmode(args.channel.id); if (!channelSlowmode) { - sendErrorMessage(pluginData, msg.channel, "Channel doesn't have slowmode!"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Channel doesn't have slowmode!"); return; } const me = pluginData.guild.members.cache.get(pluginData.client.user!.id)!; const missingPermissions = getMissingChannelPermissions(me, args.channel, BOT_SLOWMODE_CLEAR_PERMISSIONS); if (missingPermissions) { - sendErrorMessage( - pluginData, - msg.channel, - `Unable to clear slowmode. ${missingPermissionError(missingPermissions)}`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `Unable to clear slowmode. ${missingPermissionError(missingPermissions)}`); return; } @@ -41,9 +39,8 @@ export const SlowmodeClearCmd = slowmodeCmd({ if (args.channel.type === ChannelType.GuildText) { await clearBotSlowmodeFromUserId(pluginData, args.channel, args.user.id, args.force); } else { - sendErrorMessage( - pluginData, - msg.channel, + pluginData.getPlugin(CommonPlugin).sendErrorMessage( + msg, asSingleLine(` Failed to clear slowmode from **${renderUserUsername(args.user)}** in <#${args.channel.id}>: Threads cannot have Bot Slowmode @@ -52,9 +49,8 @@ export const SlowmodeClearCmd = slowmodeCmd({ return; } } catch (e) { - sendErrorMessage( - pluginData, - msg.channel, + pluginData.getPlugin(CommonPlugin).sendErrorMessage( + msg, asSingleLine(` Failed to clear slowmode from **${renderUserUsername(args.user)}** in <#${args.channel.id}>: \`${escapeInlineCode(e.message)}\` @@ -63,10 +59,8 @@ export const SlowmodeClearCmd = slowmodeCmd({ return; } - sendSuccessMessage( - pluginData, - msg.channel, - `Slowmode cleared from **${renderUserUsername(args.user)}** in <#${args.channel.id}>`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(msg, `Slowmode cleared from **${renderUserUsername(args.user)}** in <#${args.channel.id}>`); }, }); diff --git a/backend/src/plugins/Slowmode/commands/SlowmodeSetCmd.ts b/backend/src/plugins/Slowmode/commands/SlowmodeSetCmd.ts index 44d5c111..0d088b43 100644 --- a/backend/src/plugins/Slowmode/commands/SlowmodeSetCmd.ts +++ b/backend/src/plugins/Slowmode/commands/SlowmodeSetCmd.ts @@ -1,10 +1,10 @@ import { escapeInlineCode, PermissionsBitField } from "discord.js"; import humanizeDuration from "humanize-duration"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { asSingleLine, DAYS, HOURS, MINUTES } from "../../../utils"; import { getMissingPermissions } from "../../../utils/getMissingPermissions"; import { missingPermissionError } from "../../../utils/missingPermissionError"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { BOT_SLOWMODE_PERMISSIONS, NATIVE_SLOWMODE_PERMISSIONS } from "../requiredPermissions"; import { slowmodeCmd } from "../types"; import { actualDisableSlowmodeCmd } from "../util/actualDisableSlowmodeCmd"; @@ -40,7 +40,9 @@ export const SlowmodeSetCmd = slowmodeCmd({ const channel = args.channel || msg.channel; if (!channel.isTextBased() || channel.isThread()) { - sendErrorMessage(pluginData, msg.channel, "Slowmode can only be set on non-thread text-based channels"); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, "Slowmode can only be set on non-thread text-based channels"); return; } @@ -56,29 +58,26 @@ export const SlowmodeSetCmd = slowmodeCmd({ const mode = (args.mode as TMode) || defaultMode; if (!validModes.includes(mode)) { - sendErrorMessage(pluginData, msg.channel, "--mode must be 'bot' or 'native'"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "--mode must be 'bot' or 'native'"); return; } // Validate durations if (mode === "native" && args.time > MAX_NATIVE_SLOWMODE) { - sendErrorMessage(pluginData, msg.channel, "Native slowmode can only be set to 6h or less"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Native slowmode can only be set to 6h or less"); return; } if (mode === "bot" && args.time > MAX_BOT_SLOWMODE) { - sendErrorMessage( - pluginData, - msg.channel, - `Sorry, bot managed slowmodes can be at most 100 years long. Maybe 99 would be enough?`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `Sorry, bot managed slowmodes can be at most 100 years long. Maybe 99 would be enough?`); return; } if (mode === "bot" && args.time < MIN_BOT_SLOWMODE) { - sendErrorMessage( - pluginData, - msg.channel, + pluginData.getPlugin(CommonPlugin).sendErrorMessage( + msg, asSingleLine(` Bot managed slowmode must be 15min or more. Use \`--mode native\` to use native slowmodes for short slowmodes instead. @@ -96,11 +95,9 @@ export const SlowmodeSetCmd = slowmodeCmd({ NATIVE_SLOWMODE_PERMISSIONS, ); if (missingPermissions) { - sendErrorMessage( - pluginData, - msg.channel, - `Unable to set native slowmode. ${missingPermissionError(missingPermissions)}`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `Unable to set native slowmode. ${missingPermissionError(missingPermissions)}`); return; } } @@ -111,11 +108,9 @@ export const SlowmodeSetCmd = slowmodeCmd({ BOT_SLOWMODE_PERMISSIONS, ); if (missingPermissions) { - sendErrorMessage( - pluginData, - msg.channel, - `Unable to set bot managed slowmode. ${missingPermissionError(missingPermissions)}`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `Unable to set bot managed slowmode. ${missingPermissionError(missingPermissions)}`); return; } } @@ -134,7 +129,9 @@ export const SlowmodeSetCmd = slowmodeCmd({ try { await channel.setRateLimitPerUser(rateLimitSeconds); } catch (e) { - sendErrorMessage(pluginData, msg.channel, `Failed to set native slowmode: ${escapeInlineCode(e.message)}`); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `Failed to set native slowmode: ${escapeInlineCode(e.message)}`); return; } } else { @@ -153,10 +150,8 @@ export const SlowmodeSetCmd = slowmodeCmd({ const humanizedSlowmodeTime = humanizeDuration(args.time); const slowmodeType = mode === "native" ? "native slowmode" : "bot-maintained slowmode"; - sendSuccessMessage( - pluginData, - msg.channel, - `Set ${humanizedSlowmodeTime} slowmode for <#${channel.id}> (${slowmodeType})`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(msg, `Set ${humanizedSlowmodeTime} slowmode for <#${channel.id}> (${slowmodeType})`); }, }); diff --git a/backend/src/plugins/Slowmode/util/actualDisableSlowmodeCmd.ts b/backend/src/plugins/Slowmode/util/actualDisableSlowmodeCmd.ts index 2bc00bed..72c86a04 100644 --- a/backend/src/plugins/Slowmode/util/actualDisableSlowmodeCmd.ts +++ b/backend/src/plugins/Slowmode/util/actualDisableSlowmodeCmd.ts @@ -1,8 +1,8 @@ import { Message } from "discord.js"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { noop } from "../../../utils"; import { getMissingChannelPermissions } from "../../../utils/getMissingChannelPermissions"; import { missingPermissionError } from "../../../utils/missingPermissionError"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { BOT_SLOWMODE_DISABLE_PERMISSIONS } from "../requiredPermissions"; import { disableBotSlowmodeForChannel } from "./disableBotSlowmodeForChannel"; @@ -11,18 +11,16 @@ export async function actualDisableSlowmodeCmd(msg: Message, args, pluginData) { const hasNativeSlowmode = args.channel.rateLimitPerUser; if (!botSlowmode && hasNativeSlowmode === 0) { - sendErrorMessage(pluginData, msg.channel, "Channel is not on slowmode!"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Channel is not on slowmode!"); return; } const me = pluginData.guild.members.cache.get(pluginData.client.user!.id); const missingPermissions = getMissingChannelPermissions(me, args.channel, BOT_SLOWMODE_DISABLE_PERMISSIONS); if (missingPermissions) { - sendErrorMessage( - pluginData, - msg.channel, - `Unable to disable slowmode. ${missingPermissionError(missingPermissions)}`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `Unable to disable slowmode. ${missingPermissionError(missingPermissions)}`); return; } @@ -41,13 +39,14 @@ export async function actualDisableSlowmodeCmd(msg: Message, args, pluginData) { } if (failedUsers.length) { - sendSuccessMessage( - pluginData, - msg.channel, - `Slowmode disabled! Failed to clear slowmode from the following users:\n\n<@!${failedUsers.join(">\n<@!")}>`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage( + msg, + `Slowmode disabled! Failed to clear slowmode from the following users:\n\n<@!${failedUsers.join(">\n<@!")}>`, + ); } else { - sendSuccessMessage(pluginData, msg.channel, "Slowmode disabled!"); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, "Slowmode disabled!"); initMsg.delete().catch(noop); } } diff --git a/backend/src/plugins/Spam/util/logAndDetectMessageSpam.ts b/backend/src/plugins/Spam/util/logAndDetectMessageSpam.ts index b2a46432..4c8a4e25 100644 --- a/backend/src/plugins/Spam/util/logAndDetectMessageSpam.ts +++ b/backend/src/plugins/Spam/util/logAndDetectMessageSpam.ts @@ -76,10 +76,13 @@ export async function logAndDetectMessageSpam( (spamConfig.mute_time && convertDelayStringToMS(spamConfig.mute_time.toString())) ?? 120 * 1000; try { + const reason = "Automatic spam detection"; + muteResult = await mutesPlugin.muteUser( member.id, muteTime, - "Automatic spam detection", + reason, + reason, { caseArgs: { modId: pluginData.client.user!.id, diff --git a/backend/src/plugins/Spam/util/logAndDetectOtherSpam.ts b/backend/src/plugins/Spam/util/logAndDetectOtherSpam.ts index 3a339b5f..5b83c9a1 100644 --- a/backend/src/plugins/Spam/util/logAndDetectOtherSpam.ts +++ b/backend/src/plugins/Spam/util/logAndDetectOtherSpam.ts @@ -40,10 +40,13 @@ export async function logAndDetectOtherSpam( (spamConfig.mute_time && convertDelayStringToMS(spamConfig.mute_time.toString())) ?? 120 * 1000; try { + const reason = "Automatic spam detection"; + await mutesPlugin.muteUser( member.id, muteTime, - "Automatic spam detection", + reason, + reason, { caseArgs: { modId: pluginData.client.user!.id, diff --git a/backend/src/plugins/Starboard/commands/MigratePinsCmd.ts b/backend/src/plugins/Starboard/commands/MigratePinsCmd.ts index 7fba0241..d074c948 100644 --- a/backend/src/plugins/Starboard/commands/MigratePinsCmd.ts +++ b/backend/src/plugins/Starboard/commands/MigratePinsCmd.ts @@ -1,6 +1,6 @@ import { Snowflake, TextChannel } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { starboardCmd } from "../types"; import { saveMessageToStarboard } from "../util/saveMessageToStarboard"; @@ -19,13 +19,13 @@ export const MigratePinsCmd = starboardCmd({ const config = await pluginData.config.get(); const starboard = config.boards[args.starboardName]; if (!starboard) { - sendErrorMessage(pluginData, msg.channel, "Unknown starboard specified"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Unknown starboard specified"); return; } const starboardChannel = pluginData.guild.channels.cache.get(starboard.channel_id as Snowflake); if (!starboardChannel || !(starboardChannel instanceof TextChannel)) { - sendErrorMessage(pluginData, msg.channel, "Starboard has an unknown/invalid channel id"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Starboard has an unknown/invalid channel id"); return; } @@ -43,10 +43,8 @@ export const MigratePinsCmd = starboardCmd({ await saveMessageToStarboard(pluginData, pin, starboard); } - sendSuccessMessage( - pluginData, - msg.channel, - `Pins migrated from <#${args.pinChannel.id}> to <#${starboardChannel.id}>!`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(msg, `Pins migrated from <#${args.pinChannel.id}> to <#${starboardChannel.id}>!`); }, }); diff --git a/backend/src/plugins/Tags/commands/TagCreateCmd.ts b/backend/src/plugins/Tags/commands/TagCreateCmd.ts index 10c81e87..0ee452f5 100644 --- a/backend/src/plugins/Tags/commands/TagCreateCmd.ts +++ b/backend/src/plugins/Tags/commands/TagCreateCmd.ts @@ -1,6 +1,6 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { TemplateParseError, parseTemplate } from "../../../templateFormatter"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { tagsCmd } from "../types"; export const TagCreateCmd = tagsCmd({ @@ -17,7 +17,7 @@ export const TagCreateCmd = tagsCmd({ parseTemplate(args.body); } catch (e) { if (e instanceof TemplateParseError) { - sendErrorMessage(pluginData, msg.channel, `Invalid tag syntax: ${e.message}`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `Invalid tag syntax: ${e.message}`); return; } else { throw e; @@ -27,6 +27,6 @@ export const TagCreateCmd = tagsCmd({ await pluginData.state.tags.createOrUpdate(args.tag, args.body, msg.author.id); const prefix = pluginData.config.get().prefix; - sendSuccessMessage(pluginData, msg.channel, `Tag set! Use it with: \`${prefix}${args.tag}\``); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, `Tag set! Use it with: \`${prefix}${args.tag}\``); }, }); diff --git a/backend/src/plugins/Tags/commands/TagDeleteCmd.ts b/backend/src/plugins/Tags/commands/TagDeleteCmd.ts index 47cb623d..174b7b64 100644 --- a/backend/src/plugins/Tags/commands/TagDeleteCmd.ts +++ b/backend/src/plugins/Tags/commands/TagDeleteCmd.ts @@ -1,5 +1,5 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { tagsCmd } from "../types"; export const TagDeleteCmd = tagsCmd({ @@ -13,11 +13,11 @@ export const TagDeleteCmd = tagsCmd({ async run({ message: msg, args, pluginData }) { const tag = await pluginData.state.tags.find(args.tag); if (!tag) { - sendErrorMessage(pluginData, msg.channel, "No tag with that name"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "No tag with that name"); return; } await pluginData.state.tags.delete(args.tag); - sendSuccessMessage(pluginData, msg.channel, "Tag deleted!"); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, "Tag deleted!"); }, }); diff --git a/backend/src/plugins/Tags/commands/TagEvalCmd.ts b/backend/src/plugins/Tags/commands/TagEvalCmd.ts index 55659d30..a5de9a77 100644 --- a/backend/src/plugins/Tags/commands/TagEvalCmd.ts +++ b/backend/src/plugins/Tags/commands/TagEvalCmd.ts @@ -1,8 +1,8 @@ import { MessageCreateOptions } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage } from "../../../pluginUtils"; import { TemplateParseError } from "../../../templateFormatter"; import { memberToTemplateSafeMember, userToTemplateSafeUser } from "../../../utils/templateSafeObjects"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { tagsCmd } from "../types"; import { renderTagBody } from "../util/renderTagBody"; @@ -28,14 +28,14 @@ export const TagEvalCmd = tagsCmd({ )) as MessageCreateOptions; if (!rendered.content && !rendered.embeds?.length) { - sendErrorMessage(pluginData, msg.channel, "Evaluation resulted in an empty text"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Evaluation resulted in an empty text"); return; } msg.channel.send(rendered); } catch (e) { if (e instanceof TemplateParseError) { - sendErrorMessage(pluginData, msg.channel, `Failed to render tag: ${e.message}`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `Failed to render tag: ${e.message}`); return; } diff --git a/backend/src/plugins/Tags/commands/TagSourceCmd.ts b/backend/src/plugins/Tags/commands/TagSourceCmd.ts index 9e0e5cef..6690f8f7 100644 --- a/backend/src/plugins/Tags/commands/TagSourceCmd.ts +++ b/backend/src/plugins/Tags/commands/TagSourceCmd.ts @@ -1,6 +1,7 @@ import moment from "moment-timezone"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { getBaseUrl, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { getBaseUrl } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { tagsCmd } from "../types"; export const TagSourceCmd = tagsCmd({ @@ -17,18 +18,18 @@ export const TagSourceCmd = tagsCmd({ if (args.delete) { const actualTag = await pluginData.state.tags.find(args.tag); if (!actualTag) { - sendErrorMessage(pluginData, msg.channel, "No tag with that name"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "No tag with that name"); return; } await pluginData.state.tags.delete(args.tag); - sendSuccessMessage(pluginData, msg.channel, "Tag deleted!"); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, "Tag deleted!"); return; } const tag = await pluginData.state.tags.find(args.tag); if (!tag) { - sendErrorMessage(pluginData, msg.channel, "No tag with that name"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "No tag with that name"); return; } diff --git a/backend/src/plugins/TimeAndDate/commands/ResetTimezoneCmd.ts b/backend/src/plugins/TimeAndDate/commands/ResetTimezoneCmd.ts index db59965a..2c39519e 100644 --- a/backend/src/plugins/TimeAndDate/commands/ResetTimezoneCmd.ts +++ b/backend/src/plugins/TimeAndDate/commands/ResetTimezoneCmd.ts @@ -1,4 +1,4 @@ -import { sendSuccessMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { getGuildTz } from "../functions/getGuildTz"; import { timeAndDateCmd } from "../types"; @@ -11,10 +11,8 @@ export const ResetTimezoneCmd = timeAndDateCmd({ async run({ pluginData, message }) { await pluginData.state.memberTimezones.reset(message.author.id); const serverTimezone = getGuildTz(pluginData); - sendSuccessMessage( - pluginData, - message.channel, - `Your timezone has been reset to server default, **${serverTimezone}**`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(message, `Your timezone has been reset to server default, **${serverTimezone}**`); }, }); diff --git a/backend/src/plugins/TimeAndDate/commands/SetTimezoneCmd.ts b/backend/src/plugins/TimeAndDate/commands/SetTimezoneCmd.ts index 90d00b3b..70acf129 100644 --- a/backend/src/plugins/TimeAndDate/commands/SetTimezoneCmd.ts +++ b/backend/src/plugins/TimeAndDate/commands/SetTimezoneCmd.ts @@ -1,8 +1,8 @@ import { escapeInlineCode } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; import { trimLines } from "../../../utils"; import { parseFuzzyTimezone } from "../../../utils/parseFuzzyTimezone"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { timeAndDateCmd } from "../types"; export const SetTimezoneCmd = timeAndDateCmd({ @@ -16,9 +16,8 @@ export const SetTimezoneCmd = timeAndDateCmd({ async run({ pluginData, message, args }) { const parsedTz = parseFuzzyTimezone(args.timezone); if (!parsedTz) { - sendErrorMessage( - pluginData, - message.channel, + pluginData.getPlugin(CommonPlugin).sendErrorMessage( + message, trimLines(` Invalid timezone: \`${escapeInlineCode(args.timezone)}\` Zeppelin uses timezone locations rather than specific timezone names. @@ -29,6 +28,6 @@ export const SetTimezoneCmd = timeAndDateCmd({ } await pluginData.state.memberTimezones.set(message.author.id, parsedTz); - sendSuccessMessage(pluginData, message.channel, `Your timezone is now set to **${parsedTz}**`); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(message, `Your timezone is now set to **${parsedTz}**`); }, }); diff --git a/backend/src/plugins/Utility/UtilityPlugin.ts b/backend/src/plugins/Utility/UtilityPlugin.ts index 68f6987a..9d966d8c 100644 --- a/backend/src/plugins/Utility/UtilityPlugin.ts +++ b/backend/src/plugins/Utility/UtilityPlugin.ts @@ -5,8 +5,9 @@ import { GuildCases } from "../../data/GuildCases"; import { GuildLogs } from "../../data/GuildLogs"; import { GuildSavedMessages } from "../../data/GuildSavedMessages"; import { Supporters } from "../../data/Supporters"; -import { makeIoTsConfigParser, sendSuccessMessage } from "../../pluginUtils"; +import { makeIoTsConfigParser } from "../../pluginUtils"; import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners"; +import { CommonPlugin } from "../Common/CommonPlugin"; import { LogsPlugin } from "../Logs/LogsPlugin"; import { ModActionsPlugin } from "../ModActions/ModActionsPlugin"; import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin"; @@ -169,8 +170,8 @@ export const UtilityPlugin = zeppelinGuildPlugin()({ }, userInfo(pluginData) { - return (userId: Snowflake, requestMemberId?: Snowflake) => { - return getUserInfoEmbed(pluginData, userId, false, requestMemberId); + return (userId: Snowflake) => { + return getUserInfoEmbed(pluginData, userId, false); }; }, @@ -214,7 +215,7 @@ export const UtilityPlugin = zeppelinGuildPlugin()({ const { guild } = pluginData; if (activeReloads.has(guild.id)) { - sendSuccessMessage(pluginData, activeReloads.get(guild.id)!, "Reloaded!"); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(activeReloads.get(guild.id)!, "Reloaded!"); activeReloads.delete(guild.id); } }, diff --git a/backend/src/plugins/Utility/commands/AvatarCmd.ts b/backend/src/plugins/Utility/commands/AvatarCmd.ts index ef44a2cb..fe81cd15 100644 --- a/backend/src/plugins/Utility/commands/AvatarCmd.ts +++ b/backend/src/plugins/Utility/commands/AvatarCmd.ts @@ -1,7 +1,7 @@ import { APIEmbed, ImageFormat } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage } from "../../../pluginUtils"; import { UnknownUser, renderUserUsername } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { utilityCmd } from "../types"; export const AvatarCmd = utilityCmd({ @@ -24,7 +24,7 @@ export const AvatarCmd = utilityCmd({ }; msg.channel.send({ embeds: [embed] }); } else { - sendErrorMessage(pluginData, msg.channel, "Invalid user ID"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Invalid user ID"); } }, }); diff --git a/backend/src/plugins/Utility/commands/ChannelInfoCmd.ts b/backend/src/plugins/Utility/commands/ChannelInfoCmd.ts index bbef9bcf..5b4a70bb 100644 --- a/backend/src/plugins/Utility/commands/ChannelInfoCmd.ts +++ b/backend/src/plugins/Utility/commands/ChannelInfoCmd.ts @@ -1,5 +1,5 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { getChannelInfoEmbed } from "../functions/getChannelInfoEmbed"; import { utilityCmd } from "../types"; @@ -16,7 +16,7 @@ export const ChannelInfoCmd = utilityCmd({ async run({ message, args, pluginData }) { const embed = await getChannelInfoEmbed(pluginData, args.channel); if (!embed) { - sendErrorMessage(pluginData, message.channel, "Unknown channel"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Unknown channel"); return; } diff --git a/backend/src/plugins/Utility/commands/CleanCmd.ts b/backend/src/plugins/Utility/commands/CleanCmd.ts index e47dc413..11e7bcfb 100644 --- a/backend/src/plugins/Utility/commands/CleanCmd.ts +++ b/backend/src/plugins/Utility/commands/CleanCmd.ts @@ -5,9 +5,10 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; import { LogType } from "../../../data/LogType"; import { SavedMessage } from "../../../data/entities/SavedMessage"; import { humanizeDurationShort } from "../../../humanizeDurationShort"; -import { getBaseUrl, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { getBaseUrl } from "../../../pluginUtils"; import { ModActionsPlugin } from "../../../plugins/ModActions/ModActionsPlugin"; import { DAYS, SECONDS, chunkArray, getInviteCodesInString, noop } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { LogsPlugin } from "../../Logs/LogsPlugin"; import { UtilityPluginType, utilityCmd } from "../types"; @@ -82,19 +83,22 @@ export interface CleanArgs { export async function cleanCmd(pluginData: GuildPluginData, args: CleanArgs | any, msg) { if (args.count > MAX_CLEAN_COUNT || args.count <= 0) { - sendErrorMessage( - pluginData, - msg.channel, - `Clean count must be between 1 and ${MAX_CLEAN_COUNT}`, - undefined, - args["response-interaction"], - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage( + msg, + `Clean count must be between 1 and ${MAX_CLEAN_COUNT}`, + undefined, + args["response-interaction"], + ); return; } const targetChannel = args.channel ? pluginData.guild.channels.cache.get(args.channel as Snowflake) : msg.channel; if (!targetChannel?.isTextBased()) { - sendErrorMessage(pluginData, msg.channel, `Invalid channel specified`, undefined, args["response-interaction"]); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `Invalid channel specified`, undefined, args["response-interaction"]); return; } @@ -106,13 +110,14 @@ export async function cleanCmd(pluginData: GuildPluginData, a categoryId: targetChannel.parentId, }); if (configForTargetChannel.can_clean !== true) { - sendErrorMessage( - pluginData, - msg.channel, - `Missing permissions to use clean on that channel`, - undefined, - args["response-interaction"], - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage( + msg, + `Missing permissions to use clean on that channel`, + undefined, + args["response-interaction"], + ); return; } } @@ -218,22 +223,14 @@ export async function cleanCmd(pluginData: GuildPluginData, a } } - responseMsg = await sendSuccessMessage( - pluginData, - msg.channel, - responseText, - undefined, - args["response-interaction"], - ); + responseMsg = await pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(msg, responseText, undefined, args["response-interaction"]); } else { const responseText = `Found no messages to clean${note ? ` (${note})` : ""}!`; - responseMsg = await sendErrorMessage( - pluginData, - msg.channel, - responseText, - undefined, - args["response-interaction"], - ); + responseMsg = await pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, responseText, undefined, args["response-interaction"]); } cleaningMessage?.delete(); diff --git a/backend/src/plugins/Utility/commands/ContextCmd.ts b/backend/src/plugins/Utility/commands/ContextCmd.ts index ceec4407..eb613f57 100644 --- a/backend/src/plugins/Utility/commands/ContextCmd.ts +++ b/backend/src/plugins/Utility/commands/ContextCmd.ts @@ -1,8 +1,8 @@ import { Snowflake, TextChannel } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage } from "../../../pluginUtils"; import { messageLink } from "../../../utils"; import { canReadChannel } from "../../../utils/canReadChannel"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { utilityCmd } from "../types"; export const ContextCmd = utilityCmd({ @@ -23,7 +23,7 @@ export const ContextCmd = utilityCmd({ async run({ message: msg, args, pluginData }) { if (args.channel && !(args.channel instanceof TextChannel)) { - sendErrorMessage(pluginData, msg.channel, "Channel must be a text channel"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Channel must be a text channel"); return; } @@ -31,7 +31,7 @@ export const ContextCmd = utilityCmd({ const messageId = args.messageId ?? args.message.messageId; if (!canReadChannel(channel, msg.member)) { - sendErrorMessage(pluginData, msg.channel, "Message context not found"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Message context not found"); return; } @@ -42,7 +42,7 @@ export const ContextCmd = utilityCmd({ }) )[0]; if (!previousMessage) { - sendErrorMessage(pluginData, msg.channel, "Message context not found"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Message context not found"); return; } diff --git a/backend/src/plugins/Utility/commands/EmojiInfoCmd.ts b/backend/src/plugins/Utility/commands/EmojiInfoCmd.ts index 5c89f3eb..114652a9 100644 --- a/backend/src/plugins/Utility/commands/EmojiInfoCmd.ts +++ b/backend/src/plugins/Utility/commands/EmojiInfoCmd.ts @@ -1,5 +1,5 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { getCustomEmojiId } from "../functions/getCustomEmojiId"; import { getEmojiInfoEmbed } from "../functions/getEmojiInfoEmbed"; import { utilityCmd } from "../types"; @@ -17,13 +17,13 @@ export const EmojiInfoCmd = utilityCmd({ async run({ message, args, pluginData }) { const emojiId = getCustomEmojiId(args.emoji); if (!emojiId) { - sendErrorMessage(pluginData, message.channel, "Emoji not found"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Emoji not found"); return; } const embed = await getEmojiInfoEmbed(pluginData, emojiId); if (!embed) { - sendErrorMessage(pluginData, message.channel, "Emoji not found"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Emoji not found"); return; } diff --git a/backend/src/plugins/Utility/commands/InfoCmd.ts b/backend/src/plugins/Utility/commands/InfoCmd.ts index 63d0ae81..23ffa8ac 100644 --- a/backend/src/plugins/Utility/commands/InfoCmd.ts +++ b/backend/src/plugins/Utility/commands/InfoCmd.ts @@ -1,10 +1,10 @@ import { Snowflake } from "discord.js"; import { getChannelId, getRoleId } from "knub/helpers"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage } from "../../../pluginUtils"; import { isValidSnowflake, noop, parseInviteCodeInput, resolveInvite, resolveUser } from "../../../utils"; import { canReadChannel } from "../../../utils/canReadChannel"; import { resolveMessageTarget } from "../../../utils/resolveMessageTarget"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { getChannelInfoEmbed } from "../functions/getChannelInfoEmbed"; import { getCustomEmojiId } from "../functions/getCustomEmojiId"; import { getEmojiInfoEmbed } from "../functions/getEmojiInfoEmbed"; @@ -42,7 +42,7 @@ export const InfoCmd = utilityCmd({ const channelId = getChannelId(value); const channel = channelId && pluginData.guild.channels.cache.get(channelId as Snowflake); if (channel) { - const embed = await getChannelInfoEmbed(pluginData, channelId!, message.author.id); + const embed = await getChannelInfoEmbed(pluginData, channelId!); if (embed) { message.channel.send({ embeds: [embed] }); return; @@ -54,7 +54,7 @@ export const InfoCmd = utilityCmd({ if (userCfg.can_server) { const guild = await pluginData.client.guilds.fetch(value as Snowflake).catch(noop); if (guild) { - const embed = await getServerInfoEmbed(pluginData, value, message.author.id); + const embed = await getServerInfoEmbed(pluginData, value); if (embed) { message.channel.send({ embeds: [embed] }); return; @@ -66,7 +66,7 @@ export const InfoCmd = utilityCmd({ if (userCfg.can_userinfo) { const user = await resolveUser(pluginData.client, value); if (user && userCfg.can_userinfo) { - const embed = await getUserInfoEmbed(pluginData, user.id, Boolean(args.compact), message.author.id); + const embed = await getUserInfoEmbed(pluginData, user.id, Boolean(args.compact)); if (embed) { message.channel.send({ embeds: [embed] }); return; @@ -79,12 +79,7 @@ export const InfoCmd = utilityCmd({ const messageTarget = await resolveMessageTarget(pluginData, value); if (messageTarget) { if (canReadChannel(messageTarget.channel, message.member)) { - const embed = await getMessageInfoEmbed( - pluginData, - messageTarget.channel.id, - messageTarget.messageId, - message.author.id, - ); + const embed = await getMessageInfoEmbed(pluginData, messageTarget.channel.id, messageTarget.messageId); if (embed) { message.channel.send({ embeds: [embed] }); return; @@ -112,7 +107,7 @@ export const InfoCmd = utilityCmd({ if (userCfg.can_server) { const serverPreview = await getGuildPreview(pluginData.client, value).catch(() => null); if (serverPreview) { - const embed = await getServerInfoEmbed(pluginData, value, message.author.id); + const embed = await getServerInfoEmbed(pluginData, value); if (embed) { message.channel.send({ embeds: [embed] }); return; @@ -125,7 +120,7 @@ export const InfoCmd = utilityCmd({ const roleId = getRoleId(value); const role = roleId && pluginData.guild.roles.cache.get(roleId as Snowflake); if (role) { - const embed = await getRoleInfoEmbed(pluginData, role, message.author.id); + const embed = await getRoleInfoEmbed(pluginData, role); message.channel.send({ embeds: [embed] }); return; } @@ -145,16 +140,17 @@ export const InfoCmd = utilityCmd({ // 9. Arbitrary ID if (isValidSnowflake(value) && userCfg.can_snowflake) { - const embed = await getSnowflakeInfoEmbed(pluginData, value, true, message.author.id); + const embed = await getSnowflakeInfoEmbed(value, true); message.channel.send({ embeds: [embed] }); return; } // 10. No can do - sendErrorMessage( - pluginData, - message.channel, - "Could not find anything with that value or you are lacking permission for the snowflake type", - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage( + message, + "Could not find anything with that value or you are lacking permission for the snowflake type", + ); }, }); diff --git a/backend/src/plugins/Utility/commands/InviteInfoCmd.ts b/backend/src/plugins/Utility/commands/InviteInfoCmd.ts index df34123a..262ab94a 100644 --- a/backend/src/plugins/Utility/commands/InviteInfoCmd.ts +++ b/backend/src/plugins/Utility/commands/InviteInfoCmd.ts @@ -1,6 +1,6 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage } from "../../../pluginUtils"; import { parseInviteCodeInput } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { getInviteInfoEmbed } from "../functions/getInviteInfoEmbed"; import { utilityCmd } from "../types"; @@ -18,7 +18,7 @@ export const InviteInfoCmd = utilityCmd({ const inviteCode = parseInviteCodeInput(args.inviteCode); const embed = await getInviteInfoEmbed(pluginData, inviteCode); if (!embed) { - sendErrorMessage(pluginData, message.channel, "Unknown invite"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Unknown invite"); return; } diff --git a/backend/src/plugins/Utility/commands/JumboCmd.ts b/backend/src/plugins/Utility/commands/JumboCmd.ts index 3dd1d30a..a8cf8678 100644 --- a/backend/src/plugins/Utility/commands/JumboCmd.ts +++ b/backend/src/plugins/Utility/commands/JumboCmd.ts @@ -3,8 +3,8 @@ import { AttachmentBuilder } from "discord.js"; import fs from "fs"; import twemoji from "twemoji"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage } from "../../../pluginUtils"; import { downloadFile, isEmoji, SECONDS } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { utilityCmd } from "../types"; const fsp = fs.promises; @@ -51,7 +51,7 @@ export const JumboCmd = utilityCmd({ let file: AttachmentBuilder | undefined; if (!isEmoji(args.emoji)) { - sendErrorMessage(pluginData, msg.channel, "Invalid emoji"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Invalid emoji"); return; } @@ -87,7 +87,7 @@ export const JumboCmd = utilityCmd({ } } if (!image) { - sendErrorMessage(pluginData, msg.channel, "Error occurred while jumboing default emoji"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Error occurred while jumboing default emoji"); return; } diff --git a/backend/src/plugins/Utility/commands/MessageInfoCmd.ts b/backend/src/plugins/Utility/commands/MessageInfoCmd.ts index 82096250..88df8eff 100644 --- a/backend/src/plugins/Utility/commands/MessageInfoCmd.ts +++ b/backend/src/plugins/Utility/commands/MessageInfoCmd.ts @@ -1,6 +1,6 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage } from "../../../pluginUtils"; import { canReadChannel } from "../../../utils/canReadChannel"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { getMessageInfoEmbed } from "../functions/getMessageInfoEmbed"; import { utilityCmd } from "../types"; @@ -16,18 +16,13 @@ export const MessageInfoCmd = utilityCmd({ async run({ message, args, pluginData }) { if (!canReadChannel(args.message.channel, message.member)) { - sendErrorMessage(pluginData, message.channel, "Unknown message"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Unknown message"); return; } - const embed = await getMessageInfoEmbed( - pluginData, - args.message.channel.id, - args.message.messageId, - message.author.id, - ); + const embed = await getMessageInfoEmbed(pluginData, args.message.channel.id, args.message.messageId); if (!embed) { - sendErrorMessage(pluginData, message.channel, "Unknown message"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Unknown message"); return; } diff --git a/backend/src/plugins/Utility/commands/NicknameCmd.ts b/backend/src/plugins/Utility/commands/NicknameCmd.ts index 9821ef32..63d5eac8 100644 --- a/backend/src/plugins/Utility/commands/NicknameCmd.ts +++ b/backend/src/plugins/Utility/commands/NicknameCmd.ts @@ -1,7 +1,8 @@ import { escapeBold } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { canActOn, sendSuccessMessage } from "../../../pluginUtils"; +import { canActOn } from "../../../pluginUtils"; import { errorMessage } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { utilityCmd } from "../types"; export const NicknameCmd = utilityCmd({ @@ -45,10 +46,11 @@ export const NicknameCmd = utilityCmd({ return; } - sendSuccessMessage( - pluginData, - msg.channel, - `Changed nickname of <@!${args.member.id}> from **${oldNickname}** to **${args.nickname}**`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage( + msg, + `Changed nickname of <@!${args.member.id}> from **${oldNickname}** to **${args.nickname}**`, + ); }, }); diff --git a/backend/src/plugins/Utility/commands/NicknameResetCmd.ts b/backend/src/plugins/Utility/commands/NicknameResetCmd.ts index f86a33c9..61417419 100644 --- a/backend/src/plugins/Utility/commands/NicknameResetCmd.ts +++ b/backend/src/plugins/Utility/commands/NicknameResetCmd.ts @@ -1,6 +1,7 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { canActOn, sendSuccessMessage } from "../../../pluginUtils"; +import { canActOn } from "../../../pluginUtils"; import { errorMessage } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { utilityCmd } from "../types"; export const NicknameResetCmd = utilityCmd({ @@ -31,6 +32,6 @@ export const NicknameResetCmd = utilityCmd({ return; } - sendSuccessMessage(pluginData, msg.channel, `The nickname of <@!${args.member.id}> has been reset`); + pluginData.getPlugin(CommonPlugin).sendSuccessMessage(msg, `The nickname of <@!${args.member.id}> has been reset`); }, }); diff --git a/backend/src/plugins/Utility/commands/RoleInfoCmd.ts b/backend/src/plugins/Utility/commands/RoleInfoCmd.ts index b04b49a7..6f540b4b 100644 --- a/backend/src/plugins/Utility/commands/RoleInfoCmd.ts +++ b/backend/src/plugins/Utility/commands/RoleInfoCmd.ts @@ -13,7 +13,7 @@ export const RoleInfoCmd = utilityCmd({ }, async run({ message, args, pluginData }) { - const embed = await getRoleInfoEmbed(pluginData, args.role, message.author.id); + const embed = await getRoleInfoEmbed(pluginData, args.role); message.channel.send({ embeds: [embed] }); }, }); diff --git a/backend/src/plugins/Utility/commands/RolesCmd.ts b/backend/src/plugins/Utility/commands/RolesCmd.ts index 86c09554..d04903f9 100644 --- a/backend/src/plugins/Utility/commands/RolesCmd.ts +++ b/backend/src/plugins/Utility/commands/RolesCmd.ts @@ -1,7 +1,7 @@ import { Role } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage } from "../../../pluginUtils"; import { chunkArray, sorter, trimLines } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { refreshMembersIfNeeded } from "../refreshMembers"; import { utilityCmd } from "../types"; @@ -62,7 +62,7 @@ export const RolesCmd = utilityCmd({ } else if (sort === "name") { roles.sort(sorter((r) => r.name.toLowerCase(), sortDir)); } else { - sendErrorMessage(pluginData, msg.channel, "Unknown sorting method"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Unknown sorting method"); return; } diff --git a/backend/src/plugins/Utility/commands/ServerInfoCmd.ts b/backend/src/plugins/Utility/commands/ServerInfoCmd.ts index 30fb7efe..2e5d7ba5 100644 --- a/backend/src/plugins/Utility/commands/ServerInfoCmd.ts +++ b/backend/src/plugins/Utility/commands/ServerInfoCmd.ts @@ -1,5 +1,5 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { getServerInfoEmbed } from "../functions/getServerInfoEmbed"; import { utilityCmd } from "../types"; @@ -15,9 +15,9 @@ export const ServerInfoCmd = utilityCmd({ async run({ message, pluginData, args }) { const serverId = args.serverId || pluginData.guild.id; - const serverInfoEmbed = await getServerInfoEmbed(pluginData, serverId, message.author.id); + const serverInfoEmbed = await getServerInfoEmbed(pluginData, serverId); if (!serverInfoEmbed) { - sendErrorMessage(pluginData, message.channel, "Could not find information for that server"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "Could not find information for that server"); return; } diff --git a/backend/src/plugins/Utility/commands/SnowflakeInfoCmd.ts b/backend/src/plugins/Utility/commands/SnowflakeInfoCmd.ts index 59f43893..bf0e859f 100644 --- a/backend/src/plugins/Utility/commands/SnowflakeInfoCmd.ts +++ b/backend/src/plugins/Utility/commands/SnowflakeInfoCmd.ts @@ -12,8 +12,8 @@ export const SnowflakeInfoCmd = utilityCmd({ id: ct.anyId(), }, - async run({ message, args, pluginData }) { - const embed = await getSnowflakeInfoEmbed(pluginData, args.id, false, message.author.id); + async run({ message, args }) { + const embed = await getSnowflakeInfoEmbed(args.id, false); message.channel.send({ embeds: [embed] }); }, }); diff --git a/backend/src/plugins/Utility/commands/SourceCmd.ts b/backend/src/plugins/Utility/commands/SourceCmd.ts index 54c24647..be3a4bab 100644 --- a/backend/src/plugins/Utility/commands/SourceCmd.ts +++ b/backend/src/plugins/Utility/commands/SourceCmd.ts @@ -1,7 +1,8 @@ import moment from "moment-timezone"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { getBaseUrl, sendErrorMessage } from "../../../pluginUtils"; +import { getBaseUrl } from "../../../pluginUtils"; import { canReadChannel } from "../../../utils/canReadChannel"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { utilityCmd } from "../types"; export const SourceCmd = utilityCmd({ @@ -16,13 +17,13 @@ export const SourceCmd = utilityCmd({ async run({ message: cmdMessage, args, pluginData }) { if (!canReadChannel(args.message.channel, cmdMessage.member)) { - sendErrorMessage(pluginData, cmdMessage.channel, "Unknown message"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(cmdMessage, "Unknown message"); return; } const message = await args.message.channel.messages.fetch(args.message.messageId); if (!message) { - sendErrorMessage(pluginData, cmdMessage.channel, "Unknown message"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(cmdMessage, "Unknown message"); return; } diff --git a/backend/src/plugins/Utility/commands/UserInfoCmd.ts b/backend/src/plugins/Utility/commands/UserInfoCmd.ts index c7ce8b48..6ba99548 100644 --- a/backend/src/plugins/Utility/commands/UserInfoCmd.ts +++ b/backend/src/plugins/Utility/commands/UserInfoCmd.ts @@ -1,5 +1,5 @@ import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { sendErrorMessage } from "../../../pluginUtils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { getUserInfoEmbed } from "../functions/getUserInfoEmbed"; import { utilityCmd } from "../types"; @@ -17,9 +17,9 @@ export const UserInfoCmd = utilityCmd({ async run({ message, args, pluginData }) { const userId = args.user?.id || message.author.id; - const embed = await getUserInfoEmbed(pluginData, userId, args.compact, message.author.id); + const embed = await getUserInfoEmbed(pluginData, userId, args.compact); if (!embed) { - sendErrorMessage(pluginData, message.channel, "User not found"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(message, "User not found"); return; } diff --git a/backend/src/plugins/Utility/commands/VcdisconnectCmd.ts b/backend/src/plugins/Utility/commands/VcdisconnectCmd.ts index 0f82458a..f5bdf43c 100644 --- a/backend/src/plugins/Utility/commands/VcdisconnectCmd.ts +++ b/backend/src/plugins/Utility/commands/VcdisconnectCmd.ts @@ -1,7 +1,8 @@ import { VoiceChannel } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { canActOn, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { canActOn } from "../../../pluginUtils"; import { renderUserUsername } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { LogsPlugin } from "../../Logs/LogsPlugin"; import { utilityCmd } from "../types"; @@ -17,12 +18,12 @@ export const VcdisconnectCmd = utilityCmd({ async run({ message: msg, args, pluginData }) { if (!canActOn(pluginData, msg.member, args.member)) { - sendErrorMessage(pluginData, msg.channel, "Cannot move: insufficient permissions"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Cannot move: insufficient permissions"); return; } if (!args.member.voice?.channelId) { - sendErrorMessage(pluginData, msg.channel, "Member is not in a voice channel"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Member is not in a voice channel"); return; } const channel = pluginData.guild.channels.cache.get(args.member.voice.channelId) as VoiceChannel; @@ -30,7 +31,7 @@ export const VcdisconnectCmd = utilityCmd({ try { await args.member.voice.disconnect(); } catch { - sendErrorMessage(pluginData, msg.channel, "Failed to disconnect member"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Failed to disconnect member"); return; } @@ -40,10 +41,8 @@ export const VcdisconnectCmd = utilityCmd({ oldChannel: channel, }); - sendSuccessMessage( - pluginData, - msg.channel, - `**${renderUserUsername(args.member.user)}** disconnected from **${channel.name}**`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(msg, `**${renderUserUsername(args.member.user)}** disconnected from **${channel.name}**`); }, }); diff --git a/backend/src/plugins/Utility/commands/VcmoveCmd.ts b/backend/src/plugins/Utility/commands/VcmoveCmd.ts index db00161e..ba9e998d 100644 --- a/backend/src/plugins/Utility/commands/VcmoveCmd.ts +++ b/backend/src/plugins/Utility/commands/VcmoveCmd.ts @@ -1,7 +1,8 @@ import { ChannelType, Snowflake, VoiceChannel } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes"; -import { canActOn, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils"; +import { canActOn } from "../../../pluginUtils"; import { channelMentionRegex, isSnowflake, renderUserUsername, simpleClosestStringMatch } from "../../../utils"; +import { CommonPlugin } from "../../Common/CommonPlugin"; import { LogsPlugin } from "../../Logs/LogsPlugin"; import { utilityCmd } from "../types"; @@ -23,7 +24,7 @@ export const VcmoveCmd = utilityCmd({ // Snowflake -> resolve channel directly 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"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Unknown or non-voice channel"); return; } @@ -33,7 +34,7 @@ export const VcmoveCmd = utilityCmd({ const channelId = args.channel.match(channelMentionRegex)![1]; const potentialChannel = pluginData.guild.channels.cache.get(channelId as Snowflake); if (!potentialChannel || !(potentialChannel instanceof VoiceChannel)) { - sendErrorMessage(pluginData, msg.channel, "Unknown or non-voice channel"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Unknown or non-voice channel"); return; } @@ -45,7 +46,7 @@ export const VcmoveCmd = utilityCmd({ ); const closestMatch = simpleClosestStringMatch(args.channel, voiceChannels, (ch) => ch.name); if (!closestMatch) { - sendErrorMessage(pluginData, msg.channel, "No matching voice channels"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "No matching voice channels"); return; } @@ -53,12 +54,12 @@ export const VcmoveCmd = utilityCmd({ } if (!args.member.voice?.channelId) { - sendErrorMessage(pluginData, msg.channel, "Member is not in a voice channel"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Member is not in a voice channel"); return; } if (args.member.voice.channelId === channel.id) { - sendErrorMessage(pluginData, msg.channel, "Member is already on that channel!"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Member is already on that channel!"); return; } @@ -69,7 +70,7 @@ export const VcmoveCmd = utilityCmd({ channel: channel.id, }); } catch { - sendErrorMessage(pluginData, msg.channel, "Failed to move member"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Failed to move member"); return; } @@ -80,11 +81,9 @@ export const VcmoveCmd = utilityCmd({ newChannel: channel, }); - sendSuccessMessage( - pluginData, - msg.channel, - `**${renderUserUsername(args.member.user)}** moved to **${channel.name}**`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage(msg, `**${renderUserUsername(args.member.user)}** moved to **${channel.name}**`); }, }); @@ -106,7 +105,7 @@ export const VcmoveAllCmd = utilityCmd({ // Snowflake -> resolve channel directly 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"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Unknown or non-voice channel"); return; } @@ -116,7 +115,7 @@ export const VcmoveAllCmd = utilityCmd({ const channelId = args.channel.match(channelMentionRegex)![1]; const potentialChannel = pluginData.guild.channels.cache.get(channelId as Snowflake); if (!potentialChannel || !(potentialChannel instanceof VoiceChannel)) { - sendErrorMessage(pluginData, msg.channel, "Unknown or non-voice channel"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Unknown or non-voice channel"); return; } @@ -128,7 +127,7 @@ export const VcmoveAllCmd = utilityCmd({ ); const closestMatch = simpleClosestStringMatch(args.channel, voiceChannels, (ch) => ch.name); if (!closestMatch) { - sendErrorMessage(pluginData, msg.channel, "No matching voice channels"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "No matching voice channels"); return; } @@ -136,12 +135,12 @@ export const VcmoveAllCmd = utilityCmd({ } if (args.oldChannel.members.size === 0) { - sendErrorMessage(pluginData, msg.channel, "Voice channel is empty"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Voice channel is empty"); return; } if (args.oldChannel.id === channel.id) { - sendErrorMessage(pluginData, msg.channel, "Cant move from and to the same channel!"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Cant move from and to the same channel!"); return; } @@ -154,11 +153,12 @@ export const VcmoveAllCmd = utilityCmd({ // Check for permissions but allow self-moves if (currMember.id !== msg.member.id && !canActOn(pluginData, msg.member, currMember)) { - sendErrorMessage( - pluginData, - msg.channel, - `Failed to move ${renderUserUsername(currMember.user)} (${currMember.id}): You cannot act on this member`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage( + msg, + `Failed to move ${renderUserUsername(currMember.user)} (${currMember.id}): You cannot act on this member`, + ); errAmt++; continue; } @@ -169,14 +169,12 @@ export const VcmoveAllCmd = utilityCmd({ }); } catch { if (msg.member.id === currMember.id) { - sendErrorMessage(pluginData, msg.channel, "Unknown error when trying to move members"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "Unknown error when trying to move members"); return; } - sendErrorMessage( - pluginData, - msg.channel, - `Failed to move ${renderUserUsername(currMember.user)} (${currMember.id})`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendErrorMessage(msg, `Failed to move ${renderUserUsername(currMember.user)} (${currMember.id})`); errAmt++; continue; } @@ -190,13 +188,14 @@ export const VcmoveAllCmd = utilityCmd({ } if (moveAmt !== errAmt) { - sendSuccessMessage( - pluginData, - msg.channel, - `${moveAmt - errAmt} members from **${args.oldChannel.name}** moved to **${channel.name}**`, - ); + pluginData + .getPlugin(CommonPlugin) + .sendSuccessMessage( + msg, + `${moveAmt - errAmt} members from **${args.oldChannel.name}** moved to **${channel.name}**`, + ); } else { - sendErrorMessage(pluginData, msg.channel, `Failed to move any members.`); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, `Failed to move any members.`); } }, }); diff --git a/backend/src/plugins/Utility/functions/getChannelInfoEmbed.ts b/backend/src/plugins/Utility/functions/getChannelInfoEmbed.ts index ee006f5f..33a04b8e 100644 --- a/backend/src/plugins/Utility/functions/getChannelInfoEmbed.ts +++ b/backend/src/plugins/Utility/functions/getChannelInfoEmbed.ts @@ -22,7 +22,6 @@ const FORUM_CHANNEL_ICON = export async function getChannelInfoEmbed( pluginData: GuildPluginData, channelId: string, - requestMemberId?: string, ): Promise { const channel = pluginData.guild.channels.cache.get(channelId as Snowflake); if (!channel) { diff --git a/backend/src/plugins/Utility/functions/getMessageInfoEmbed.ts b/backend/src/plugins/Utility/functions/getMessageInfoEmbed.ts index 1568a3e3..4b615cf0 100644 --- a/backend/src/plugins/Utility/functions/getMessageInfoEmbed.ts +++ b/backend/src/plugins/Utility/functions/getMessageInfoEmbed.ts @@ -9,7 +9,6 @@ import { trimEmptyLines, trimLines, } from "../../../utils"; -import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin"; import { UtilityPluginType } from "../types"; const MESSAGE_ICON = "https://cdn.discordapp.com/attachments/740650744830623756/740685652152025088/message.png"; @@ -18,7 +17,6 @@ export async function getMessageInfoEmbed( pluginData: GuildPluginData, channelId: string, messageId: string, - requestMemberId?: string, ): Promise { const message = await (pluginData.guild.channels.resolve(channelId as Snowflake) as TextChannel).messages .fetch(messageId as Snowflake) @@ -27,8 +25,6 @@ export async function getMessageInfoEmbed( return null; } - const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin); - const embed: EmbedWith<"fields" | "author"> = { fields: [], author: { diff --git a/backend/src/plugins/Utility/functions/getRoleInfoEmbed.ts b/backend/src/plugins/Utility/functions/getRoleInfoEmbed.ts index fa3188ec..dd19d9b2 100644 --- a/backend/src/plugins/Utility/functions/getRoleInfoEmbed.ts +++ b/backend/src/plugins/Utility/functions/getRoleInfoEmbed.ts @@ -6,11 +6,7 @@ import { UtilityPluginType } from "../types"; const MENTION_ICON = "https://cdn.discordapp.com/attachments/705009450855039042/839284872152481792/mention.png"; -export async function getRoleInfoEmbed( - pluginData: GuildPluginData, - role: Role, - requestMemberId?: string, -): Promise { +export async function getRoleInfoEmbed(pluginData: GuildPluginData, role: Role): Promise { const embed: EmbedWith<"fields" | "author" | "color"> = { fields: [], author: { diff --git a/backend/src/plugins/Utility/functions/getServerInfoEmbed.ts b/backend/src/plugins/Utility/functions/getServerInfoEmbed.ts index d0202db7..bbd1f78f 100644 --- a/backend/src/plugins/Utility/functions/getServerInfoEmbed.ts +++ b/backend/src/plugins/Utility/functions/getServerInfoEmbed.ts @@ -25,7 +25,6 @@ const prettifyFeature = (feature: string): string => export async function getServerInfoEmbed( pluginData: GuildPluginData, serverId: string, - requestMemberId?: string, ): Promise { const thisServer = serverId === pluginData.guild.id ? pluginData.guild : null; const [restGuild, guildPreview] = await Promise.all([ diff --git a/backend/src/plugins/Utility/functions/getSnowflakeInfoEmbed.ts b/backend/src/plugins/Utility/functions/getSnowflakeInfoEmbed.ts index ef676fd1..8449ba74 100644 --- a/backend/src/plugins/Utility/functions/getSnowflakeInfoEmbed.ts +++ b/backend/src/plugins/Utility/functions/getSnowflakeInfoEmbed.ts @@ -1,17 +1,10 @@ import { APIEmbed } from "discord.js"; -import { GuildPluginData } from "knub"; import { EmbedWith, preEmbedPadding } from "../../../utils"; import { snowflakeToTimestamp } from "../../../utils/snowflakeToTimestamp"; -import { UtilityPluginType } from "../types"; const SNOWFLAKE_ICON = "https://cdn.discordapp.com/attachments/740650744830623756/742020790471491668/snowflake.png"; -export async function getSnowflakeInfoEmbed( - pluginData: GuildPluginData, - snowflake: string, - showUnknownWarning = false, - requestMemberId?: string, -): Promise { +export async function getSnowflakeInfoEmbed(snowflake: string, showUnknownWarning = false): Promise { const embed: EmbedWith<"fields" | "author"> = { fields: [], author: { diff --git a/backend/src/plugins/Utility/functions/getUserInfoEmbed.ts b/backend/src/plugins/Utility/functions/getUserInfoEmbed.ts index ef8d2320..b568a833 100644 --- a/backend/src/plugins/Utility/functions/getUserInfoEmbed.ts +++ b/backend/src/plugins/Utility/functions/getUserInfoEmbed.ts @@ -13,7 +13,6 @@ import { trimLines, UnknownUser, } from "../../../utils"; -import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin"; import { UtilityPluginType } from "../types"; const MAX_ROLES_TO_DISPLAY = 15; @@ -27,7 +26,6 @@ export async function getUserInfoEmbed( pluginData: GuildPluginData, userId: string, compact = false, - requestMemberId?: string, ): Promise { const user = await resolveUser(pluginData.client, userId); if (!user || user instanceof UnknownUser) { @@ -40,8 +38,6 @@ export async function getUserInfoEmbed( fields: [], }; - const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin); - embed.author = { name: `${user.bot ? "Bot" : "User"}: ${renderUsername(user.username, user.discriminator)}`, }; diff --git a/backend/src/plugins/Utility/search.ts b/backend/src/plugins/Utility/search.ts index 19710b58..07e3477d 100644 --- a/backend/src/plugins/Utility/search.ts +++ b/backend/src/plugins/Utility/search.ts @@ -13,11 +13,12 @@ import escapeStringRegexp from "escape-string-regexp"; import { ArgsFromSignatureOrArray, GuildPluginData } from "knub"; import moment from "moment-timezone"; import { RegExpRunner, allowTimeout } from "../../RegExpRunner"; -import { getBaseUrl, sendErrorMessage } from "../../pluginUtils"; +import { getBaseUrl } from "../../pluginUtils"; import { MINUTES, multiSorter, renderUserUsername, sorter, trimLines } from "../../utils"; import { asyncFilter } from "../../utils/async"; import { hasDiscordPermissions } from "../../utils/hasDiscordPermissions"; import { InvalidRegexError, inputPatternToRegExp } from "../../validatorUtils"; +import { CommonPlugin } from "../Common/CommonPlugin"; import { banSearchSignature } from "./commands/BanSearchCmd"; import { searchCmdSignature } from "./commands/SearchCmd"; import { getUserInfoEmbed } from "./functions/getUserInfoEmbed"; @@ -115,12 +116,12 @@ export async function displaySearch( } } catch (e) { if (e instanceof SearchError) { - sendErrorMessage(pluginData, msg.channel, e.message); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, e.message); return; } if (e instanceof InvalidRegexError) { - sendErrorMessage(pluginData, msg.channel, e.message); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, e.message); return; } @@ -128,7 +129,7 @@ export async function displaySearch( } if (searchResult.totalResults === 0) { - sendErrorMessage(pluginData, msg.channel, "No results found"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "No results found"); return; } @@ -259,12 +260,12 @@ export async function archiveSearch( } } catch (e) { if (e instanceof SearchError) { - sendErrorMessage(pluginData, msg.channel, e.message); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, e.message); return; } if (e instanceof InvalidRegexError) { - sendErrorMessage(pluginData, msg.channel, e.message); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, e.message); return; } @@ -272,7 +273,7 @@ export async function archiveSearch( } if (results.totalResults === 0) { - sendErrorMessage(pluginData, msg.channel, "No results found"); + pluginData.getPlugin(CommonPlugin).sendErrorMessage(msg, "No results found"); return; } diff --git a/backend/src/plugins/availablePlugins.ts b/backend/src/plugins/availablePlugins.ts index 45119f0f..61597215 100644 --- a/backend/src/plugins/availablePlugins.ts +++ b/backend/src/plugins/availablePlugins.ts @@ -5,6 +5,7 @@ import { BotControlPlugin } from "./BotControl/BotControlPlugin"; import { CasesPlugin } from "./Cases/CasesPlugin"; import { CensorPlugin } from "./Censor/CensorPlugin"; import { ChannelArchiverPlugin } from "./ChannelArchiver/ChannelArchiverPlugin"; +import { CommonPlugin } from "./Common/CommonPlugin"; import { CompanionChannelsPlugin } from "./CompanionChannels/CompanionChannelsPlugin"; import { ContextMenuPlugin } from "./ContextMenus/ContextMenuPlugin"; import { CountersPlugin } from "./Counters/CountersPlugin"; @@ -78,6 +79,7 @@ export const guildPlugins: Array> = [ InternalPosterPlugin, RoleManagerPlugin, RoleButtonsPlugin, + CommonPlugin, ]; // prettier-ignore @@ -96,5 +98,6 @@ export const baseGuildPlugins: Array> = [ CasesPlugin, MutesPlugin, TimeAndDatePlugin, + CommonPlugin, // TODO: Replace these with proper dependencies ]; diff --git a/backend/src/utils.ts b/backend/src/utils.ts index c6c705db..61938019 100644 --- a/backend/src/utils.ts +++ b/backend/src/utils.ts @@ -1,6 +1,7 @@ import { APIEmbed, ChannelType, + ChatInputCommandInteraction, Client, DiscordAPIError, EmbedData, @@ -1409,11 +1410,11 @@ export async function resolveStickerId(bot: Client, id: Snowflake): Promise { - return waitForButtonConfirm(channel, content, { restrictToId: userId }); + return waitForButtonConfirm(context, content, { restrictToId: userId }); } export function messageSummary(msg: SavedMessage) { diff --git a/backend/src/utils/createPaginatedMessage.ts b/backend/src/utils/createPaginatedMessage.ts index d1075499..e1be4ea4 100644 --- a/backend/src/utils/createPaginatedMessage.ts +++ b/backend/src/utils/createPaginatedMessage.ts @@ -7,7 +7,6 @@ import { MessageReaction, PartialMessageReaction, PartialUser, - TextBasedChannel, User, } from "discord.js"; import { sendContextResponse } from "../pluginUtils"; @@ -29,7 +28,7 @@ const defaultOpts: PaginateMessageOpts = { export async function createPaginatedMessage( client: Client, - context: TextBasedChannel | User | ChatInputCommandInteraction, + context: Message | User | ChatInputCommandInteraction, totalPages: number, loadPageFn: LoadPageFn, opts: Partial = {}, diff --git a/backend/src/utils/waitForInteraction.ts b/backend/src/utils/waitForInteraction.ts index 64cab738..c2cc659b 100644 --- a/backend/src/utils/waitForInteraction.ts +++ b/backend/src/utils/waitForInteraction.ts @@ -3,10 +3,10 @@ import { ButtonBuilder, ButtonStyle, ChatInputCommandInteraction, + Message, MessageActionRowComponentBuilder, MessageComponentInteraction, MessageCreateOptions, - TextBasedChannel, User, } from "discord.js"; import moment from "moment"; @@ -15,8 +15,8 @@ import { isContextInteraction } from "../pluginUtils"; import { noop } from "../utils"; export async function waitForButtonConfirm( - context: TextBasedChannel | User | ChatInputCommandInteraction, - toPost: MessageCreateOptions, + context: Message | User | ChatInputCommandInteraction, + toPost: Omit, options?: WaitForOptions, ): Promise { return new Promise(async (resolve) => { @@ -33,9 +33,17 @@ export async function waitForButtonConfirm( .setLabel(options?.cancelText || "Cancel") .setCustomId(`cancelButton:${idMod}:${uuidv4()}`), ]); - const sendMethod = contextIsInteraction ? (context.replied ? "followUp" : "reply") : "send"; + const sendMethod = () => { + return contextIsInteraction + ? context.replied + ? context.followUp + : context.reply + : "send" in context + ? context.send + : context.channel.send; + }; const extraParameters = contextIsInteraction ? { fetchReply: true } : {}; - const message = await context[sendMethod]({ ...toPost, components: [row], ...extraParameters }); + const message = await sendMethod()({ ...toPost, components: [row], ...extraParameters }); const collector = message.createMessageComponentCollector({ time: 10000 }); diff --git a/dashboard/package-lock.json b/dashboard/package-lock.json index cf8fc8d3..e68d6930 100644 --- a/dashboard/package-lock.json +++ b/dashboard/package-lock.json @@ -3629,9 +3629,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001507", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001507.tgz", - "integrity": "sha512-SFpUDoSLCaE5XYL2jfqe9ova/pbQHEmbheDf5r4diNwbAgR3qxM9NQtfsiSscjqoya5K7kFcHPUQ+VsUkIJR4A==", + "version": "1.0.30001587", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz", + "integrity": "sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==", "dev": true, "funding": [ {