3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-06-06 23:55:03 +00:00

refactor: move defaults to config schemas

This commit is contained in:
Dragory 2025-05-23 01:12:52 +00:00
parent 09eb8e92f2
commit 83d35052c3
No known key found for this signature in database
91 changed files with 450 additions and 888 deletions

View file

@ -49,7 +49,7 @@
"fp-ts": "^2.0.1", "fp-ts": "^2.0.1",
"humanize-duration": "^3.15.0", "humanize-duration": "^3.15.0",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"knub": "^32.0.0-next.23", "knub": "^32.0.0-next.25",
"knub-command-manager": "^9.1.0", "knub-command-manager": "^9.1.0",
"last-commit-log": "^2.1.0", "last-commit-log": "^2.1.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",

View file

@ -131,7 +131,7 @@ export function initDocs(router: express.Router) {
config: cmd.config, config: cmd.config,
})); }));
const defaultOptions = pluginInfo.plugin.defaultOptions || {}; const defaultOptions = (pluginInfo.plugin as any /* TODO */).defaultOptions || {};
res.json({ res.json({
name: pluginInfo.plugin.name, name: pluginInfo.plugin.name,

View file

@ -28,10 +28,13 @@ export async function validateGuildConfig(config: any): Promise<string | null> {
} }
const plugin = pluginNameToPlugin.get(pluginName)!; const plugin = pluginNameToPlugin.get(pluginName)!;
const configManager = new PluginConfigManager(plugin.defaultOptions || { config: {} }, pluginOptions, { const configManager = new PluginConfigManager({}, {
configSchema: plugin.configSchema,
defaultOverrides: plugin.defaultOverrides ?? [],
levels: {}, levels: {},
parser: plugin.configParser, customOverrideCriteriaFunctions: plugin.customOverrideCriteriaFunctions,
}); });
try { try {
await configManager.init(); await configManager.init();
} catch (err) { } catch (err) {

View file

@ -73,7 +73,7 @@ function overrides(configSchema: z.ZodType): z.ZodType {
const pluginSchemaMap = availableGuildPlugins.reduce((map, pluginInfo) => { const pluginSchemaMap = availableGuildPlugins.reduce((map, pluginInfo) => {
map[pluginInfo.plugin.name] = z.object({ map[pluginInfo.plugin.name] = z.object({
config: pluginInfo.docs.configSchema.optional(), config: pluginInfo.docs.configSchema.optional(),
overrides: overrides(pluginInfo.docs.configSchema).optional(), overrides: z.array(overrides(pluginInfo.docs.configSchema)).optional(),
}); });
return map; return map;
}, {}); }, {});

View file

@ -27,6 +27,7 @@ import { AnyPluginData, BasePluginData, CommandContext, ExtendedMatchParams, Gui
import { isStaff } from "./staff.js"; import { isStaff } from "./staff.js";
import { TZeppelinKnub } from "./types.js"; import { TZeppelinKnub } from "./types.js";
import { Tail } from "./utils/typeUtils.js"; import { Tail } from "./utils/typeUtils.js";
import z from "zod/v4";
const { getMemberLevel } = helpers; const { getMemberLevel } = helpers;
@ -166,7 +167,7 @@ export async function deleteContextResponse(response: ContextResponse): Promise<
await response.delete(); await response.delete();
} }
export async function getConfigForContext<TPluginData extends BasePluginData<any>>(config: PluginConfigManager<TPluginData>, context: GenericCommandSource): Promise<TPluginData["_pluginType"]["config"]> { export async function getConfigForContext<TPluginData extends BasePluginData<any>>(config: PluginConfigManager<TPluginData>, context: GenericCommandSource): Promise<z.output<TPluginData["_pluginType"]["configSchema"]>> {
if (context instanceof ChatInputCommandInteraction) { if (context instanceof ChatInputCommandInteraction) {
// TODO: Support for modal interactions (here and Knub) // TODO: Support for modal interactions (here and Knub)
return config.getForInteraction(context); return config.getForInteraction(context);

View file

@ -8,19 +8,11 @@ import { onMessageCreate } from "./util/onMessageCreate.js";
import { onMessageDelete } from "./util/onMessageDelete.js"; import { onMessageDelete } from "./util/onMessageDelete.js";
import { onMessageDeleteBulk } from "./util/onMessageDeleteBulk.js"; import { onMessageDeleteBulk } from "./util/onMessageDeleteBulk.js";
const defaultOptions: PluginOptions<AutoDeletePluginType> = {
config: {
enabled: false,
delay: "5s",
},
};
export const AutoDeletePlugin = guildPlugin<AutoDeletePluginType>()({ export const AutoDeletePlugin = guildPlugin<AutoDeletePluginType>()({
name: "auto_delete", name: "auto_delete",
dependencies: () => [TimeAndDatePlugin, LogsPlugin], dependencies: () => [TimeAndDatePlugin, LogsPlugin],
configParser: (input) => zAutoDeleteConfig.parse(input), configSchema: zAutoDeleteConfig,
defaultOptions,
beforeLoad(pluginData) { beforeLoad(pluginData) {
const { state, guild } = pluginData; const { state, guild } = pluginData;

View file

@ -14,12 +14,12 @@ export interface IDeletionQueueItem {
} }
export const zAutoDeleteConfig = z.strictObject({ export const zAutoDeleteConfig = z.strictObject({
enabled: z.boolean(), enabled: z.boolean().default(false),
delay: zDelayString, delay: zDelayString.default("5s"),
}); });
export interface AutoDeletePluginType extends BasePluginType { export interface AutoDeletePluginType extends BasePluginType {
config: z.output<typeof zAutoDeleteConfig>; configSchema: typeof zAutoDeleteConfig;
state: { state: {
guildSavedMessages: GuildSavedMessages; guildSavedMessages: GuildSavedMessages;
guildLogs: GuildLogs; guildLogs: GuildLogs;

View file

@ -1,4 +1,4 @@
import { PluginOptions, guildPlugin } from "knub"; import { PluginOverride, guildPlugin } from "knub";
import { GuildAutoReactions } from "../../data/GuildAutoReactions.js"; import { GuildAutoReactions } from "../../data/GuildAutoReactions.js";
import { GuildSavedMessages } from "../../data/GuildSavedMessages.js"; import { GuildSavedMessages } from "../../data/GuildSavedMessages.js";
import { CommonPlugin } from "../Common/CommonPlugin.js"; import { CommonPlugin } from "../Common/CommonPlugin.js";
@ -8,19 +8,14 @@ import { NewAutoReactionsCmd } from "./commands/NewAutoReactionsCmd.js";
import { AddReactionsEvt } from "./events/AddReactionsEvt.js"; import { AddReactionsEvt } from "./events/AddReactionsEvt.js";
import { AutoReactionsPluginType, zAutoReactionsConfig } from "./types.js"; import { AutoReactionsPluginType, zAutoReactionsConfig } from "./types.js";
const defaultOptions: PluginOptions<AutoReactionsPluginType> = { const defaultOverrides: Array<PluginOverride<AutoReactionsPluginType>> = [
config: { {
can_manage: false, level: ">=100",
}, config: {
overrides: [ can_manage: true,
{
level: ">=100",
config: {
can_manage: true,
},
}, },
], },
}; ];
export const AutoReactionsPlugin = guildPlugin<AutoReactionsPluginType>()({ export const AutoReactionsPlugin = guildPlugin<AutoReactionsPluginType>()({
name: "auto_reactions", name: "auto_reactions",
@ -30,8 +25,8 @@ export const AutoReactionsPlugin = guildPlugin<AutoReactionsPluginType>()({
LogsPlugin, LogsPlugin,
], ],
configParser: (input) => zAutoReactionsConfig.parse(input), configSchema: zAutoReactionsConfig,
defaultOptions, defaultOverrides,
// prettier-ignore // prettier-ignore
messageCommands: [ messageCommands: [

View file

@ -7,11 +7,11 @@ import { AutoReaction } from "../../data/entities/AutoReaction.js";
import { CommonPlugin } from "../Common/CommonPlugin.js"; import { CommonPlugin } from "../Common/CommonPlugin.js";
export const zAutoReactionsConfig = z.strictObject({ export const zAutoReactionsConfig = z.strictObject({
can_manage: z.boolean(), can_manage: z.boolean().default(false),
}); });
export interface AutoReactionsPluginType extends BasePluginType { export interface AutoReactionsPluginType extends BasePluginType {
config: z.output<typeof zAutoReactionsConfig>; configSchema: typeof zAutoReactionsConfig;
state: { state: {
logs: GuildLogs; logs: GuildLogs;
savedMessages: GuildSavedMessages; savedMessages: GuildSavedMessages;

View file

@ -34,29 +34,6 @@ import { clearOldRecentActions } from "./functions/clearOldRecentActions.js";
import { clearOldRecentSpam } from "./functions/clearOldRecentSpam.js"; import { clearOldRecentSpam } from "./functions/clearOldRecentSpam.js";
import { AutomodPluginType, zAutomodConfig } from "./types.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<AutomodPluginType>()({ export const AutomodPlugin = guildPlugin<AutomodPluginType>()({
name: "automod", name: "automod",
@ -71,8 +48,7 @@ export const AutomodPlugin = guildPlugin<AutomodPluginType>()({
RoleManagerPlugin, RoleManagerPlugin,
], ],
defaultOptions, configSchema: zAutomodConfig,
configParser: (input) => zAutomodConfig.parse(input),
customOverrideCriteriaFunctions: { customOverrideCriteriaFunctions: {
antiraid_level: (pluginData, matchParams, value) => { antiraid_level: (pluginData, matchParams, value) => {

View file

@ -9,24 +9,12 @@ interface MatchResultType {
mode: "blacklist" | "whitelist"; mode: "blacklist" | "whitelist";
} }
const baseConfig = z.strictObject({ const configSchema = z.strictObject({
filetype_blacklist: z.array(z.string().max(32)).max(255).default([]), whitelist_enabled: z.boolean().default(false),
filetype_whitelist: z.array(z.string().max(32)).max(255).default([]), 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<MatchResultType>()({ export const MatchAttachmentTypeTrigger = automodTrigger<MatchResultType>()({
configSchema, configSchema,

View file

@ -1,31 +1,19 @@
import { escapeInlineCode } from "discord.js"; import { escapeInlineCode } from "discord.js";
import z from "zod/v4";
import { asSingleLine, messageSummary, verboseChannelMention } from "../../../utils.js"; import { asSingleLine, messageSummary, verboseChannelMention } from "../../../utils.js";
import { automodTrigger } from "../helpers.js"; import { automodTrigger } from "../helpers.js";
import z from "zod/v4";
interface MatchResultType { interface MatchResultType {
matchedType: string; matchedType: string;
mode: "blacklist" | "whitelist"; mode: "blacklist" | "whitelist";
} }
const baseConfig = z.strictObject({ const configSchema = z.strictObject({
mime_type_blacklist: z.array(z.string().max(32)).max(255).default([]), whitelist_enabled: z.boolean().default(false),
mime_type_whitelist: z.array(z.string().max(32)).max(255).default([]), 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<MatchResultType>()({ export const MatchMimeTypeTrigger = automodTrigger<MatchResultType>()({
configSchema, configSchema,

View file

@ -58,14 +58,14 @@ const zRule = z.strictObject({
export type TRule = z.infer<typeof zRule>; export type TRule = z.infer<typeof zRule>;
export const zAutomodConfig = z.strictObject({ export const zAutomodConfig = z.strictObject({
rules: zBoundedRecord(z.record(z.string().max(100), zRule), 0, 255), rules: zBoundedRecord(z.record(z.string().max(100), zRule), 0, 255).default({}),
antiraid_levels: z.array(z.string().max(100)).max(10), antiraid_levels: z.array(z.string().max(100)).max(10).default(["low", "medium", "high"]),
can_set_antiraid: z.boolean(), can_set_antiraid: z.boolean().default(false),
can_view_antiraid: z.boolean(), can_view_antiraid: z.boolean().default(false),
}); });
export interface AutomodPluginType extends BasePluginType { export interface AutomodPluginType extends BasePluginType {
config: z.output<typeof zAutomodConfig>; configSchema: typeof zAutomodConfig;
customOverrideCriteria: { customOverrideCriteria: {
antiraid_level?: string; antiraid_level?: string;

View file

@ -23,21 +23,9 @@ import { RestPerformanceCmd } from "./commands/RestPerformanceCmd.js";
import { ServersCmd } from "./commands/ServersCmd.js"; import { ServersCmd } from "./commands/ServersCmd.js";
import { BotControlPluginType, zBotControlConfig } from "./types.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<BotControlPluginType>()({ export const BotControlPlugin = globalPlugin<BotControlPluginType>()({
name: "bot_control", name: "bot_control",
configParser: (input) => zBotControlConfig.parse(input), configSchema: zBotControlConfig,
defaultOptions,
// prettier-ignore // prettier-ignore
messageCommands: [ messageCommands: [

View file

@ -7,16 +7,16 @@ import { GuildArchives } from "../../data/GuildArchives.js";
import { zBoundedCharacters } from "../../utils.js"; import { zBoundedCharacters } from "../../utils.js";
export const zBotControlConfig = z.strictObject({ export const zBotControlConfig = z.strictObject({
can_use: z.boolean(), can_use: z.boolean().default(false),
can_eligible: z.boolean(), can_eligible: z.boolean().default(false),
can_performance: z.boolean(), can_performance: z.boolean().default(false),
can_add_server_from_invite: z.boolean(), can_add_server_from_invite: z.boolean().default(false),
can_list_dashboard_perms: z.boolean(), can_list_dashboard_perms: z.boolean().default(false),
update_cmd: zBoundedCharacters(0, 2000).nullable(), update_cmd: zBoundedCharacters(0, 2000).nullable().default(null),
}); });
export interface BotControlPluginType extends BasePluginType { export interface BotControlPluginType extends BasePluginType {
config: z.output<typeof zBotControlConfig>; configSchema: typeof zBotControlConfig;
state: { state: {
archives: GuildArchives; archives: GuildArchives;
allowedGuilds: AllowedGuilds; allowedGuilds: AllowedGuilds;

View file

@ -20,23 +20,11 @@ function getLogsPlugin(): Promise<any> {
return import("../Logs/LogsPlugin.js") as Promise<any>; return import("../Logs/LogsPlugin.js") as Promise<any>;
} }
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<CasesPluginType>()({ export const CasesPlugin = guildPlugin<CasesPluginType>()({
name: "cases", name: "cases",
dependencies: async () => [TimeAndDatePlugin, InternalPosterPlugin, (await getLogsPlugin()).LogsPlugin], dependencies: async () => [TimeAndDatePlugin, InternalPosterPlugin, (await getLogsPlugin()).LogsPlugin],
configParser: (input) => zCasesConfig.parse(input), configSchema: zCasesConfig,
defaultOptions,
public(pluginData) { public(pluginData) {
return { return {

View file

@ -11,16 +11,16 @@ import { zColor } from "../../utils/zColor.js";
const caseKeys = keys(CaseNameToType) as U.ListOf<keyof typeof CaseNameToType>; const caseKeys = keys(CaseNameToType) as U.ListOf<keyof typeof CaseNameToType>;
export const zCasesConfig = z.strictObject({ export const zCasesConfig = z.strictObject({
log_automatic_actions: z.boolean(), log_automatic_actions: z.boolean().default(true),
case_log_channel: zSnowflake.nullable(), case_log_channel: zSnowflake.nullable().default(null),
show_relative_times: z.boolean(), show_relative_times: z.boolean().default(true),
relative_time_cutoff: zDelayString.default("1w"), relative_time_cutoff: zDelayString.default("1w"),
case_colors: z.record(z.enum(caseKeys), zColor).nullable(), case_colors: z.record(z.enum(caseKeys), zColor).nullable().default(null),
case_icons: z.record(z.enum(caseKeys), zBoundedCharacters(0, 100)).nullable(), case_icons: z.record(z.enum(caseKeys), zBoundedCharacters(0, 100)).nullable().default(null),
}); });
export interface CasesPluginType extends BasePluginType { export interface CasesPluginType extends BasePluginType {
config: z.infer<typeof zCasesConfig>; configSchema: typeof zCasesConfig;
state: { state: {
logs: GuildLogs; logs: GuildLogs;
cases: GuildCases; cases: GuildCases;

View file

@ -1,4 +1,4 @@
import { PluginOptions, guildPlugin } from "knub"; import { PluginOptions, PluginOverride, guildPlugin } from "knub";
import { GuildLogs } from "../../data/GuildLogs.js"; import { GuildLogs } from "../../data/GuildLogs.js";
import { GuildSavedMessages } from "../../data/GuildSavedMessages.js"; import { GuildSavedMessages } from "../../data/GuildSavedMessages.js";
import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners.js"; import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners.js";
@ -7,46 +7,26 @@ import { CensorPluginType, zCensorConfig } from "./types.js";
import { onMessageCreate } from "./util/onMessageCreate.js"; import { onMessageCreate } from "./util/onMessageCreate.js";
import { onMessageUpdate } from "./util/onMessageUpdate.js"; import { onMessageUpdate } from "./util/onMessageUpdate.js";
const defaultOptions: PluginOptions<CensorPluginType> = { const defaultOverrides: Array<PluginOverride<CensorPluginType>> = [
config: { {
filter_zalgo: false, level: ">=50",
filter_invites: false, config: {
invite_guild_whitelist: null, filter_zalgo: false,
invite_guild_blacklist: null, filter_invites: false,
invite_code_whitelist: null, filter_domains: false,
invite_code_blacklist: null, blocked_tokens: null,
allow_group_dm_invites: false, blocked_words: null,
blocked_regex: null,
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,
},
}, },
], },
}; ];
export const CensorPlugin = guildPlugin<CensorPluginType>()({ export const CensorPlugin = guildPlugin<CensorPluginType>()({
name: "censor", name: "censor",
dependencies: () => [LogsPlugin], dependencies: () => [LogsPlugin],
configParser: (input) => zCensorConfig.parse(input), configSchema: zCensorConfig,
defaultOptions, defaultOverrides,
beforeLoad(pluginData) { beforeLoad(pluginData) {
const { state, guild } = pluginData; const { state, guild } = pluginData;

View file

@ -6,23 +6,23 @@ import { GuildSavedMessages } from "../../data/GuildSavedMessages.js";
import { zBoundedCharacters, zRegex, zSnowflake } from "../../utils.js"; import { zBoundedCharacters, zRegex, zSnowflake } from "../../utils.js";
export const zCensorConfig = z.strictObject({ export const zCensorConfig = z.strictObject({
filter_zalgo: z.boolean(), filter_zalgo: z.boolean().default(false),
filter_invites: z.boolean(), filter_invites: z.boolean().default(false),
invite_guild_whitelist: z.array(zSnowflake).nullable(), invite_guild_whitelist: z.array(zSnowflake).nullable().default(null),
invite_guild_blacklist: z.array(zSnowflake).nullable(), invite_guild_blacklist: z.array(zSnowflake).nullable().default(null),
invite_code_whitelist: z.array(zBoundedCharacters(0, 16)).nullable(), invite_code_whitelist: z.array(zBoundedCharacters(0, 16)).nullable().default(null),
invite_code_blacklist: z.array(zBoundedCharacters(0, 16)).nullable(), invite_code_blacklist: z.array(zBoundedCharacters(0, 16)).nullable().default(null),
allow_group_dm_invites: z.boolean(), allow_group_dm_invites: z.boolean().default(false),
filter_domains: z.boolean(), filter_domains: z.boolean().default(false),
domain_whitelist: z.array(zBoundedCharacters(0, 255)).nullable(), domain_whitelist: z.array(zBoundedCharacters(0, 255)).nullable().default(null),
domain_blacklist: z.array(zBoundedCharacters(0, 255)).nullable(), domain_blacklist: z.array(zBoundedCharacters(0, 255)).nullable().default(null),
blocked_tokens: z.array(zBoundedCharacters(0, 2000)).nullable(), blocked_tokens: z.array(zBoundedCharacters(0, 2000)).nullable().default(null),
blocked_words: z.array(zBoundedCharacters(0, 2000)).nullable(), blocked_words: z.array(zBoundedCharacters(0, 2000)).nullable().default(null),
blocked_regex: z.array(zRegex(z.string().max(1000))).nullable(), blocked_regex: z.array(zRegex(z.string().max(1000))).nullable().default(null),
}); });
export interface CensorPluginType extends BasePluginType { export interface CensorPluginType extends BasePluginType {
config: z.infer<typeof zCensorConfig>; configSchema: typeof zCensorConfig;
state: { state: {
serverLogs: GuildLogs; serverLogs: GuildLogs;
savedMessages: GuildSavedMessages; savedMessages: GuildSavedMessages;

View file

@ -1,15 +1,14 @@
import { guildPlugin } from "knub"; import { guildPlugin } from "knub";
import z from "zod/v4";
import { CommonPlugin } from "../Common/CommonPlugin.js"; import { CommonPlugin } from "../Common/CommonPlugin.js";
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin.js"; import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin.js";
import { ArchiveChannelCmd } from "./commands/ArchiveChannelCmd.js"; import { ArchiveChannelCmd } from "./commands/ArchiveChannelCmd.js";
import { ChannelArchiverPluginType } from "./types.js"; import { ChannelArchiverPluginType, zChannelArchiverPluginConfig } from "./types.js";
export const ChannelArchiverPlugin = guildPlugin<ChannelArchiverPluginType>()({ export const ChannelArchiverPlugin = guildPlugin<ChannelArchiverPluginType>()({
name: "channel_archiver", name: "channel_archiver",
dependencies: () => [TimeAndDatePlugin], dependencies: () => [TimeAndDatePlugin],
configParser: (input) => z.strictObject({}).parse(input), configSchema: zChannelArchiverPluginConfig,
// prettier-ignore // prettier-ignore
messageCommands: [ messageCommands: [

View file

@ -1,7 +1,11 @@
import { BasePluginType, guildPluginMessageCommand, pluginUtils } from "knub"; import { BasePluginType, guildPluginMessageCommand, pluginUtils } from "knub";
import { CommonPlugin } from "../Common/CommonPlugin.js"; import { CommonPlugin } from "../Common/CommonPlugin.js";
import { z } from "zod/v4";
export const zChannelArchiverPluginConfig = z.strictObject({});
export interface ChannelArchiverPluginType extends BasePluginType { export interface ChannelArchiverPluginType extends BasePluginType {
configSchema: typeof zChannelArchiverPluginConfig;
state: { state: {
common: pluginUtils.PluginPublicInterface<typeof CommonPlugin>; common: pluginUtils.PluginPublicInterface<typeof CommonPlugin>;
}; };

View file

@ -1,35 +1,19 @@
import { import {
Attachment, Attachment,
ChatInputCommandInteraction,
InteractionResponse,
Message,
MessageCreateOptions,
MessageMentionOptions, MessageMentionOptions,
ModalSubmitInteraction,
SendableChannels, SendableChannels,
TextBasedChannel, TextBasedChannel
User,
} from "discord.js"; } from "discord.js";
import { PluginOptions, guildPlugin } from "knub"; import { guildPlugin } from "knub";
import { logger } from "../../logger.js"; import { GenericCommandSource, sendContextResponse } from "../../pluginUtils.js";
import { GenericCommandSource, isContextInteraction, sendContextResponse } from "../../pluginUtils.js";
import { errorMessage, successMessage } from "../../utils.js"; import { errorMessage, successMessage } from "../../utils.js";
import { getErrorEmoji, getSuccessEmoji } from "./functions/getEmoji.js"; import { getErrorEmoji, getSuccessEmoji } from "./functions/getEmoji.js";
import { CommonPluginType, zCommonConfig } from "./types.js"; import { CommonPluginType, zCommonConfig } from "./types.js";
const defaultOptions: PluginOptions<CommonPluginType> = {
config: {
success_emoji: "✅",
error_emoji: "❌",
attachment_storing_channel: null,
},
};
export const CommonPlugin = guildPlugin<CommonPluginType>()({ export const CommonPlugin = guildPlugin<CommonPluginType>()({
name: "common", name: "common",
dependencies: () => [], dependencies: () => [],
configParser: (input) => zCommonConfig.parse(input), configSchema: zCommonConfig,
defaultOptions,
public(pluginData) { public(pluginData) {
return { return {
getSuccessEmoji, getSuccessEmoji,

View file

@ -2,11 +2,11 @@ import { BasePluginType } from "knub";
import z from "zod/v4"; import z from "zod/v4";
export const zCommonConfig = z.strictObject({ export const zCommonConfig = z.strictObject({
success_emoji: z.string(), success_emoji: z.string().default("✅"),
error_emoji: z.string(), error_emoji: z.string().default("❌"),
attachment_storing_channel: z.nullable(z.string()), attachment_storing_channel: z.nullable(z.string()).default(null),
}); });
export interface CommonPluginType extends BasePluginType { export interface CommonPluginType extends BasePluginType {
config: z.output<typeof zCommonConfig>; configSchema: typeof zCommonConfig;
} }

View file

@ -4,18 +4,11 @@ import { LogsPlugin } from "../Logs/LogsPlugin.js";
import { VoiceStateUpdateEvt } from "./events/VoiceStateUpdateEvt.js"; import { VoiceStateUpdateEvt } from "./events/VoiceStateUpdateEvt.js";
import { CompanionChannelsPluginType, zCompanionChannelsConfig } from "./types.js"; import { CompanionChannelsPluginType, zCompanionChannelsConfig } from "./types.js";
const defaultOptions = {
config: {
entries: {},
},
};
export const CompanionChannelsPlugin = guildPlugin<CompanionChannelsPluginType>()({ export const CompanionChannelsPlugin = guildPlugin<CompanionChannelsPluginType>()({
name: "companion_channels", name: "companion_channels",
dependencies: () => [LogsPlugin], dependencies: () => [LogsPlugin],
configParser: (input) => zCompanionChannelsConfig.parse(input), configSchema: zCompanionChannelsConfig,
defaultOptions,
events: [VoiceStateUpdateEvt], events: [VoiceStateUpdateEvt],

View file

@ -13,11 +13,11 @@ export const zCompanionChannelOpts = z.strictObject({
export type TCompanionChannelOpts = z.infer<typeof zCompanionChannelOpts>; export type TCompanionChannelOpts = z.infer<typeof zCompanionChannelOpts>;
export const zCompanionChannelsConfig = z.strictObject({ 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 { export interface CompanionChannelsPluginType extends BasePluginType {
config: z.infer<typeof zCompanionChannelsConfig>; configSchema: typeof zCompanionChannelsConfig;
state: { state: {
errorCooldownManager: CooldownManager; errorCooldownManager: CooldownManager;
serverLogs: GuildLogs; serverLogs: GuildLogs;

View file

@ -1,4 +1,4 @@
import { PluginOptions, guildPlugin } from "knub"; import { PluginOptions, PluginOverride, guildPlugin } from "knub";
import { GuildCases } from "../../data/GuildCases.js"; import { GuildCases } from "../../data/GuildCases.js";
import { CasesPlugin } from "../Cases/CasesPlugin.js"; import { CasesPlugin } from "../Cases/CasesPlugin.js";
import { LogsPlugin } from "../Logs/LogsPlugin.js"; import { LogsPlugin } from "../Logs/LogsPlugin.js";
@ -13,30 +13,23 @@ import { NoteCmd } from "./commands/NoteUserCtxCmd.js";
import { WarnCmd } from "./commands/WarnUserCtxCmd.js"; import { WarnCmd } from "./commands/WarnUserCtxCmd.js";
import { ContextMenuPluginType, zContextMenusConfig } from "./types.js"; import { ContextMenuPluginType, zContextMenusConfig } from "./types.js";
const defaultOptions: PluginOptions<ContextMenuPluginType> = { const defaultOverrides: Array<PluginOverride<ContextMenuPluginType>> = [
config: { {
can_use: false, level: ">=50",
config: {
can_use: true,
can_open_mod_menu: false, can_open_mod_menu: true,
},
overrides: [
{
level: ">=50",
config: {
can_use: true,
can_open_mod_menu: true,
},
}, },
], },
}; ];
export const ContextMenuPlugin = guildPlugin<ContextMenuPluginType>()({ export const ContextMenuPlugin = guildPlugin<ContextMenuPluginType>()({
name: "context_menu", name: "context_menu",
dependencies: () => [CasesPlugin, MutesPlugin, ModActionsPlugin, LogsPlugin, UtilityPlugin], dependencies: () => [CasesPlugin, MutesPlugin, ModActionsPlugin, LogsPlugin, UtilityPlugin],
configParser: (input) => zContextMenusConfig.parse(input), configSchema: zContextMenusConfig,
defaultOptions, defaultOverrides,
contextMenuCommands: [ModMenuCmd, NoteCmd, WarnCmd, MuteCmd, BanCmd, CleanCmd], contextMenuCommands: [ModMenuCmd, NoteCmd, WarnCmd, MuteCmd, BanCmd, CleanCmd],

View file

@ -4,12 +4,12 @@ import z from "zod/v4";
import { GuildCases } from "../../data/GuildCases.js"; import { GuildCases } from "../../data/GuildCases.js";
export const zContextMenusConfig = z.strictObject({ export const zContextMenusConfig = z.strictObject({
can_use: z.boolean(), can_use: z.boolean().default(false),
can_open_mod_menu: z.boolean(), can_open_mod_menu: z.boolean().default(false),
}); });
export interface ContextMenuPluginType extends BasePluginType { export interface ContextMenuPluginType extends BasePluginType {
config: z.infer<typeof zContextMenusConfig>; configSchema: typeof zContextMenusConfig;
state: { state: {
cases: GuildCases; cases: GuildCases;
}; };

View file

@ -1,5 +1,5 @@
import { EventEmitter } from "events"; import { EventEmitter } from "events";
import { PluginOptions, guildPlugin } from "knub"; import { PluginOptions, PluginOverride, guildPlugin } from "knub";
import { GuildCounters } from "../../data/GuildCounters.js"; import { GuildCounters } from "../../data/GuildCounters.js";
import { buildCounterConditionString, CounterTrigger, getReverseCounterComparisonOp, parseCounterConditionString } from "../../data/entities/CounterTrigger.js"; import { buildCounterConditionString, CounterTrigger, getReverseCounterComparisonOp, parseCounterConditionString } from "../../data/entities/CounterTrigger.js";
import { makePublicFn } from "../../pluginUtils.js"; import { makePublicFn } from "../../pluginUtils.js";
@ -23,28 +23,20 @@ import { CountersPluginType, zCountersConfig } from "./types.js";
const DECAY_APPLY_INTERVAL = 5 * MINUTES; const DECAY_APPLY_INTERVAL = 5 * MINUTES;
const defaultOptions: PluginOptions<CountersPluginType> = { const defaultOverrides: Array<PluginOverride<CountersPluginType>> = [
config: { {
counters: {}, level: ">=50",
can_view: false, config: {
can_edit: false, can_view: true,
can_reset_all: false, },
}, },
overrides: [ {
{ level: ">=100",
level: ">=50", config: {
config: { can_edit: true,
can_view: 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". * 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<CountersPluginType> = {
export const CountersPlugin = guildPlugin<CountersPluginType>()({ export const CountersPlugin = guildPlugin<CountersPluginType>()({
name: "counters", name: "counters",
defaultOptions, configSchema: zCountersConfig,
// TODO: Separate input and output types defaultOverrides,
configParser: (input) => zCountersConfig.parse(input),
public(pluginData) { public(pluginData) {
return { return {

View file

@ -69,10 +69,10 @@ export const zCounter = z.strictObject({
}); });
export const zCountersConfig = z.strictObject({ export const zCountersConfig = z.strictObject({
counters: zBoundedRecord(z.record(zBoundedCharacters(0, 100), zCounter), 0, MAX_COUNTERS), counters: zBoundedRecord(z.record(zBoundedCharacters(0, 100), zCounter), 0, MAX_COUNTERS).default({}),
can_view: z.boolean(), can_view: z.boolean().default(false),
can_edit: z.boolean(), can_edit: z.boolean().default(false),
can_reset_all: z.boolean(), can_reset_all: z.boolean().default(false),
}); });
export interface CounterEvents { export interface CounterEvents {
@ -86,7 +86,7 @@ export interface CounterEventEmitter extends EventEmitter {
} }
export interface CountersPluginType extends BasePluginType { export interface CountersPluginType extends BasePluginType {
config: z.infer<typeof zCountersConfig>; configSchema: typeof zCountersConfig;
state: { state: {
counters: GuildCounters; counters: GuildCounters;
counterIds: Record<string, number>; counterIds: Record<string, number>;

View file

@ -16,18 +16,11 @@ import { LogsPlugin } from "../Logs/LogsPlugin.js";
import { runEvent } from "./functions/runEvent.js"; import { runEvent } from "./functions/runEvent.js";
import { CustomEventsPluginType, zCustomEventsConfig } from "./types.js"; import { CustomEventsPluginType, zCustomEventsConfig } from "./types.js";
const defaultOptions = {
config: {
events: {},
},
};
export const CustomEventsPlugin = guildPlugin<CustomEventsPluginType>()({ export const CustomEventsPlugin = guildPlugin<CustomEventsPluginType>()({
name: "custom_events", name: "custom_events",
dependencies: () => [LogsPlugin], dependencies: () => [LogsPlugin],
configParser: (input) => zCustomEventsConfig.parse(input), configSchema: zCustomEventsConfig,
defaultOptions,
beforeStart(pluginData) { beforeStart(pluginData) {
pluginData.state.common = pluginData.getPlugin(CommonPlugin); pluginData.state.common = pluginData.getPlugin(CommonPlugin);

View file

@ -37,11 +37,11 @@ export const zCustomEvent = z.strictObject({
export type TCustomEvent = z.infer<typeof zCustomEvent>; export type TCustomEvent = z.infer<typeof zCustomEvent>;
export const zCustomEventsConfig = z.strictObject({ 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 { export interface CustomEventsPluginType extends BasePluginType {
config: z.infer<typeof zCustomEventsConfig>; configSchema: typeof zCustomEventsConfig;
state: { state: {
clearTriggers: () => void; clearTriggers: () => void;
common: pluginUtils.PluginPublicInterface<typeof CommonPlugin>; common: pluginUtils.PluginPublicInterface<typeof CommonPlugin>;

View file

@ -3,13 +3,7 @@ import { BasePluginType, GlobalPluginData, globalPlugin, globalPluginEventListen
import { AllowedGuilds } from "../../data/AllowedGuilds.js"; import { AllowedGuilds } from "../../data/AllowedGuilds.js";
import { Configs } from "../../data/Configs.js"; import { Configs } from "../../data/Configs.js";
import { env } from "../../env.js"; import { env } from "../../env.js";
import { zGuildAccessMonitorConfig } from "./types.js"; import { GuildAccessMonitorPluginType, zGuildAccessMonitorConfig } from "./types.js";
interface GuildAccessMonitorPluginType extends BasePluginType {
state: {
allowedGuilds: AllowedGuilds;
};
}
async function checkGuild(pluginData: GlobalPluginData<GuildAccessMonitorPluginType>, guild: Guild) { async function checkGuild(pluginData: GlobalPluginData<GuildAccessMonitorPluginType>, guild: Guild) {
if (!(await pluginData.state.allowedGuilds.isAllowed(guild.id))) { if (!(await pluginData.state.allowedGuilds.isAllowed(guild.id))) {
@ -24,7 +18,7 @@ async function checkGuild(pluginData: GlobalPluginData<GuildAccessMonitorPluginT
*/ */
export const GuildAccessMonitorPlugin = globalPlugin<GuildAccessMonitorPluginType>()({ export const GuildAccessMonitorPlugin = globalPlugin<GuildAccessMonitorPluginType>()({
name: "guild_access_monitor", name: "guild_access_monitor",
configParser: (input) => zGuildAccessMonitorConfig.parse(input), configSchema: zGuildAccessMonitorConfig,
events: [ events: [
globalPluginEventListener<GuildAccessMonitorPluginType>()({ globalPluginEventListener<GuildAccessMonitorPluginType>()({

View file

@ -1,3 +1,12 @@
import { BasePluginType } from "knub";
import { z } from "zod/v4"; import { z } from "zod/v4";
import { AllowedGuilds } from "../../data/AllowedGuilds.js";
export const zGuildAccessMonitorConfig = z.strictObject({}); export const zGuildAccessMonitorConfig = z.strictObject({});
export interface GuildAccessMonitorPluginType extends BasePluginType {
configSchema: typeof zGuildAccessMonitorConfig;
state: {
allowedGuilds: AllowedGuilds;
};
}

View file

@ -1,13 +1,12 @@
import { globalPlugin } from "knub"; import { globalPlugin } from "knub";
import z from "zod/v4";
import { Configs } from "../../data/Configs.js"; import { Configs } from "../../data/Configs.js";
import { reloadChangedGuilds } from "./functions/reloadChangedGuilds.js"; import { reloadChangedGuilds } from "./functions/reloadChangedGuilds.js";
import { GuildConfigReloaderPluginType } from "./types.js"; import { GuildConfigReloaderPluginType, zGuildConfigReloaderPluginConfig } from "./types.js";
export const GuildConfigReloaderPlugin = globalPlugin<GuildConfigReloaderPluginType>()({ export const GuildConfigReloaderPlugin = globalPlugin<GuildConfigReloaderPluginType>()({
name: "guild_config_reloader", name: "guild_config_reloader",
configParser: (input) => z.strictObject({}).parse(input), configSchema: zGuildConfigReloaderPluginConfig,
async beforeLoad(pluginData) { async beforeLoad(pluginData) {
const { state } = pluginData; const { state } = pluginData;

View file

@ -1,8 +1,8 @@
import { ZeppelinPluginDocs } from "../../types.js"; import { ZeppelinPluginDocs } from "../../types.js";
import { zGuildConfigReloaderPlugin } from "./types.js"; import { zGuildConfigReloaderPluginConfig } from "./types.js";
export const guildConfigReloaderPluginDocs: ZeppelinPluginDocs = { export const guildConfigReloaderPluginDocs: ZeppelinPluginDocs = {
prettyName: "Guild config reloader", prettyName: "Guild config reloader",
type: "internal", type: "internal",
configSchema: zGuildConfigReloaderPlugin, configSchema: zGuildConfigReloaderPluginConfig,
}; };

View file

@ -3,10 +3,10 @@ import { z } from "zod/v4";
import { Configs } from "../../data/Configs.js"; import { Configs } from "../../data/Configs.js";
import Timeout = NodeJS.Timeout; import Timeout = NodeJS.Timeout;
export const zGuildConfigReloaderPlugin = z.strictObject({}); export const zGuildConfigReloaderPluginConfig = z.strictObject({});
export interface GuildConfigReloaderPluginType extends BasePluginType { export interface GuildConfigReloaderPluginType extends BasePluginType {
config: z.infer<typeof zGuildConfigReloaderPlugin>; configSchema: typeof zGuildConfigReloaderPluginConfig;
state: { state: {
guildConfigs: Configs; guildConfigs: Configs;
unloaded: boolean; unloaded: boolean;

View file

@ -1,15 +1,14 @@
import { Guild } from "discord.js"; import { Guild } from "discord.js";
import { guildPlugin, guildPluginEventListener } from "knub"; import { guildPlugin, guildPluginEventListener } from "knub";
import z from "zod/v4";
import { AllowedGuilds } from "../../data/AllowedGuilds.js"; import { AllowedGuilds } from "../../data/AllowedGuilds.js";
import { ApiPermissionAssignments } from "../../data/ApiPermissionAssignments.js"; import { ApiPermissionAssignments } from "../../data/ApiPermissionAssignments.js";
import { MINUTES } from "../../utils.js"; import { MINUTES } from "../../utils.js";
import { GuildInfoSaverPluginType } from "./types.js"; import { GuildInfoSaverPluginType, zGuildInfoSaverConfig } from "./types.js";
export const GuildInfoSaverPlugin = guildPlugin<GuildInfoSaverPluginType>()({ export const GuildInfoSaverPlugin = guildPlugin<GuildInfoSaverPluginType>()({
name: "guild_info_saver", name: "guild_info_saver",
configParser: (input) => z.strictObject({}).parse(input), configSchema: zGuildInfoSaverConfig,
events: [ events: [
guildPluginEventListener({ guildPluginEventListener({

View file

@ -4,7 +4,7 @@ import { z } from "zod/v4";
export const zGuildInfoSaverConfig = z.strictObject({}); export const zGuildInfoSaverConfig = z.strictObject({});
export interface GuildInfoSaverPluginType extends BasePluginType { export interface GuildInfoSaverPluginType extends BasePluginType {
config: z.infer<typeof zGuildInfoSaverConfig>; configSchema: typeof zGuildInfoSaverConfig;
state: { state: {
updateInterval: NodeJS.Timeout; updateInterval: NodeJS.Timeout;
}; };

View file

@ -1,5 +1,4 @@
import { guildPlugin } from "knub"; import { guildPlugin } from "knub";
import z from "zod/v4";
import { GuildMemberCache } from "../../data/GuildMemberCache.js"; import { GuildMemberCache } from "../../data/GuildMemberCache.js";
import { makePublicFn } from "../../pluginUtils.js"; import { makePublicFn } from "../../pluginUtils.js";
import { SECONDS } from "../../utils.js"; import { SECONDS } from "../../utils.js";
@ -10,14 +9,14 @@ import { updateMemberCacheOnMessage } from "./events/updateMemberCacheOnMessage.
import { updateMemberCacheOnRoleChange } from "./events/updateMemberCacheOnRoleChange.js"; import { updateMemberCacheOnRoleChange } from "./events/updateMemberCacheOnRoleChange.js";
import { updateMemberCacheOnVoiceStateUpdate } from "./events/updateMemberCacheOnVoiceStateUpdate.js"; import { updateMemberCacheOnVoiceStateUpdate } from "./events/updateMemberCacheOnVoiceStateUpdate.js";
import { getCachedMemberData } from "./functions/getCachedMemberData.js"; import { getCachedMemberData } from "./functions/getCachedMemberData.js";
import { GuildMemberCachePluginType } from "./types.js"; import { GuildMemberCachePluginType, zGuildMemberCacheConfig } from "./types.js";
const PENDING_SAVE_INTERVAL = 30 * SECONDS; const PENDING_SAVE_INTERVAL = 30 * SECONDS;
export const GuildMemberCachePlugin = guildPlugin<GuildMemberCachePluginType>()({ export const GuildMemberCachePlugin = guildPlugin<GuildMemberCachePluginType>()({
name: "guild_member_cache", name: "guild_member_cache",
configParser: (input) => z.strictObject({}).parse(input), configSchema: zGuildMemberCacheConfig,
events: [ events: [
updateMemberCacheOnMemberUpdate, updateMemberCacheOnMemberUpdate,

View file

@ -5,7 +5,7 @@ import { GuildMemberCache } from "../../data/GuildMemberCache.js";
export const zGuildMemberCacheConfig = z.strictObject({}); export const zGuildMemberCacheConfig = z.strictObject({});
export interface GuildMemberCachePluginType extends BasePluginType { export interface GuildMemberCachePluginType extends BasePluginType {
config: z.infer<typeof zGuildMemberCacheConfig>; configSchema: typeof zGuildMemberCacheConfig;
state: { state: {
memberCache: GuildMemberCache; memberCache: GuildMemberCache;
saveInterval: NodeJS.Timeout; saveInterval: NodeJS.Timeout;

View file

@ -5,18 +5,12 @@ import { Webhooks } from "../../data/Webhooks.js";
import { makePublicFn } from "../../pluginUtils.js"; import { makePublicFn } from "../../pluginUtils.js";
import { editMessage } from "./functions/editMessage.js"; import { editMessage } from "./functions/editMessage.js";
import { sendMessage } from "./functions/sendMessage.js"; import { sendMessage } from "./functions/sendMessage.js";
import { InternalPosterPluginType } from "./types.js"; import { InternalPosterPluginType, zInternalPosterConfig } from "./types.js";
const defaultOptions: PluginOptions<InternalPosterPluginType> = {
config: {},
overrides: [],
};
export const InternalPosterPlugin = guildPlugin<InternalPosterPluginType>()({ export const InternalPosterPlugin = guildPlugin<InternalPosterPluginType>()({
name: "internal_poster", name: "internal_poster",
configParser: (input) => z.strictObject({}).parse(input), configSchema: zInternalPosterConfig,
defaultOptions,
public(pluginData) { public(pluginData) {
return { return {

View file

@ -4,10 +4,10 @@ import { z } from "zod/v4";
import { Queue } from "../../Queue.js"; import { Queue } from "../../Queue.js";
import { Webhooks } from "../../data/Webhooks.js"; import { Webhooks } from "../../data/Webhooks.js";
export const zInternalPosterConfig = z.strictObject({}); export const zInternalPosterConfig = z.strictObject({}).default({});
export interface InternalPosterPluginType extends BasePluginType { export interface InternalPosterPluginType extends BasePluginType {
config: z.infer<typeof zInternalPosterConfig>; configSchema: typeof zInternalPosterConfig;
state: { state: {
queue: Queue; queue: Queue;
webhooks: Webhooks; webhooks: Webhooks;

View file

@ -11,12 +11,11 @@ import { LocateUserPluginType, zLocateUserConfig } from "./types.js";
import { clearExpiredAlert } from "./utils/clearExpiredAlert.js"; import { clearExpiredAlert } from "./utils/clearExpiredAlert.js";
import { fillActiveAlertsList } from "./utils/fillAlertsList.js"; import { fillActiveAlertsList } from "./utils/fillAlertsList.js";
const defaultOptions: PluginOptions<LocateUserPluginType> = { export const LocateUserPlugin = guildPlugin<LocateUserPluginType>()({
config: { name: "locate_user",
can_where: false,
can_alert: false, configSchema: zLocateUserConfig,
}, defaultOverrides: [
overrides: [
{ {
level: ">=50", level: ">=50",
config: { config: {
@ -25,13 +24,6 @@ const defaultOptions: PluginOptions<LocateUserPluginType> = {
}, },
}, },
], ],
};
export const LocateUserPlugin = guildPlugin<LocateUserPluginType>()({
name: "locate_user",
configParser: (input) => zLocateUserConfig.parse(input),
defaultOptions,
// prettier-ignore // prettier-ignore
messageCommands: [ messageCommands: [

View file

@ -4,12 +4,12 @@ import { GuildVCAlerts } from "../../data/GuildVCAlerts.js";
import { CommonPlugin } from "../Common/CommonPlugin.js"; import { CommonPlugin } from "../Common/CommonPlugin.js";
export const zLocateUserConfig = z.strictObject({ export const zLocateUserConfig = z.strictObject({
can_where: z.boolean(), can_where: z.boolean().default(false),
can_alert: z.boolean(), can_alert: z.boolean().default(false),
}); });
export interface LocateUserPluginType extends BasePluginType { export interface LocateUserPluginType extends BasePluginType {
config: z.infer<typeof zLocateUserConfig>; configSchema: typeof zLocateUserConfig;
state: { state: {
alerts: GuildVCAlerts; alerts: GuildVCAlerts;
usersWithAlerts: string[]; usersWithAlerts: string[];

View file

@ -1,5 +1,4 @@
import { CooldownManager, PluginOptions, guildPlugin } from "knub"; import { CooldownManager, guildPlugin } from "knub";
import DefaultLogMessages from "../../data/DefaultLogMessages.json" with { type: "json" };
import { GuildArchives } from "../../data/GuildArchives.js"; import { GuildArchives } from "../../data/GuildArchives.js";
import { GuildCases } from "../../data/GuildCases.js"; import { GuildCases } from "../../data/GuildCases.js";
import { GuildLogs } from "../../data/GuildLogs.js"; import { GuildLogs } from "../../data/GuildLogs.js";
@ -115,17 +114,12 @@ function getCasesPlugin(): Promise<any> {
return import("../Cases/CasesPlugin.js") as Promise<any>; return import("../Cases/CasesPlugin.js") as Promise<any>;
} }
const defaultOptions: PluginOptions<LogsPluginType> = { export const LogsPlugin = guildPlugin<LogsPluginType>()({
config: { name: "logs",
channels: {},
format: DefaultLogMessages,
ping_user: true,
allow_user_mentions: false,
timestamp_format: "[<t:]X[>]",
include_embed_timestamp: true,
},
overrides: [ dependencies: async () => [TimeAndDatePlugin, InternalPosterPlugin, (await getCasesPlugin()).CasesPlugin],
configSchema: zLogsConfig,
defaultOverrides: [
{ {
level: ">=50", level: ">=50",
config: { config: {
@ -134,14 +128,6 @@ const defaultOptions: PluginOptions<LogsPluginType> = {
}, },
}, },
], ],
};
export const LogsPlugin = guildPlugin<LogsPluginType>()({
name: "logs",
dependencies: async () => [TimeAndDatePlugin, InternalPosterPlugin, (await getCasesPlugin()).CasesPlugin],
configParser: (input) => zLogsConfig.parse(input),
defaultOptions,
events: [ events: [
LogsGuildMemberAddEvt, LogsGuildMemberAddEvt,

View file

@ -21,6 +21,7 @@ import {
TemplateSafeUnknownUser, TemplateSafeUnknownUser,
TemplateSafeUser, TemplateSafeUser,
} from "../../utils/templateSafeObjects.js"; } from "../../utils/templateSafeObjects.js";
import DefaultLogMessages from "../../data/DefaultLogMessages.json" with { type: "json" };
const DEFAULT_BATCH_TIME = 1000; const DEFAULT_BATCH_TIME = 1000;
const MIN_BATCH_TIME = 250; const MIN_BATCH_TIME = 250;
@ -53,20 +54,20 @@ const zLogChannelMap = z.record(zSnowflake, zLogChannel);
export type TLogChannelMap = z.infer<typeof zLogChannelMap>; export type TLogChannelMap = z.infer<typeof zLogChannelMap>;
export const zLogsConfig = z.strictObject({ export const zLogsConfig = z.strictObject({
channels: zLogChannelMap, channels: zLogChannelMap.default({}),
format: zLogFormats, 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 // 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(), ping_user: z.boolean().default(true),
allow_user_mentions: z.boolean(), allow_user_mentions: z.boolean().default(false),
timestamp_format: z.string().nullable(), timestamp_format: z.string().nullable().default("[<t:]X[>]"),
include_embed_timestamp: z.boolean(), 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 // 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 const FORMAT_NO_TIMESTAMP = "__NO_TIMESTAMP__";
export interface LogsPluginType extends BasePluginType { export interface LogsPluginType extends BasePluginType {
config: z.infer<typeof zLogsConfig>; configSchema: typeof zLogsConfig;
state: { state: {
guildLogs: GuildLogs; guildLogs: GuildLogs;
savedMessages: GuildSavedMessages; savedMessages: GuildSavedMessages;

View file

@ -11,11 +11,11 @@ import {
} from "./events/SaveMessagesEvts.js"; } from "./events/SaveMessagesEvts.js";
import { MessageSaverPluginType, zMessageSaverConfig } from "./types.js"; import { MessageSaverPluginType, zMessageSaverConfig } from "./types.js";
const defaultOptions: PluginOptions<MessageSaverPluginType> = { export const MessageSaverPlugin = guildPlugin<MessageSaverPluginType>()({
config: { name: "message_saver",
can_manage: false,
}, configSchema: zMessageSaverConfig,
overrides: [ defaultOverrides: [
{ {
level: ">=100", level: ">=100",
config: { config: {
@ -23,13 +23,6 @@ const defaultOptions: PluginOptions<MessageSaverPluginType> = {
}, },
}, },
], ],
};
export const MessageSaverPlugin = guildPlugin<MessageSaverPluginType>()({
name: "message_saver",
configParser: (input) => zMessageSaverConfig.parse(input),
defaultOptions,
// prettier-ignore // prettier-ignore
messageCommands: [ messageCommands: [

View file

@ -4,11 +4,11 @@ import { GuildSavedMessages } from "../../data/GuildSavedMessages.js";
import { CommonPlugin } from "../Common/CommonPlugin.js"; import { CommonPlugin } from "../Common/CommonPlugin.js";
export const zMessageSaverConfig = z.strictObject({ export const zMessageSaverConfig = z.strictObject({
can_manage: z.boolean(), can_manage: z.boolean().default(false),
}); });
export interface MessageSaverPluginType extends BasePluginType { export interface MessageSaverPluginType extends BasePluginType {
config: z.infer<typeof zMessageSaverConfig>; configSchema: typeof zMessageSaverConfig;
state: { state: {
savedMessages: GuildSavedMessages; savedMessages: GuildSavedMessages;
common: pluginUtils.PluginPublicInterface<typeof CommonPlugin>; common: pluginUtils.PluginPublicInterface<typeof CommonPlugin>;

View file

@ -72,47 +72,14 @@ import { offModActionsEvent } from "./functions/offModActionsEvent.js";
import { onModActionsEvent } from "./functions/onModActionsEvent.js"; import { onModActionsEvent } from "./functions/onModActionsEvent.js";
import { updateCase } from "./functions/updateCase.js"; import { updateCase } from "./functions/updateCase.js";
import { warnMember } from "./functions/warnMember.js"; import { warnMember } from "./functions/warnMember.js";
import { AttachmentLinkReactionType, ModActionsPluginType, modActionsSlashGroup, zModActionsConfig } from "./types.js"; import { ModActionsPluginType, modActionsSlashGroup, zModActionsConfig } from "./types.js";
const defaultOptions = { export const ModActionsPlugin = guildPlugin<ModActionsPluginType>()({
config: { name: "mod_actions",
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,
can_note: false, dependencies: () => [TimeAndDatePlugin, CasesPlugin, MutesPlugin, LogsPlugin],
can_warn: false, configSchema: zModActionsConfig,
can_mute: false, defaultOverrides: [
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: [
{ {
level: ">=50", level: ">=50",
config: { config: {
@ -137,14 +104,6 @@ const defaultOptions = {
}, },
}, },
], ],
};
export const ModActionsPlugin = guildPlugin<ModActionsPluginType>()({
name: "mod_actions",
dependencies: () => [TimeAndDatePlugin, CasesPlugin, MutesPlugin, LogsPlugin],
configParser: (input) => zModActionsConfig.parse(input),
defaultOptions,
events: [CreateBanCaseOnManualBanEvt, CreateUnbanCaseOnManualUnbanEvt, PostAlertOnMemberJoinEvt, AuditLogEvents], events: [CreateBanCaseOnManualBanEvt, CreateUnbanCaseOnManualUnbanEvt, PostAlertOnMemberJoinEvt, AuditLogEvents],

View file

@ -22,39 +22,39 @@ import { CommonPlugin } from "../Common/CommonPlugin.js";
export type AttachmentLinkReactionType = "none" | "warn" | "restrict" | null; export type AttachmentLinkReactionType = "none" | "warn" | "restrict" | null;
export const zModActionsConfig = z.strictObject({ export const zModActionsConfig = z.strictObject({
dm_on_warn: z.boolean(), dm_on_warn: z.boolean().default(true),
dm_on_kick: z.boolean(), dm_on_kick: z.boolean().default(false),
dm_on_ban: z.boolean(), dm_on_ban: z.boolean().default(false),
message_on_warn: z.boolean(), message_on_warn: z.boolean().default(false),
message_on_kick: z.boolean(), message_on_kick: z.boolean().default(false),
message_on_ban: z.boolean(), message_on_ban: z.boolean().default(false),
message_channel: z.nullable(z.string()), message_channel: z.nullable(z.string()).default(null),
warn_message: z.nullable(z.string()), warn_message: z.nullable(z.string()).default("You have received a warning on the {guildName} server: {reason}"),
kick_message: z.nullable(z.string()), kick_message: z.nullable(z.string()).default("You have been kicked from the {guildName} server. Reason given: {reason}"),
ban_message: z.nullable(z.string()), ban_message: z.nullable(z.string()).default("You have been banned from the {guildName} server. Reason given: {reason}"),
tempban_message: z.nullable(z.string()), 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(), alert_on_rejoin: z.boolean().default(false),
alert_channel: z.nullable(z.string()), alert_channel: z.nullable(z.string()).default(null),
warn_notify_enabled: z.boolean(), warn_notify_enabled: z.boolean().default(false),
warn_notify_threshold: z.number(), warn_notify_threshold: z.number().default(5),
warn_notify_message: z.string(), 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(), ban_delete_message_days: z.number().default(1),
attachment_link_reaction: z.nullable(z.union([z.literal("none"), z.literal("warn"), z.literal("restrict")])), attachment_link_reaction: z.nullable(z.union([z.literal("none"), z.literal("warn"), z.literal("restrict")])).default("warn"),
can_note: z.boolean(), can_note: z.boolean().default(false),
can_warn: z.boolean(), can_warn: z.boolean().default(false),
can_mute: z.boolean(), can_mute: z.boolean().default(false),
can_kick: z.boolean(), can_kick: z.boolean().default(false),
can_ban: z.boolean(), can_ban: z.boolean().default(false),
can_unban: z.boolean(), can_unban: z.boolean().default(false),
can_view: z.boolean(), can_view: z.boolean().default(false),
can_addcase: z.boolean(), can_addcase: z.boolean().default(false),
can_massunban: z.boolean(), can_massunban: z.boolean().default(false),
can_massban: z.boolean(), can_massban: z.boolean().default(false),
can_massmute: z.boolean(), can_massmute: z.boolean().default(false),
can_hidecase: z.boolean(), can_hidecase: z.boolean().default(false),
can_deletecase: z.boolean(), can_deletecase: z.boolean().default(false),
can_act_as_other: z.boolean(), can_act_as_other: z.boolean().default(false),
create_cases_for_manual_actions: z.boolean(), create_cases_for_manual_actions: z.boolean().default(true),
}); });
export interface ModActionsEvents { export interface ModActionsEvents {
@ -72,7 +72,7 @@ export interface ModActionsEventEmitter extends EventEmitter {
} }
export interface ModActionsPluginType extends BasePluginType { export interface ModActionsPluginType extends BasePluginType {
config: z.infer<typeof zModActionsConfig>; configSchema: typeof zModActionsConfig;
state: { state: {
mutes: GuildMutes; mutes: GuildMutes;
cases: GuildCases; cases: GuildCases;

View file

@ -26,27 +26,12 @@ import { renewTimeoutMute } from "./functions/renewTimeoutMute.js";
import { unmuteUser } from "./functions/unmuteUser.js"; import { unmuteUser } from "./functions/unmuteUser.js";
import { MutesPluginType, zMutesConfig } from "./types.js"; import { MutesPluginType, zMutesConfig } from "./types.js";
const defaultOptions = { export const MutesPlugin = guildPlugin<MutesPluginType>()({
config: { name: "mutes",
mute_role: null,
move_to_voice_channel: null,
kick_from_voice_channel: false,
dm_on_mute: false, dependencies: () => [CasesPlugin, LogsPlugin, RoleManagerPlugin],
dm_on_update: false, configSchema: zMutesConfig,
message_on_mute: false, defaultOverrides: [
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: [
{ {
level: ">=50", level: ">=50",
config: { config: {
@ -60,14 +45,6 @@ const defaultOptions = {
}, },
}, },
], ],
};
export const MutesPlugin = guildPlugin<MutesPluginType>()({
name: "mutes",
dependencies: () => [CasesPlugin, LogsPlugin, RoleManagerPlugin],
configParser: (input) => zMutesConfig.parse(input),
defaultOptions,
// prettier-ignore // prettier-ignore
messageCommands: [ messageCommands: [

View file

@ -13,23 +13,23 @@ import { CaseArgs } from "../Cases/types.js";
import { CommonPlugin } from "../Common/CommonPlugin.js"; import { CommonPlugin } from "../Common/CommonPlugin.js";
export const zMutesConfig = z.strictObject({ export const zMutesConfig = z.strictObject({
mute_role: zSnowflake.nullable(), mute_role: zSnowflake.nullable().default(null),
move_to_voice_channel: zSnowflake.nullable(), move_to_voice_channel: zSnowflake.nullable().default(null),
kick_from_voice_channel: z.boolean(), kick_from_voice_channel: z.boolean().default(false),
dm_on_mute: z.boolean(), dm_on_mute: z.boolean().default(false),
dm_on_update: z.boolean(), dm_on_update: z.boolean().default(false),
message_on_mute: z.boolean(), message_on_mute: z.boolean().default(false),
message_on_update: z.boolean(), message_on_update: z.boolean().default(false),
message_channel: z.string().nullable(), message_channel: z.string().nullable().default(null),
mute_message: z.string().nullable(), mute_message: z.string().nullable().default("You have been muted on the {guildName} server. Reason given: {reason}"),
timed_mute_message: z.string().nullable(), 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(), 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), 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), restore_roles_on_mute: z.union([z.boolean(), z.array(zSnowflake)]).default(false),
can_view_list: z.boolean(), can_view_list: z.boolean().default(false),
can_cleanup: z.boolean(), can_cleanup: z.boolean().default(false),
}); });
export interface MutesEvents { export interface MutesEvents {
@ -43,7 +43,7 @@ export interface MutesEventEmitter extends EventEmitter {
} }
export interface MutesPluginType extends BasePluginType { export interface MutesPluginType extends BasePluginType {
config: z.infer<typeof zMutesConfig>; configSchema: typeof zMutesConfig;
state: { state: {
mutes: GuildMutes; mutes: GuildMutes;
cases: GuildCases; cases: GuildCases;

View file

@ -6,11 +6,11 @@ import { CommonPlugin } from "../Common/CommonPlugin.js";
import { NamesCmd } from "./commands/NamesCmd.js"; import { NamesCmd } from "./commands/NamesCmd.js";
import { NameHistoryPluginType, zNameHistoryConfig } from "./types.js"; import { NameHistoryPluginType, zNameHistoryConfig } from "./types.js";
const defaultOptions: PluginOptions<NameHistoryPluginType> = { export const NameHistoryPlugin = guildPlugin<NameHistoryPluginType>()({
config: { name: "name_history",
can_view: false,
}, configSchema: zNameHistoryConfig,
overrides: [ defaultOverrides: [
{ {
level: ">=50", level: ">=50",
config: { config: {
@ -18,13 +18,6 @@ const defaultOptions: PluginOptions<NameHistoryPluginType> = {
}, },
}, },
], ],
};
export const NameHistoryPlugin = guildPlugin<NameHistoryPluginType>()({
name: "name_history",
configParser: (input) => zNameHistoryConfig.parse(input),
defaultOptions,
// prettier-ignore // prettier-ignore
messageCommands: [ messageCommands: [

View file

@ -6,11 +6,11 @@ import { UsernameHistory } from "../../data/UsernameHistory.js";
import { CommonPlugin } from "../Common/CommonPlugin.js"; import { CommonPlugin } from "../Common/CommonPlugin.js";
export const zNameHistoryConfig = z.strictObject({ export const zNameHistoryConfig = z.strictObject({
can_view: z.boolean(), can_view: z.boolean().default(false),
}); });
export interface NameHistoryPluginType extends BasePluginType { export interface NameHistoryPluginType extends BasePluginType {
config: z.infer<typeof zNameHistoryConfig>; configSchema: typeof zNameHistoryConfig;
state: { state: {
nicknameHistory: GuildNicknameHistory; nicknameHistory: GuildNicknameHistory;
usernameHistory: UsernameHistory; usernameHistory: UsernameHistory;

View file

@ -7,20 +7,11 @@ import { LoadDataEvt } from "./events/LoadDataEvt.js";
import { StoreDataEvt } from "./events/StoreDataEvt.js"; import { StoreDataEvt } from "./events/StoreDataEvt.js";
import { PersistPluginType, zPersistConfig } from "./types.js"; import { PersistPluginType, zPersistConfig } from "./types.js";
const defaultOptions: PluginOptions<PersistPluginType> = {
config: {
persisted_roles: [],
persist_nicknames: false,
persist_voice_mutes: false,
},
};
export const PersistPlugin = guildPlugin<PersistPluginType>()({ export const PersistPlugin = guildPlugin<PersistPluginType>()({
name: "persist", name: "persist",
dependencies: () => [LogsPlugin, RoleManagerPlugin], dependencies: () => [LogsPlugin, RoleManagerPlugin],
configParser: (input) => zPersistConfig.parse(input), configSchema: zPersistConfig,
defaultOptions,
// prettier-ignore // prettier-ignore
events: [ events: [

View file

@ -5,14 +5,13 @@ import { GuildPersistedData } from "../../data/GuildPersistedData.js";
import { zSnowflake } from "../../utils.js"; import { zSnowflake } from "../../utils.js";
export const zPersistConfig = z.strictObject({ export const zPersistConfig = z.strictObject({
persisted_roles: z.array(zSnowflake), persisted_roles: z.array(zSnowflake).default([]),
persist_nicknames: z.boolean(), persist_nicknames: z.boolean().default(false),
persist_voice_mutes: z.boolean(), persist_voice_mutes: z.boolean().default(false),
}); });
export interface PersistPluginType extends BasePluginType { export interface PersistPluginType extends BasePluginType {
config: z.infer<typeof zPersistConfig>; configSchema: typeof zPersistConfig;
state: { state: {
persistedData: GuildPersistedData; persistedData: GuildPersistedData;
logs: GuildLogs; logs: GuildLogs;

View file

@ -4,18 +4,10 @@ import { makePublicFn } from "../../pluginUtils.js";
import { getDomainInfo } from "./functions/getDomainInfo.js"; import { getDomainInfo } from "./functions/getDomainInfo.js";
import { PhishermanPluginType, zPhishermanConfig } from "./types.js"; import { PhishermanPluginType, zPhishermanConfig } from "./types.js";
const defaultOptions: PluginOptions<PhishermanPluginType> = {
config: {
api_key: null,
},
overrides: [],
};
export const PhishermanPlugin = guildPlugin<PhishermanPluginType>()({ export const PhishermanPlugin = guildPlugin<PhishermanPluginType>()({
name: "phisherman", name: "phisherman",
configParser: (input) => zPhishermanConfig.parse(input), configSchema: zPhishermanConfig,
defaultOptions,
public(pluginData) { public(pluginData) {
return { return {

View file

@ -2,12 +2,11 @@ import { BasePluginType } from "knub";
import z from "zod/v4"; import z from "zod/v4";
export const zPhishermanConfig = z.strictObject({ 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 { export interface PhishermanPluginType extends BasePluginType {
config: z.infer<typeof zPhishermanConfig>; configSchema: typeof zPhishermanConfig;
state: { state: {
validApiKey: string | null; validApiKey: string | null;
}; };

View file

@ -1,15 +1,15 @@
import { PluginOptions, guildPlugin } from "knub"; import { guildPlugin } from "knub";
import { GuildPingableRoles } from "../../data/GuildPingableRoles.js"; import { GuildPingableRoles } from "../../data/GuildPingableRoles.js";
import { CommonPlugin } from "../Common/CommonPlugin.js"; import { CommonPlugin } from "../Common/CommonPlugin.js";
import { PingableRoleDisableCmd } from "./commands/PingableRoleDisableCmd.js"; import { PingableRoleDisableCmd } from "./commands/PingableRoleDisableCmd.js";
import { PingableRoleEnableCmd } from "./commands/PingableRoleEnableCmd.js"; import { PingableRoleEnableCmd } from "./commands/PingableRoleEnableCmd.js";
import { PingableRolesPluginType, zPingableRolesConfig } from "./types.js"; import { PingableRolesPluginType, zPingableRolesConfig } from "./types.js";
const defaultOptions: PluginOptions<PingableRolesPluginType> = { export const PingableRolesPlugin = guildPlugin<PingableRolesPluginType>()({
config: { name: "pingable_roles",
can_manage: false,
}, configSchema: zPingableRolesConfig,
overrides: [ defaultOverrides: [
{ {
level: ">=100", level: ">=100",
config: { config: {
@ -17,13 +17,6 @@ const defaultOptions: PluginOptions<PingableRolesPluginType> = {
}, },
}, },
], ],
};
export const PingableRolesPlugin = guildPlugin<PingableRolesPluginType>()({
name: "pingable_roles",
configParser: (input) => zPingableRolesConfig.parse(input),
defaultOptions,
// prettier-ignore // prettier-ignore
messageCommands: [ messageCommands: [

View file

@ -5,12 +5,11 @@ import { PingableRole } from "../../data/entities/PingableRole.js";
import { CommonPlugin } from "../Common/CommonPlugin.js"; import { CommonPlugin } from "../Common/CommonPlugin.js";
export const zPingableRolesConfig = z.strictObject({ export const zPingableRolesConfig = z.strictObject({
can_manage: z.boolean(), can_manage: z.boolean().default(false),
}); });
export interface PingableRolesPluginType extends BasePluginType { export interface PingableRolesPluginType extends BasePluginType {
config: z.infer<typeof zPingableRolesConfig>; configSchema: typeof zPingableRolesConfig;
state: { state: {
pingableRoles: GuildPingableRoles; pingableRoles: GuildPingableRoles;
cache: Map<string, PingableRole[]>; cache: Map<string, PingableRole[]>;

View file

@ -1,4 +1,4 @@
import { PluginOptions, guildPlugin } from "knub"; import { guildPlugin } from "knub";
import { onGuildEvent } from "../../data/GuildEvents.js"; import { onGuildEvent } from "../../data/GuildEvents.js";
import { GuildLogs } from "../../data/GuildLogs.js"; import { GuildLogs } from "../../data/GuildLogs.js";
import { GuildSavedMessages } from "../../data/GuildSavedMessages.js"; import { GuildSavedMessages } from "../../data/GuildSavedMessages.js";
@ -16,11 +16,12 @@ import { ScheduledPostsShowCmd } from "./commands/ScheduledPostsShowCmd.js";
import { PostPluginType, zPostConfig } from "./types.js"; import { PostPluginType, zPostConfig } from "./types.js";
import { postScheduledPost } from "./util/postScheduledPost.js"; import { postScheduledPost } from "./util/postScheduledPost.js";
const defaultOptions: PluginOptions<PostPluginType> = { export const PostPlugin = guildPlugin<PostPluginType>()({
config: { name: "post",
can_post: false,
}, dependencies: () => [TimeAndDatePlugin, LogsPlugin],
overrides: [ configSchema: zPostConfig,
defaultOverrides: [
{ {
level: ">=100", level: ">=100",
config: { config: {
@ -28,14 +29,6 @@ const defaultOptions: PluginOptions<PostPluginType> = {
}, },
}, },
], ],
};
export const PostPlugin = guildPlugin<PostPluginType>()({
name: "post",
dependencies: () => [TimeAndDatePlugin, LogsPlugin],
configParser: (input) => zPostConfig.parse(input),
defaultOptions,
// prettier-ignore // prettier-ignore
messageCommands: [ messageCommands: [

View file

@ -6,11 +6,11 @@ import { GuildScheduledPosts } from "../../data/GuildScheduledPosts.js";
import { CommonPlugin } from "../Common/CommonPlugin.js"; import { CommonPlugin } from "../Common/CommonPlugin.js";
export const zPostConfig = z.strictObject({ export const zPostConfig = z.strictObject({
can_post: z.boolean(), can_post: z.boolean().default(false),
}); });
export interface PostPluginType extends BasePluginType { export interface PostPluginType extends BasePluginType {
config: z.infer<typeof zPostConfig>; configSchema: typeof zPostConfig;
state: { state: {
savedMessages: GuildSavedMessages; savedMessages: GuildSavedMessages;
scheduledPosts: GuildScheduledPosts; scheduledPosts: GuildScheduledPosts;

View file

@ -11,19 +11,12 @@ import { AddReactionRoleEvt } from "./events/AddReactionRoleEvt.js";
import { MessageDeletedEvt } from "./events/MessageDeletedEvt.js"; import { MessageDeletedEvt } from "./events/MessageDeletedEvt.js";
import { ReactionRolesPluginType, zReactionRolesConfig } from "./types.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<ReactionRolesPluginType>()({
name: "reaction_roles",
const defaultOptions: PluginOptions<ReactionRolesPluginType> = { dependencies: () => [LogsPlugin],
config: { configSchema: zReactionRolesConfig,
auto_refresh_interval: MIN_AUTO_REFRESH, defaultOverrides: [
remove_user_reactions: true,
can_manage: false,
button_groups: null,
},
overrides: [
{ {
level: ">=100", level: ">=100",
config: { config: {
@ -31,14 +24,6 @@ const defaultOptions: PluginOptions<ReactionRolesPluginType> = {
}, },
}, },
], ],
};
export const ReactionRolesPlugin = guildPlugin<ReactionRolesPluginType>()({
name: "reaction_roles",
dependencies: () => [LogsPlugin],
configParser: (input) => zReactionRolesConfig.parse(input),
defaultOptions,
// prettier-ignore // prettier-ignore
messageCommands: [ messageCommands: [

View file

@ -5,11 +5,13 @@ import { GuildReactionRoles } from "../../data/GuildReactionRoles.js";
import { GuildSavedMessages } from "../../data/GuildSavedMessages.js"; import { GuildSavedMessages } from "../../data/GuildSavedMessages.js";
import { CommonPlugin } from "../Common/CommonPlugin.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({ export const zReactionRolesConfig = z.strictObject({
auto_refresh_interval: z.number(), auto_refresh_interval: z.number().min(MIN_AUTO_REFRESH).default(MIN_AUTO_REFRESH),
remove_user_reactions: z.boolean(), remove_user_reactions: z.boolean().default(true),
can_manage: z.boolean(), can_manage: z.boolean().default(false),
button_groups: z.nullable(z.unknown()), button_groups: z.null().default(null),
}); });
export type RoleChangeMode = "+" | "-"; export type RoleChangeMode = "+" | "-";
@ -27,7 +29,7 @@ const zReactionRolePair = z.union([z.tuple([z.string(), z.string(), z.string()])
export type TReactionRolePair = z.infer<typeof zReactionRolePair>; export type TReactionRolePair = z.infer<typeof zReactionRolePair>;
export interface ReactionRolesPluginType extends BasePluginType { export interface ReactionRolesPluginType extends BasePluginType {
config: z.infer<typeof zReactionRolesConfig>; configSchema: typeof zReactionRolesConfig;
state: { state: {
reactionRoles: GuildReactionRoles; reactionRoles: GuildReactionRoles;
savedMessages: GuildSavedMessages; savedMessages: GuildSavedMessages;

View file

@ -9,11 +9,12 @@ import { RemindersDeleteCmd } from "./commands/RemindersDeleteCmd.js";
import { postReminder } from "./functions/postReminder.js"; import { postReminder } from "./functions/postReminder.js";
import { RemindersPluginType, zRemindersConfig } from "./types.js"; import { RemindersPluginType, zRemindersConfig } from "./types.js";
const defaultOptions: PluginOptions<RemindersPluginType> = { export const RemindersPlugin = guildPlugin<RemindersPluginType>()({
config: { name: "reminders",
can_use: false,
}, dependencies: () => [TimeAndDatePlugin],
overrides: [ configSchema: zRemindersConfig,
defaultOverrides: [
{ {
level: ">=50", level: ">=50",
config: { config: {
@ -21,14 +22,6 @@ const defaultOptions: PluginOptions<RemindersPluginType> = {
}, },
}, },
], ],
};
export const RemindersPlugin = guildPlugin<RemindersPluginType>()({
name: "reminders",
dependencies: () => [TimeAndDatePlugin],
configParser: (input) => zRemindersConfig.parse(input),
defaultOptions,
// prettier-ignore // prettier-ignore
messageCommands: [ messageCommands: [

View file

@ -4,12 +4,11 @@ import { GuildReminders } from "../../data/GuildReminders.js";
import { CommonPlugin } from "../Common/CommonPlugin.js"; import { CommonPlugin } from "../Common/CommonPlugin.js";
export const zRemindersConfig = z.strictObject({ export const zRemindersConfig = z.strictObject({
can_use: z.boolean(), can_use: z.boolean().default(false),
}); });
export interface RemindersPluginType extends BasePluginType { export interface RemindersPluginType extends BasePluginType {
config: z.infer<typeof zRemindersConfig>; configSchema: typeof zRemindersConfig;
state: { state: {
reminders: GuildReminders; reminders: GuildReminders;
tries: Map<number, number>; tries: Map<number, number>;

View file

@ -11,22 +11,15 @@ import { RoleButtonsPluginType, zRoleButtonsConfig } from "./types.js";
export const RoleButtonsPlugin = guildPlugin<RoleButtonsPluginType>()({ export const RoleButtonsPlugin = guildPlugin<RoleButtonsPluginType>()({
name: "role_buttons", name: "role_buttons",
defaultOptions: { configSchema: zRoleButtonsConfig,
config: { defaultOverrides: [
buttons: {}, {
can_reset: false, level: ">=100",
}, config: {
overrides: [ can_reset: true,
{
level: ">=100",
config: {
can_reset: true,
},
}, },
], },
}, ],
configParser: (input) => zRoleButtonsConfig.parse(input),
dependencies: () => [LogsPlugin, RoleManagerPlugin], dependencies: () => [LogsPlugin, RoleManagerPlugin],

View file

@ -67,8 +67,8 @@ export type TRoleButtonsConfigItem = z.infer<typeof zRoleButtonsConfigItem>;
export const zRoleButtonsConfig = z export const zRoleButtonsConfig = z
.strictObject({ .strictObject({
buttons: zBoundedRecord(z.record(zBoundedCharacters(1, 16), zRoleButtonsConfigItem), 0, 100), buttons: zBoundedRecord(z.record(zBoundedCharacters(1, 16), zRoleButtonsConfigItem), 0, 100).default({}),
can_reset: z.boolean(), can_reset: z.boolean().default(false),
}) })
.refine( .refine(
(parsed) => { (parsed) => {
@ -91,7 +91,7 @@ export const zRoleButtonsConfig = z
); );
export interface RoleButtonsPluginType extends BasePluginType { export interface RoleButtonsPluginType extends BasePluginType {
config: z.infer<typeof zRoleButtonsConfig>; configSchema: typeof zRoleButtonsConfig;
state: { state: {
roleButtons: GuildRoleButtons; roleButtons: GuildRoleButtons;
common: pluginUtils.PluginPublicInterface<typeof CommonPlugin>; common: pluginUtils.PluginPublicInterface<typeof CommonPlugin>;

View file

@ -13,7 +13,7 @@ export const RoleManagerPlugin = guildPlugin<RoleManagerPluginType>()({
name: "role_manager", name: "role_manager",
dependencies: () => [LogsPlugin], dependencies: () => [LogsPlugin],
configParser: (input) => zRoleManagerConfig.parse(input), configSchema: zRoleManagerConfig,
public(pluginData) { public(pluginData) {
return { return {

View file

@ -5,7 +5,7 @@ import { GuildRoleQueue } from "../../data/GuildRoleQueue.js";
export const zRoleManagerConfig = z.strictObject({}); export const zRoleManagerConfig = z.strictObject({});
export interface RoleManagerPluginType extends BasePluginType { export interface RoleManagerPluginType extends BasePluginType {
config: z.infer<typeof zRoleManagerConfig>; configSchema: typeof zRoleManagerConfig;
state: { state: {
roleQueue: GuildRoleQueue; roleQueue: GuildRoleQueue;
roleAssignmentLoopRunning: boolean; roleAssignmentLoopRunning: boolean;

View file

@ -9,13 +9,12 @@ import { MassRemoveRoleCmd } from "./commands/MassRemoveRoleCmd.js";
import { RemoveRoleCmd } from "./commands/RemoveRoleCmd.js"; import { RemoveRoleCmd } from "./commands/RemoveRoleCmd.js";
import { RolesPluginType, zRolesConfig } from "./types.js"; import { RolesPluginType, zRolesConfig } from "./types.js";
const defaultOptions: PluginOptions<RolesPluginType> = { export const RolesPlugin = guildPlugin<RolesPluginType>()({
config: { name: "roles",
can_assign: false,
can_mass_assign: false, dependencies: () => [LogsPlugin, RoleManagerPlugin],
assignable_roles: [], configSchema: zRolesConfig,
}, defaultOverrides: [
overrides: [
{ {
level: ">=50", level: ">=50",
config: { config: {
@ -29,14 +28,6 @@ const defaultOptions: PluginOptions<RolesPluginType> = {
}, },
}, },
], ],
};
export const RolesPlugin = guildPlugin<RolesPluginType>()({
name: "roles",
dependencies: () => [LogsPlugin, RoleManagerPlugin],
configParser: (input) => zRolesConfig.parse(input),
defaultOptions,
// prettier-ignore // prettier-ignore
messageCommands: [ messageCommands: [

View file

@ -4,13 +4,13 @@ import { GuildLogs } from "../../data/GuildLogs.js";
import { CommonPlugin } from "../Common/CommonPlugin.js"; import { CommonPlugin } from "../Common/CommonPlugin.js";
export const zRolesConfig = z.strictObject({ export const zRolesConfig = z.strictObject({
can_assign: z.boolean(), can_assign: z.boolean().default(false),
can_mass_assign: z.boolean(), can_mass_assign: z.boolean().default(false),
assignable_roles: z.array(z.string()).max(100), assignable_roles: z.array(z.string()).max(100).default([]),
}); });
export interface RolesPluginType extends BasePluginType { export interface RolesPluginType extends BasePluginType {
config: z.infer<typeof zRolesConfig>; configSchema: typeof zRolesConfig;
state: { state: {
logs: GuildLogs; logs: GuildLogs;
common: pluginUtils.PluginPublicInterface<typeof CommonPlugin>; common: pluginUtils.PluginPublicInterface<typeof CommonPlugin>;

View file

@ -5,18 +5,10 @@ import { RoleHelpCmd } from "./commands/RoleHelpCmd.js";
import { RoleRemoveCmd } from "./commands/RoleRemoveCmd.js"; import { RoleRemoveCmd } from "./commands/RoleRemoveCmd.js";
import { SelfGrantableRolesPluginType, zSelfGrantableRolesConfig } from "./types.js"; import { SelfGrantableRolesPluginType, zSelfGrantableRolesConfig } from "./types.js";
const defaultOptions: PluginOptions<SelfGrantableRolesPluginType> = {
config: {
entries: {},
mention_roles: false,
},
};
export const SelfGrantableRolesPlugin = guildPlugin<SelfGrantableRolesPluginType>()({ export const SelfGrantableRolesPlugin = guildPlugin<SelfGrantableRolesPluginType>()({
name: "self_grantable_roles", name: "self_grantable_roles",
configParser: (input) => zSelfGrantableRolesConfig.parse(input), configSchema: zSelfGrantableRolesConfig,
defaultOptions,
// prettier-ignore // prettier-ignore
messageCommands: [ messageCommands: [

View file

@ -20,12 +20,12 @@ const zSelfGrantableRoleEntry = z.strictObject({
export type TSelfGrantableRoleEntry = z.infer<typeof zSelfGrantableRoleEntry>; export type TSelfGrantableRoleEntry = z.infer<typeof zSelfGrantableRoleEntry>;
export const zSelfGrantableRolesConfig = z.strictObject({ export const zSelfGrantableRolesConfig = z.strictObject({
entries: zBoundedRecord(z.record(zBoundedCharacters(0, 255), zSelfGrantableRoleEntry), 0, 100), entries: zBoundedRecord(z.record(zBoundedCharacters(0, 255), zSelfGrantableRoleEntry), 0, 100).default({}),
mention_roles: z.boolean(), mention_roles: z.boolean().default(false),
}); });
export interface SelfGrantableRolesPluginType extends BasePluginType { export interface SelfGrantableRolesPluginType extends BasePluginType {
config: z.infer<typeof zSelfGrantableRolesConfig>; configSchema: typeof zSelfGrantableRolesConfig;
state: { state: {
cooldowns: CooldownManager; cooldowns: CooldownManager;
common: pluginUtils.PluginPublicInterface<typeof CommonPlugin>; common: pluginUtils.PluginPublicInterface<typeof CommonPlugin>;

View file

@ -1,4 +1,4 @@
import { PluginOptions, guildPlugin } from "knub"; import { guildPlugin } from "knub";
import { GuildLogs } from "../../data/GuildLogs.js"; import { GuildLogs } from "../../data/GuildLogs.js";
import { GuildSavedMessages } from "../../data/GuildSavedMessages.js"; import { GuildSavedMessages } from "../../data/GuildSavedMessages.js";
import { GuildSlowmodes } from "../../data/GuildSlowmodes.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 BOT_SLOWMODE_CLEAR_INTERVAL = 60 * SECONDS;
const defaultOptions: PluginOptions<SlowmodePluginType> = {
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<SlowmodePluginType>()({ export const SlowmodePlugin = guildPlugin<SlowmodePluginType>()({
name: "slowmode", name: "slowmode",
@ -43,8 +24,16 @@ export const SlowmodePlugin = guildPlugin<SlowmodePluginType>()({
LogsPlugin, LogsPlugin,
], ],
configParser: (input) => zSlowmodeConfig.parse(input), configSchema: zSlowmodeConfig,
defaultOptions, defaultOverrides: [
{
level: ">=50",
config: {
can_manage: true,
is_affected: false,
},
},
],
// prettier-ignore // prettier-ignore
messageCommands: [ messageCommands: [

View file

@ -7,14 +7,14 @@ import { SlowmodeChannel } from "../../data/entities/SlowmodeChannel.js";
import { CommonPlugin } from "../Common/CommonPlugin.js"; import { CommonPlugin } from "../Common/CommonPlugin.js";
export const zSlowmodeConfig = z.strictObject({ export const zSlowmodeConfig = z.strictObject({
use_native_slowmode: z.boolean(), use_native_slowmode: z.boolean().default(true),
can_manage: z.boolean(), can_manage: z.boolean().default(false),
is_affected: z.boolean(), is_affected: z.boolean().default(true),
}); });
export interface SlowmodePluginType extends BasePluginType { export interface SlowmodePluginType extends BasePluginType {
config: z.infer<typeof zSlowmodeConfig>; configSchema: typeof zSlowmodeConfig;
state: { state: {
slowmodes: GuildSlowmodes; slowmodes: GuildSlowmodes;
savedMessages: GuildSavedMessages; savedMessages: GuildSavedMessages;

View file

@ -1,4 +1,4 @@
import { PluginOptions, guildPlugin } from "knub"; import { guildPlugin } from "knub";
import { GuildArchives } from "../../data/GuildArchives.js"; import { GuildArchives } from "../../data/GuildArchives.js";
import { GuildLogs } from "../../data/GuildLogs.js"; import { GuildLogs } from "../../data/GuildLogs.js";
import { GuildMutes } from "../../data/GuildMutes.js"; import { GuildMutes } from "../../data/GuildMutes.js";
@ -9,20 +9,12 @@ import { SpamPluginType, zSpamConfig } from "./types.js";
import { clearOldRecentActions } from "./util/clearOldRecentActions.js"; import { clearOldRecentActions } from "./util/clearOldRecentActions.js";
import { onMessageCreate } from "./util/onMessageCreate.js"; import { onMessageCreate } from "./util/onMessageCreate.js";
const defaultOptions: PluginOptions<SpamPluginType> = { export const SpamPlugin = guildPlugin<SpamPluginType>()({
config: { name: "spam",
max_censor: null,
max_messages: null, dependencies: () => [LogsPlugin],
max_mentions: null, configSchema: zSpamConfig,
max_links: null, defaultOverrides: [
max_attachments: null,
max_emojis: null,
max_newlines: null,
max_duplicates: null,
max_characters: null,
max_voice_moves: null,
},
overrides: [
{ {
level: ">=50", level: ">=50",
config: { config: {
@ -38,14 +30,6 @@ const defaultOptions: PluginOptions<SpamPluginType> = {
}, },
}, },
], ],
};
export const SpamPlugin = guildPlugin<SpamPluginType>()({
name: "spam",
dependencies: () => [LogsPlugin],
configParser: (input) => zSpamConfig.parse(input),
defaultOptions,
// prettier-ignore // prettier-ignore
events: [ events: [

View file

@ -18,16 +18,16 @@ const zBaseSingleSpamConfig = z.strictObject({
export type TBaseSingleSpamConfig = z.infer<typeof zBaseSingleSpamConfig>; export type TBaseSingleSpamConfig = z.infer<typeof zBaseSingleSpamConfig>;
export const zSpamConfig = z.strictObject({ export const zSpamConfig = z.strictObject({
max_censor: zBaseSingleSpamConfig.nullable(), max_censor: zBaseSingleSpamConfig.nullable().default(null),
max_messages: zBaseSingleSpamConfig.nullable(), max_messages: zBaseSingleSpamConfig.nullable().default(null),
max_mentions: zBaseSingleSpamConfig.nullable(), max_mentions: zBaseSingleSpamConfig.nullable().default(null),
max_links: zBaseSingleSpamConfig.nullable(), max_links: zBaseSingleSpamConfig.nullable().default(null),
max_attachments: zBaseSingleSpamConfig.nullable(), max_attachments: zBaseSingleSpamConfig.nullable().default(null),
max_emojis: zBaseSingleSpamConfig.nullable(), max_emojis: zBaseSingleSpamConfig.nullable().default(null),
max_newlines: zBaseSingleSpamConfig.nullable(), max_newlines: zBaseSingleSpamConfig.nullable().default(null),
max_duplicates: zBaseSingleSpamConfig.nullable(), max_duplicates: zBaseSingleSpamConfig.nullable().default(null),
max_characters: zBaseSingleSpamConfig.nullable(), max_characters: zBaseSingleSpamConfig.nullable().default(null),
max_voice_moves: zBaseSingleSpamConfig.nullable(), max_voice_moves: zBaseSingleSpamConfig.nullable().default(null),
}); });
export enum RecentActionType { export enum RecentActionType {
@ -52,7 +52,7 @@ export interface IRecentAction<T> {
} }
export interface SpamPluginType extends BasePluginType { export interface SpamPluginType extends BasePluginType {
config: z.infer<typeof zSpamConfig>; configSchema: typeof zSpamConfig;
state: { state: {
logs: GuildLogs; logs: GuildLogs;
archives: GuildArchives; archives: GuildArchives;

View file

@ -1,4 +1,4 @@
import { PluginOptions, guildPlugin } from "knub"; import { guildPlugin } from "knub";
import { GuildSavedMessages } from "../../data/GuildSavedMessages.js"; import { GuildSavedMessages } from "../../data/GuildSavedMessages.js";
import { GuildStarboardMessages } from "../../data/GuildStarboardMessages.js"; import { GuildStarboardMessages } from "../../data/GuildStarboardMessages.js";
import { GuildStarboardReactions } from "../../data/GuildStarboardReactions.js"; import { GuildStarboardReactions } from "../../data/GuildStarboardReactions.js";
@ -9,13 +9,11 @@ import { StarboardReactionRemoveAllEvt, StarboardReactionRemoveEvt } from "./eve
import { StarboardPluginType, zStarboardConfig } from "./types.js"; import { StarboardPluginType, zStarboardConfig } from "./types.js";
import { onMessageDelete } from "./util/onMessageDelete.js"; import { onMessageDelete } from "./util/onMessageDelete.js";
const defaultOptions: PluginOptions<StarboardPluginType> = { export const StarboardPlugin = guildPlugin<StarboardPluginType>()({
config: { name: "starboard",
can_migrate: false,
boards: {},
},
overrides: [ configSchema: zStarboardConfig,
defaultOverrides: [
{ {
level: ">=100", level: ">=100",
config: { config: {
@ -23,13 +21,6 @@ const defaultOptions: PluginOptions<StarboardPluginType> = {
}, },
}, },
], ],
};
export const StarboardPlugin = guildPlugin<StarboardPluginType>()({
name: "starboard",
configParser: (input) => zStarboardConfig.parse(input),
defaultOptions,
// prettier-ignore // prettier-ignore
messageCommands: [ messageCommands: [

View file

@ -19,13 +19,12 @@ const zStarboardOpts = z.strictObject({
export type TStarboardOpts = z.infer<typeof zStarboardOpts>; export type TStarboardOpts = z.infer<typeof zStarboardOpts>;
export const zStarboardConfig = z.strictObject({ export const zStarboardConfig = z.strictObject({
boards: zBoundedRecord(z.record(z.string(), zStarboardOpts), 0, 100), boards: zBoundedRecord(z.record(z.string(), zStarboardOpts), 0, 100).default({}),
can_migrate: z.boolean(), can_migrate: z.boolean().default(false),
}); });
export interface StarboardPluginType extends BasePluginType { export interface StarboardPluginType extends BasePluginType {
config: z.infer<typeof zStarboardConfig>; configSchema: typeof zStarboardConfig;
state: { state: {
savedMessages: GuildSavedMessages; savedMessages: GuildSavedMessages;
starboardMessages: GuildStarboardMessages; starboardMessages: GuildStarboardMessages;

View file

@ -1,5 +1,5 @@
import { Snowflake } from "discord.js"; import { Snowflake } from "discord.js";
import { PluginOptions, guildPlugin } from "knub"; import { guildPlugin } from "knub";
import moment from "moment-timezone"; import moment from "moment-timezone";
import { GuildArchives } from "../../data/GuildArchives.js"; import { GuildArchives } from "../../data/GuildArchives.js";
import { GuildLogs } from "../../data/GuildLogs.js"; import { GuildLogs } from "../../data/GuildLogs.js";
@ -22,25 +22,12 @@ import { onMessageCreate } from "./util/onMessageCreate.js";
import { onMessageDelete } from "./util/onMessageDelete.js"; import { onMessageDelete } from "./util/onMessageDelete.js";
import { renderTagBody } from "./util/renderTagBody.js"; import { renderTagBody } from "./util/renderTagBody.js";
const defaultOptions: PluginOptions<TagsPluginType> = { export const TagsPlugin = guildPlugin<TagsPluginType>()({
config: { name: "tags",
prefix: "!!",
delete_with_command: true,
user_tag_cooldown: null, dependencies: () => [LogsPlugin],
global_tag_cooldown: null, configSchema: zTagsConfig,
user_cooldown: null, defaultOverrides: [
allow_mentions: false,
global_cooldown: null,
auto_delete_command: false,
categories: {},
can_create: false,
can_use: false,
can_list: false,
},
overrides: [
{ {
level: ">=50", level: ">=50",
config: { config: {
@ -50,13 +37,6 @@ const defaultOptions: PluginOptions<TagsPluginType> = {
}, },
}, },
], ],
};
export const TagsPlugin = guildPlugin<TagsPluginType>()({
name: "tags",
dependencies: () => [LogsPlugin],
defaultOptions,
// prettier-ignore // prettier-ignore
messageCommands: [ messageCommands: [
@ -79,8 +59,6 @@ export const TagsPlugin = guildPlugin<TagsPluginType>()({
}; };
}, },
configParser: (input) => zTagsConfig.parse(input),
beforeLoad(pluginData) { beforeLoad(pluginData) {
const { state, guild } = pluginData; const { state, guild } = pluginData;

View file

@ -33,28 +33,28 @@ export type TTagCategory = z.infer<typeof zTagCategory>;
export const zTagsConfig = z export const zTagsConfig = z
.strictObject({ .strictObject({
prefix: z.string(), prefix: z.string().default("!!"),
delete_with_command: z.boolean(), delete_with_command: z.boolean().default(true),
user_tag_cooldown: z.union([z.string(), z.number()]).nullable(), // Per user, per 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(), // Any 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(), // Per user user_cooldown: z.union([z.string(), z.number()]).nullable().default(null), // Per user
allow_mentions: z.boolean(), // Per user allow_mentions: z.boolean().default(false), // Per user
global_cooldown: z.union([z.string(), z.number()]).nullable(), // Any tag use global_cooldown: z.union([z.string(), z.number()]).nullable().default(null), // Any tag use
auto_delete_command: z.boolean(), // Any tag 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_create: z.boolean().default(false),
can_use: z.boolean(), can_use: z.boolean().default(false),
can_list: z.boolean(), can_list: z.boolean().default(false),
}) })
.refine((parsed) => !(parsed.auto_delete_command && parsed.delete_with_command), { .refine((parsed) => !(parsed.auto_delete_command && parsed.delete_with_command), {
message: "Cannot have both (category specific) delete_with_command and auto_delete_command enabled", message: "Cannot have both (category specific) delete_with_command and auto_delete_command enabled",
}); });
export interface TagsPluginType extends BasePluginType { export interface TagsPluginType extends BasePluginType {
config: z.infer<typeof zTagsConfig>; configSchema: typeof zTagsConfig;
state: { state: {
archives: GuildArchives; archives: GuildArchives;
tags: GuildTags; tags: GuildTags;

View file

@ -13,14 +13,11 @@ import { inGuildTz } from "./functions/inGuildTz.js";
import { inMemberTz } from "./functions/inMemberTz.js"; import { inMemberTz } from "./functions/inMemberTz.js";
import { TimeAndDatePluginType, zTimeAndDateConfig } from "./types.js"; import { TimeAndDatePluginType, zTimeAndDateConfig } from "./types.js";
const defaultOptions: PluginOptions<TimeAndDatePluginType> = { export const TimeAndDatePlugin = guildPlugin<TimeAndDatePluginType>()({
config: { name: "time_and_date",
timezone: "Etc/UTC",
can_set_timezone: false,
date_formats: defaultDateFormats,
},
overrides: [ configSchema: zTimeAndDateConfig,
defaultOverrides: [
{ {
level: ">=50", level: ">=50",
config: { config: {
@ -28,13 +25,6 @@ const defaultOptions: PluginOptions<TimeAndDatePluginType> = {
}, },
}, },
], ],
};
export const TimeAndDatePlugin = guildPlugin<TimeAndDatePluginType>()({
name: "time_and_date",
configParser: (input) => zTimeAndDateConfig.parse(input),
defaultOptions,
// prettier-ignore // prettier-ignore
messageCommands: [ messageCommands: [

View file

@ -10,13 +10,13 @@ import { defaultDateFormats } from "./defaultDateFormats.js";
const zDateFormatKeys = z.enum(keys(defaultDateFormats) as U.ListOf<keyof typeof defaultDateFormats>); const zDateFormatKeys = z.enum(keys(defaultDateFormats) as U.ListOf<keyof typeof defaultDateFormats>);
export const zTimeAndDateConfig = z.strictObject({ export const zTimeAndDateConfig = z.strictObject({
timezone: zValidTimezone(z.string()), timezone: zValidTimezone(z.string()).default("Etc/UTC"),
date_formats: z.record(zDateFormatKeys, z.string()).nullable(), date_formats: z.record(zDateFormatKeys, z.string()).nullable().default(defaultDateFormats),
can_set_timezone: z.boolean(), can_set_timezone: z.boolean().default(false),
}); });
export interface TimeAndDatePluginType extends BasePluginType { export interface TimeAndDatePluginType extends BasePluginType {
config: z.infer<typeof zTimeAndDateConfig>; configSchema: typeof zTimeAndDateConfig;
state: { state: {
memberTimezones: GuildMemberTimezones; memberTimezones: GuildMemberTimezones;
common: pluginUtils.PluginPublicInterface<typeof CommonPlugin>; common: pluginUtils.PluginPublicInterface<typeof CommonPlugin>;

View file

@ -7,7 +7,7 @@ import { UsernameSaverPluginType, zUsernameSaverConfig } from "./types.js";
export const UsernameSaverPlugin = guildPlugin<UsernameSaverPluginType>()({ export const UsernameSaverPlugin = guildPlugin<UsernameSaverPluginType>()({
name: "username_saver", name: "username_saver",
configParser: (input) => zUsernameSaverConfig.parse(input), configSchema: zUsernameSaverConfig,
// prettier-ignore // prettier-ignore
events: [ events: [

View file

@ -6,7 +6,7 @@ import { UsernameHistory } from "../../data/UsernameHistory.js";
export const zUsernameSaverConfig = z.strictObject({}); export const zUsernameSaverConfig = z.strictObject({});
export interface UsernameSaverPluginType extends BasePluginType { export interface UsernameSaverPluginType extends BasePluginType {
config: z.infer<typeof zUsernameSaverConfig>; configSchema: typeof zUsernameSaverConfig;
state: { state: {
usernameHistory: UsernameHistory; usernameHistory: UsernameHistory;
updateQueue: Queue; updateQueue: Queue;

View file

@ -1,5 +1,5 @@
import { Snowflake } from "discord.js"; import { Snowflake } from "discord.js";
import { PluginOptions, guildPlugin } from "knub"; import { guildPlugin } from "knub";
import { GuildArchives } from "../../data/GuildArchives.js"; import { GuildArchives } from "../../data/GuildArchives.js";
import { GuildCases } from "../../data/GuildCases.js"; import { GuildCases } from "../../data/GuildCases.js";
import { GuildLogs } from "../../data/GuildLogs.js"; import { GuildLogs } from "../../data/GuildLogs.js";
@ -38,45 +38,21 @@ import { UserInfoCmd } from "./commands/UserInfoCmd.js";
import { VcdisconnectCmd } from "./commands/VcdisconnectCmd.js"; import { VcdisconnectCmd } from "./commands/VcdisconnectCmd.js";
import { VcmoveAllCmd, VcmoveCmd } from "./commands/VcmoveCmd.js"; import { VcmoveAllCmd, VcmoveCmd } from "./commands/VcmoveCmd.js";
import { AutoJoinThreadEvt, AutoJoinThreadSyncEvt } from "./events/AutoJoinThreadEvt.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 { getUserInfoEmbed } from "./functions/getUserInfoEmbed.js";
import { hasPermission } from "./functions/hasPermission.js"; import { hasPermission } from "./functions/hasPermission.js";
import { activeReloads } from "./guildReloads.js"; import { activeReloads } from "./guildReloads.js";
import { refreshMembersIfNeeded } from "./refreshMembers.js"; import { refreshMembersIfNeeded } from "./refreshMembers.js";
import { UtilityPluginType, zUtilityConfig } from "./types.js"; import { UtilityPluginType, zUtilityConfig } from "./types.js";
import { cleanMessages } from "./functions/cleanMessages.js";
import { fetchChannelMessagesToClean } from "./functions/fetchChannelMessagesToClean.js";
const defaultOptions: PluginOptions<UtilityPluginType> = { export const UtilityPlugin = guildPlugin<UtilityPluginType>()({
config: { name: "utility",
can_roles: false,
can_level: false, dependencies: () => [TimeAndDatePlugin, ModActionsPlugin, LogsPlugin],
can_search: false,
can_clean: false, configSchema: zUtilityConfig,
can_info: false, defaultOverrides: [
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: [
{ {
level: ">=50", level: ">=50",
config: { config: {
@ -112,14 +88,6 @@ const defaultOptions: PluginOptions<UtilityPluginType> = {
}, },
}, },
], ],
};
export const UtilityPlugin = guildPlugin<UtilityPluginType>()({
name: "utility",
dependencies: () => [TimeAndDatePlugin, ModActionsPlugin, LogsPlugin],
configParser: (input) => zUtilityConfig.parse(input),
defaultOptions,
// prettier-ignore // prettier-ignore
messageCommands: [ messageCommands: [

View file

@ -9,37 +9,37 @@ import { Supporters } from "../../data/Supporters.js";
import { CommonPlugin } from "../Common/CommonPlugin.js"; import { CommonPlugin } from "../Common/CommonPlugin.js";
export const zUtilityConfig = z.strictObject({ export const zUtilityConfig = z.strictObject({
can_roles: z.boolean(), can_roles: z.boolean().default(false),
can_level: z.boolean(), can_level: z.boolean().default(false),
can_search: z.boolean(), can_search: z.boolean().default(false),
can_clean: z.boolean(), can_clean: z.boolean().default(false),
can_info: z.boolean(), can_info: z.boolean().default(false),
can_server: z.boolean(), can_server: z.boolean().default(false),
can_inviteinfo: z.boolean(), can_inviteinfo: z.boolean().default(false),
can_channelinfo: z.boolean(), can_channelinfo: z.boolean().default(false),
can_messageinfo: z.boolean(), can_messageinfo: z.boolean().default(false),
can_userinfo: z.boolean(), can_userinfo: z.boolean().default(false),
can_roleinfo: z.boolean(), can_roleinfo: z.boolean().default(false),
can_emojiinfo: z.boolean(), can_emojiinfo: z.boolean().default(false),
can_snowflake: z.boolean(), can_snowflake: z.boolean().default(false),
can_reload_guild: z.boolean(), can_reload_guild: z.boolean().default(false),
can_nickname: z.boolean(), can_nickname: z.boolean().default(false),
can_ping: z.boolean(), can_ping: z.boolean().default(false),
can_source: z.boolean(), can_source: z.boolean().default(false),
can_vcmove: z.boolean(), can_vcmove: z.boolean().default(false),
can_vckick: z.boolean(), can_vckick: z.boolean().default(false),
can_help: z.boolean(), can_help: z.boolean().default(false),
can_about: z.boolean(), can_about: z.boolean().default(false),
can_context: z.boolean(), can_context: z.boolean().default(false),
can_jumbo: z.boolean(), can_jumbo: z.boolean().default(false),
jumbo_size: z.number(), jumbo_size: z.number().default(128),
can_avatar: z.boolean(), can_avatar: z.boolean().default(false),
info_on_single_result: z.boolean(), info_on_single_result: z.boolean().default(true),
autojoin_threads: z.boolean(), autojoin_threads: z.boolean().default(true),
}); });
export interface UtilityPluginType extends BasePluginType { export interface UtilityPluginType extends BasePluginType {
config: z.infer<typeof zUtilityConfig>; configSchema: typeof zUtilityConfig;
state: { state: {
logs: GuildLogs; logs: GuildLogs;
cases: GuildCases; cases: GuildCases;

View file

@ -4,20 +4,11 @@ import { LogsPlugin } from "../Logs/LogsPlugin.js";
import { SendWelcomeMessageEvt } from "./events/SendWelcomeMessageEvt.js"; import { SendWelcomeMessageEvt } from "./events/SendWelcomeMessageEvt.js";
import { WelcomeMessagePluginType, zWelcomeMessageConfig } from "./types.js"; import { WelcomeMessagePluginType, zWelcomeMessageConfig } from "./types.js";
const defaultOptions: PluginOptions<WelcomeMessagePluginType> = {
config: {
send_dm: false,
send_to_channel: null,
message: null,
},
};
export const WelcomeMessagePlugin = guildPlugin<WelcomeMessagePluginType>()({ export const WelcomeMessagePlugin = guildPlugin<WelcomeMessagePluginType>()({
name: "welcome_message", name: "welcome_message",
dependencies: () => [LogsPlugin], dependencies: () => [LogsPlugin],
configParser: (input) => zWelcomeMessageConfig.parse(input), configSchema: zWelcomeMessageConfig,
defaultOptions,
// prettier-ignore // prettier-ignore
events: [ events: [

View file

@ -3,13 +3,13 @@ import z from "zod/v4";
import { GuildLogs } from "../../data/GuildLogs.js"; import { GuildLogs } from "../../data/GuildLogs.js";
export const zWelcomeMessageConfig = z.strictObject({ export const zWelcomeMessageConfig = z.strictObject({
send_dm: z.boolean(), send_dm: z.boolean().default(false),
send_to_channel: z.string().nullable(), send_to_channel: z.string().nullable().default(null),
message: z.string().nullable(), message: z.string().nullable().default(null),
}); });
export interface WelcomeMessagePluginType extends BasePluginType { export interface WelcomeMessagePluginType extends BasePluginType {
config: z.infer<typeof zWelcomeMessageConfig>; configSchema: typeof zWelcomeMessageConfig;
state: { state: {
logs: GuildLogs; logs: GuildLogs;
sentWelcomeMessages: Set<string>; sentWelcomeMessages: Set<string>;

8
package-lock.json generated
View file

@ -43,7 +43,7 @@
"fp-ts": "^2.0.1", "fp-ts": "^2.0.1",
"humanize-duration": "^3.15.0", "humanize-duration": "^3.15.0",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"knub": "^32.0.0-next.23", "knub": "^32.0.0-next.25",
"knub-command-manager": "^9.1.0", "knub-command-manager": "^9.1.0",
"last-commit-log": "^2.1.0", "last-commit-log": "^2.1.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
@ -12806,9 +12806,9 @@
} }
}, },
"node_modules/knub": { "node_modules/knub": {
"version": "32.0.0-next.23", "version": "32.0.0-next.25",
"resolved": "https://registry.npmjs.org/knub/-/knub-32.0.0-next.23.tgz", "resolved": "https://registry.npmjs.org/knub/-/knub-32.0.0-next.25.tgz",
"integrity": "sha512-kDv6QhE5ALL9bew0GJtzFh2HpyOECCZ6gGBnZNcKUekxWh3LdKW2nYuo1kfqTycEM/5zn7uiHTGLVxfea9LNxA==", "integrity": "sha512-5ki+0f3PD7v3mRH2ew4RIy1aXMXvUUqPGyikUjCBR8/5EF277/GNwqxC8pA5CDJi8/e29UeGyx/mqHKBvGoTXw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"discord-api-types": "^0.38.8", "discord-api-types": "^0.38.8",