diff --git a/backend/src/RegExpRunner.ts b/backend/src/RegExpRunner.ts index a65eae3a..ea37fe03 100644 --- a/backend/src/RegExpRunner.ts +++ b/backend/src/RegExpRunner.ts @@ -1,5 +1,5 @@ -import { EventEmitter } from "node:events"; import { CooldownManager } from "knub"; +import { EventEmitter } from "node:events"; import { RegExpWorker, TimeoutError } from "regexp-worker"; import { MINUTES, SECONDS } from "./utils.js"; import Timeout = NodeJS.Timeout; diff --git a/backend/src/api/docs.ts b/backend/src/api/docs.ts index ec12dacd..1989e486 100644 --- a/backend/src/api/docs.ts +++ b/backend/src/api/docs.ts @@ -73,7 +73,10 @@ function formatZodConfigSchema(schema: z.ZodType) { return schema.def.values; } if (isZodIntersection(schema)) { - return [formatZodConfigSchema(schema.def.left as z.ZodType), formatZodConfigSchema(schema.def.right as z.ZodType)].join(" & "); + return [ + formatZodConfigSchema(schema.def.left as z.ZodType), + formatZodConfigSchema(schema.def.right as z.ZodType), + ].join(" & "); } if (schema.def.type === "string") { return "string"; @@ -131,7 +134,7 @@ export function initDocs(router: express.Router) { config: cmd.config, })); - const defaultOptions = (pluginInfo.plugin as any /* TODO */).defaultOptions || {}; + const defaultOptions = (pluginInfo.plugin as any) /* TODO */.defaultOptions || {}; res.json({ name: pluginInfo.plugin.name, diff --git a/backend/src/configValidator.ts b/backend/src/configValidator.ts index 04e475ad..7cf6851d 100644 --- a/backend/src/configValidator.ts +++ b/backend/src/configValidator.ts @@ -28,12 +28,15 @@ export async function validateGuildConfig(config: any): Promise { } const plugin = pluginNameToPlugin.get(pluginName)!; - const configManager = new PluginConfigManager({}, { - configSchema: plugin.configSchema, - defaultOverrides: plugin.defaultOverrides ?? [], - levels: {}, - customOverrideCriteriaFunctions: plugin.customOverrideCriteriaFunctions, - }); + const configManager = new PluginConfigManager( + {}, + { + configSchema: plugin.configSchema, + defaultOverrides: plugin.defaultOverrides ?? [], + levels: {}, + customOverrideCriteriaFunctions: plugin.customOverrideCriteriaFunctions, + }, + ); try { await configManager.init(); diff --git a/backend/src/env.ts b/backend/src/env.ts index f2a387fd..6af1d525 100644 --- a/backend/src/env.ts +++ b/backend/src/env.ts @@ -37,6 +37,7 @@ const envType = z.object({ .optional(), PHISHERMAN_API_KEY: z.string().optional(), + FISHFISH_API_KEY: z.string().optional(), DB_HOST: z.string().optional(), DB_PORT: z.preprocess((v) => Number(v), z.number()).optional(), diff --git a/backend/src/exportSchemas.ts b/backend/src/exportSchemas.ts index e5e80984..c55e3faf 100644 --- a/backend/src/exportSchemas.ts +++ b/backend/src/exportSchemas.ts @@ -1,8 +1,8 @@ +import fs from "node:fs"; import { z } from "zod/v4"; import { availableGuildPlugins } from "./plugins/availablePlugins.js"; import { zZeppelinGuildConfig } from "./types.js"; import { deepPartial } from "./utils/zodDeepPartial.js"; -import fs from "node:fs"; const basePluginOverrideCriteriaSchema = z.strictObject({ channel: z diff --git a/backend/src/pluginUtils.ts b/backend/src/pluginUtils.ts index 9d1936ce..6d9c0cf8 100644 --- a/backend/src/pluginUtils.ts +++ b/backend/src/pluginUtils.ts @@ -3,7 +3,6 @@ */ import { - BaseChannel, BitField, BitFieldResolvable, ChatInputCommandInteraction, @@ -19,15 +18,21 @@ import { MessageFlagsString, ModalSubmitInteraction, PermissionsBitField, - SendableChannels, TextBasedChannel, - User, } from "discord.js"; -import { AnyPluginData, BasePluginData, CommandContext, ExtendedMatchParams, GuildPluginData, helpers, PluginConfigManager } from "knub"; +import { + AnyPluginData, + BasePluginData, + CommandContext, + ExtendedMatchParams, + GuildPluginData, + helpers, + PluginConfigManager, +} from "knub"; +import z from "zod/v4"; import { isStaff } from "./staff.js"; import { TZeppelinKnub } from "./types.js"; import { Tail } from "./utils/typeUtils.js"; -import z from "zod/v4"; const { getMemberLevel } = helpers; @@ -66,18 +71,14 @@ export type GenericCommandSource = Message | CommandInteraction | ModalSubmitInt export function isContextInteraction( context: GenericCommandSource, ): context is CommandInteraction | ModalSubmitInteraction { - return (context instanceof CommandInteraction || context instanceof ModalSubmitInteraction); + return context instanceof CommandInteraction || context instanceof ModalSubmitInteraction; } -export function isContextMessage( - context: GenericCommandSource, -): context is Message { - return (context instanceof Message); +export function isContextMessage(context: GenericCommandSource): context is Message { + return context instanceof Message; } -export async function getContextChannel( - context: GenericCommandSource, -): Promise { +export async function getContextChannel(context: GenericCommandSource): Promise { if (isContextInteraction(context)) { return context.channel; } @@ -87,9 +88,7 @@ export async function getContextChannel( throw new Error("Unknown context type"); } -export function getContextChannelId( - context: GenericCommandSource, -): string | null { +export function getContextChannelId(context: GenericCommandSource): string | null { return context.channelId; } @@ -104,13 +103,10 @@ export async function fetchContextChannel(context: GenericCommandSource) { return (await context.guild.channels.fetch(channelId))!; } -function flagsWithEphemeral< - TFlags extends string, - TType extends number | bigint ->(flags: BitFieldResolvable, ephemeral: boolean): BitFieldResolvable< - TFlags | Extract, - TType | MessageFlags.Ephemeral -> { +function flagsWithEphemeral( + flags: BitFieldResolvable, + ephemeral: boolean, +): BitFieldResolvable, TType | MessageFlags.Ephemeral> { if (!ephemeral) { return flags; } @@ -150,7 +146,7 @@ export async function sendContextResponse( if (!contextChannel?.isSendable()) { throw new Error("Context channel does not exist or is not sendable"); } - + return contextChannel.send(content); } @@ -167,7 +163,10 @@ export async function deleteContextResponse(response: ContextResponse): Promise< await response.delete(); } -export async function getConfigForContext>(config: PluginConfigManager, context: GenericCommandSource): Promise> { +export async function getConfigForContext>( + config: PluginConfigManager, + context: GenericCommandSource, +): Promise> { if (context instanceof ChatInputCommandInteraction) { // TODO: Support for modal interactions (here and Knub) return config.getForInteraction(context); diff --git a/backend/src/plugins/AutoDelete/AutoDeletePlugin.ts b/backend/src/plugins/AutoDelete/AutoDeletePlugin.ts index 532d5b96..a60b800f 100644 --- a/backend/src/plugins/AutoDelete/AutoDeletePlugin.ts +++ b/backend/src/plugins/AutoDelete/AutoDeletePlugin.ts @@ -1,4 +1,4 @@ -import { PluginOptions, guildPlugin } from "knub"; +import { guildPlugin } from "knub"; import { GuildLogs } from "../../data/GuildLogs.js"; import { GuildSavedMessages } from "../../data/GuildSavedMessages.js"; import { LogsPlugin } from "../Logs/LogsPlugin.js"; diff --git a/backend/src/plugins/AutoDelete/util/deleteNextItem.ts b/backend/src/plugins/AutoDelete/util/deleteNextItem.ts index 883dd9fd..217f69cb 100644 --- a/backend/src/plugins/AutoDelete/util/deleteNextItem.ts +++ b/backend/src/plugins/AutoDelete/util/deleteNextItem.ts @@ -1,4 +1,4 @@ -import { ChannelType, PermissionsBitField, Snowflake } from "discord.js"; +import { PermissionsBitField, Snowflake } from "discord.js"; import { GuildPluginData } from "knub"; import moment from "moment-timezone"; import { LogType } from "../../../data/LogType.js"; diff --git a/backend/src/plugins/Automod/triggers/matchMimeType.ts b/backend/src/plugins/Automod/triggers/matchMimeType.ts index 16fc277a..8a1bb8f5 100644 --- a/backend/src/plugins/Automod/triggers/matchMimeType.ts +++ b/backend/src/plugins/Automod/triggers/matchMimeType.ts @@ -1,7 +1,7 @@ import { escapeInlineCode } from "discord.js"; +import z from "zod/v4"; import { asSingleLine, messageSummary, verboseChannelMention } from "../../../utils.js"; import { automodTrigger } from "../helpers.js"; -import z from "zod/v4"; interface MatchResultType { matchedType: string; diff --git a/backend/src/plugins/Cases/functions/getCaseEmbed.ts b/backend/src/plugins/Cases/functions/getCaseEmbed.ts index 6683c7b8..15bcae1c 100644 --- a/backend/src/plugins/Cases/functions/getCaseEmbed.ts +++ b/backend/src/plugins/Cases/functions/getCaseEmbed.ts @@ -1,4 +1,10 @@ -import { escapeCodeBlock, InteractionEditReplyOptions, InteractionReplyOptions, MessageCreateOptions, MessageEditOptions } from "discord.js"; +import { + escapeCodeBlock, + InteractionEditReplyOptions, + InteractionReplyOptions, + MessageCreateOptions, + MessageEditOptions, +} from "discord.js"; import { GuildPluginData } from "knub"; import moment from "moment-timezone"; import { CaseTypes } from "../../../data/CaseTypes.js"; diff --git a/backend/src/plugins/Censor/CensorPlugin.ts b/backend/src/plugins/Censor/CensorPlugin.ts index b9fd524c..ad91b27e 100644 --- a/backend/src/plugins/Censor/CensorPlugin.ts +++ b/backend/src/plugins/Censor/CensorPlugin.ts @@ -1,4 +1,4 @@ -import { PluginOptions, PluginOverride, guildPlugin } from "knub"; +import { PluginOverride, guildPlugin } from "knub"; import { GuildLogs } from "../../data/GuildLogs.js"; import { GuildSavedMessages } from "../../data/GuildSavedMessages.js"; import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners.js"; diff --git a/backend/src/plugins/Censor/types.ts b/backend/src/plugins/Censor/types.ts index 0a7bc228..9e36f316 100644 --- a/backend/src/plugins/Censor/types.ts +++ b/backend/src/plugins/Censor/types.ts @@ -18,7 +18,10 @@ export const zCensorConfig = z.strictObject({ domain_blacklist: z.array(zBoundedCharacters(0, 255)).nullable().default(null), blocked_tokens: z.array(zBoundedCharacters(0, 2000)).nullable().default(null), blocked_words: z.array(zBoundedCharacters(0, 2000)).nullable().default(null), - blocked_regex: z.array(zRegex(z.string().max(1000))).nullable().default(null), + blocked_regex: z + .array(zRegex(z.string().max(1000))) + .nullable() + .default(null), }); export interface CensorPluginType extends BasePluginType { diff --git a/backend/src/plugins/ChannelArchiver/types.ts b/backend/src/plugins/ChannelArchiver/types.ts index e2efe460..440b2f80 100644 --- a/backend/src/plugins/ChannelArchiver/types.ts +++ b/backend/src/plugins/ChannelArchiver/types.ts @@ -1,6 +1,6 @@ import { BasePluginType, guildPluginMessageCommand, pluginUtils } from "knub"; -import { CommonPlugin } from "../Common/CommonPlugin.js"; import { z } from "zod/v4"; +import { CommonPlugin } from "../Common/CommonPlugin.js"; export const zChannelArchiverPluginConfig = z.strictObject({}); diff --git a/backend/src/plugins/Common/CommonPlugin.ts b/backend/src/plugins/Common/CommonPlugin.ts index 91d38881..6befad91 100644 --- a/backend/src/plugins/Common/CommonPlugin.ts +++ b/backend/src/plugins/Common/CommonPlugin.ts @@ -1,9 +1,4 @@ -import { - Attachment, - MessageMentionOptions, - SendableChannels, - TextBasedChannel -} from "discord.js"; +import { Attachment, MessageMentionOptions, SendableChannels, TextBasedChannel } from "discord.js"; import { guildPlugin } from "knub"; import { GenericCommandSource, sendContextResponse } from "../../pluginUtils.js"; import { errorMessage, successMessage } from "../../utils.js"; @@ -28,9 +23,7 @@ export const CommonPlugin = guildPlugin()({ ) => { const emoji = getSuccessEmoji(pluginData); const formattedBody = successMessage(body, emoji); - const content = allowedMentions - ? { content: formattedBody, allowedMentions } - : { content: formattedBody }; + const content = allowedMentions ? { content: formattedBody, allowedMentions } : { content: formattedBody }; if ("isSendable" in context) { return context.send(content); } @@ -46,9 +39,7 @@ export const CommonPlugin = guildPlugin()({ ) => { const emoji = getErrorEmoji(pluginData); const formattedBody = errorMessage(body, emoji); - const content = allowedMentions - ? { content: formattedBody, allowedMentions } - : { content: formattedBody }; + const content = allowedMentions ? { content: formattedBody, allowedMentions } : { content: formattedBody }; if ("isSendable" in context) { return context.send(content); } @@ -67,9 +58,7 @@ export const CommonPlugin = guildPlugin()({ ); } if (!channel.isSendable()) { - throw new Error( - "Passed attachment storage channel is not sendable", - ); + throw new Error("Passed attachment storage channel is not sendable"); } return channel.send({ diff --git a/backend/src/plugins/ContextMenus/ContextMenuPlugin.ts b/backend/src/plugins/ContextMenus/ContextMenuPlugin.ts index 1ec47d2e..e4d33a78 100644 --- a/backend/src/plugins/ContextMenus/ContextMenuPlugin.ts +++ b/backend/src/plugins/ContextMenus/ContextMenuPlugin.ts @@ -1,4 +1,4 @@ -import { PluginOptions, PluginOverride, guildPlugin } from "knub"; +import { PluginOverride, guildPlugin } from "knub"; import { GuildCases } from "../../data/GuildCases.js"; import { CasesPlugin } from "../Cases/CasesPlugin.js"; import { LogsPlugin } from "../Logs/LogsPlugin.js"; diff --git a/backend/src/plugins/ContextMenus/actions/clean.ts b/backend/src/plugins/ContextMenus/actions/clean.ts index 43f2010c..69f17336 100644 --- a/backend/src/plugins/ContextMenus/actions/clean.ts +++ b/backend/src/plugins/ContextMenus/actions/clean.ts @@ -34,7 +34,7 @@ export async function cleanAction( .catch((err) => logger.error(`Clean interaction reply failed: ${err}`)); return; } - + const targetChannel = await pluginData.guild.channels.fetch(targetChannelId); if (!targetChannel?.isTextBased()) { await interaction @@ -62,7 +62,11 @@ export async function cleanAction( if (fetchMessagesResult.messages.length > 0) { await utility.cleanMessages(targetChannel, fetchMessagesResult.messages, interaction.user); - interaction.editReply(`Cleaned ${fetchMessagesResult.messages.length} ${fetchMessagesResult.messages.length === 1 ? "message" : "messages"}`); + interaction.editReply( + `Cleaned ${fetchMessagesResult.messages.length} ${ + fetchMessagesResult.messages.length === 1 ? "message" : "messages" + }`, + ); } else { interaction.editReply("No messages to clean"); } diff --git a/backend/src/plugins/Counters/CountersPlugin.ts b/backend/src/plugins/Counters/CountersPlugin.ts index 87c4a60e..63c967e6 100644 --- a/backend/src/plugins/Counters/CountersPlugin.ts +++ b/backend/src/plugins/Counters/CountersPlugin.ts @@ -1,7 +1,12 @@ import { EventEmitter } from "events"; -import { PluginOptions, PluginOverride, guildPlugin } from "knub"; +import { PluginOverride, guildPlugin } from "knub"; import { GuildCounters } from "../../data/GuildCounters.js"; -import { buildCounterConditionString, CounterTrigger, getReverseCounterComparisonOp, parseCounterConditionString } from "../../data/entities/CounterTrigger.js"; +import { + CounterTrigger, + buildCounterConditionString, + getReverseCounterComparisonOp, + parseCounterConditionString, +} from "../../data/entities/CounterTrigger.js"; import { makePublicFn } from "../../pluginUtils.js"; import { MINUTES, convertDelayStringToMS } from "../../utils.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; @@ -98,7 +103,9 @@ export const CountersPlugin = guildPlugin()({ // Initialize triggers for (const [triggerName, trigger] of Object.entries(counter.triggers)) { const parsedCondition = parseCounterConditionString(trigger.condition)!; - const rawReverseCondition = trigger.reverse_condition || buildCounterConditionString(getReverseCounterComparisonOp(parsedCondition[0]), parsedCondition[1]); + const rawReverseCondition = + trigger.reverse_condition || + buildCounterConditionString(getReverseCounterComparisonOp(parsedCondition[0]), parsedCondition[1]); const parsedReverseCondition = parseCounterConditionString(rawReverseCondition)!; const counterTrigger = await state.counters.initCounterTrigger( dbCounter.id, diff --git a/backend/src/plugins/Counters/types.ts b/backend/src/plugins/Counters/types.ts index 03bfc91a..d58de125 100644 --- a/backend/src/plugins/Counters/types.ts +++ b/backend/src/plugins/Counters/types.ts @@ -15,19 +15,18 @@ import Timeout = NodeJS.Timeout; const MAX_COUNTERS = 5; const MAX_TRIGGERS_PER_COUNTER = 5; -export const zTrigger = z - .strictObject({ - // Dummy type because name gets replaced by the property key in transform() - pretty_name: zBoundedCharacters(0, 100).nullable().default(null), - condition: zBoundedCharacters(1, 64).refine((str) => parseCounterConditionString(str) !== null, { - message: "Invalid counter trigger condition", - }), - reverse_condition: zBoundedCharacters(1, 64) - .refine((str) => parseCounterConditionString(str) !== null, { - message: "Invalid counter trigger reverse condition", - }) - .optional(), - }); +export const zTrigger = z.strictObject({ + // Dummy type because name gets replaced by the property key in transform() + pretty_name: zBoundedCharacters(0, 100).nullable().default(null), + condition: zBoundedCharacters(1, 64).refine((str) => parseCounterConditionString(str) !== null, { + message: "Invalid counter trigger condition", + }), + reverse_condition: zBoundedCharacters(1, 64) + .refine((str) => parseCounterConditionString(str) !== null, { + message: "Invalid counter trigger reverse condition", + }) + .optional(), +}); const zTriggerFromString = zBoundedCharacters(0, 100).transform((val, ctx) => { const parsedCondition = parseCounterConditionString(val); diff --git a/backend/src/plugins/CustomEvents/functions/runEvent.ts b/backend/src/plugins/CustomEvents/functions/runEvent.ts index b91fb61c..33a0f9c3 100644 --- a/backend/src/plugins/CustomEvents/functions/runEvent.ts +++ b/backend/src/plugins/CustomEvents/functions/runEvent.ts @@ -1,4 +1,3 @@ -import { Message } from "discord.js"; import { GuildPluginData } from "knub"; import { TemplateSafeValueContainer } from "../../../templateFormatter.js"; import { ActionError } from "../ActionError.js"; diff --git a/backend/src/plugins/GuildAccessMonitor/GuildAccessMonitorPlugin.ts b/backend/src/plugins/GuildAccessMonitor/GuildAccessMonitorPlugin.ts index 06eca255..ad2c4dfe 100644 --- a/backend/src/plugins/GuildAccessMonitor/GuildAccessMonitorPlugin.ts +++ b/backend/src/plugins/GuildAccessMonitor/GuildAccessMonitorPlugin.ts @@ -1,5 +1,5 @@ import { Guild } from "discord.js"; -import { BasePluginType, GlobalPluginData, globalPlugin, globalPluginEventListener } from "knub"; +import { GlobalPluginData, globalPlugin, globalPluginEventListener } from "knub"; import { AllowedGuilds } from "../../data/AllowedGuilds.js"; import { Configs } from "../../data/Configs.js"; import { env } from "../../env.js"; diff --git a/backend/src/plugins/InternalPoster/InternalPosterPlugin.ts b/backend/src/plugins/InternalPoster/InternalPosterPlugin.ts index 3aeb649b..82592ec6 100644 --- a/backend/src/plugins/InternalPoster/InternalPosterPlugin.ts +++ b/backend/src/plugins/InternalPoster/InternalPosterPlugin.ts @@ -1,5 +1,4 @@ -import { PluginOptions, guildPlugin } from "knub"; -import z from "zod/v4"; +import { guildPlugin } from "knub"; import { Queue } from "../../Queue.js"; import { Webhooks } from "../../data/Webhooks.js"; import { makePublicFn } from "../../pluginUtils.js"; diff --git a/backend/src/plugins/LocateUser/LocateUserPlugin.ts b/backend/src/plugins/LocateUser/LocateUserPlugin.ts index 32915dd1..d9650618 100644 --- a/backend/src/plugins/LocateUser/LocateUserPlugin.ts +++ b/backend/src/plugins/LocateUser/LocateUserPlugin.ts @@ -1,4 +1,4 @@ -import { PluginOptions, guildPlugin } from "knub"; +import { guildPlugin } from "knub"; import { onGuildEvent } from "../../data/GuildEvents.js"; import { GuildVCAlerts } from "../../data/GuildVCAlerts.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; diff --git a/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts b/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts index b204ad77..fcdf5301 100644 --- a/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts +++ b/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts @@ -1,4 +1,4 @@ -import { PluginOptions, guildPlugin } from "knub"; +import { guildPlugin } from "knub"; import { GuildSavedMessages } from "../../data/GuildSavedMessages.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; import { SaveMessagesToDBCmd } from "./commands/SaveMessagesToDB.js"; diff --git a/backend/src/plugins/ModActions/commands/addcase/AddCaseMsgCmd.ts b/backend/src/plugins/ModActions/commands/addcase/AddCaseMsgCmd.ts index e4be443e..938bc28f 100644 --- a/backend/src/plugins/ModActions/commands/addcase/AddCaseMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/addcase/AddCaseMsgCmd.ts @@ -31,7 +31,7 @@ export const AddCaseMsgCmd = modActionsMsgCmd({ return; } - const member = msg.member || await msg.guild.members.fetch(msg.author.id); + const member = msg.member || (await msg.guild.members.fetch(msg.author.id)); // The moderator who did the action is the message author or, if used, the specified -mod let mod = member; diff --git a/backend/src/plugins/ModActions/commands/ban/BanMsgCmd.ts b/backend/src/plugins/ModActions/commands/ban/BanMsgCmd.ts index d5272ef5..184e252b 100644 --- a/backend/src/plugins/ModActions/commands/ban/BanMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/ban/BanMsgCmd.ts @@ -41,7 +41,7 @@ export const BanMsgCmd = modActionsMsgCmd({ return; } - const member = msg.member || await msg.guild.members.fetch(msg.author.id); + const member = msg.member || (await msg.guild.members.fetch(msg.author.id)); // The moderator who did the action is the message author or, if used, the specified -mod let mod = member; diff --git a/backend/src/plugins/ModActions/commands/cases/CasesUserMsgCmd.ts b/backend/src/plugins/ModActions/commands/cases/CasesUserMsgCmd.ts index 808f8b26..dac00506 100644 --- a/backend/src/plugins/ModActions/commands/cases/CasesUserMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/cases/CasesUserMsgCmd.ts @@ -41,7 +41,7 @@ export const CasesUserMsgCmd = modActionsMsgCmd({ pluginData.state.common.sendErrorMessage(msg, `User not found`); return; } - + const member = await resolveMessageMember(msg); return actualCasesCmd( diff --git a/backend/src/plugins/ModActions/commands/deletecase/actualDeleteCaseCmd.ts b/backend/src/plugins/ModActions/commands/deletecase/actualDeleteCaseCmd.ts index f3a6322c..6d01afa9 100644 --- a/backend/src/plugins/ModActions/commands/deletecase/actualDeleteCaseCmd.ts +++ b/backend/src/plugins/ModActions/commands/deletecase/actualDeleteCaseCmd.ts @@ -48,12 +48,7 @@ export async function actualDeleteCaseCmd( content: "Delete the following case? Answer 'Yes' to continue, 'No' to cancel.", }); - const reply = await helpers.waitForReply( - pluginData.client, - channel, - author.id, - 15 * SECONDS, - ); + const reply = await helpers.waitForReply(pluginData.client, channel, author.id, 15 * SECONDS); const normalizedReply = (reply?.content || "").toLowerCase().trim(); if (normalizedReply !== "yes" && normalizedReply !== "y") { sendContextResponse(context, "Cancelled. Case was not deleted."); diff --git a/backend/src/plugins/ModActions/commands/forcemute/ForceMuteMsgCmd.ts b/backend/src/plugins/ModActions/commands/forcemute/ForceMuteMsgCmd.ts index 4be9c104..129eb9e5 100644 --- a/backend/src/plugins/ModActions/commands/forcemute/ForceMuteMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/forcemute/ForceMuteMsgCmd.ts @@ -39,7 +39,7 @@ export const ForceMuteMsgCmd = modActionsMsgCmd({ return; } - const authorMember = await resolveMessageMember(msg) + const authorMember = await resolveMessageMember(msg); const memberToMute = await resolveMember(pluginData.client, pluginData.guild, user.id); // Make sure we're allowed to mute this user diff --git a/backend/src/plugins/ModActions/commands/kick/KickMsgCmd.ts b/backend/src/plugins/ModActions/commands/kick/KickMsgCmd.ts index 27ad3796..ec7c692b 100644 --- a/backend/src/plugins/ModActions/commands/kick/KickMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/kick/KickMsgCmd.ts @@ -1,10 +1,10 @@ import { hasPermission } from "knub/helpers"; import { commandTypeHelpers as ct } from "../../../../commandTypes.js"; +import { resolveMessageMember } from "../../../../pluginUtils.js"; import { resolveUser } from "../../../../utils.js"; import { readContactMethodsFromArgs } from "../../functions/readContactMethodsFromArgs.js"; import { modActionsMsgCmd } from "../../types.js"; import { actualKickCmd } from "./actualKickCmd.js"; -import { resolveMessageMember } from "../../../../pluginUtils.js"; const opts = { mod: ct.member({ option: true }), diff --git a/backend/src/plugins/ModActions/commands/massban/MassBanMsgCmd.ts b/backend/src/plugins/ModActions/commands/massban/MassBanMsgCmd.ts index ae76a372..438f088e 100644 --- a/backend/src/plugins/ModActions/commands/massban/MassBanMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/massban/MassBanMsgCmd.ts @@ -1,6 +1,6 @@ import { waitForReply } from "knub/helpers"; import { commandTypeHelpers as ct } from "../../../../commandTypes.js"; -import { getContextChannel, resolveMessageMember, sendContextResponse } from "../../../../pluginUtils.js"; +import { resolveMessageMember } from "../../../../pluginUtils.js"; import { modActionsMsgCmd } from "../../types.js"; import { actualMassBanCmd } from "./actualMassBanCmd.js"; diff --git a/backend/src/plugins/ModActions/commands/massban/actualMassBanCmd.ts b/backend/src/plugins/ModActions/commands/massban/actualMassBanCmd.ts index 58f9cb4a..7ab0d46e 100644 --- a/backend/src/plugins/ModActions/commands/massban/actualMassBanCmd.ts +++ b/backend/src/plugins/ModActions/commands/massban/actualMassBanCmd.ts @@ -3,7 +3,14 @@ import { GuildPluginData } from "knub"; import { CaseTypes } from "../../../../data/CaseTypes.js"; import { LogType } from "../../../../data/LogType.js"; import { humanizeDurationShort } from "../../../../humanizeDuration.js"; -import { canActOn, deleteContextResponse, editContextResponse, getConfigForContext, getContextChannel, isContextInteraction, sendContextResponse } from "../../../../pluginUtils.js"; +import { + canActOn, + deleteContextResponse, + editContextResponse, + getConfigForContext, + isContextInteraction, + sendContextResponse, +} from "../../../../pluginUtils.js"; import { DAYS, MINUTES, SECONDS, noop } from "../../../../utils.js"; import { CasesPlugin } from "../../../Cases/CasesPlugin.js"; import { LogsPlugin } from "../../../Logs/LogsPlugin.js"; diff --git a/backend/src/plugins/ModActions/commands/massmute/MassMuteMsgCmd.ts b/backend/src/plugins/ModActions/commands/massmute/MassMuteMsgCmd.ts index ea3881ba..fe96490a 100644 --- a/backend/src/plugins/ModActions/commands/massmute/MassMuteMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/massmute/MassMuteMsgCmd.ts @@ -1,6 +1,6 @@ import { waitForReply } from "knub/helpers"; import { commandTypeHelpers as ct } from "../../../../commandTypes.js"; -import { getContextChannel, resolveMessageMember, sendContextResponse } from "../../../../pluginUtils.js"; +import { resolveMessageMember } from "../../../../pluginUtils.js"; import { modActionsMsgCmd } from "../../types.js"; import { actualMassMuteCmd } from "./actualMassMuteCmd.js"; diff --git a/backend/src/plugins/ModActions/commands/massmute/actualMassMuteCmd.ts b/backend/src/plugins/ModActions/commands/massmute/actualMassMuteCmd.ts index 64f7722d..3c6d109b 100644 --- a/backend/src/plugins/ModActions/commands/massmute/actualMassMuteCmd.ts +++ b/backend/src/plugins/ModActions/commands/massmute/actualMassMuteCmd.ts @@ -3,6 +3,7 @@ import { GuildPluginData } from "knub"; import { LogType } from "../../../../data/LogType.js"; import { logger } from "../../../../logger.js"; import { canActOn, deleteContextResponse, isContextInteraction, sendContextResponse } from "../../../../pluginUtils.js"; +import { noop } from "../../../../utils.js"; import { LogsPlugin } from "../../../Logs/LogsPlugin.js"; import { MutesPlugin } from "../../../Mutes/MutesPlugin.js"; import { handleAttachmentLinkDetectionAndGetRestriction } from "../../functions/attachmentLinkReaction.js"; @@ -11,7 +12,6 @@ import { formatReasonWithMessageLinkForAttachments, } from "../../functions/formatReasonForAttachments.js"; import { ModActionsPluginType } from "../../types.js"; -import { noop } from "../../../../utils.js"; export async function actualMassMuteCmd( pluginData: GuildPluginData, diff --git a/backend/src/plugins/ModActions/commands/massunban/MassUnbanMsgCmd.ts b/backend/src/plugins/ModActions/commands/massunban/MassUnbanMsgCmd.ts index 8dbc4d99..c7166675 100644 --- a/backend/src/plugins/ModActions/commands/massunban/MassUnbanMsgCmd.ts +++ b/backend/src/plugins/ModActions/commands/massunban/MassUnbanMsgCmd.ts @@ -1,6 +1,6 @@ import { waitForReply } from "knub/helpers"; import { commandTypeHelpers as ct } from "../../../../commandTypes.js"; -import { getContextChannel, resolveMessageMember, sendContextResponse } from "../../../../pluginUtils.js"; +import { resolveMessageMember } from "../../../../pluginUtils.js"; import { modActionsMsgCmd } from "../../types.js"; import { actualMassUnbanCmd } from "./actualMassUnbanCmd.js"; diff --git a/backend/src/plugins/ModActions/types.ts b/backend/src/plugins/ModActions/types.ts index 0a4894c4..7f4c0aa6 100644 --- a/backend/src/plugins/ModActions/types.ts +++ b/backend/src/plugins/ModActions/types.ts @@ -30,16 +30,28 @@ export const zModActionsConfig = z.strictObject({ message_on_ban: z.boolean().default(false), message_channel: z.nullable(z.string()).default(null), warn_message: z.nullable(z.string()).default("You have received a warning on the {guildName} server: {reason}"), - kick_message: z.nullable(z.string()).default("You have been kicked from the {guildName} server. Reason given: {reason}"), - ban_message: z.nullable(z.string()).default("You have been banned from the {guildName} server. Reason given: {reason}"), - tempban_message: z.nullable(z.string()).default("You have been banned from the {guildName} server for {banTime}. Reason given: {reason}"), + kick_message: z + .nullable(z.string()) + .default("You have been kicked from the {guildName} server. Reason given: {reason}"), + ban_message: z + .nullable(z.string()) + .default("You have been banned from the {guildName} server. Reason given: {reason}"), + tempban_message: z + .nullable(z.string()) + .default("You have been banned from the {guildName} server for {banTime}. Reason given: {reason}"), alert_on_rejoin: z.boolean().default(false), alert_channel: z.nullable(z.string()).default(null), warn_notify_enabled: z.boolean().default(false), warn_notify_threshold: z.number().default(5), - warn_notify_message: z.string().default("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?"), + warn_notify_message: z + .string() + .default( + "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: z.number().default(1), - attachment_link_reaction: z.nullable(z.union([z.literal("none"), z.literal("warn"), z.literal("restrict")])).default("warn"), + attachment_link_reaction: z + .nullable(z.union([z.literal("none"), z.literal("warn"), z.literal("restrict")])) + .default("warn"), can_note: z.boolean().default(false), can_warn: z.boolean().default(false), can_mute: z.boolean().default(false), diff --git a/backend/src/plugins/Mutes/types.ts b/backend/src/plugins/Mutes/types.ts index 67fa1913..b133134c 100644 --- a/backend/src/plugins/Mutes/types.ts +++ b/backend/src/plugins/Mutes/types.ts @@ -23,7 +23,10 @@ export const zMutesConfig = z.strictObject({ message_on_update: z.boolean().default(false), message_channel: z.string().nullable().default(null), mute_message: z.string().nullable().default("You have been muted on the {guildName} server. Reason given: {reason}"), - timed_mute_message: z.string().nullable().default("You have been muted on the {guildName} server for {time}. Reason given: {reason}"), + timed_mute_message: z + .string() + .nullable() + .default("You have been muted on the {guildName} server for {time}. Reason given: {reason}"), update_mute_message: z.string().nullable().default("Your mute on the {guildName} server has been updated to {time}."), remove_roles_on_mute: z.union([z.boolean(), z.array(zSnowflake)]).default(false), restore_roles_on_mute: z.union([z.boolean(), z.array(zSnowflake)]).default(false), diff --git a/backend/src/plugins/NameHistory/NameHistoryPlugin.ts b/backend/src/plugins/NameHistory/NameHistoryPlugin.ts index 204710f8..57d72922 100644 --- a/backend/src/plugins/NameHistory/NameHistoryPlugin.ts +++ b/backend/src/plugins/NameHistory/NameHistoryPlugin.ts @@ -1,4 +1,4 @@ -import { PluginOptions, guildPlugin } from "knub"; +import { guildPlugin } from "knub"; import { Queue } from "../../Queue.js"; import { GuildNicknameHistory } from "../../data/GuildNicknameHistory.js"; import { UsernameHistory } from "../../data/UsernameHistory.js"; diff --git a/backend/src/plugins/Persist/PersistPlugin.ts b/backend/src/plugins/Persist/PersistPlugin.ts index 76c9150d..40008373 100644 --- a/backend/src/plugins/Persist/PersistPlugin.ts +++ b/backend/src/plugins/Persist/PersistPlugin.ts @@ -1,4 +1,4 @@ -import { PluginOptions, guildPlugin } from "knub"; +import { guildPlugin } from "knub"; import { GuildLogs } from "../../data/GuildLogs.js"; import { GuildPersistedData } from "../../data/GuildPersistedData.js"; import { LogsPlugin } from "../Logs/LogsPlugin.js"; diff --git a/backend/src/plugins/ReactionRoles/ReactionRolesPlugin.ts b/backend/src/plugins/ReactionRoles/ReactionRolesPlugin.ts index e06c9d78..7c8e2ef7 100644 --- a/backend/src/plugins/ReactionRoles/ReactionRolesPlugin.ts +++ b/backend/src/plugins/ReactionRoles/ReactionRolesPlugin.ts @@ -1,4 +1,4 @@ -import { PluginOptions, guildPlugin } from "knub"; +import { guildPlugin } from "knub"; import { Queue } from "../../Queue.js"; import { GuildReactionRoles } from "../../data/GuildReactionRoles.js"; import { GuildSavedMessages } from "../../data/GuildSavedMessages.js"; diff --git a/backend/src/plugins/ReactionRoles/commands/InitReactionRolesCmd.ts b/backend/src/plugins/ReactionRoles/commands/InitReactionRolesCmd.ts index f864153e..9212bf8e 100644 --- a/backend/src/plugins/ReactionRoles/commands/InitReactionRolesCmd.ts +++ b/backend/src/plugins/ReactionRoles/commands/InitReactionRolesCmd.ts @@ -1,10 +1,10 @@ import { Snowflake } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes.js"; +import { resolveMessageMember } from "../../../pluginUtils.js"; import { canUseEmoji, isDiscordAPIError, isValidEmoji, noop, trimPluginDescription } from "../../../utils.js"; import { canReadChannel } from "../../../utils/canReadChannel.js"; import { TReactionRolePair, reactionRolesCmd } from "../types.js"; import { applyReactionRoleReactionsToMessage } from "../util/applyReactionRoleReactionsToMessage.js"; -import { resolveMessageMember } from "../../../pluginUtils.js"; const CLEAR_ROLES_EMOJI = "❌"; diff --git a/backend/src/plugins/Reminders/RemindersPlugin.ts b/backend/src/plugins/Reminders/RemindersPlugin.ts index a36f47e0..5a779288 100644 --- a/backend/src/plugins/Reminders/RemindersPlugin.ts +++ b/backend/src/plugins/Reminders/RemindersPlugin.ts @@ -1,4 +1,4 @@ -import { PluginOptions, guildPlugin } from "knub"; +import { guildPlugin } from "knub"; import { onGuildEvent } from "../../data/GuildEvents.js"; import { GuildReminders } from "../../data/GuildReminders.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; diff --git a/backend/src/plugins/Roles/RolesPlugin.ts b/backend/src/plugins/Roles/RolesPlugin.ts index af45821c..03d3ec3d 100644 --- a/backend/src/plugins/Roles/RolesPlugin.ts +++ b/backend/src/plugins/Roles/RolesPlugin.ts @@ -1,4 +1,4 @@ -import { PluginOptions, guildPlugin } from "knub"; +import { guildPlugin } from "knub"; import { GuildLogs } from "../../data/GuildLogs.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; import { LogsPlugin } from "../Logs/LogsPlugin.js"; diff --git a/backend/src/plugins/SelfGrantableRoles/SelfGrantableRolesPlugin.ts b/backend/src/plugins/SelfGrantableRoles/SelfGrantableRolesPlugin.ts index d56418cd..04cc2826 100644 --- a/backend/src/plugins/SelfGrantableRoles/SelfGrantableRolesPlugin.ts +++ b/backend/src/plugins/SelfGrantableRoles/SelfGrantableRolesPlugin.ts @@ -1,4 +1,4 @@ -import { CooldownManager, PluginOptions, guildPlugin } from "knub"; +import { CooldownManager, guildPlugin } from "knub"; import { CommonPlugin } from "../Common/CommonPlugin.js"; import { RoleAddCmd } from "./commands/RoleAddCmd.js"; import { RoleHelpCmd } from "./commands/RoleHelpCmd.js"; diff --git a/backend/src/plugins/SelfGrantableRoles/commands/RoleAddCmd.ts b/backend/src/plugins/SelfGrantableRoles/commands/RoleAddCmd.ts index 0a3d268a..999eda3c 100644 --- a/backend/src/plugins/SelfGrantableRoles/commands/RoleAddCmd.ts +++ b/backend/src/plugins/SelfGrantableRoles/commands/RoleAddCmd.ts @@ -1,12 +1,12 @@ import { Role, Snowflake } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes.js"; +import { resolveMessageMember } from "../../../pluginUtils.js"; import { memberRolesLock } from "../../../utils/lockNameHelpers.js"; import { selfGrantableRolesCmd } from "../types.js"; import { findMatchingRoles } from "../util/findMatchingRoles.js"; import { getApplyingEntries } from "../util/getApplyingEntries.js"; import { normalizeRoleNames } from "../util/normalizeRoleNames.js"; import { splitRoleNames } from "../util/splitRoleNames.js"; -import { resolveMessageMember } from "../../../pluginUtils.js"; export const RoleAddCmd = selfGrantableRolesCmd({ trigger: ["role", "role add"], diff --git a/backend/src/plugins/SelfGrantableRoles/commands/RoleRemoveCmd.ts b/backend/src/plugins/SelfGrantableRoles/commands/RoleRemoveCmd.ts index 611b75bb..ca921962 100644 --- a/backend/src/plugins/SelfGrantableRoles/commands/RoleRemoveCmd.ts +++ b/backend/src/plugins/SelfGrantableRoles/commands/RoleRemoveCmd.ts @@ -1,12 +1,12 @@ import { Snowflake } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes.js"; +import { resolveMessageMember } from "../../../pluginUtils.js"; import { memberRolesLock } from "../../../utils/lockNameHelpers.js"; import { selfGrantableRolesCmd } from "../types.js"; import { findMatchingRoles } from "../util/findMatchingRoles.js"; import { getApplyingEntries } from "../util/getApplyingEntries.js"; import { normalizeRoleNames } from "../util/normalizeRoleNames.js"; import { splitRoleNames } from "../util/splitRoleNames.js"; -import { resolveMessageMember } from "../../../pluginUtils.js"; export const RoleRemoveCmd = selfGrantableRolesCmd({ trigger: "role remove", diff --git a/backend/src/plugins/Tags/commands/TagEvalCmd.ts b/backend/src/plugins/Tags/commands/TagEvalCmd.ts index f55eea32..61dc7fac 100644 --- a/backend/src/plugins/Tags/commands/TagEvalCmd.ts +++ b/backend/src/plugins/Tags/commands/TagEvalCmd.ts @@ -1,11 +1,11 @@ import { MessageCreateOptions } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes.js"; import { logger } from "../../../logger.js"; +import { resolveMessageMember } from "../../../pluginUtils.js"; import { TemplateParseError } from "../../../templateFormatter.js"; import { memberToTemplateSafeMember, userToTemplateSafeUser } from "../../../utils/templateSafeObjects.js"; import { tagsCmd } from "../types.js"; import { renderTagBody } from "../util/renderTagBody.js"; -import { resolveMessageMember } from "../../../pluginUtils.js"; export const TagEvalCmd = tagsCmd({ trigger: "tag eval", diff --git a/backend/src/plugins/TimeAndDate/TimeAndDatePlugin.ts b/backend/src/plugins/TimeAndDate/TimeAndDatePlugin.ts index 12395a44..46a60773 100644 --- a/backend/src/plugins/TimeAndDate/TimeAndDatePlugin.ts +++ b/backend/src/plugins/TimeAndDate/TimeAndDatePlugin.ts @@ -1,11 +1,10 @@ -import { PluginOptions, guildPlugin } from "knub"; +import { guildPlugin } from "knub"; import { GuildMemberTimezones } from "../../data/GuildMemberTimezones.js"; import { makePublicFn } from "../../pluginUtils.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; import { ResetTimezoneCmd } from "./commands/ResetTimezoneCmd.js"; import { SetTimezoneCmd } from "./commands/SetTimezoneCmd.js"; import { ViewTimezoneCmd } from "./commands/ViewTimezoneCmd.js"; -import { defaultDateFormats } from "./defaultDateFormats.js"; import { getDateFormat } from "./functions/getDateFormat.js"; import { getGuildTz } from "./functions/getGuildTz.js"; import { getMemberTz } from "./functions/getMemberTz.js"; diff --git a/backend/src/plugins/Utility/commands/ContextCmd.ts b/backend/src/plugins/Utility/commands/ContextCmd.ts index 2af1219f..94f4786a 100644 --- a/backend/src/plugins/Utility/commands/ContextCmd.ts +++ b/backend/src/plugins/Utility/commands/ContextCmd.ts @@ -1,9 +1,9 @@ import { Snowflake, TextChannel } from "discord.js"; import { commandTypeHelpers as ct } from "../../../commandTypes.js"; +import { resolveMessageMember } from "../../../pluginUtils.js"; import { messageLink } from "../../../utils.js"; import { canReadChannel } from "../../../utils/canReadChannel.js"; import { utilityCmd } from "../types.js"; -import { resolveMessageMember } from "../../../pluginUtils.js"; export const ContextCmd = utilityCmd({ trigger: "context", diff --git a/backend/src/plugins/Utility/commands/InfoCmd.ts b/backend/src/plugins/Utility/commands/InfoCmd.ts index e9df7104..8c92e786 100644 --- a/backend/src/plugins/Utility/commands/InfoCmd.ts +++ b/backend/src/plugins/Utility/commands/InfoCmd.ts @@ -1,6 +1,7 @@ import { Snowflake } from "discord.js"; import { getChannelId, getRoleId } from "knub/helpers"; import { commandTypeHelpers as ct } from "../../../commandTypes.js"; +import { resolveMessageMember } from "../../../pluginUtils.js"; import { isValidSnowflake, noop, parseInviteCodeInput, resolveInvite, resolveUser } from "../../../utils.js"; import { canReadChannel } from "../../../utils/canReadChannel.js"; import { resolveMessageTarget } from "../../../utils/resolveMessageTarget.js"; @@ -15,7 +16,6 @@ import { getServerInfoEmbed } from "../functions/getServerInfoEmbed.js"; import { getSnowflakeInfoEmbed } from "../functions/getSnowflakeInfoEmbed.js"; import { getUserInfoEmbed } from "../functions/getUserInfoEmbed.js"; import { utilityCmd } from "../types.js"; -import { resolveMessageMember } from "../../../pluginUtils.js"; export const InfoCmd = utilityCmd({ trigger: "info", diff --git a/backend/src/plugins/Utility/functions/cleanMessages.ts b/backend/src/plugins/Utility/functions/cleanMessages.ts index 0cc4d2b7..be707984 100644 --- a/backend/src/plugins/Utility/functions/cleanMessages.ts +++ b/backend/src/plugins/Utility/functions/cleanMessages.ts @@ -1,11 +1,11 @@ -import { GuildPluginData } from "knub"; -import { UtilityPluginType } from "../types.js"; import { GuildBasedChannel, Snowflake, TextBasedChannel, User } from "discord.js"; +import { GuildPluginData } from "knub"; import { SavedMessage } from "../../../data/entities/SavedMessage.js"; import { LogType } from "../../../data/LogType.js"; -import { chunkArray } from "../../../utils.js"; import { getBaseUrl } from "../../../pluginUtils.js"; +import { chunkArray } from "../../../utils.js"; import { LogsPlugin } from "../../Logs/LogsPlugin.js"; +import { UtilityPluginType } from "../types.js"; export async function cleanMessages( pluginData: GuildPluginData, diff --git a/backend/src/plugins/Utility/functions/fetchChannelMessagesToClean.ts b/backend/src/plugins/Utility/functions/fetchChannelMessagesToClean.ts index 82048123..6aed5e56 100644 --- a/backend/src/plugins/Utility/functions/fetchChannelMessagesToClean.ts +++ b/backend/src/plugins/Utility/functions/fetchChannelMessagesToClean.ts @@ -1,11 +1,11 @@ import { GuildBasedChannel, Message, OmitPartialGroupDMChannel, Snowflake, TextBasedChannel } from "discord.js"; -import { DAYS, getInviteCodesInString } from "../../../utils.js"; import { GuildPluginData } from "knub"; -import { UtilityPluginType } from "../types.js"; -import { snowflakeToTimestamp } from "../../../utils/snowflakeToTimestamp.js"; +import { SavedMessage } from "../../../data/entities/SavedMessage.js"; import { humanizeDurationShort } from "../../../humanizeDuration.js"; import { allowTimeout } from "../../../RegExpRunner.js"; -import { SavedMessage } from "../../../data/entities/SavedMessage.js"; +import { DAYS, getInviteCodesInString } from "../../../utils.js"; +import { snowflakeToTimestamp } from "../../../utils/snowflakeToTimestamp.js"; +import { UtilityPluginType } from "../types.js"; const MAX_CLEAN_COUNT = 300; const MAX_CLEAN_TIME = 1 * DAYS; @@ -33,7 +33,11 @@ export interface ErrorResult { export type FetchChannelMessagesToCleanResult = SuccessResult | ErrorResult; -export async function fetchChannelMessagesToClean(pluginData: GuildPluginData, targetChannel: GuildBasedChannel & TextBasedChannel, opts: FetchChannelMessagesToCleanOpts): Promise { +export async function fetchChannelMessagesToClean( + pluginData: GuildPluginData, + targetChannel: GuildBasedChannel & TextBasedChannel, + opts: FetchChannelMessagesToCleanOpts, +): Promise { if (opts.count > MAX_CLEAN_COUNT || opts.count <= 0) { return { error: `Clean count must be between 1 and ${MAX_CLEAN_COUNT}` }; } @@ -75,7 +79,10 @@ export async function fetchChannelMessagesToClean(pluginData: GuildPluginData( - schema: T, - fn: (schema: $ZodType) => TResult, + schema: T, + fn: (schema: $ZodType) => TResult, ): TResult; -/** +/** * Applies {@link fn} to each element of the schema recursively, replacing every schema with its return value. * The rewriting is applied bottom-up (ie. {@link fn} will get called on "children" first). */ export function mapOnSchema(schema: $ZodType, fn: (schema: $ZodType) => $ZodType): $ZodType { - // Cache results to support recursive schemas - const results = new Map<$ZodType, $ZodType | typeof RESOLVING>(); + // Cache results to support recursive schemas + const results = new Map<$ZodType, $ZodType | typeof RESOLVING>(); - function mapElement(s: $ZodType) { - const value = results.get(s); - if (value === RESOLVING) { - throw new Error("Recursive schema access detected"); - } else if (value !== undefined) { - return value; - } - - results.set(s, RESOLVING); - const result = mapOnSchema(s, fn); - results.set(s, result); - return result; + function mapElement(s: $ZodType) { + const value = results.get(s); + if (value === RESOLVING) { + throw new Error("Recursive schema access detected"); + } else if (value !== undefined) { + return value; } - function mapInner() { - if (schema instanceof z.ZodObject) { - const newShape: Record = {}; - for (const [key, value] of Object.entries(schema.shape)) { - newShape[key] = mapElement(value); - } + results.set(s, RESOLVING); + const result = mapOnSchema(s, fn); + results.set(s, result); + return result; + } - return new z.ZodObject({ - ...schema.def, - shape: newShape, - }); - } else if (schema instanceof z.ZodArray) { - return new z.ZodArray({ - ...schema.def, - type: "array", - element: mapElement(schema.def.element), - }); - } else if (schema instanceof z.ZodMap) { - return new z.ZodMap({ - ...schema.def, - keyType: mapElement(schema.def.keyType), - valueType: mapElement(schema.def.valueType), - }); - } else if (schema instanceof z.ZodSet) { - return new z.ZodSet({ - ...schema.def, - valueType: mapElement(schema.def.valueType), - }); - } else if (schema instanceof z.ZodOptional) { - return new z.ZodOptional({ - ...schema.def, - innerType: mapElement(schema.def.innerType), - }); - } else if (schema instanceof z.ZodNullable) { - return new z.ZodNullable({ - ...schema.def, - innerType: mapElement(schema.def.innerType), - }); - } else if (schema instanceof z.ZodDefault) { - return new z.ZodDefault({ - ...schema.def, - innerType: mapElement(schema.def.innerType), - }); - } else if (schema instanceof z.ZodReadonly) { - return new z.ZodReadonly({ - ...schema.def, - innerType: mapElement(schema.def.innerType), - }); - } else if (schema instanceof z.ZodLazy) { - return new z.ZodLazy({ - ...schema.def, - // NB: This leaks `fn` into the schema, but there is no other way to support recursive schemas - getter: () => mapElement(schema._def.getter()), - }); - } else if (schema instanceof z.ZodPromise) { - return new z.ZodPromise({ - ...schema.def, - innerType: mapElement(schema.def.innerType), - }); - } else if (schema instanceof z.ZodCatch) { - return new z.ZodCatch({ - ...schema.def, - innerType: mapElement(schema._def.innerType), - }); - } else if (schema instanceof z.ZodTuple) { - return new z.ZodTuple({ - ...schema.def, - items: schema.def.items.map((item: $ZodType) => mapElement(item)), - rest: schema.def.rest && mapElement(schema.def.rest), - }); - } else if (schema instanceof z.ZodDiscriminatedUnion) { - return new z.ZodDiscriminatedUnion({ - ...schema.def, - options: schema.options.map((option) => mapOnSchema(option, fn)), - }); - } else if (schema instanceof z.ZodUnion) { - return new z.ZodUnion({ - ...schema.def, - options: schema.options.map((option) => mapOnSchema(option, fn)), - }); - } else if (schema instanceof z.ZodIntersection) { - return new z.ZodIntersection({ - ...schema.def, - right: mapElement(schema.def.right), - left: mapElement(schema.def.left), - }); - } else if (schema instanceof z.ZodRecord) { - return new z.ZodRecord({ - ...schema.def, - keyType: mapElement(schema.def.keyType) as $ZodRecordKey, - valueType: mapElement(schema.def.valueType), - }); - } else { - return schema; - } + function mapInner() { + if (schema instanceof z.ZodObject) { + const newShape: Record = {}; + for (const [key, value] of Object.entries(schema.shape)) { + newShape[key] = mapElement(value); + } + + return new z.ZodObject({ + ...schema.def, + shape: newShape, + }); + } else if (schema instanceof z.ZodArray) { + return new z.ZodArray({ + ...schema.def, + type: "array", + element: mapElement(schema.def.element), + }); + } else if (schema instanceof z.ZodMap) { + return new z.ZodMap({ + ...schema.def, + keyType: mapElement(schema.def.keyType), + valueType: mapElement(schema.def.valueType), + }); + } else if (schema instanceof z.ZodSet) { + return new z.ZodSet({ + ...schema.def, + valueType: mapElement(schema.def.valueType), + }); + } else if (schema instanceof z.ZodOptional) { + return new z.ZodOptional({ + ...schema.def, + innerType: mapElement(schema.def.innerType), + }); + } else if (schema instanceof z.ZodNullable) { + return new z.ZodNullable({ + ...schema.def, + innerType: mapElement(schema.def.innerType), + }); + } else if (schema instanceof z.ZodDefault) { + return new z.ZodDefault({ + ...schema.def, + innerType: mapElement(schema.def.innerType), + }); + } else if (schema instanceof z.ZodReadonly) { + return new z.ZodReadonly({ + ...schema.def, + innerType: mapElement(schema.def.innerType), + }); + } else if (schema instanceof z.ZodLazy) { + return new z.ZodLazy({ + ...schema.def, + // NB: This leaks `fn` into the schema, but there is no other way to support recursive schemas + getter: () => mapElement(schema._def.getter()), + }); + } else if (schema instanceof z.ZodPromise) { + return new z.ZodPromise({ + ...schema.def, + innerType: mapElement(schema.def.innerType), + }); + } else if (schema instanceof z.ZodCatch) { + return new z.ZodCatch({ + ...schema.def, + innerType: mapElement(schema._def.innerType), + }); + } else if (schema instanceof z.ZodTuple) { + return new z.ZodTuple({ + ...schema.def, + items: schema.def.items.map((item: $ZodType) => mapElement(item)), + rest: schema.def.rest && mapElement(schema.def.rest), + }); + } else if (schema instanceof z.ZodDiscriminatedUnion) { + return new z.ZodDiscriminatedUnion({ + ...schema.def, + options: schema.options.map((option) => mapOnSchema(option, fn)), + }); + } else if (schema instanceof z.ZodUnion) { + return new z.ZodUnion({ + ...schema.def, + options: schema.options.map((option) => mapOnSchema(option, fn)), + }); + } else if (schema instanceof z.ZodIntersection) { + return new z.ZodIntersection({ + ...schema.def, + right: mapElement(schema.def.right), + left: mapElement(schema.def.left), + }); + } else if (schema instanceof z.ZodRecord) { + return new z.ZodRecord({ + ...schema.def, + keyType: mapElement(schema.def.keyType) as $ZodRecordKey, + valueType: mapElement(schema.def.valueType), + }); + } else { + return schema; } + } - return fn(mapInner()); + return fn(mapInner()); } export function deepPartial(schema: T): T { - return mapOnSchema(schema, (s) => (s instanceof z.ZodObject ? s.partial() : s)) as T; + return mapOnSchema(schema, (s) => (s instanceof z.ZodObject ? s.partial() : s)) as T; } /** Make all object schemas "strict" (ie. fail on unknown keys), except if they are marked as `.passthrough()` */ export function deepStrict(schema: T): T { - return mapOnSchema(schema, (s) => - s instanceof z.ZodObject /* && s.def.unknownKeys !== "passthrough" */ ? s.strict() : s, - ) as T; + return mapOnSchema(schema, (s) => + s instanceof z.ZodObject /* && s.def.unknownKeys !== "passthrough" */ ? s.strict() : s, + ) as T; } export function deepStrictAll(schema: T): T { - return mapOnSchema(schema, (s) => (s instanceof z.ZodObject ? s.strict() : s)) as T; + return mapOnSchema(schema, (s) => (s instanceof z.ZodObject ? s.strict() : s)) as T; }