From 83d35052c3576cadf378a6ad10ad6884accc2db4 Mon Sep 17 00:00:00 2001 From: Dragory <2606411+Dragory@users.noreply.github.com> Date: Fri, 23 May 2025 01:12:52 +0000 Subject: [PATCH] refactor: move defaults to config schemas --- backend/package.json | 2 +- backend/src/api/docs.ts | 2 +- backend/src/configValidator.ts | 7 +- backend/src/exportSchemas.ts | 2 +- backend/src/pluginUtils.ts | 3 +- .../plugins/AutoDelete/AutoDeletePlugin.ts | 10 +-- backend/src/plugins/AutoDelete/types.ts | 6 +- .../AutoReactions/AutoReactionsPlugin.ts | 25 +++---- backend/src/plugins/AutoReactions/types.ts | 4 +- backend/src/plugins/Automod/AutomodPlugin.ts | 26 +------ .../Automod/triggers/matchAttachmentType.ts | 20 ++---- .../plugins/Automod/triggers/matchMimeType.ts | 22 ++---- backend/src/plugins/Automod/types.ts | 10 +-- .../plugins/BotControl/BotControlPlugin.ts | 14 +--- backend/src/plugins/BotControl/types.ts | 14 ++-- backend/src/plugins/Cases/CasesPlugin.ts | 14 +--- backend/src/plugins/Cases/types.ts | 12 ++-- backend/src/plugins/Censor/CensorPlugin.ts | 50 ++++---------- backend/src/plugins/Censor/types.ts | 28 ++++---- .../ChannelArchiver/ChannelArchiverPlugin.ts | 5 +- backend/src/plugins/ChannelArchiver/types.ts | 4 ++ backend/src/plugins/Common/CommonPlugin.ts | 24 ++----- backend/src/plugins/Common/types.ts | 8 +-- .../CompanionChannelsPlugin.ts | 9 +-- .../src/plugins/CompanionChannels/types.ts | 4 +- .../plugins/ContextMenus/ContextMenuPlugin.ts | 29 +++----- backend/src/plugins/ContextMenus/types.ts | 6 +- .../src/plugins/Counters/CountersPlugin.ts | 39 ++++------- backend/src/plugins/Counters/types.ts | 10 +-- .../CustomEvents/CustomEventsPlugin.ts | 9 +-- backend/src/plugins/CustomEvents/types.ts | 4 +- .../GuildAccessMonitorPlugin.ts | 10 +-- .../src/plugins/GuildAccessMonitor/types.ts | 9 +++ .../GuildConfigReloaderPlugin.ts | 5 +- .../src/plugins/GuildConfigReloader/docs.ts | 4 +- .../src/plugins/GuildConfigReloader/types.ts | 4 +- .../GuildInfoSaver/GuildInfoSaverPlugin.ts | 5 +- backend/src/plugins/GuildInfoSaver/types.ts | 2 +- .../GuildMemberCachePlugin.ts | 5 +- backend/src/plugins/GuildMemberCache/types.ts | 2 +- .../InternalPoster/InternalPosterPlugin.ts | 10 +-- backend/src/plugins/InternalPoster/types.ts | 4 +- .../plugins/LocateUser/LocateUserPlugin.ts | 18 ++--- backend/src/plugins/LocateUser/types.ts | 6 +- backend/src/plugins/Logs/LogsPlugin.ts | 26 ++----- backend/src/plugins/Logs/types.ts | 15 ++-- .../MessageSaver/MessageSaverPlugin.ts | 17 ++--- backend/src/plugins/MessageSaver/types.ts | 4 +- .../plugins/ModActions/ModActionsPlugin.ts | 53 ++------------- backend/src/plugins/ModActions/types.ts | 68 +++++++++---------- backend/src/plugins/Mutes/MutesPlugin.ts | 33 ++------- backend/src/plugins/Mutes/types.ts | 28 ++++---- .../plugins/NameHistory/NameHistoryPlugin.ts | 17 ++--- backend/src/plugins/NameHistory/types.ts | 4 +- backend/src/plugins/Persist/PersistPlugin.ts | 11 +-- backend/src/plugins/Persist/types.ts | 9 ++- .../plugins/Phisherman/PhishermanPlugin.ts | 10 +-- backend/src/plugins/Phisherman/types.ts | 5 +- .../PingableRoles/PingableRolesPlugin.ts | 19 ++---- backend/src/plugins/PingableRoles/types.ts | 5 +- backend/src/plugins/Post/PostPlugin.ts | 21 ++---- backend/src/plugins/Post/types.ts | 4 +- .../ReactionRoles/ReactionRolesPlugin.ts | 25 ++----- backend/src/plugins/ReactionRoles/types.ts | 12 ++-- .../src/plugins/Reminders/RemindersPlugin.ts | 19 ++---- backend/src/plugins/Reminders/types.ts | 5 +- .../plugins/RoleButtons/RoleButtonsPlugin.ts | 23 +++---- backend/src/plugins/RoleButtons/types.ts | 6 +- .../plugins/RoleManager/RoleManagerPlugin.ts | 2 +- backend/src/plugins/RoleManager/types.ts | 2 +- backend/src/plugins/Roles/RolesPlugin.ts | 21 ++---- backend/src/plugins/Roles/types.ts | 8 +-- .../SelfGrantableRolesPlugin.ts | 10 +-- .../src/plugins/SelfGrantableRoles/types.ts | 6 +- .../src/plugins/Slowmode/SlowmodePlugin.ts | 33 +++------ backend/src/plugins/Slowmode/types.ts | 8 +-- backend/src/plugins/Spam/SpamPlugin.ts | 30 ++------ backend/src/plugins/Spam/types.ts | 22 +++--- .../src/plugins/Starboard/StarboardPlugin.ts | 19 ++---- backend/src/plugins/Starboard/types.ts | 7 +- backend/src/plugins/Tags/TagsPlugin.ts | 34 ++-------- backend/src/plugins/Tags/types.ts | 26 +++---- .../plugins/TimeAndDate/TimeAndDatePlugin.ts | 18 ++--- backend/src/plugins/TimeAndDate/types.ts | 8 +-- .../UsernameSaver/UsernameSaverPlugin.ts | 2 +- backend/src/plugins/UsernameSaver/types.ts | 2 +- backend/src/plugins/Utility/UtilityPlugin.ts | 52 +++----------- backend/src/plugins/Utility/types.ts | 56 +++++++-------- .../WelcomeMessage/WelcomeMessagePlugin.ts | 11 +-- backend/src/plugins/WelcomeMessage/types.ts | 8 +-- package-lock.json | 8 +-- 91 files changed, 450 insertions(+), 888 deletions(-) diff --git a/backend/package.json b/backend/package.json index 13d39d27..37ef719f 100644 --- a/backend/package.json +++ b/backend/package.json @@ -49,7 +49,7 @@ "fp-ts": "^2.0.1", "humanize-duration": "^3.15.0", "js-yaml": "^4.1.0", - "knub": "^32.0.0-next.23", + "knub": "^32.0.0-next.25", "knub-command-manager": "^9.1.0", "last-commit-log": "^2.1.0", "lodash-es": "^4.17.21", diff --git a/backend/src/api/docs.ts b/backend/src/api/docs.ts index 9f2971e4..ec12dacd 100644 --- a/backend/src/api/docs.ts +++ b/backend/src/api/docs.ts @@ -131,7 +131,7 @@ export function initDocs(router: express.Router) { config: cmd.config, })); - const defaultOptions = pluginInfo.plugin.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 ece85b94..04e475ad 100644 --- a/backend/src/configValidator.ts +++ b/backend/src/configValidator.ts @@ -28,10 +28,13 @@ export async function validateGuildConfig(config: any): Promise { } const plugin = pluginNameToPlugin.get(pluginName)!; - const configManager = new PluginConfigManager(plugin.defaultOptions || { config: {} }, pluginOptions, { + const configManager = new PluginConfigManager({}, { + configSchema: plugin.configSchema, + defaultOverrides: plugin.defaultOverrides ?? [], levels: {}, - parser: plugin.configParser, + customOverrideCriteriaFunctions: plugin.customOverrideCriteriaFunctions, }); + try { await configManager.init(); } catch (err) { diff --git a/backend/src/exportSchemas.ts b/backend/src/exportSchemas.ts index e00dade4..e5e80984 100644 --- a/backend/src/exportSchemas.ts +++ b/backend/src/exportSchemas.ts @@ -73,7 +73,7 @@ function overrides(configSchema: z.ZodType): z.ZodType { const pluginSchemaMap = availableGuildPlugins.reduce((map, pluginInfo) => { map[pluginInfo.plugin.name] = z.object({ config: pluginInfo.docs.configSchema.optional(), - overrides: overrides(pluginInfo.docs.configSchema).optional(), + overrides: z.array(overrides(pluginInfo.docs.configSchema)).optional(), }); return map; }, {}); diff --git a/backend/src/pluginUtils.ts b/backend/src/pluginUtils.ts index 5a6dc910..9d1936ce 100644 --- a/backend/src/pluginUtils.ts +++ b/backend/src/pluginUtils.ts @@ -27,6 +27,7 @@ import { AnyPluginData, BasePluginData, CommandContext, ExtendedMatchParams, Gui import { isStaff } from "./staff.js"; import { TZeppelinKnub } from "./types.js"; import { Tail } from "./utils/typeUtils.js"; +import z from "zod/v4"; const { getMemberLevel } = helpers; @@ -166,7 +167,7 @@ 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 ab9d8ba7..532d5b96 100644 --- a/backend/src/plugins/AutoDelete/AutoDeletePlugin.ts +++ b/backend/src/plugins/AutoDelete/AutoDeletePlugin.ts @@ -8,19 +8,11 @@ import { onMessageCreate } from "./util/onMessageCreate.js"; import { onMessageDelete } from "./util/onMessageDelete.js"; import { onMessageDeleteBulk } from "./util/onMessageDeleteBulk.js"; -const defaultOptions: PluginOptions = { - config: { - enabled: false, - delay: "5s", - }, -}; - export const AutoDeletePlugin = guildPlugin()({ name: "auto_delete", dependencies: () => [TimeAndDatePlugin, LogsPlugin], - configParser: (input) => zAutoDeleteConfig.parse(input), - defaultOptions, + configSchema: zAutoDeleteConfig, beforeLoad(pluginData) { const { state, guild } = pluginData; diff --git a/backend/src/plugins/AutoDelete/types.ts b/backend/src/plugins/AutoDelete/types.ts index b03ea600..32260d61 100644 --- a/backend/src/plugins/AutoDelete/types.ts +++ b/backend/src/plugins/AutoDelete/types.ts @@ -14,12 +14,12 @@ export interface IDeletionQueueItem { } export const zAutoDeleteConfig = z.strictObject({ - enabled: z.boolean(), - delay: zDelayString, + enabled: z.boolean().default(false), + delay: zDelayString.default("5s"), }); export interface AutoDeletePluginType extends BasePluginType { - config: z.output; + configSchema: typeof zAutoDeleteConfig; state: { guildSavedMessages: GuildSavedMessages; guildLogs: GuildLogs; diff --git a/backend/src/plugins/AutoReactions/AutoReactionsPlugin.ts b/backend/src/plugins/AutoReactions/AutoReactionsPlugin.ts index 915eab26..b90b6202 100644 --- a/backend/src/plugins/AutoReactions/AutoReactionsPlugin.ts +++ b/backend/src/plugins/AutoReactions/AutoReactionsPlugin.ts @@ -1,4 +1,4 @@ -import { PluginOptions, guildPlugin } from "knub"; +import { PluginOverride, guildPlugin } from "knub"; import { GuildAutoReactions } from "../../data/GuildAutoReactions.js"; import { GuildSavedMessages } from "../../data/GuildSavedMessages.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; @@ -8,19 +8,14 @@ import { NewAutoReactionsCmd } from "./commands/NewAutoReactionsCmd.js"; import { AddReactionsEvt } from "./events/AddReactionsEvt.js"; import { AutoReactionsPluginType, zAutoReactionsConfig } from "./types.js"; -const defaultOptions: PluginOptions = { - config: { - can_manage: false, - }, - overrides: [ - { - level: ">=100", - config: { - can_manage: true, - }, +const defaultOverrides: Array> = [ + { + level: ">=100", + config: { + can_manage: true, }, - ], -}; + }, +]; export const AutoReactionsPlugin = guildPlugin()({ name: "auto_reactions", @@ -30,8 +25,8 @@ export const AutoReactionsPlugin = guildPlugin()({ LogsPlugin, ], - configParser: (input) => zAutoReactionsConfig.parse(input), - defaultOptions, + configSchema: zAutoReactionsConfig, + defaultOverrides, // prettier-ignore messageCommands: [ diff --git a/backend/src/plugins/AutoReactions/types.ts b/backend/src/plugins/AutoReactions/types.ts index f69291a7..1d234a35 100644 --- a/backend/src/plugins/AutoReactions/types.ts +++ b/backend/src/plugins/AutoReactions/types.ts @@ -7,11 +7,11 @@ import { AutoReaction } from "../../data/entities/AutoReaction.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; export const zAutoReactionsConfig = z.strictObject({ - can_manage: z.boolean(), + can_manage: z.boolean().default(false), }); export interface AutoReactionsPluginType extends BasePluginType { - config: z.output; + configSchema: typeof zAutoReactionsConfig; state: { logs: GuildLogs; savedMessages: GuildSavedMessages; diff --git a/backend/src/plugins/Automod/AutomodPlugin.ts b/backend/src/plugins/Automod/AutomodPlugin.ts index de38d544..9e260cdf 100644 --- a/backend/src/plugins/Automod/AutomodPlugin.ts +++ b/backend/src/plugins/Automod/AutomodPlugin.ts @@ -34,29 +34,6 @@ import { clearOldRecentActions } from "./functions/clearOldRecentActions.js"; import { clearOldRecentSpam } from "./functions/clearOldRecentSpam.js"; import { AutomodPluginType, zAutomodConfig } from "./types.js"; -const defaultOptions = { - config: { - rules: {}, - antiraid_levels: ["low", "medium", "high"], - can_set_antiraid: false, - can_view_antiraid: false, - }, - overrides: [ - { - level: ">=50", - config: { - can_view_antiraid: true, - }, - }, - { - level: ">=100", - config: { - can_set_antiraid: true, - }, - }, - ], -}; - export const AutomodPlugin = guildPlugin()({ name: "automod", @@ -71,8 +48,7 @@ export const AutomodPlugin = guildPlugin()({ RoleManagerPlugin, ], - defaultOptions, - configParser: (input) => zAutomodConfig.parse(input), + configSchema: zAutomodConfig, customOverrideCriteriaFunctions: { antiraid_level: (pluginData, matchParams, value) => { diff --git a/backend/src/plugins/Automod/triggers/matchAttachmentType.ts b/backend/src/plugins/Automod/triggers/matchAttachmentType.ts index 8b7f0d3f..5848a175 100644 --- a/backend/src/plugins/Automod/triggers/matchAttachmentType.ts +++ b/backend/src/plugins/Automod/triggers/matchAttachmentType.ts @@ -9,24 +9,12 @@ interface MatchResultType { mode: "blacklist" | "whitelist"; } -const baseConfig = z.strictObject({ - filetype_blacklist: z.array(z.string().max(32)).max(255).default([]), +const configSchema = z.strictObject({ + whitelist_enabled: z.boolean().default(false), filetype_whitelist: z.array(z.string().max(32)).max(255).default([]), + blacklist_enabled: z.boolean().default(false), + filetype_blacklist: z.array(z.string().max(32)).max(255).default([]), }); -const configWithWhitelist = baseConfig.merge( - z.strictObject({ - whitelist_enabled: z.literal(true), - blacklist_enabled: z.literal(false).default(false), - }), -); -const configWithBlacklist = baseConfig.merge( - z.strictObject({ - blacklist_enabled: z.literal(true), - whitelist_enabled: z.literal(false).default(false), - }), -); - -const configSchema = z.union([configWithWhitelist, configWithBlacklist]); export const MatchAttachmentTypeTrigger = automodTrigger()({ configSchema, diff --git a/backend/src/plugins/Automod/triggers/matchMimeType.ts b/backend/src/plugins/Automod/triggers/matchMimeType.ts index 404ca7ea..16fc277a 100644 --- a/backend/src/plugins/Automod/triggers/matchMimeType.ts +++ b/backend/src/plugins/Automod/triggers/matchMimeType.ts @@ -1,31 +1,19 @@ 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; mode: "blacklist" | "whitelist"; } -const baseConfig = z.strictObject({ - mime_type_blacklist: z.array(z.string().max(32)).max(255).default([]), +const configSchema = z.strictObject({ + whitelist_enabled: z.boolean().default(false), mime_type_whitelist: z.array(z.string().max(32)).max(255).default([]), + blacklist_enabled: z.boolean().default(false), + mime_type_blacklist: z.array(z.string().max(32)).max(255).default([]), }); -const configWithWhitelist = baseConfig.merge( - z.strictObject({ - whitelist_enabled: z.literal(true), - blacklist_enabled: z.literal(false).default(false), - }), -); -const configWithBlacklist = baseConfig.merge( - z.strictObject({ - blacklist_enabled: z.literal(true), - whitelist_enabled: z.literal(false).default(false), - }), -); - -const configSchema = z.union([configWithWhitelist, configWithBlacklist]); export const MatchMimeTypeTrigger = automodTrigger()({ configSchema, diff --git a/backend/src/plugins/Automod/types.ts b/backend/src/plugins/Automod/types.ts index 688f347f..51fc9375 100644 --- a/backend/src/plugins/Automod/types.ts +++ b/backend/src/plugins/Automod/types.ts @@ -58,14 +58,14 @@ const zRule = z.strictObject({ export type TRule = z.infer; export const zAutomodConfig = z.strictObject({ - rules: zBoundedRecord(z.record(z.string().max(100), zRule), 0, 255), - antiraid_levels: z.array(z.string().max(100)).max(10), - can_set_antiraid: z.boolean(), - can_view_antiraid: z.boolean(), + rules: zBoundedRecord(z.record(z.string().max(100), zRule), 0, 255).default({}), + antiraid_levels: z.array(z.string().max(100)).max(10).default(["low", "medium", "high"]), + can_set_antiraid: z.boolean().default(false), + can_view_antiraid: z.boolean().default(false), }); export interface AutomodPluginType extends BasePluginType { - config: z.output; + configSchema: typeof zAutomodConfig; customOverrideCriteria: { antiraid_level?: string; diff --git a/backend/src/plugins/BotControl/BotControlPlugin.ts b/backend/src/plugins/BotControl/BotControlPlugin.ts index 2c504751..bad32a4d 100644 --- a/backend/src/plugins/BotControl/BotControlPlugin.ts +++ b/backend/src/plugins/BotControl/BotControlPlugin.ts @@ -23,21 +23,9 @@ import { RestPerformanceCmd } from "./commands/RestPerformanceCmd.js"; import { ServersCmd } from "./commands/ServersCmd.js"; import { BotControlPluginType, zBotControlConfig } from "./types.js"; -const defaultOptions = { - config: { - can_use: false, - can_eligible: false, - can_performance: false, - can_add_server_from_invite: false, - can_list_dashboard_perms: false, - update_cmd: null, - }, -}; - export const BotControlPlugin = globalPlugin()({ name: "bot_control", - configParser: (input) => zBotControlConfig.parse(input), - defaultOptions, + configSchema: zBotControlConfig, // prettier-ignore messageCommands: [ diff --git a/backend/src/plugins/BotControl/types.ts b/backend/src/plugins/BotControl/types.ts index 4226991d..2cdef313 100644 --- a/backend/src/plugins/BotControl/types.ts +++ b/backend/src/plugins/BotControl/types.ts @@ -7,16 +7,16 @@ import { GuildArchives } from "../../data/GuildArchives.js"; import { zBoundedCharacters } from "../../utils.js"; export const zBotControlConfig = z.strictObject({ - can_use: z.boolean(), - can_eligible: z.boolean(), - can_performance: z.boolean(), - can_add_server_from_invite: z.boolean(), - can_list_dashboard_perms: z.boolean(), - update_cmd: zBoundedCharacters(0, 2000).nullable(), + can_use: z.boolean().default(false), + can_eligible: z.boolean().default(false), + can_performance: z.boolean().default(false), + can_add_server_from_invite: z.boolean().default(false), + can_list_dashboard_perms: z.boolean().default(false), + update_cmd: zBoundedCharacters(0, 2000).nullable().default(null), }); export interface BotControlPluginType extends BasePluginType { - config: z.output; + configSchema: typeof zBotControlConfig; state: { archives: GuildArchives; allowedGuilds: AllowedGuilds; diff --git a/backend/src/plugins/Cases/CasesPlugin.ts b/backend/src/plugins/Cases/CasesPlugin.ts index 8e5e66f3..2b97246c 100644 --- a/backend/src/plugins/Cases/CasesPlugin.ts +++ b/backend/src/plugins/Cases/CasesPlugin.ts @@ -20,23 +20,11 @@ function getLogsPlugin(): Promise { return import("../Logs/LogsPlugin.js") as Promise; } -const defaultOptions = { - config: { - log_automatic_actions: true, - case_log_channel: null, - show_relative_times: true, - relative_time_cutoff: "7d", - case_colors: null, - case_icons: null, - }, -}; - export const CasesPlugin = guildPlugin()({ name: "cases", dependencies: async () => [TimeAndDatePlugin, InternalPosterPlugin, (await getLogsPlugin()).LogsPlugin], - configParser: (input) => zCasesConfig.parse(input), - defaultOptions, + configSchema: zCasesConfig, public(pluginData) { return { diff --git a/backend/src/plugins/Cases/types.ts b/backend/src/plugins/Cases/types.ts index 4974901b..24ba6bf7 100644 --- a/backend/src/plugins/Cases/types.ts +++ b/backend/src/plugins/Cases/types.ts @@ -11,16 +11,16 @@ import { zColor } from "../../utils/zColor.js"; const caseKeys = keys(CaseNameToType) as U.ListOf; export const zCasesConfig = z.strictObject({ - log_automatic_actions: z.boolean(), - case_log_channel: zSnowflake.nullable(), - show_relative_times: z.boolean(), + log_automatic_actions: z.boolean().default(true), + case_log_channel: zSnowflake.nullable().default(null), + show_relative_times: z.boolean().default(true), relative_time_cutoff: zDelayString.default("1w"), - case_colors: z.record(z.enum(caseKeys), zColor).nullable(), - case_icons: z.record(z.enum(caseKeys), zBoundedCharacters(0, 100)).nullable(), + case_colors: z.record(z.enum(caseKeys), zColor).nullable().default(null), + case_icons: z.record(z.enum(caseKeys), zBoundedCharacters(0, 100)).nullable().default(null), }); export interface CasesPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zCasesConfig; state: { logs: GuildLogs; cases: GuildCases; diff --git a/backend/src/plugins/Censor/CensorPlugin.ts b/backend/src/plugins/Censor/CensorPlugin.ts index c9503690..b9fd524c 100644 --- a/backend/src/plugins/Censor/CensorPlugin.ts +++ b/backend/src/plugins/Censor/CensorPlugin.ts @@ -1,4 +1,4 @@ -import { PluginOptions, guildPlugin } from "knub"; +import { PluginOptions, PluginOverride, guildPlugin } from "knub"; import { GuildLogs } from "../../data/GuildLogs.js"; import { GuildSavedMessages } from "../../data/GuildSavedMessages.js"; import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners.js"; @@ -7,46 +7,26 @@ import { CensorPluginType, zCensorConfig } from "./types.js"; import { onMessageCreate } from "./util/onMessageCreate.js"; import { onMessageUpdate } from "./util/onMessageUpdate.js"; -const defaultOptions: PluginOptions = { - config: { - filter_zalgo: false, - filter_invites: false, - invite_guild_whitelist: null, - invite_guild_blacklist: null, - invite_code_whitelist: null, - invite_code_blacklist: null, - allow_group_dm_invites: false, - - filter_domains: false, - domain_whitelist: null, - domain_blacklist: null, - - blocked_tokens: null, - blocked_words: null, - blocked_regex: null, - }, - - overrides: [ - { - level: ">=50", - config: { - filter_zalgo: false, - filter_invites: false, - filter_domains: false, - blocked_tokens: null, - blocked_words: null, - blocked_regex: null, - }, +const defaultOverrides: Array> = [ + { + level: ">=50", + config: { + filter_zalgo: false, + filter_invites: false, + filter_domains: false, + blocked_tokens: null, + blocked_words: null, + blocked_regex: null, }, - ], -}; + }, +]; export const CensorPlugin = guildPlugin()({ name: "censor", dependencies: () => [LogsPlugin], - configParser: (input) => zCensorConfig.parse(input), - defaultOptions, + configSchema: zCensorConfig, + defaultOverrides, beforeLoad(pluginData) { const { state, guild } = pluginData; diff --git a/backend/src/plugins/Censor/types.ts b/backend/src/plugins/Censor/types.ts index 812e2e23..0a7bc228 100644 --- a/backend/src/plugins/Censor/types.ts +++ b/backend/src/plugins/Censor/types.ts @@ -6,23 +6,23 @@ import { GuildSavedMessages } from "../../data/GuildSavedMessages.js"; import { zBoundedCharacters, zRegex, zSnowflake } from "../../utils.js"; export const zCensorConfig = z.strictObject({ - filter_zalgo: z.boolean(), - filter_invites: z.boolean(), - invite_guild_whitelist: z.array(zSnowflake).nullable(), - invite_guild_blacklist: z.array(zSnowflake).nullable(), - invite_code_whitelist: z.array(zBoundedCharacters(0, 16)).nullable(), - invite_code_blacklist: z.array(zBoundedCharacters(0, 16)).nullable(), - allow_group_dm_invites: z.boolean(), - filter_domains: z.boolean(), - domain_whitelist: z.array(zBoundedCharacters(0, 255)).nullable(), - domain_blacklist: z.array(zBoundedCharacters(0, 255)).nullable(), - blocked_tokens: z.array(zBoundedCharacters(0, 2000)).nullable(), - blocked_words: z.array(zBoundedCharacters(0, 2000)).nullable(), - blocked_regex: z.array(zRegex(z.string().max(1000))).nullable(), + filter_zalgo: z.boolean().default(false), + filter_invites: z.boolean().default(false), + invite_guild_whitelist: z.array(zSnowflake).nullable().default(null), + invite_guild_blacklist: z.array(zSnowflake).nullable().default(null), + invite_code_whitelist: z.array(zBoundedCharacters(0, 16)).nullable().default(null), + invite_code_blacklist: z.array(zBoundedCharacters(0, 16)).nullable().default(null), + allow_group_dm_invites: z.boolean().default(false), + filter_domains: z.boolean().default(false), + domain_whitelist: z.array(zBoundedCharacters(0, 255)).nullable().default(null), + 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), }); export interface CensorPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zCensorConfig; state: { serverLogs: GuildLogs; savedMessages: GuildSavedMessages; diff --git a/backend/src/plugins/ChannelArchiver/ChannelArchiverPlugin.ts b/backend/src/plugins/ChannelArchiver/ChannelArchiverPlugin.ts index dc4b5080..3dc5c049 100644 --- a/backend/src/plugins/ChannelArchiver/ChannelArchiverPlugin.ts +++ b/backend/src/plugins/ChannelArchiver/ChannelArchiverPlugin.ts @@ -1,15 +1,14 @@ import { guildPlugin } from "knub"; -import z from "zod/v4"; import { CommonPlugin } from "../Common/CommonPlugin.js"; import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin.js"; import { ArchiveChannelCmd } from "./commands/ArchiveChannelCmd.js"; -import { ChannelArchiverPluginType } from "./types.js"; +import { ChannelArchiverPluginType, zChannelArchiverPluginConfig } from "./types.js"; export const ChannelArchiverPlugin = guildPlugin()({ name: "channel_archiver", dependencies: () => [TimeAndDatePlugin], - configParser: (input) => z.strictObject({}).parse(input), + configSchema: zChannelArchiverPluginConfig, // prettier-ignore messageCommands: [ diff --git a/backend/src/plugins/ChannelArchiver/types.ts b/backend/src/plugins/ChannelArchiver/types.ts index bf264775..e2efe460 100644 --- a/backend/src/plugins/ChannelArchiver/types.ts +++ b/backend/src/plugins/ChannelArchiver/types.ts @@ -1,7 +1,11 @@ import { BasePluginType, guildPluginMessageCommand, pluginUtils } from "knub"; import { CommonPlugin } from "../Common/CommonPlugin.js"; +import { z } from "zod/v4"; + +export const zChannelArchiverPluginConfig = z.strictObject({}); export interface ChannelArchiverPluginType extends BasePluginType { + configSchema: typeof zChannelArchiverPluginConfig; state: { common: pluginUtils.PluginPublicInterface; }; diff --git a/backend/src/plugins/Common/CommonPlugin.ts b/backend/src/plugins/Common/CommonPlugin.ts index b0fcd31f..91d38881 100644 --- a/backend/src/plugins/Common/CommonPlugin.ts +++ b/backend/src/plugins/Common/CommonPlugin.ts @@ -1,35 +1,19 @@ import { Attachment, - ChatInputCommandInteraction, - InteractionResponse, - Message, - MessageCreateOptions, MessageMentionOptions, - ModalSubmitInteraction, SendableChannels, - TextBasedChannel, - User, + TextBasedChannel } from "discord.js"; -import { PluginOptions, guildPlugin } from "knub"; -import { logger } from "../../logger.js"; -import { GenericCommandSource, isContextInteraction, sendContextResponse } from "../../pluginUtils.js"; +import { guildPlugin } from "knub"; +import { GenericCommandSource, sendContextResponse } from "../../pluginUtils.js"; import { errorMessage, successMessage } from "../../utils.js"; import { getErrorEmoji, getSuccessEmoji } from "./functions/getEmoji.js"; import { CommonPluginType, zCommonConfig } from "./types.js"; -const defaultOptions: PluginOptions = { - config: { - success_emoji: "✅", - error_emoji: "❌", - attachment_storing_channel: null, - }, -}; - export const CommonPlugin = guildPlugin()({ name: "common", dependencies: () => [], - configParser: (input) => zCommonConfig.parse(input), - defaultOptions, + configSchema: zCommonConfig, public(pluginData) { return { getSuccessEmoji, diff --git a/backend/src/plugins/Common/types.ts b/backend/src/plugins/Common/types.ts index cf3ab991..f982a1d1 100644 --- a/backend/src/plugins/Common/types.ts +++ b/backend/src/plugins/Common/types.ts @@ -2,11 +2,11 @@ import { BasePluginType } from "knub"; import z from "zod/v4"; export const zCommonConfig = z.strictObject({ - success_emoji: z.string(), - error_emoji: z.string(), - attachment_storing_channel: z.nullable(z.string()), + success_emoji: z.string().default("✅"), + error_emoji: z.string().default("❌"), + attachment_storing_channel: z.nullable(z.string()).default(null), }); export interface CommonPluginType extends BasePluginType { - config: z.output; + configSchema: typeof zCommonConfig; } diff --git a/backend/src/plugins/CompanionChannels/CompanionChannelsPlugin.ts b/backend/src/plugins/CompanionChannels/CompanionChannelsPlugin.ts index fd6fe3f7..1dee4fae 100644 --- a/backend/src/plugins/CompanionChannels/CompanionChannelsPlugin.ts +++ b/backend/src/plugins/CompanionChannels/CompanionChannelsPlugin.ts @@ -4,18 +4,11 @@ import { LogsPlugin } from "../Logs/LogsPlugin.js"; import { VoiceStateUpdateEvt } from "./events/VoiceStateUpdateEvt.js"; import { CompanionChannelsPluginType, zCompanionChannelsConfig } from "./types.js"; -const defaultOptions = { - config: { - entries: {}, - }, -}; - export const CompanionChannelsPlugin = guildPlugin()({ name: "companion_channels", dependencies: () => [LogsPlugin], - configParser: (input) => zCompanionChannelsConfig.parse(input), - defaultOptions, + configSchema: zCompanionChannelsConfig, events: [VoiceStateUpdateEvt], diff --git a/backend/src/plugins/CompanionChannels/types.ts b/backend/src/plugins/CompanionChannels/types.ts index 31db9498..6f0bc12f 100644 --- a/backend/src/plugins/CompanionChannels/types.ts +++ b/backend/src/plugins/CompanionChannels/types.ts @@ -13,11 +13,11 @@ export const zCompanionChannelOpts = z.strictObject({ export type TCompanionChannelOpts = z.infer; export const zCompanionChannelsConfig = z.strictObject({ - entries: z.record(zBoundedCharacters(0, 100), zCompanionChannelOpts), + entries: z.record(zBoundedCharacters(0, 100), zCompanionChannelOpts).default({}), }); export interface CompanionChannelsPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zCompanionChannelsConfig; state: { errorCooldownManager: CooldownManager; serverLogs: GuildLogs; diff --git a/backend/src/plugins/ContextMenus/ContextMenuPlugin.ts b/backend/src/plugins/ContextMenus/ContextMenuPlugin.ts index a8739785..1ec47d2e 100644 --- a/backend/src/plugins/ContextMenus/ContextMenuPlugin.ts +++ b/backend/src/plugins/ContextMenus/ContextMenuPlugin.ts @@ -1,4 +1,4 @@ -import { PluginOptions, guildPlugin } from "knub"; +import { PluginOptions, PluginOverride, guildPlugin } from "knub"; import { GuildCases } from "../../data/GuildCases.js"; import { CasesPlugin } from "../Cases/CasesPlugin.js"; import { LogsPlugin } from "../Logs/LogsPlugin.js"; @@ -13,30 +13,23 @@ import { NoteCmd } from "./commands/NoteUserCtxCmd.js"; import { WarnCmd } from "./commands/WarnUserCtxCmd.js"; import { ContextMenuPluginType, zContextMenusConfig } from "./types.js"; -const defaultOptions: PluginOptions = { - config: { - can_use: false, +const defaultOverrides: Array> = [ + { + level: ">=50", + config: { + can_use: true, - can_open_mod_menu: false, - }, - overrides: [ - { - level: ">=50", - config: { - can_use: true, - - can_open_mod_menu: true, - }, + can_open_mod_menu: true, }, - ], -}; + }, +]; export const ContextMenuPlugin = guildPlugin()({ name: "context_menu", dependencies: () => [CasesPlugin, MutesPlugin, ModActionsPlugin, LogsPlugin, UtilityPlugin], - configParser: (input) => zContextMenusConfig.parse(input), - defaultOptions, + configSchema: zContextMenusConfig, + defaultOverrides, contextMenuCommands: [ModMenuCmd, NoteCmd, WarnCmd, MuteCmd, BanCmd, CleanCmd], diff --git a/backend/src/plugins/ContextMenus/types.ts b/backend/src/plugins/ContextMenus/types.ts index 07c74d9c..80c56dd1 100644 --- a/backend/src/plugins/ContextMenus/types.ts +++ b/backend/src/plugins/ContextMenus/types.ts @@ -4,12 +4,12 @@ import z from "zod/v4"; import { GuildCases } from "../../data/GuildCases.js"; export const zContextMenusConfig = z.strictObject({ - can_use: z.boolean(), - can_open_mod_menu: z.boolean(), + can_use: z.boolean().default(false), + can_open_mod_menu: z.boolean().default(false), }); export interface ContextMenuPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zContextMenusConfig; state: { cases: GuildCases; }; diff --git a/backend/src/plugins/Counters/CountersPlugin.ts b/backend/src/plugins/Counters/CountersPlugin.ts index 7e507cd5..87c4a60e 100644 --- a/backend/src/plugins/Counters/CountersPlugin.ts +++ b/backend/src/plugins/Counters/CountersPlugin.ts @@ -1,5 +1,5 @@ import { EventEmitter } from "events"; -import { PluginOptions, guildPlugin } from "knub"; +import { PluginOptions, PluginOverride, guildPlugin } from "knub"; import { GuildCounters } from "../../data/GuildCounters.js"; import { buildCounterConditionString, CounterTrigger, getReverseCounterComparisonOp, parseCounterConditionString } from "../../data/entities/CounterTrigger.js"; import { makePublicFn } from "../../pluginUtils.js"; @@ -23,28 +23,20 @@ import { CountersPluginType, zCountersConfig } from "./types.js"; const DECAY_APPLY_INTERVAL = 5 * MINUTES; -const defaultOptions: PluginOptions = { - config: { - counters: {}, - can_view: false, - can_edit: false, - can_reset_all: false, +const defaultOverrides: Array> = [ + { + level: ">=50", + config: { + can_view: true, + }, }, - overrides: [ - { - level: ">=50", - config: { - can_view: true, - }, + { + level: ">=100", + config: { + can_edit: true, }, - { - level: ">=100", - config: { - can_edit: true, - }, - }, - ], -}; + }, +]; /** * The Counters plugin keeps track of simple integer values that are tied to a user, channel, both, or neither — "counters". @@ -59,9 +51,8 @@ const defaultOptions: PluginOptions = { export const CountersPlugin = guildPlugin()({ name: "counters", - defaultOptions, - // TODO: Separate input and output types - configParser: (input) => zCountersConfig.parse(input), + configSchema: zCountersConfig, + defaultOverrides, public(pluginData) { return { diff --git a/backend/src/plugins/Counters/types.ts b/backend/src/plugins/Counters/types.ts index 29ef6519..03bfc91a 100644 --- a/backend/src/plugins/Counters/types.ts +++ b/backend/src/plugins/Counters/types.ts @@ -69,10 +69,10 @@ export const zCounter = z.strictObject({ }); export const zCountersConfig = z.strictObject({ - counters: zBoundedRecord(z.record(zBoundedCharacters(0, 100), zCounter), 0, MAX_COUNTERS), - can_view: z.boolean(), - can_edit: z.boolean(), - can_reset_all: z.boolean(), + counters: zBoundedRecord(z.record(zBoundedCharacters(0, 100), zCounter), 0, MAX_COUNTERS).default({}), + can_view: z.boolean().default(false), + can_edit: z.boolean().default(false), + can_reset_all: z.boolean().default(false), }); export interface CounterEvents { @@ -86,7 +86,7 @@ export interface CounterEventEmitter extends EventEmitter { } export interface CountersPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zCountersConfig; state: { counters: GuildCounters; counterIds: Record; diff --git a/backend/src/plugins/CustomEvents/CustomEventsPlugin.ts b/backend/src/plugins/CustomEvents/CustomEventsPlugin.ts index c61d66f4..7115ea9d 100644 --- a/backend/src/plugins/CustomEvents/CustomEventsPlugin.ts +++ b/backend/src/plugins/CustomEvents/CustomEventsPlugin.ts @@ -16,18 +16,11 @@ import { LogsPlugin } from "../Logs/LogsPlugin.js"; import { runEvent } from "./functions/runEvent.js"; import { CustomEventsPluginType, zCustomEventsConfig } from "./types.js"; -const defaultOptions = { - config: { - events: {}, - }, -}; - export const CustomEventsPlugin = guildPlugin()({ name: "custom_events", dependencies: () => [LogsPlugin], - configParser: (input) => zCustomEventsConfig.parse(input), - defaultOptions, + configSchema: zCustomEventsConfig, beforeStart(pluginData) { pluginData.state.common = pluginData.getPlugin(CommonPlugin); diff --git a/backend/src/plugins/CustomEvents/types.ts b/backend/src/plugins/CustomEvents/types.ts index f401258c..877fe3fe 100644 --- a/backend/src/plugins/CustomEvents/types.ts +++ b/backend/src/plugins/CustomEvents/types.ts @@ -37,11 +37,11 @@ export const zCustomEvent = z.strictObject({ export type TCustomEvent = z.infer; export const zCustomEventsConfig = z.strictObject({ - events: zBoundedRecord(z.record(zBoundedCharacters(0, 100), zCustomEvent), 0, 100), + events: zBoundedRecord(z.record(zBoundedCharacters(0, 100), zCustomEvent), 0, 100).default({}), }); export interface CustomEventsPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zCustomEventsConfig; state: { clearTriggers: () => void; common: pluginUtils.PluginPublicInterface; diff --git a/backend/src/plugins/GuildAccessMonitor/GuildAccessMonitorPlugin.ts b/backend/src/plugins/GuildAccessMonitor/GuildAccessMonitorPlugin.ts index a573cde4..06eca255 100644 --- a/backend/src/plugins/GuildAccessMonitor/GuildAccessMonitorPlugin.ts +++ b/backend/src/plugins/GuildAccessMonitor/GuildAccessMonitorPlugin.ts @@ -3,13 +3,7 @@ import { BasePluginType, GlobalPluginData, globalPlugin, globalPluginEventListen import { AllowedGuilds } from "../../data/AllowedGuilds.js"; import { Configs } from "../../data/Configs.js"; import { env } from "../../env.js"; -import { zGuildAccessMonitorConfig } from "./types.js"; - -interface GuildAccessMonitorPluginType extends BasePluginType { - state: { - allowedGuilds: AllowedGuilds; - }; -} +import { GuildAccessMonitorPluginType, zGuildAccessMonitorConfig } from "./types.js"; async function checkGuild(pluginData: GlobalPluginData, guild: Guild) { if (!(await pluginData.state.allowedGuilds.isAllowed(guild.id))) { @@ -24,7 +18,7 @@ async function checkGuild(pluginData: GlobalPluginData()({ name: "guild_access_monitor", - configParser: (input) => zGuildAccessMonitorConfig.parse(input), + configSchema: zGuildAccessMonitorConfig, events: [ globalPluginEventListener()({ diff --git a/backend/src/plugins/GuildAccessMonitor/types.ts b/backend/src/plugins/GuildAccessMonitor/types.ts index 1eb60817..5e6b1eb2 100644 --- a/backend/src/plugins/GuildAccessMonitor/types.ts +++ b/backend/src/plugins/GuildAccessMonitor/types.ts @@ -1,3 +1,12 @@ +import { BasePluginType } from "knub"; import { z } from "zod/v4"; +import { AllowedGuilds } from "../../data/AllowedGuilds.js"; export const zGuildAccessMonitorConfig = z.strictObject({}); + +export interface GuildAccessMonitorPluginType extends BasePluginType { + configSchema: typeof zGuildAccessMonitorConfig; + state: { + allowedGuilds: AllowedGuilds; + }; +} diff --git a/backend/src/plugins/GuildConfigReloader/GuildConfigReloaderPlugin.ts b/backend/src/plugins/GuildConfigReloader/GuildConfigReloaderPlugin.ts index 33dbbf55..e90cb48c 100644 --- a/backend/src/plugins/GuildConfigReloader/GuildConfigReloaderPlugin.ts +++ b/backend/src/plugins/GuildConfigReloader/GuildConfigReloaderPlugin.ts @@ -1,13 +1,12 @@ import { globalPlugin } from "knub"; -import z from "zod/v4"; import { Configs } from "../../data/Configs.js"; import { reloadChangedGuilds } from "./functions/reloadChangedGuilds.js"; -import { GuildConfigReloaderPluginType } from "./types.js"; +import { GuildConfigReloaderPluginType, zGuildConfigReloaderPluginConfig } from "./types.js"; export const GuildConfigReloaderPlugin = globalPlugin()({ name: "guild_config_reloader", - configParser: (input) => z.strictObject({}).parse(input), + configSchema: zGuildConfigReloaderPluginConfig, async beforeLoad(pluginData) { const { state } = pluginData; diff --git a/backend/src/plugins/GuildConfigReloader/docs.ts b/backend/src/plugins/GuildConfigReloader/docs.ts index a3fb923e..93ce6693 100644 --- a/backend/src/plugins/GuildConfigReloader/docs.ts +++ b/backend/src/plugins/GuildConfigReloader/docs.ts @@ -1,8 +1,8 @@ import { ZeppelinPluginDocs } from "../../types.js"; -import { zGuildConfigReloaderPlugin } from "./types.js"; +import { zGuildConfigReloaderPluginConfig } from "./types.js"; export const guildConfigReloaderPluginDocs: ZeppelinPluginDocs = { prettyName: "Guild config reloader", type: "internal", - configSchema: zGuildConfigReloaderPlugin, + configSchema: zGuildConfigReloaderPluginConfig, }; diff --git a/backend/src/plugins/GuildConfigReloader/types.ts b/backend/src/plugins/GuildConfigReloader/types.ts index af9b62cf..ae054856 100644 --- a/backend/src/plugins/GuildConfigReloader/types.ts +++ b/backend/src/plugins/GuildConfigReloader/types.ts @@ -3,10 +3,10 @@ import { z } from "zod/v4"; import { Configs } from "../../data/Configs.js"; import Timeout = NodeJS.Timeout; -export const zGuildConfigReloaderPlugin = z.strictObject({}); +export const zGuildConfigReloaderPluginConfig = z.strictObject({}); export interface GuildConfigReloaderPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zGuildConfigReloaderPluginConfig; state: { guildConfigs: Configs; unloaded: boolean; diff --git a/backend/src/plugins/GuildInfoSaver/GuildInfoSaverPlugin.ts b/backend/src/plugins/GuildInfoSaver/GuildInfoSaverPlugin.ts index 5271027c..753801ac 100644 --- a/backend/src/plugins/GuildInfoSaver/GuildInfoSaverPlugin.ts +++ b/backend/src/plugins/GuildInfoSaver/GuildInfoSaverPlugin.ts @@ -1,15 +1,14 @@ import { Guild } from "discord.js"; import { guildPlugin, guildPluginEventListener } from "knub"; -import z from "zod/v4"; import { AllowedGuilds } from "../../data/AllowedGuilds.js"; import { ApiPermissionAssignments } from "../../data/ApiPermissionAssignments.js"; import { MINUTES } from "../../utils.js"; -import { GuildInfoSaverPluginType } from "./types.js"; +import { GuildInfoSaverPluginType, zGuildInfoSaverConfig } from "./types.js"; export const GuildInfoSaverPlugin = guildPlugin()({ name: "guild_info_saver", - configParser: (input) => z.strictObject({}).parse(input), + configSchema: zGuildInfoSaverConfig, events: [ guildPluginEventListener({ diff --git a/backend/src/plugins/GuildInfoSaver/types.ts b/backend/src/plugins/GuildInfoSaver/types.ts index 32118760..3172856d 100644 --- a/backend/src/plugins/GuildInfoSaver/types.ts +++ b/backend/src/plugins/GuildInfoSaver/types.ts @@ -4,7 +4,7 @@ import { z } from "zod/v4"; export const zGuildInfoSaverConfig = z.strictObject({}); export interface GuildInfoSaverPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zGuildInfoSaverConfig; state: { updateInterval: NodeJS.Timeout; }; diff --git a/backend/src/plugins/GuildMemberCache/GuildMemberCachePlugin.ts b/backend/src/plugins/GuildMemberCache/GuildMemberCachePlugin.ts index bdab13b7..33fea080 100644 --- a/backend/src/plugins/GuildMemberCache/GuildMemberCachePlugin.ts +++ b/backend/src/plugins/GuildMemberCache/GuildMemberCachePlugin.ts @@ -1,5 +1,4 @@ import { guildPlugin } from "knub"; -import z from "zod/v4"; import { GuildMemberCache } from "../../data/GuildMemberCache.js"; import { makePublicFn } from "../../pluginUtils.js"; import { SECONDS } from "../../utils.js"; @@ -10,14 +9,14 @@ import { updateMemberCacheOnMessage } from "./events/updateMemberCacheOnMessage. import { updateMemberCacheOnRoleChange } from "./events/updateMemberCacheOnRoleChange.js"; import { updateMemberCacheOnVoiceStateUpdate } from "./events/updateMemberCacheOnVoiceStateUpdate.js"; import { getCachedMemberData } from "./functions/getCachedMemberData.js"; -import { GuildMemberCachePluginType } from "./types.js"; +import { GuildMemberCachePluginType, zGuildMemberCacheConfig } from "./types.js"; const PENDING_SAVE_INTERVAL = 30 * SECONDS; export const GuildMemberCachePlugin = guildPlugin()({ name: "guild_member_cache", - configParser: (input) => z.strictObject({}).parse(input), + configSchema: zGuildMemberCacheConfig, events: [ updateMemberCacheOnMemberUpdate, diff --git a/backend/src/plugins/GuildMemberCache/types.ts b/backend/src/plugins/GuildMemberCache/types.ts index 77f15920..32be0f6d 100644 --- a/backend/src/plugins/GuildMemberCache/types.ts +++ b/backend/src/plugins/GuildMemberCache/types.ts @@ -5,7 +5,7 @@ import { GuildMemberCache } from "../../data/GuildMemberCache.js"; export const zGuildMemberCacheConfig = z.strictObject({}); export interface GuildMemberCachePluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zGuildMemberCacheConfig; state: { memberCache: GuildMemberCache; saveInterval: NodeJS.Timeout; diff --git a/backend/src/plugins/InternalPoster/InternalPosterPlugin.ts b/backend/src/plugins/InternalPoster/InternalPosterPlugin.ts index 79ca3c04..3aeb649b 100644 --- a/backend/src/plugins/InternalPoster/InternalPosterPlugin.ts +++ b/backend/src/plugins/InternalPoster/InternalPosterPlugin.ts @@ -5,18 +5,12 @@ import { Webhooks } from "../../data/Webhooks.js"; import { makePublicFn } from "../../pluginUtils.js"; import { editMessage } from "./functions/editMessage.js"; import { sendMessage } from "./functions/sendMessage.js"; -import { InternalPosterPluginType } from "./types.js"; - -const defaultOptions: PluginOptions = { - config: {}, - overrides: [], -}; +import { InternalPosterPluginType, zInternalPosterConfig } from "./types.js"; export const InternalPosterPlugin = guildPlugin()({ name: "internal_poster", - configParser: (input) => z.strictObject({}).parse(input), - defaultOptions, + configSchema: zInternalPosterConfig, public(pluginData) { return { diff --git a/backend/src/plugins/InternalPoster/types.ts b/backend/src/plugins/InternalPoster/types.ts index 90571ea7..13d4b214 100644 --- a/backend/src/plugins/InternalPoster/types.ts +++ b/backend/src/plugins/InternalPoster/types.ts @@ -4,10 +4,10 @@ import { z } from "zod/v4"; import { Queue } from "../../Queue.js"; import { Webhooks } from "../../data/Webhooks.js"; -export const zInternalPosterConfig = z.strictObject({}); +export const zInternalPosterConfig = z.strictObject({}).default({}); export interface InternalPosterPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zInternalPosterConfig; state: { queue: Queue; webhooks: Webhooks; diff --git a/backend/src/plugins/LocateUser/LocateUserPlugin.ts b/backend/src/plugins/LocateUser/LocateUserPlugin.ts index b16a29a9..32915dd1 100644 --- a/backend/src/plugins/LocateUser/LocateUserPlugin.ts +++ b/backend/src/plugins/LocateUser/LocateUserPlugin.ts @@ -11,12 +11,11 @@ import { LocateUserPluginType, zLocateUserConfig } from "./types.js"; import { clearExpiredAlert } from "./utils/clearExpiredAlert.js"; import { fillActiveAlertsList } from "./utils/fillAlertsList.js"; -const defaultOptions: PluginOptions = { - config: { - can_where: false, - can_alert: false, - }, - overrides: [ +export const LocateUserPlugin = guildPlugin()({ + name: "locate_user", + + configSchema: zLocateUserConfig, + defaultOverrides: [ { level: ">=50", config: { @@ -25,13 +24,6 @@ const defaultOptions: PluginOptions = { }, }, ], -}; - -export const LocateUserPlugin = guildPlugin()({ - name: "locate_user", - - configParser: (input) => zLocateUserConfig.parse(input), - defaultOptions, // prettier-ignore messageCommands: [ diff --git a/backend/src/plugins/LocateUser/types.ts b/backend/src/plugins/LocateUser/types.ts index 14302403..e84c673c 100644 --- a/backend/src/plugins/LocateUser/types.ts +++ b/backend/src/plugins/LocateUser/types.ts @@ -4,12 +4,12 @@ import { GuildVCAlerts } from "../../data/GuildVCAlerts.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; export const zLocateUserConfig = z.strictObject({ - can_where: z.boolean(), - can_alert: z.boolean(), + can_where: z.boolean().default(false), + can_alert: z.boolean().default(false), }); export interface LocateUserPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zLocateUserConfig; state: { alerts: GuildVCAlerts; usersWithAlerts: string[]; diff --git a/backend/src/plugins/Logs/LogsPlugin.ts b/backend/src/plugins/Logs/LogsPlugin.ts index be2593a5..0485351c 100644 --- a/backend/src/plugins/Logs/LogsPlugin.ts +++ b/backend/src/plugins/Logs/LogsPlugin.ts @@ -1,5 +1,4 @@ -import { CooldownManager, PluginOptions, guildPlugin } from "knub"; -import DefaultLogMessages from "../../data/DefaultLogMessages.json" with { type: "json" }; +import { CooldownManager, guildPlugin } from "knub"; import { GuildArchives } from "../../data/GuildArchives.js"; import { GuildCases } from "../../data/GuildCases.js"; import { GuildLogs } from "../../data/GuildLogs.js"; @@ -115,17 +114,12 @@ function getCasesPlugin(): Promise { return import("../Cases/CasesPlugin.js") as Promise; } -const defaultOptions: PluginOptions = { - config: { - channels: {}, - format: DefaultLogMessages, - ping_user: true, - allow_user_mentions: false, - timestamp_format: "[]", - include_embed_timestamp: true, - }, +export const LogsPlugin = guildPlugin()({ + name: "logs", - overrides: [ + dependencies: async () => [TimeAndDatePlugin, InternalPosterPlugin, (await getCasesPlugin()).CasesPlugin], + configSchema: zLogsConfig, + defaultOverrides: [ { level: ">=50", config: { @@ -134,14 +128,6 @@ const defaultOptions: PluginOptions = { }, }, ], -}; - -export const LogsPlugin = guildPlugin()({ - name: "logs", - - dependencies: async () => [TimeAndDatePlugin, InternalPosterPlugin, (await getCasesPlugin()).CasesPlugin], - configParser: (input) => zLogsConfig.parse(input), - defaultOptions, events: [ LogsGuildMemberAddEvt, diff --git a/backend/src/plugins/Logs/types.ts b/backend/src/plugins/Logs/types.ts index a757524a..07fcae41 100644 --- a/backend/src/plugins/Logs/types.ts +++ b/backend/src/plugins/Logs/types.ts @@ -21,6 +21,7 @@ import { TemplateSafeUnknownUser, TemplateSafeUser, } from "../../utils/templateSafeObjects.js"; +import DefaultLogMessages from "../../data/DefaultLogMessages.json" with { type: "json" }; const DEFAULT_BATCH_TIME = 1000; const MIN_BATCH_TIME = 250; @@ -53,20 +54,20 @@ const zLogChannelMap = z.record(zSnowflake, zLogChannel); export type TLogChannelMap = z.infer; export const zLogsConfig = z.strictObject({ - channels: zLogChannelMap, - format: zLogFormats, + channels: zLogChannelMap.default({}), + format: zLogFormats.default(DefaultLogMessages), // Legacy/deprecated, if below is false mentions wont actually ping. In case you really want the old behavior, set below to true - ping_user: z.boolean(), - allow_user_mentions: z.boolean(), - timestamp_format: z.string().nullable(), - include_embed_timestamp: z.boolean(), + ping_user: z.boolean().default(true), + allow_user_mentions: z.boolean().default(false), + timestamp_format: z.string().nullable().default("[]"), + include_embed_timestamp: z.boolean().default(true), }); // Hacky way of allowing a """null""" default value for config.format.timestamp due to legacy io-ts reasons export const FORMAT_NO_TIMESTAMP = "__NO_TIMESTAMP__"; export interface LogsPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zLogsConfig; state: { guildLogs: GuildLogs; savedMessages: GuildSavedMessages; diff --git a/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts b/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts index 21042298..b204ad77 100644 --- a/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts +++ b/backend/src/plugins/MessageSaver/MessageSaverPlugin.ts @@ -11,11 +11,11 @@ import { } from "./events/SaveMessagesEvts.js"; import { MessageSaverPluginType, zMessageSaverConfig } from "./types.js"; -const defaultOptions: PluginOptions = { - config: { - can_manage: false, - }, - overrides: [ +export const MessageSaverPlugin = guildPlugin()({ + name: "message_saver", + + configSchema: zMessageSaverConfig, + defaultOverrides: [ { level: ">=100", config: { @@ -23,13 +23,6 @@ const defaultOptions: PluginOptions = { }, }, ], -}; - -export const MessageSaverPlugin = guildPlugin()({ - name: "message_saver", - - configParser: (input) => zMessageSaverConfig.parse(input), - defaultOptions, // prettier-ignore messageCommands: [ diff --git a/backend/src/plugins/MessageSaver/types.ts b/backend/src/plugins/MessageSaver/types.ts index f7e0495d..d1f0e77e 100644 --- a/backend/src/plugins/MessageSaver/types.ts +++ b/backend/src/plugins/MessageSaver/types.ts @@ -4,11 +4,11 @@ import { GuildSavedMessages } from "../../data/GuildSavedMessages.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; export const zMessageSaverConfig = z.strictObject({ - can_manage: z.boolean(), + can_manage: z.boolean().default(false), }); export interface MessageSaverPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zMessageSaverConfig; state: { savedMessages: GuildSavedMessages; common: pluginUtils.PluginPublicInterface; diff --git a/backend/src/plugins/ModActions/ModActionsPlugin.ts b/backend/src/plugins/ModActions/ModActionsPlugin.ts index 798f2f12..80c75680 100644 --- a/backend/src/plugins/ModActions/ModActionsPlugin.ts +++ b/backend/src/plugins/ModActions/ModActionsPlugin.ts @@ -72,47 +72,14 @@ import { offModActionsEvent } from "./functions/offModActionsEvent.js"; import { onModActionsEvent } from "./functions/onModActionsEvent.js"; import { updateCase } from "./functions/updateCase.js"; import { warnMember } from "./functions/warnMember.js"; -import { AttachmentLinkReactionType, ModActionsPluginType, modActionsSlashGroup, zModActionsConfig } from "./types.js"; +import { ModActionsPluginType, modActionsSlashGroup, zModActionsConfig } from "./types.js"; -const defaultOptions = { - config: { - dm_on_warn: true, - dm_on_kick: false, - dm_on_ban: false, - message_on_warn: false, - message_on_kick: false, - message_on_ban: false, - message_channel: null, - warn_message: "You have received a warning on the {guildName} server: {reason}", - kick_message: "You have been kicked from the {guildName} server. Reason given: {reason}", - ban_message: "You have been banned from the {guildName} server. Reason given: {reason}", - tempban_message: "You have been banned from the {guildName} server for {banTime}. Reason given: {reason}", - alert_on_rejoin: false, - alert_channel: null, - warn_notify_enabled: false, - warn_notify_threshold: 5, - 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, +export const ModActionsPlugin = guildPlugin()({ + name: "mod_actions", - can_note: false, - can_warn: false, - can_mute: false, - can_kick: false, - can_ban: false, - can_unban: false, - can_view: false, - can_addcase: false, - can_massunban: false, - can_massban: false, - can_massmute: false, - can_hidecase: false, - can_deletecase: false, - can_act_as_other: false, - create_cases_for_manual_actions: true, - }, - overrides: [ + dependencies: () => [TimeAndDatePlugin, CasesPlugin, MutesPlugin, LogsPlugin], + configSchema: zModActionsConfig, + defaultOverrides: [ { level: ">=50", config: { @@ -137,14 +104,6 @@ const defaultOptions = { }, }, ], -}; - -export const ModActionsPlugin = guildPlugin()({ - name: "mod_actions", - - dependencies: () => [TimeAndDatePlugin, CasesPlugin, MutesPlugin, LogsPlugin], - configParser: (input) => zModActionsConfig.parse(input), - defaultOptions, events: [CreateBanCaseOnManualBanEvt, CreateUnbanCaseOnManualUnbanEvt, PostAlertOnMemberJoinEvt, AuditLogEvents], diff --git a/backend/src/plugins/ModActions/types.ts b/backend/src/plugins/ModActions/types.ts index f7e52bfc..0a4894c4 100644 --- a/backend/src/plugins/ModActions/types.ts +++ b/backend/src/plugins/ModActions/types.ts @@ -22,39 +22,39 @@ import { CommonPlugin } from "../Common/CommonPlugin.js"; export type AttachmentLinkReactionType = "none" | "warn" | "restrict" | null; export const zModActionsConfig = z.strictObject({ - dm_on_warn: z.boolean(), - dm_on_kick: z.boolean(), - dm_on_ban: z.boolean(), - message_on_warn: z.boolean(), - message_on_kick: z.boolean(), - message_on_ban: z.boolean(), - message_channel: z.nullable(z.string()), - warn_message: z.nullable(z.string()), - kick_message: z.nullable(z.string()), - ban_message: z.nullable(z.string()), - tempban_message: z.nullable(z.string()), - alert_on_rejoin: z.boolean(), - alert_channel: z.nullable(z.string()), - warn_notify_enabled: z.boolean(), - warn_notify_threshold: z.number(), - warn_notify_message: z.string(), - ban_delete_message_days: z.number(), - attachment_link_reaction: z.nullable(z.union([z.literal("none"), z.literal("warn"), z.literal("restrict")])), - can_note: z.boolean(), - can_warn: z.boolean(), - can_mute: z.boolean(), - can_kick: z.boolean(), - can_ban: z.boolean(), - can_unban: z.boolean(), - can_view: z.boolean(), - can_addcase: z.boolean(), - can_massunban: z.boolean(), - can_massban: z.boolean(), - can_massmute: z.boolean(), - can_hidecase: z.boolean(), - can_deletecase: z.boolean(), - can_act_as_other: z.boolean(), - create_cases_for_manual_actions: z.boolean(), + dm_on_warn: z.boolean().default(true), + dm_on_kick: z.boolean().default(false), + dm_on_ban: z.boolean().default(false), + message_on_warn: z.boolean().default(false), + message_on_kick: z.boolean().default(false), + 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}"), + 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?"), + 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"), + can_note: z.boolean().default(false), + can_warn: z.boolean().default(false), + can_mute: z.boolean().default(false), + can_kick: z.boolean().default(false), + can_ban: z.boolean().default(false), + can_unban: z.boolean().default(false), + can_view: z.boolean().default(false), + can_addcase: z.boolean().default(false), + can_massunban: z.boolean().default(false), + can_massban: z.boolean().default(false), + can_massmute: z.boolean().default(false), + can_hidecase: z.boolean().default(false), + can_deletecase: z.boolean().default(false), + can_act_as_other: z.boolean().default(false), + create_cases_for_manual_actions: z.boolean().default(true), }); export interface ModActionsEvents { @@ -72,7 +72,7 @@ export interface ModActionsEventEmitter extends EventEmitter { } export interface ModActionsPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zModActionsConfig; state: { mutes: GuildMutes; cases: GuildCases; diff --git a/backend/src/plugins/Mutes/MutesPlugin.ts b/backend/src/plugins/Mutes/MutesPlugin.ts index 9eccb855..0a302ee2 100644 --- a/backend/src/plugins/Mutes/MutesPlugin.ts +++ b/backend/src/plugins/Mutes/MutesPlugin.ts @@ -26,27 +26,12 @@ import { renewTimeoutMute } from "./functions/renewTimeoutMute.js"; import { unmuteUser } from "./functions/unmuteUser.js"; import { MutesPluginType, zMutesConfig } from "./types.js"; -const defaultOptions = { - config: { - mute_role: null, - move_to_voice_channel: null, - kick_from_voice_channel: false, +export const MutesPlugin = guildPlugin()({ + name: "mutes", - dm_on_mute: false, - dm_on_update: false, - message_on_mute: false, - message_on_update: false, - message_channel: null, - mute_message: "You have been muted on the {guildName} server. Reason given: {reason}", - timed_mute_message: "You have been muted on the {guildName} server for {time}. Reason given: {reason}", - update_mute_message: "Your mute on the {guildName} server has been updated to {time}.", - remove_roles_on_mute: false, - restore_roles_on_mute: false, - - can_view_list: false, - can_cleanup: false, - }, - overrides: [ + dependencies: () => [CasesPlugin, LogsPlugin, RoleManagerPlugin], + configSchema: zMutesConfig, + defaultOverrides: [ { level: ">=50", config: { @@ -60,14 +45,6 @@ const defaultOptions = { }, }, ], -}; - -export const MutesPlugin = guildPlugin()({ - name: "mutes", - - dependencies: () => [CasesPlugin, LogsPlugin, RoleManagerPlugin], - configParser: (input) => zMutesConfig.parse(input), - defaultOptions, // prettier-ignore messageCommands: [ diff --git a/backend/src/plugins/Mutes/types.ts b/backend/src/plugins/Mutes/types.ts index 94d9a499..67fa1913 100644 --- a/backend/src/plugins/Mutes/types.ts +++ b/backend/src/plugins/Mutes/types.ts @@ -13,23 +13,23 @@ import { CaseArgs } from "../Cases/types.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; export const zMutesConfig = z.strictObject({ - mute_role: zSnowflake.nullable(), - move_to_voice_channel: zSnowflake.nullable(), - kick_from_voice_channel: z.boolean(), + mute_role: zSnowflake.nullable().default(null), + move_to_voice_channel: zSnowflake.nullable().default(null), + kick_from_voice_channel: z.boolean().default(false), - dm_on_mute: z.boolean(), - dm_on_update: z.boolean(), - message_on_mute: z.boolean(), - message_on_update: z.boolean(), - message_channel: z.string().nullable(), - mute_message: z.string().nullable(), - timed_mute_message: z.string().nullable(), - update_mute_message: z.string().nullable(), + dm_on_mute: z.boolean().default(false), + dm_on_update: z.boolean().default(false), + message_on_mute: z.boolean().default(false), + 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}"), + 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), - can_view_list: z.boolean(), - can_cleanup: z.boolean(), + can_view_list: z.boolean().default(false), + can_cleanup: z.boolean().default(false), }); export interface MutesEvents { @@ -43,7 +43,7 @@ export interface MutesEventEmitter extends EventEmitter { } export interface MutesPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zMutesConfig; state: { mutes: GuildMutes; cases: GuildCases; diff --git a/backend/src/plugins/NameHistory/NameHistoryPlugin.ts b/backend/src/plugins/NameHistory/NameHistoryPlugin.ts index 1cb28123..204710f8 100644 --- a/backend/src/plugins/NameHistory/NameHistoryPlugin.ts +++ b/backend/src/plugins/NameHistory/NameHistoryPlugin.ts @@ -6,11 +6,11 @@ import { CommonPlugin } from "../Common/CommonPlugin.js"; import { NamesCmd } from "./commands/NamesCmd.js"; import { NameHistoryPluginType, zNameHistoryConfig } from "./types.js"; -const defaultOptions: PluginOptions = { - config: { - can_view: false, - }, - overrides: [ +export const NameHistoryPlugin = guildPlugin()({ + name: "name_history", + + configSchema: zNameHistoryConfig, + defaultOverrides: [ { level: ">=50", config: { @@ -18,13 +18,6 @@ const defaultOptions: PluginOptions = { }, }, ], -}; - -export const NameHistoryPlugin = guildPlugin()({ - name: "name_history", - - configParser: (input) => zNameHistoryConfig.parse(input), - defaultOptions, // prettier-ignore messageCommands: [ diff --git a/backend/src/plugins/NameHistory/types.ts b/backend/src/plugins/NameHistory/types.ts index 259f4b7b..84e9b968 100644 --- a/backend/src/plugins/NameHistory/types.ts +++ b/backend/src/plugins/NameHistory/types.ts @@ -6,11 +6,11 @@ import { UsernameHistory } from "../../data/UsernameHistory.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; export const zNameHistoryConfig = z.strictObject({ - can_view: z.boolean(), + can_view: z.boolean().default(false), }); export interface NameHistoryPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zNameHistoryConfig; state: { nicknameHistory: GuildNicknameHistory; usernameHistory: UsernameHistory; diff --git a/backend/src/plugins/Persist/PersistPlugin.ts b/backend/src/plugins/Persist/PersistPlugin.ts index 7d9a5d6e..76c9150d 100644 --- a/backend/src/plugins/Persist/PersistPlugin.ts +++ b/backend/src/plugins/Persist/PersistPlugin.ts @@ -7,20 +7,11 @@ import { LoadDataEvt } from "./events/LoadDataEvt.js"; import { StoreDataEvt } from "./events/StoreDataEvt.js"; import { PersistPluginType, zPersistConfig } from "./types.js"; -const defaultOptions: PluginOptions = { - config: { - persisted_roles: [], - persist_nicknames: false, - persist_voice_mutes: false, - }, -}; - export const PersistPlugin = guildPlugin()({ name: "persist", dependencies: () => [LogsPlugin, RoleManagerPlugin], - configParser: (input) => zPersistConfig.parse(input), - defaultOptions, + configSchema: zPersistConfig, // prettier-ignore events: [ diff --git a/backend/src/plugins/Persist/types.ts b/backend/src/plugins/Persist/types.ts index 1c6fc714..bb48a1fd 100644 --- a/backend/src/plugins/Persist/types.ts +++ b/backend/src/plugins/Persist/types.ts @@ -5,14 +5,13 @@ import { GuildPersistedData } from "../../data/GuildPersistedData.js"; import { zSnowflake } from "../../utils.js"; export const zPersistConfig = z.strictObject({ - persisted_roles: z.array(zSnowflake), - persist_nicknames: z.boolean(), - persist_voice_mutes: z.boolean(), + persisted_roles: z.array(zSnowflake).default([]), + persist_nicknames: z.boolean().default(false), + persist_voice_mutes: z.boolean().default(false), }); export interface PersistPluginType extends BasePluginType { - config: z.infer; - + configSchema: typeof zPersistConfig; state: { persistedData: GuildPersistedData; logs: GuildLogs; diff --git a/backend/src/plugins/Phisherman/PhishermanPlugin.ts b/backend/src/plugins/Phisherman/PhishermanPlugin.ts index 3e1b4a50..c3637160 100644 --- a/backend/src/plugins/Phisherman/PhishermanPlugin.ts +++ b/backend/src/plugins/Phisherman/PhishermanPlugin.ts @@ -4,18 +4,10 @@ import { makePublicFn } from "../../pluginUtils.js"; import { getDomainInfo } from "./functions/getDomainInfo.js"; import { PhishermanPluginType, zPhishermanConfig } from "./types.js"; -const defaultOptions: PluginOptions = { - config: { - api_key: null, - }, - overrides: [], -}; - export const PhishermanPlugin = guildPlugin()({ name: "phisherman", - configParser: (input) => zPhishermanConfig.parse(input), - defaultOptions, + configSchema: zPhishermanConfig, public(pluginData) { return { diff --git a/backend/src/plugins/Phisherman/types.ts b/backend/src/plugins/Phisherman/types.ts index 77c9bfbc..980de42b 100644 --- a/backend/src/plugins/Phisherman/types.ts +++ b/backend/src/plugins/Phisherman/types.ts @@ -2,12 +2,11 @@ import { BasePluginType } from "knub"; import z from "zod/v4"; export const zPhishermanConfig = z.strictObject({ - api_key: z.string().max(255).nullable(), + api_key: z.string().max(255).nullable().default(null), }); export interface PhishermanPluginType extends BasePluginType { - config: z.infer; - + configSchema: typeof zPhishermanConfig; state: { validApiKey: string | null; }; diff --git a/backend/src/plugins/PingableRoles/PingableRolesPlugin.ts b/backend/src/plugins/PingableRoles/PingableRolesPlugin.ts index 636208ee..2790dc5b 100644 --- a/backend/src/plugins/PingableRoles/PingableRolesPlugin.ts +++ b/backend/src/plugins/PingableRoles/PingableRolesPlugin.ts @@ -1,15 +1,15 @@ -import { PluginOptions, guildPlugin } from "knub"; +import { guildPlugin } from "knub"; import { GuildPingableRoles } from "../../data/GuildPingableRoles.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; import { PingableRoleDisableCmd } from "./commands/PingableRoleDisableCmd.js"; import { PingableRoleEnableCmd } from "./commands/PingableRoleEnableCmd.js"; import { PingableRolesPluginType, zPingableRolesConfig } from "./types.js"; -const defaultOptions: PluginOptions = { - config: { - can_manage: false, - }, - overrides: [ +export const PingableRolesPlugin = guildPlugin()({ + name: "pingable_roles", + + configSchema: zPingableRolesConfig, + defaultOverrides: [ { level: ">=100", config: { @@ -17,13 +17,6 @@ const defaultOptions: PluginOptions = { }, }, ], -}; - -export const PingableRolesPlugin = guildPlugin()({ - name: "pingable_roles", - - configParser: (input) => zPingableRolesConfig.parse(input), - defaultOptions, // prettier-ignore messageCommands: [ diff --git a/backend/src/plugins/PingableRoles/types.ts b/backend/src/plugins/PingableRoles/types.ts index 4e9c623d..58f3c636 100644 --- a/backend/src/plugins/PingableRoles/types.ts +++ b/backend/src/plugins/PingableRoles/types.ts @@ -5,12 +5,11 @@ import { PingableRole } from "../../data/entities/PingableRole.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; export const zPingableRolesConfig = z.strictObject({ - can_manage: z.boolean(), + can_manage: z.boolean().default(false), }); export interface PingableRolesPluginType extends BasePluginType { - config: z.infer; - + configSchema: typeof zPingableRolesConfig; state: { pingableRoles: GuildPingableRoles; cache: Map; diff --git a/backend/src/plugins/Post/PostPlugin.ts b/backend/src/plugins/Post/PostPlugin.ts index b5e9a83a..47c9e62c 100644 --- a/backend/src/plugins/Post/PostPlugin.ts +++ b/backend/src/plugins/Post/PostPlugin.ts @@ -1,4 +1,4 @@ -import { PluginOptions, guildPlugin } from "knub"; +import { guildPlugin } from "knub"; import { onGuildEvent } from "../../data/GuildEvents.js"; import { GuildLogs } from "../../data/GuildLogs.js"; import { GuildSavedMessages } from "../../data/GuildSavedMessages.js"; @@ -16,11 +16,12 @@ import { ScheduledPostsShowCmd } from "./commands/ScheduledPostsShowCmd.js"; import { PostPluginType, zPostConfig } from "./types.js"; import { postScheduledPost } from "./util/postScheduledPost.js"; -const defaultOptions: PluginOptions = { - config: { - can_post: false, - }, - overrides: [ +export const PostPlugin = guildPlugin()({ + name: "post", + + dependencies: () => [TimeAndDatePlugin, LogsPlugin], + configSchema: zPostConfig, + defaultOverrides: [ { level: ">=100", config: { @@ -28,14 +29,6 @@ const defaultOptions: PluginOptions = { }, }, ], -}; - -export const PostPlugin = guildPlugin()({ - name: "post", - - dependencies: () => [TimeAndDatePlugin, LogsPlugin], - configParser: (input) => zPostConfig.parse(input), - defaultOptions, // prettier-ignore messageCommands: [ diff --git a/backend/src/plugins/Post/types.ts b/backend/src/plugins/Post/types.ts index 73fcbeca..0f9add61 100644 --- a/backend/src/plugins/Post/types.ts +++ b/backend/src/plugins/Post/types.ts @@ -6,11 +6,11 @@ import { GuildScheduledPosts } from "../../data/GuildScheduledPosts.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; export const zPostConfig = z.strictObject({ - can_post: z.boolean(), + can_post: z.boolean().default(false), }); export interface PostPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zPostConfig; state: { savedMessages: GuildSavedMessages; scheduledPosts: GuildScheduledPosts; diff --git a/backend/src/plugins/ReactionRoles/ReactionRolesPlugin.ts b/backend/src/plugins/ReactionRoles/ReactionRolesPlugin.ts index 6d819fa7..e06c9d78 100644 --- a/backend/src/plugins/ReactionRoles/ReactionRolesPlugin.ts +++ b/backend/src/plugins/ReactionRoles/ReactionRolesPlugin.ts @@ -11,19 +11,12 @@ import { AddReactionRoleEvt } from "./events/AddReactionRoleEvt.js"; import { MessageDeletedEvt } from "./events/MessageDeletedEvt.js"; import { ReactionRolesPluginType, zReactionRolesConfig } from "./types.js"; -const MIN_AUTO_REFRESH = 1000 * 60 * 15; // 15min minimum, let's not abuse the API +export const ReactionRolesPlugin = guildPlugin()({ + name: "reaction_roles", -const defaultOptions: PluginOptions = { - config: { - auto_refresh_interval: MIN_AUTO_REFRESH, - remove_user_reactions: true, - - can_manage: false, - - button_groups: null, - }, - - overrides: [ + dependencies: () => [LogsPlugin], + configSchema: zReactionRolesConfig, + defaultOverrides: [ { level: ">=100", config: { @@ -31,14 +24,6 @@ const defaultOptions: PluginOptions = { }, }, ], -}; - -export const ReactionRolesPlugin = guildPlugin()({ - name: "reaction_roles", - - dependencies: () => [LogsPlugin], - configParser: (input) => zReactionRolesConfig.parse(input), - defaultOptions, // prettier-ignore messageCommands: [ diff --git a/backend/src/plugins/ReactionRoles/types.ts b/backend/src/plugins/ReactionRoles/types.ts index 89418363..b22a4856 100644 --- a/backend/src/plugins/ReactionRoles/types.ts +++ b/backend/src/plugins/ReactionRoles/types.ts @@ -5,11 +5,13 @@ import { GuildReactionRoles } from "../../data/GuildReactionRoles.js"; import { GuildSavedMessages } from "../../data/GuildSavedMessages.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; +const MIN_AUTO_REFRESH = 1000 * 60 * 15; // 15min minimum, let's not abuse the API + export const zReactionRolesConfig = z.strictObject({ - auto_refresh_interval: z.number(), - remove_user_reactions: z.boolean(), - can_manage: z.boolean(), - button_groups: z.nullable(z.unknown()), + auto_refresh_interval: z.number().min(MIN_AUTO_REFRESH).default(MIN_AUTO_REFRESH), + remove_user_reactions: z.boolean().default(true), + can_manage: z.boolean().default(false), + button_groups: z.null().default(null), }); export type RoleChangeMode = "+" | "-"; @@ -27,7 +29,7 @@ const zReactionRolePair = z.union([z.tuple([z.string(), z.string(), z.string()]) export type TReactionRolePair = z.infer; export interface ReactionRolesPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zReactionRolesConfig; state: { reactionRoles: GuildReactionRoles; savedMessages: GuildSavedMessages; diff --git a/backend/src/plugins/Reminders/RemindersPlugin.ts b/backend/src/plugins/Reminders/RemindersPlugin.ts index 439d7460..a36f47e0 100644 --- a/backend/src/plugins/Reminders/RemindersPlugin.ts +++ b/backend/src/plugins/Reminders/RemindersPlugin.ts @@ -9,11 +9,12 @@ import { RemindersDeleteCmd } from "./commands/RemindersDeleteCmd.js"; import { postReminder } from "./functions/postReminder.js"; import { RemindersPluginType, zRemindersConfig } from "./types.js"; -const defaultOptions: PluginOptions = { - config: { - can_use: false, - }, - overrides: [ +export const RemindersPlugin = guildPlugin()({ + name: "reminders", + + dependencies: () => [TimeAndDatePlugin], + configSchema: zRemindersConfig, + defaultOverrides: [ { level: ">=50", config: { @@ -21,14 +22,6 @@ const defaultOptions: PluginOptions = { }, }, ], -}; - -export const RemindersPlugin = guildPlugin()({ - name: "reminders", - - dependencies: () => [TimeAndDatePlugin], - configParser: (input) => zRemindersConfig.parse(input), - defaultOptions, // prettier-ignore messageCommands: [ diff --git a/backend/src/plugins/Reminders/types.ts b/backend/src/plugins/Reminders/types.ts index 8583033a..66fd8438 100644 --- a/backend/src/plugins/Reminders/types.ts +++ b/backend/src/plugins/Reminders/types.ts @@ -4,12 +4,11 @@ import { GuildReminders } from "../../data/GuildReminders.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; export const zRemindersConfig = z.strictObject({ - can_use: z.boolean(), + can_use: z.boolean().default(false), }); export interface RemindersPluginType extends BasePluginType { - config: z.infer; - + configSchema: typeof zRemindersConfig; state: { reminders: GuildReminders; tries: Map; diff --git a/backend/src/plugins/RoleButtons/RoleButtonsPlugin.ts b/backend/src/plugins/RoleButtons/RoleButtonsPlugin.ts index f7d9f581..6826fdcb 100644 --- a/backend/src/plugins/RoleButtons/RoleButtonsPlugin.ts +++ b/backend/src/plugins/RoleButtons/RoleButtonsPlugin.ts @@ -11,22 +11,15 @@ import { RoleButtonsPluginType, zRoleButtonsConfig } from "./types.js"; export const RoleButtonsPlugin = guildPlugin()({ name: "role_buttons", - defaultOptions: { - config: { - buttons: {}, - can_reset: false, - }, - overrides: [ - { - level: ">=100", - config: { - can_reset: true, - }, + configSchema: zRoleButtonsConfig, + defaultOverrides: [ + { + level: ">=100", + config: { + can_reset: true, }, - ], - }, - - configParser: (input) => zRoleButtonsConfig.parse(input), + }, + ], dependencies: () => [LogsPlugin, RoleManagerPlugin], diff --git a/backend/src/plugins/RoleButtons/types.ts b/backend/src/plugins/RoleButtons/types.ts index 64e0c7e9..8abc0bef 100644 --- a/backend/src/plugins/RoleButtons/types.ts +++ b/backend/src/plugins/RoleButtons/types.ts @@ -67,8 +67,8 @@ export type TRoleButtonsConfigItem = z.infer; export const zRoleButtonsConfig = z .strictObject({ - buttons: zBoundedRecord(z.record(zBoundedCharacters(1, 16), zRoleButtonsConfigItem), 0, 100), - can_reset: z.boolean(), + buttons: zBoundedRecord(z.record(zBoundedCharacters(1, 16), zRoleButtonsConfigItem), 0, 100).default({}), + can_reset: z.boolean().default(false), }) .refine( (parsed) => { @@ -91,7 +91,7 @@ export const zRoleButtonsConfig = z ); export interface RoleButtonsPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zRoleButtonsConfig; state: { roleButtons: GuildRoleButtons; common: pluginUtils.PluginPublicInterface; diff --git a/backend/src/plugins/RoleManager/RoleManagerPlugin.ts b/backend/src/plugins/RoleManager/RoleManagerPlugin.ts index 5137326f..ebfa294c 100644 --- a/backend/src/plugins/RoleManager/RoleManagerPlugin.ts +++ b/backend/src/plugins/RoleManager/RoleManagerPlugin.ts @@ -13,7 +13,7 @@ export const RoleManagerPlugin = guildPlugin()({ name: "role_manager", dependencies: () => [LogsPlugin], - configParser: (input) => zRoleManagerConfig.parse(input), + configSchema: zRoleManagerConfig, public(pluginData) { return { diff --git a/backend/src/plugins/RoleManager/types.ts b/backend/src/plugins/RoleManager/types.ts index 2ed0bdd7..ecdcadc2 100644 --- a/backend/src/plugins/RoleManager/types.ts +++ b/backend/src/plugins/RoleManager/types.ts @@ -5,7 +5,7 @@ import { GuildRoleQueue } from "../../data/GuildRoleQueue.js"; export const zRoleManagerConfig = z.strictObject({}); export interface RoleManagerPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zRoleManagerConfig; state: { roleQueue: GuildRoleQueue; roleAssignmentLoopRunning: boolean; diff --git a/backend/src/plugins/Roles/RolesPlugin.ts b/backend/src/plugins/Roles/RolesPlugin.ts index 2334280b..af45821c 100644 --- a/backend/src/plugins/Roles/RolesPlugin.ts +++ b/backend/src/plugins/Roles/RolesPlugin.ts @@ -9,13 +9,12 @@ import { MassRemoveRoleCmd } from "./commands/MassRemoveRoleCmd.js"; import { RemoveRoleCmd } from "./commands/RemoveRoleCmd.js"; import { RolesPluginType, zRolesConfig } from "./types.js"; -const defaultOptions: PluginOptions = { - config: { - can_assign: false, - can_mass_assign: false, - assignable_roles: [], - }, - overrides: [ +export const RolesPlugin = guildPlugin()({ + name: "roles", + + dependencies: () => [LogsPlugin, RoleManagerPlugin], + configSchema: zRolesConfig, + defaultOverrides: [ { level: ">=50", config: { @@ -29,14 +28,6 @@ const defaultOptions: PluginOptions = { }, }, ], -}; - -export const RolesPlugin = guildPlugin()({ - name: "roles", - - dependencies: () => [LogsPlugin, RoleManagerPlugin], - configParser: (input) => zRolesConfig.parse(input), - defaultOptions, // prettier-ignore messageCommands: [ diff --git a/backend/src/plugins/Roles/types.ts b/backend/src/plugins/Roles/types.ts index 35ac1556..09c381f7 100644 --- a/backend/src/plugins/Roles/types.ts +++ b/backend/src/plugins/Roles/types.ts @@ -4,13 +4,13 @@ import { GuildLogs } from "../../data/GuildLogs.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; export const zRolesConfig = z.strictObject({ - can_assign: z.boolean(), - can_mass_assign: z.boolean(), - assignable_roles: z.array(z.string()).max(100), + can_assign: z.boolean().default(false), + can_mass_assign: z.boolean().default(false), + assignable_roles: z.array(z.string()).max(100).default([]), }); export interface RolesPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zRolesConfig; state: { logs: GuildLogs; common: pluginUtils.PluginPublicInterface; diff --git a/backend/src/plugins/SelfGrantableRoles/SelfGrantableRolesPlugin.ts b/backend/src/plugins/SelfGrantableRoles/SelfGrantableRolesPlugin.ts index b97e0857..d56418cd 100644 --- a/backend/src/plugins/SelfGrantableRoles/SelfGrantableRolesPlugin.ts +++ b/backend/src/plugins/SelfGrantableRoles/SelfGrantableRolesPlugin.ts @@ -5,18 +5,10 @@ import { RoleHelpCmd } from "./commands/RoleHelpCmd.js"; import { RoleRemoveCmd } from "./commands/RoleRemoveCmd.js"; import { SelfGrantableRolesPluginType, zSelfGrantableRolesConfig } from "./types.js"; -const defaultOptions: PluginOptions = { - config: { - entries: {}, - mention_roles: false, - }, -}; - export const SelfGrantableRolesPlugin = guildPlugin()({ name: "self_grantable_roles", - configParser: (input) => zSelfGrantableRolesConfig.parse(input), - defaultOptions, + configSchema: zSelfGrantableRolesConfig, // prettier-ignore messageCommands: [ diff --git a/backend/src/plugins/SelfGrantableRoles/types.ts b/backend/src/plugins/SelfGrantableRoles/types.ts index 462d3fa9..84d95837 100644 --- a/backend/src/plugins/SelfGrantableRoles/types.ts +++ b/backend/src/plugins/SelfGrantableRoles/types.ts @@ -20,12 +20,12 @@ const zSelfGrantableRoleEntry = z.strictObject({ export type TSelfGrantableRoleEntry = z.infer; export const zSelfGrantableRolesConfig = z.strictObject({ - entries: zBoundedRecord(z.record(zBoundedCharacters(0, 255), zSelfGrantableRoleEntry), 0, 100), - mention_roles: z.boolean(), + entries: zBoundedRecord(z.record(zBoundedCharacters(0, 255), zSelfGrantableRoleEntry), 0, 100).default({}), + mention_roles: z.boolean().default(false), }); export interface SelfGrantableRolesPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zSelfGrantableRolesConfig; state: { cooldowns: CooldownManager; common: pluginUtils.PluginPublicInterface; diff --git a/backend/src/plugins/Slowmode/SlowmodePlugin.ts b/backend/src/plugins/Slowmode/SlowmodePlugin.ts index 4b80e2e1..84d6e523 100644 --- a/backend/src/plugins/Slowmode/SlowmodePlugin.ts +++ b/backend/src/plugins/Slowmode/SlowmodePlugin.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 { GuildSlowmodes } from "../../data/GuildSlowmodes.js"; @@ -16,25 +16,6 @@ import { onMessageCreate } from "./util/onMessageCreate.js"; const BOT_SLOWMODE_CLEAR_INTERVAL = 60 * SECONDS; -const defaultOptions: PluginOptions = { - config: { - use_native_slowmode: true, - - can_manage: false, - is_affected: true, - }, - - overrides: [ - { - level: ">=50", - config: { - can_manage: true, - is_affected: false, - }, - }, - ], -}; - export const SlowmodePlugin = guildPlugin()({ name: "slowmode", @@ -43,8 +24,16 @@ export const SlowmodePlugin = guildPlugin()({ LogsPlugin, ], - configParser: (input) => zSlowmodeConfig.parse(input), - defaultOptions, + configSchema: zSlowmodeConfig, + defaultOverrides: [ + { + level: ">=50", + config: { + can_manage: true, + is_affected: false, + }, + }, + ], // prettier-ignore messageCommands: [ diff --git a/backend/src/plugins/Slowmode/types.ts b/backend/src/plugins/Slowmode/types.ts index babacc79..8b064673 100644 --- a/backend/src/plugins/Slowmode/types.ts +++ b/backend/src/plugins/Slowmode/types.ts @@ -7,14 +7,14 @@ import { SlowmodeChannel } from "../../data/entities/SlowmodeChannel.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; export const zSlowmodeConfig = z.strictObject({ - use_native_slowmode: z.boolean(), + use_native_slowmode: z.boolean().default(true), - can_manage: z.boolean(), - is_affected: z.boolean(), + can_manage: z.boolean().default(false), + is_affected: z.boolean().default(true), }); export interface SlowmodePluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zSlowmodeConfig; state: { slowmodes: GuildSlowmodes; savedMessages: GuildSavedMessages; diff --git a/backend/src/plugins/Spam/SpamPlugin.ts b/backend/src/plugins/Spam/SpamPlugin.ts index c4df1eda..d278c4b8 100644 --- a/backend/src/plugins/Spam/SpamPlugin.ts +++ b/backend/src/plugins/Spam/SpamPlugin.ts @@ -1,4 +1,4 @@ -import { PluginOptions, guildPlugin } from "knub"; +import { guildPlugin } from "knub"; import { GuildArchives } from "../../data/GuildArchives.js"; import { GuildLogs } from "../../data/GuildLogs.js"; import { GuildMutes } from "../../data/GuildMutes.js"; @@ -9,20 +9,12 @@ import { SpamPluginType, zSpamConfig } from "./types.js"; import { clearOldRecentActions } from "./util/clearOldRecentActions.js"; import { onMessageCreate } from "./util/onMessageCreate.js"; -const defaultOptions: PluginOptions = { - config: { - max_censor: null, - max_messages: null, - max_mentions: null, - max_links: null, - max_attachments: null, - max_emojis: null, - max_newlines: null, - max_duplicates: null, - max_characters: null, - max_voice_moves: null, - }, - overrides: [ +export const SpamPlugin = guildPlugin()({ + name: "spam", + + dependencies: () => [LogsPlugin], + configSchema: zSpamConfig, + defaultOverrides: [ { level: ">=50", config: { @@ -38,14 +30,6 @@ const defaultOptions: PluginOptions = { }, }, ], -}; - -export const SpamPlugin = guildPlugin()({ - name: "spam", - - dependencies: () => [LogsPlugin], - configParser: (input) => zSpamConfig.parse(input), - defaultOptions, // prettier-ignore events: [ diff --git a/backend/src/plugins/Spam/types.ts b/backend/src/plugins/Spam/types.ts index 37a13320..d7f7aaec 100644 --- a/backend/src/plugins/Spam/types.ts +++ b/backend/src/plugins/Spam/types.ts @@ -18,16 +18,16 @@ const zBaseSingleSpamConfig = z.strictObject({ export type TBaseSingleSpamConfig = z.infer; export const zSpamConfig = z.strictObject({ - max_censor: zBaseSingleSpamConfig.nullable(), - max_messages: zBaseSingleSpamConfig.nullable(), - max_mentions: zBaseSingleSpamConfig.nullable(), - max_links: zBaseSingleSpamConfig.nullable(), - max_attachments: zBaseSingleSpamConfig.nullable(), - max_emojis: zBaseSingleSpamConfig.nullable(), - max_newlines: zBaseSingleSpamConfig.nullable(), - max_duplicates: zBaseSingleSpamConfig.nullable(), - max_characters: zBaseSingleSpamConfig.nullable(), - max_voice_moves: zBaseSingleSpamConfig.nullable(), + max_censor: zBaseSingleSpamConfig.nullable().default(null), + max_messages: zBaseSingleSpamConfig.nullable().default(null), + max_mentions: zBaseSingleSpamConfig.nullable().default(null), + max_links: zBaseSingleSpamConfig.nullable().default(null), + max_attachments: zBaseSingleSpamConfig.nullable().default(null), + max_emojis: zBaseSingleSpamConfig.nullable().default(null), + max_newlines: zBaseSingleSpamConfig.nullable().default(null), + max_duplicates: zBaseSingleSpamConfig.nullable().default(null), + max_characters: zBaseSingleSpamConfig.nullable().default(null), + max_voice_moves: zBaseSingleSpamConfig.nullable().default(null), }); export enum RecentActionType { @@ -52,7 +52,7 @@ export interface IRecentAction { } export interface SpamPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zSpamConfig; state: { logs: GuildLogs; archives: GuildArchives; diff --git a/backend/src/plugins/Starboard/StarboardPlugin.ts b/backend/src/plugins/Starboard/StarboardPlugin.ts index 474a2be2..759b3422 100644 --- a/backend/src/plugins/Starboard/StarboardPlugin.ts +++ b/backend/src/plugins/Starboard/StarboardPlugin.ts @@ -1,4 +1,4 @@ -import { PluginOptions, guildPlugin } from "knub"; +import { guildPlugin } from "knub"; import { GuildSavedMessages } from "../../data/GuildSavedMessages.js"; import { GuildStarboardMessages } from "../../data/GuildStarboardMessages.js"; import { GuildStarboardReactions } from "../../data/GuildStarboardReactions.js"; @@ -9,13 +9,11 @@ import { StarboardReactionRemoveAllEvt, StarboardReactionRemoveEvt } from "./eve import { StarboardPluginType, zStarboardConfig } from "./types.js"; import { onMessageDelete } from "./util/onMessageDelete.js"; -const defaultOptions: PluginOptions = { - config: { - can_migrate: false, - boards: {}, - }, +export const StarboardPlugin = guildPlugin()({ + name: "starboard", - overrides: [ + configSchema: zStarboardConfig, + defaultOverrides: [ { level: ">=100", config: { @@ -23,13 +21,6 @@ const defaultOptions: PluginOptions = { }, }, ], -}; - -export const StarboardPlugin = guildPlugin()({ - name: "starboard", - - configParser: (input) => zStarboardConfig.parse(input), - defaultOptions, // prettier-ignore messageCommands: [ diff --git a/backend/src/plugins/Starboard/types.ts b/backend/src/plugins/Starboard/types.ts index 1e8e2850..20d19834 100644 --- a/backend/src/plugins/Starboard/types.ts +++ b/backend/src/plugins/Starboard/types.ts @@ -19,13 +19,12 @@ const zStarboardOpts = z.strictObject({ export type TStarboardOpts = z.infer; export const zStarboardConfig = z.strictObject({ - boards: zBoundedRecord(z.record(z.string(), zStarboardOpts), 0, 100), - can_migrate: z.boolean(), + boards: zBoundedRecord(z.record(z.string(), zStarboardOpts), 0, 100).default({}), + can_migrate: z.boolean().default(false), }); export interface StarboardPluginType extends BasePluginType { - config: z.infer; - + configSchema: typeof zStarboardConfig; state: { savedMessages: GuildSavedMessages; starboardMessages: GuildStarboardMessages; diff --git a/backend/src/plugins/Tags/TagsPlugin.ts b/backend/src/plugins/Tags/TagsPlugin.ts index 25141ea3..71ebd109 100644 --- a/backend/src/plugins/Tags/TagsPlugin.ts +++ b/backend/src/plugins/Tags/TagsPlugin.ts @@ -1,5 +1,5 @@ import { Snowflake } from "discord.js"; -import { PluginOptions, guildPlugin } from "knub"; +import { guildPlugin } from "knub"; import moment from "moment-timezone"; import { GuildArchives } from "../../data/GuildArchives.js"; import { GuildLogs } from "../../data/GuildLogs.js"; @@ -22,25 +22,12 @@ import { onMessageCreate } from "./util/onMessageCreate.js"; import { onMessageDelete } from "./util/onMessageDelete.js"; import { renderTagBody } from "./util/renderTagBody.js"; -const defaultOptions: PluginOptions = { - config: { - prefix: "!!", - delete_with_command: true, +export const TagsPlugin = guildPlugin()({ + name: "tags", - user_tag_cooldown: null, - global_tag_cooldown: null, - user_cooldown: null, - allow_mentions: false, - global_cooldown: null, - auto_delete_command: false, - - categories: {}, - - can_create: false, - can_use: false, - can_list: false, - }, - overrides: [ + dependencies: () => [LogsPlugin], + configSchema: zTagsConfig, + defaultOverrides: [ { level: ">=50", config: { @@ -50,13 +37,6 @@ const defaultOptions: PluginOptions = { }, }, ], -}; - -export const TagsPlugin = guildPlugin()({ - name: "tags", - - dependencies: () => [LogsPlugin], - defaultOptions, // prettier-ignore messageCommands: [ @@ -79,8 +59,6 @@ export const TagsPlugin = guildPlugin()({ }; }, - configParser: (input) => zTagsConfig.parse(input), - beforeLoad(pluginData) { const { state, guild } = pluginData; diff --git a/backend/src/plugins/Tags/types.ts b/backend/src/plugins/Tags/types.ts index 51798334..0b44fff7 100644 --- a/backend/src/plugins/Tags/types.ts +++ b/backend/src/plugins/Tags/types.ts @@ -33,28 +33,28 @@ export type TTagCategory = z.infer; export const zTagsConfig = z .strictObject({ - prefix: z.string(), - delete_with_command: z.boolean(), + prefix: z.string().default("!!"), + delete_with_command: z.boolean().default(true), - user_tag_cooldown: z.union([z.string(), z.number()]).nullable(), // Per user, per tag - global_tag_cooldown: z.union([z.string(), z.number()]).nullable(), // Any user, per tag - user_cooldown: z.union([z.string(), z.number()]).nullable(), // Per user - allow_mentions: z.boolean(), // Per user - global_cooldown: z.union([z.string(), z.number()]).nullable(), // Any tag use - auto_delete_command: z.boolean(), // Any tag + user_tag_cooldown: z.union([z.string(), z.number()]).nullable().default(null), // Per user, per tag + global_tag_cooldown: z.union([z.string(), z.number()]).nullable().default(null), // Any user, per tag + user_cooldown: z.union([z.string(), z.number()]).nullable().default(null), // Per user + allow_mentions: z.boolean().default(false), // Per user + global_cooldown: z.union([z.string(), z.number()]).nullable().default(null), // Any tag use + auto_delete_command: z.boolean().default(false), // Any tag - categories: z.record(z.string(), zTagCategory), + categories: z.record(z.string(), zTagCategory).default({}), - can_create: z.boolean(), - can_use: z.boolean(), - can_list: z.boolean(), + can_create: z.boolean().default(false), + can_use: z.boolean().default(false), + can_list: z.boolean().default(false), }) .refine((parsed) => !(parsed.auto_delete_command && parsed.delete_with_command), { message: "Cannot have both (category specific) delete_with_command and auto_delete_command enabled", }); export interface TagsPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zTagsConfig; state: { archives: GuildArchives; tags: GuildTags; diff --git a/backend/src/plugins/TimeAndDate/TimeAndDatePlugin.ts b/backend/src/plugins/TimeAndDate/TimeAndDatePlugin.ts index 7de26655..12395a44 100644 --- a/backend/src/plugins/TimeAndDate/TimeAndDatePlugin.ts +++ b/backend/src/plugins/TimeAndDate/TimeAndDatePlugin.ts @@ -13,14 +13,11 @@ import { inGuildTz } from "./functions/inGuildTz.js"; import { inMemberTz } from "./functions/inMemberTz.js"; import { TimeAndDatePluginType, zTimeAndDateConfig } from "./types.js"; -const defaultOptions: PluginOptions = { - config: { - timezone: "Etc/UTC", - can_set_timezone: false, - date_formats: defaultDateFormats, - }, +export const TimeAndDatePlugin = guildPlugin()({ + name: "time_and_date", - overrides: [ + configSchema: zTimeAndDateConfig, + defaultOverrides: [ { level: ">=50", config: { @@ -28,13 +25,6 @@ const defaultOptions: PluginOptions = { }, }, ], -}; - -export const TimeAndDatePlugin = guildPlugin()({ - name: "time_and_date", - - configParser: (input) => zTimeAndDateConfig.parse(input), - defaultOptions, // prettier-ignore messageCommands: [ diff --git a/backend/src/plugins/TimeAndDate/types.ts b/backend/src/plugins/TimeAndDate/types.ts index 59885cf9..dd1b48ee 100644 --- a/backend/src/plugins/TimeAndDate/types.ts +++ b/backend/src/plugins/TimeAndDate/types.ts @@ -10,13 +10,13 @@ import { defaultDateFormats } from "./defaultDateFormats.js"; const zDateFormatKeys = z.enum(keys(defaultDateFormats) as U.ListOf); export const zTimeAndDateConfig = z.strictObject({ - timezone: zValidTimezone(z.string()), - date_formats: z.record(zDateFormatKeys, z.string()).nullable(), - can_set_timezone: z.boolean(), + timezone: zValidTimezone(z.string()).default("Etc/UTC"), + date_formats: z.record(zDateFormatKeys, z.string()).nullable().default(defaultDateFormats), + can_set_timezone: z.boolean().default(false), }); export interface TimeAndDatePluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zTimeAndDateConfig; state: { memberTimezones: GuildMemberTimezones; common: pluginUtils.PluginPublicInterface; diff --git a/backend/src/plugins/UsernameSaver/UsernameSaverPlugin.ts b/backend/src/plugins/UsernameSaver/UsernameSaverPlugin.ts index fe38fd13..5008d0a7 100644 --- a/backend/src/plugins/UsernameSaver/UsernameSaverPlugin.ts +++ b/backend/src/plugins/UsernameSaver/UsernameSaverPlugin.ts @@ -7,7 +7,7 @@ import { UsernameSaverPluginType, zUsernameSaverConfig } from "./types.js"; export const UsernameSaverPlugin = guildPlugin()({ name: "username_saver", - configParser: (input) => zUsernameSaverConfig.parse(input), + configSchema: zUsernameSaverConfig, // prettier-ignore events: [ diff --git a/backend/src/plugins/UsernameSaver/types.ts b/backend/src/plugins/UsernameSaver/types.ts index cf7417df..2bbd93bd 100644 --- a/backend/src/plugins/UsernameSaver/types.ts +++ b/backend/src/plugins/UsernameSaver/types.ts @@ -6,7 +6,7 @@ import { UsernameHistory } from "../../data/UsernameHistory.js"; export const zUsernameSaverConfig = z.strictObject({}); export interface UsernameSaverPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zUsernameSaverConfig; state: { usernameHistory: UsernameHistory; updateQueue: Queue; diff --git a/backend/src/plugins/Utility/UtilityPlugin.ts b/backend/src/plugins/Utility/UtilityPlugin.ts index 17fd8252..0ad9bde0 100644 --- a/backend/src/plugins/Utility/UtilityPlugin.ts +++ b/backend/src/plugins/Utility/UtilityPlugin.ts @@ -1,5 +1,5 @@ import { Snowflake } from "discord.js"; -import { PluginOptions, guildPlugin } from "knub"; +import { guildPlugin } from "knub"; import { GuildArchives } from "../../data/GuildArchives.js"; import { GuildCases } from "../../data/GuildCases.js"; import { GuildLogs } from "../../data/GuildLogs.js"; @@ -38,45 +38,21 @@ import { UserInfoCmd } from "./commands/UserInfoCmd.js"; import { VcdisconnectCmd } from "./commands/VcdisconnectCmd.js"; import { VcmoveAllCmd, VcmoveCmd } from "./commands/VcmoveCmd.js"; import { AutoJoinThreadEvt, AutoJoinThreadSyncEvt } from "./events/AutoJoinThreadEvt.js"; +import { cleanMessages } from "./functions/cleanMessages.js"; +import { fetchChannelMessagesToClean } from "./functions/fetchChannelMessagesToClean.js"; import { getUserInfoEmbed } from "./functions/getUserInfoEmbed.js"; import { hasPermission } from "./functions/hasPermission.js"; import { activeReloads } from "./guildReloads.js"; import { refreshMembersIfNeeded } from "./refreshMembers.js"; import { UtilityPluginType, zUtilityConfig } from "./types.js"; -import { cleanMessages } from "./functions/cleanMessages.js"; -import { fetchChannelMessagesToClean } from "./functions/fetchChannelMessagesToClean.js"; -const defaultOptions: PluginOptions = { - config: { - can_roles: false, - can_level: false, - can_search: false, - can_clean: false, - can_info: false, - can_server: false, - can_inviteinfo: false, - can_channelinfo: false, - can_messageinfo: false, - can_userinfo: false, - can_roleinfo: false, - can_emojiinfo: false, - can_snowflake: false, - can_reload_guild: false, - can_nickname: false, - can_ping: false, - can_source: false, - can_vcmove: false, - can_vckick: false, - can_help: false, - can_about: false, - can_context: false, - can_jumbo: false, - jumbo_size: 128, - can_avatar: false, - info_on_single_result: true, - autojoin_threads: true, - }, - overrides: [ +export const UtilityPlugin = guildPlugin()({ + name: "utility", + + dependencies: () => [TimeAndDatePlugin, ModActionsPlugin, LogsPlugin], + + configSchema: zUtilityConfig, + defaultOverrides: [ { level: ">=50", config: { @@ -112,14 +88,6 @@ const defaultOptions: PluginOptions = { }, }, ], -}; - -export const UtilityPlugin = guildPlugin()({ - name: "utility", - - dependencies: () => [TimeAndDatePlugin, ModActionsPlugin, LogsPlugin], - configParser: (input) => zUtilityConfig.parse(input), - defaultOptions, // prettier-ignore messageCommands: [ diff --git a/backend/src/plugins/Utility/types.ts b/backend/src/plugins/Utility/types.ts index 6a2deba4..4f181b2b 100644 --- a/backend/src/plugins/Utility/types.ts +++ b/backend/src/plugins/Utility/types.ts @@ -9,37 +9,37 @@ import { Supporters } from "../../data/Supporters.js"; import { CommonPlugin } from "../Common/CommonPlugin.js"; export const zUtilityConfig = z.strictObject({ - can_roles: z.boolean(), - can_level: z.boolean(), - can_search: z.boolean(), - can_clean: z.boolean(), - can_info: z.boolean(), - can_server: z.boolean(), - can_inviteinfo: z.boolean(), - can_channelinfo: z.boolean(), - can_messageinfo: z.boolean(), - can_userinfo: z.boolean(), - can_roleinfo: z.boolean(), - can_emojiinfo: z.boolean(), - can_snowflake: z.boolean(), - can_reload_guild: z.boolean(), - can_nickname: z.boolean(), - can_ping: z.boolean(), - can_source: z.boolean(), - can_vcmove: z.boolean(), - can_vckick: z.boolean(), - can_help: z.boolean(), - can_about: z.boolean(), - can_context: z.boolean(), - can_jumbo: z.boolean(), - jumbo_size: z.number(), - can_avatar: z.boolean(), - info_on_single_result: z.boolean(), - autojoin_threads: z.boolean(), + can_roles: z.boolean().default(false), + can_level: z.boolean().default(false), + can_search: z.boolean().default(false), + can_clean: z.boolean().default(false), + can_info: z.boolean().default(false), + can_server: z.boolean().default(false), + can_inviteinfo: z.boolean().default(false), + can_channelinfo: z.boolean().default(false), + can_messageinfo: z.boolean().default(false), + can_userinfo: z.boolean().default(false), + can_roleinfo: z.boolean().default(false), + can_emojiinfo: z.boolean().default(false), + can_snowflake: z.boolean().default(false), + can_reload_guild: z.boolean().default(false), + can_nickname: z.boolean().default(false), + can_ping: z.boolean().default(false), + can_source: z.boolean().default(false), + can_vcmove: z.boolean().default(false), + can_vckick: z.boolean().default(false), + can_help: z.boolean().default(false), + can_about: z.boolean().default(false), + can_context: z.boolean().default(false), + can_jumbo: z.boolean().default(false), + jumbo_size: z.number().default(128), + can_avatar: z.boolean().default(false), + info_on_single_result: z.boolean().default(true), + autojoin_threads: z.boolean().default(true), }); export interface UtilityPluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zUtilityConfig; state: { logs: GuildLogs; cases: GuildCases; diff --git a/backend/src/plugins/WelcomeMessage/WelcomeMessagePlugin.ts b/backend/src/plugins/WelcomeMessage/WelcomeMessagePlugin.ts index 7848393a..c5690756 100644 --- a/backend/src/plugins/WelcomeMessage/WelcomeMessagePlugin.ts +++ b/backend/src/plugins/WelcomeMessage/WelcomeMessagePlugin.ts @@ -4,20 +4,11 @@ import { LogsPlugin } from "../Logs/LogsPlugin.js"; import { SendWelcomeMessageEvt } from "./events/SendWelcomeMessageEvt.js"; import { WelcomeMessagePluginType, zWelcomeMessageConfig } from "./types.js"; -const defaultOptions: PluginOptions = { - config: { - send_dm: false, - send_to_channel: null, - message: null, - }, -}; - export const WelcomeMessagePlugin = guildPlugin()({ name: "welcome_message", dependencies: () => [LogsPlugin], - configParser: (input) => zWelcomeMessageConfig.parse(input), - defaultOptions, + configSchema: zWelcomeMessageConfig, // prettier-ignore events: [ diff --git a/backend/src/plugins/WelcomeMessage/types.ts b/backend/src/plugins/WelcomeMessage/types.ts index 815cac6e..a75062e5 100644 --- a/backend/src/plugins/WelcomeMessage/types.ts +++ b/backend/src/plugins/WelcomeMessage/types.ts @@ -3,13 +3,13 @@ import z from "zod/v4"; import { GuildLogs } from "../../data/GuildLogs.js"; export const zWelcomeMessageConfig = z.strictObject({ - send_dm: z.boolean(), - send_to_channel: z.string().nullable(), - message: z.string().nullable(), + send_dm: z.boolean().default(false), + send_to_channel: z.string().nullable().default(null), + message: z.string().nullable().default(null), }); export interface WelcomeMessagePluginType extends BasePluginType { - config: z.infer; + configSchema: typeof zWelcomeMessageConfig; state: { logs: GuildLogs; sentWelcomeMessages: Set; diff --git a/package-lock.json b/package-lock.json index cf65388a..5f2c29b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,7 +43,7 @@ "fp-ts": "^2.0.1", "humanize-duration": "^3.15.0", "js-yaml": "^4.1.0", - "knub": "^32.0.0-next.23", + "knub": "^32.0.0-next.25", "knub-command-manager": "^9.1.0", "last-commit-log": "^2.1.0", "lodash-es": "^4.17.21", @@ -12806,9 +12806,9 @@ } }, "node_modules/knub": { - "version": "32.0.0-next.23", - "resolved": "https://registry.npmjs.org/knub/-/knub-32.0.0-next.23.tgz", - "integrity": "sha512-kDv6QhE5ALL9bew0GJtzFh2HpyOECCZ6gGBnZNcKUekxWh3LdKW2nYuo1kfqTycEM/5zn7uiHTGLVxfea9LNxA==", + "version": "32.0.0-next.25", + "resolved": "https://registry.npmjs.org/knub/-/knub-32.0.0-next.25.tgz", + "integrity": "sha512-5ki+0f3PD7v3mRH2ew4RIy1aXMXvUUqPGyikUjCBR8/5EF277/GNwqxC8pA5CDJi8/e29UeGyx/mqHKBvGoTXw==", "license": "MIT", "dependencies": { "discord-api-types": "^0.38.8",