3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-05-26 02:35:03 +00:00

feat: knub v32-next; related fixes

This commit is contained in:
Dragory 2023-04-01 02:16:15 +03:00
parent 448293d6ac
commit c36d47e0b8
No known key found for this signature in database
GPG key ID: 5F387BA66DF8AAC1
89 changed files with 287 additions and 931 deletions

View file

@ -66,7 +66,7 @@ export function initDocs(app: express.Express) {
}));
const defaultOptions = plugin.defaultOptions || {};
const configSchema = plugin.configSchema && formatConfigSchema(plugin.configSchema);
const configSchema = plugin.info?.configSchema && formatConfigSchema(plugin.info.configSchema);
res.json({
name,

View file

@ -20,5 +20,5 @@ setIsAPI(true);
// Connect to the database before loading the rest of the code (that depend on the database connection)
console.log("Connecting to database..."); // tslint:disable-line
connect().then(() => {
import("./start");
import("./start.js");
});

View file

@ -36,7 +36,7 @@ export async function validateGuildConfig(config: any): Promise<string | null> {
const plugin = pluginNameToPlugin.get(pluginName)!;
try {
const mergedOptions = configUtils.mergeConfig(plugin.defaultOptions || {}, pluginOptions);
await plugin.configParser?.(mergedOptions as unknown as PluginOptions<any>, true);
await plugin.configParser?.(mergedOptions as unknown as PluginOptions<any>);
} catch (err) {
if (err instanceof ConfigValidationError || err instanceof StrictValidationError) {
return `${pluginName}: ${err.message}`;

View file

@ -2,21 +2,14 @@ import {
Client,
Events,
GatewayIntentBits,
GuildTextBasedChannel,
Message,
Options,
Partials,
RESTEvents,
TextBasedChannel,
TextChannel,
ThreadChannel,
} from "discord.js";
import { Knub, PluginError } from "knub";
import { PluginLoadError } from "knub/dist/plugins/PluginLoadError";
// Always use UTC internally
// This is also enforced for the database in data/db.ts
import { EventEmitter } from "events";
import { PluginNotLoadedError } from "knub/dist/plugins/PluginNotLoadedError";
import { Knub, PluginError, PluginLoadError, PluginNotLoadedError } from "knub";
import moment from "moment-timezone";
import { performance } from "perf_hooks";
import { AllowedGuilds } from "./data/AllowedGuilds";
@ -48,18 +41,6 @@ import { DecayingCounter } from "./utils/DecayingCounter";
import { enableProfiling } from "./utils/easyProfiler";
import { loadYamlSafely } from "./utils/loadYamlSafely";
// TODO: Remove this once fixed on upstream
declare module "knub/dist/helpers" {
export function waitForReply(
client: Client,
channel: GuildTextBasedChannel,
restrictToUserId?: string,
timeout?: number,
): Promise<Message | null>;
export function createChunkedMessage(channel: TextBasedChannel, messageText: string): Promise<Message[]>;
}
// Error handling
let recentPluginErrors = 0;
const RECENT_PLUGIN_ERROR_EXIT_THRESHOLD = 5;
@ -184,6 +165,8 @@ for (const [i, part] of actualVersionParts.entries()) {
throw new SimpleError(`Unsupported Node.js version! Must be at least ${REQUIRED_NODE_VERSION}`);
}
// Always use UTC internally
// This is also enforced for the database in data/db.ts
moment.tz.setDefault("UTC");
// Blocking check

View file

@ -4,17 +4,21 @@
import { GuildMember, Message, MessageCreateOptions, MessageMentionOptions, TextBasedChannel } from "discord.js";
import * as t from "io-ts";
import { CommandContext, configUtils, ConfigValidationError, GuildPluginData, helpers, PluginOptions } from "knub";
import { PluginOverrideCriteria } from "knub/dist/config/configTypes";
import { ExtendedMatchParams } from "knub/dist/config/PluginConfigManager"; // TODO: Export from Knub index
import { AnyPluginData } from "knub/dist/plugins/PluginData";
import {
AnyPluginData,
CommandContext,
ConfigValidationError,
ExtendedMatchParams,
GuildPluginData,
helpers,
PluginOverrideCriteria,
} from "knub";
import { logger } from "./logger";
import { ZeppelinPlugin } from "./plugins/ZeppelinPlugin";
import { isStaff } from "./staff";
import { TZeppelinKnub } from "./types";
import { deepKeyIntersect, errorMessage, successMessage, tDeepPartial, tNullable } from "./utils";
import { errorMessage, successMessage, tNullable } from "./utils";
import { Tail } from "./utils/typeUtils";
import { decodeAndValidateStrict, StrictValidationError, validate } from "./validatorUtils";
import { StrictValidationError, validate } from "./validatorUtils";
const { getMemberLevel } = helpers;
@ -91,102 +95,13 @@ export function strictValidationErrorToConfigValidationError(err: StrictValidati
);
}
export function getPluginConfigParser(blueprint: ZeppelinPlugin, customParser?: ZeppelinPlugin["configParser"]) {
return async (options: PluginOptions<any>, strict?: boolean) => {
const ident = `[getPluginConfigParser.${blueprint.name}] | `;
if (blueprint.name === "mutes") {
console.log(ident, "options => ", JSON.stringify(options));
export function makeIoTsConfigParser<Schema extends t.Type<any>>(schema: Schema): (input: unknown) => t.TypeOf<Schema> {
return (input: unknown) => {
const error = validate(schema, input);
if (error) {
throw error;
}
// 1. Validate the basic structure of plugin config
const basicOptionsValidation = validate(BasicPluginStructureType, options);
if (basicOptionsValidation instanceof StrictValidationError) {
throw strictValidationErrorToConfigValidationError(basicOptionsValidation);
}
// 2. Validate config/overrides against *partial* config schema. This ensures valid properties have valid types.
const partialConfigSchema = tDeepPartial(blueprint.configSchema);
if (options.config) {
const partialConfigValidation = validate(partialConfigSchema, options.config);
if (partialConfigValidation instanceof StrictValidationError) {
throw strictValidationErrorToConfigValidationError(partialConfigValidation);
}
}
if (options.overrides) {
for (const override of options.overrides) {
// Validate criteria and extra criteria
// FIXME: This is ugly
for (const key of Object.keys(override)) {
if (!validTopLevelOverrideKeys.includes(key)) {
if (strict) {
throw new ConfigValidationError(`Unknown override criterion '${key}'`);
}
delete override[key];
}
}
if (override.extra != null) {
for (const extraCriterion of Object.keys(override.extra)) {
if (!blueprint.customOverrideCriteriaFunctions?.[extraCriterion]) {
if (strict) {
throw new ConfigValidationError(`Unknown override extra criterion '${extraCriterion}'`);
}
delete override.extra[extraCriterion];
}
}
}
// Validate override config
const partialOverrideConfigValidation = decodeAndValidateStrict(partialConfigSchema, override.config || {});
if (partialOverrideConfigValidation instanceof StrictValidationError) {
throw strictValidationErrorToConfigValidationError(partialOverrideConfigValidation);
}
}
}
// 3. Run custom parser, if any
if (customParser) {
options = await customParser(options);
}
// 4. Merge with default options and validate/decode the entire config
let decodedConfig = {};
const decodedOverrides: Array<PluginOverrideCriteria<unknown> & { config: any }> = [];
if (options.config) {
decodedConfig = blueprint.configSchema
? decodeAndValidateStrict(blueprint.configSchema, options.config)
: options.config;
if (decodedConfig instanceof StrictValidationError) {
console.error("4.strict:", blueprint.name);
throw strictValidationErrorToConfigValidationError(decodedConfig);
}
}
if (options.overrides) {
for (const override of options.overrides) {
const overrideConfigMergedWithBaseConfig = configUtils.mergeConfig(options.config || {}, override.config || {});
const decodedOverrideConfig = blueprint.configSchema
? decodeAndValidateStrict(blueprint.configSchema, overrideConfigMergedWithBaseConfig)
: overrideConfigMergedWithBaseConfig;
if (decodedOverrideConfig instanceof StrictValidationError) {
console.error("4.overrides.strict:", blueprint.name, options, decodedOverrideConfig);
throw strictValidationErrorToConfigValidationError(decodedOverrideConfig);
}
decodedOverrides.push({
...override,
config: deepKeyIntersect(decodedOverrideConfig, override.config || {}),
});
}
}
return {
config: decodedConfig,
overrides: decodedOverrides,
};
return input as t.TypeOf<Schema>;
};
}

View file

@ -1,6 +1,7 @@
import { PluginOptions } from "knub";
import { GuildLogs } from "../../data/GuildLogs";
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { LogsPlugin } from "../Logs/LogsPlugin";
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
@ -23,10 +24,11 @@ export const AutoDeletePlugin = zeppelinGuildPlugin<AutoDeletePluginType>()({
prettyName: "Auto-delete",
description: "Allows Zeppelin to auto-delete messages from a channel after a delay",
configurationGuide: "Maximum deletion delay is currently 5 minutes",
configSchema: ConfigSchema,
},
dependencies: () => [TimeAndDatePlugin, LogsPlugin],
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
beforeLoad(pluginData) {
@ -62,7 +64,4 @@ export const AutoDeletePlugin = zeppelinGuildPlugin<AutoDeletePluginType>()({
state.guildSavedMessages.events.off("delete", state.onMessageDeleteFn);
state.guildSavedMessages.events.off("deleteBulk", state.onMessageDeleteBulkFn);
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,6 +1,7 @@
import { PluginOptions } from "knub";
import { GuildAutoReactions } from "../../data/GuildAutoReactions";
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { trimPluginDescription } from "../../utils";
import { LogsPlugin } from "../Logs/LogsPlugin";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
@ -31,6 +32,7 @@ export const AutoReactionsPlugin = zeppelinGuildPlugin<AutoReactionsPluginType>(
description: trimPluginDescription(`
Allows setting up automatic reactions to all new messages on a channel
`),
configSchema: ConfigSchema,
},
// prettier-ignore
@ -38,7 +40,7 @@ export const AutoReactionsPlugin = zeppelinGuildPlugin<AutoReactionsPluginType>(
LogsPlugin,
],
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -59,7 +61,4 @@ export const AutoReactionsPlugin = zeppelinGuildPlugin<AutoReactionsPluginType>(
state.autoReactions = GuildAutoReactions.getGuildInstance(guild.id);
state.cache = new Map();
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,3 +1,4 @@
import * as t from "io-ts";
import { configUtils, CooldownManager } from "knub";
import { GuildAntiraidLevels } from "../../data/GuildAntiraidLevels";
import { GuildArchives } from "../../data/GuildArchives";
@ -8,7 +9,7 @@ import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners";
import { MINUTES, SECONDS } from "../../utils";
import { registerEventListenersFromMap } from "../../utils/registerEventListenersFromMap";
import { unregisterEventListenersFromMap } from "../../utils/unregisterEventListenersFromMap";
import { StrictValidationError } from "../../validatorUtils";
import { StrictValidationError, validate } from "../../validatorUtils";
import { CountersPlugin } from "../Counters/CountersPlugin";
import { InternalPosterPlugin } from "../InternalPoster/InternalPosterPlugin";
import { LogsPlugin } from "../Logs/LogsPlugin";
@ -62,14 +63,15 @@ const defaultOptions = {
/**
* Config preprocessor to set default values for triggers and perform extra validation
* TODO: Separate input and output types
*/
const configParser = (options) => {
if (options.rules) {
const configParser = (input: unknown) => {
const rules = (input as any).rules;
if (rules) {
// Loop through each rule
for (const [name, rule] of Object.entries(options.rules)) {
for (const [name, rule] of Object.entries(rules)) {
if (rule == null) {
delete options.rules[name];
delete rules[name];
continue;
}
@ -179,7 +181,12 @@ const configParser = (options) => {
}
}
return options;
const error = validate(ConfigSchema, input);
if (error) {
throw error;
}
return input as t.TypeOf<typeof ConfigSchema>;
};
export const AutomodPlugin = zeppelinGuildPlugin<AutomodPluginType>()({
@ -188,7 +195,6 @@ export const AutomodPlugin = zeppelinGuildPlugin<AutomodPluginType>()({
info: pluginInfo,
// prettier-ignore
// @ts-expect-error
dependencies: () => [
LogsPlugin,
ModActionsPlugin,
@ -198,7 +204,6 @@ export const AutomodPlugin = zeppelinGuildPlugin<AutomodPluginType>()({
InternalPosterPlugin,
],
configSchema: ConfigSchema,
defaultOptions,
configParser,
@ -261,7 +266,6 @@ export const AutomodPlugin = zeppelinGuildPlugin<AutomodPluginType>()({
state.onMessageUpdateFn = (message) => runAutomodOnMessage(pluginData, message, true);
state.savedMessages.events.on("update", state.onMessageUpdateFn);
// @ts-expect-error
const countersPlugin = pluginData.getPlugin(CountersPlugin);
state.onCounterTrigger = (name, triggerName, channelId, userId) => {
@ -271,9 +275,7 @@ export const AutomodPlugin = zeppelinGuildPlugin<AutomodPluginType>()({
state.onCounterReverseTrigger = (name, triggerName, channelId, userId) => {
runAutomodOnCounterTrigger(pluginData, name, triggerName, channelId, userId, true);
};
// @ts-expect-error
countersPlugin.onCounterEvent("trigger", state.onCounterTrigger);
// @ts-expect-error
countersPlugin.onCounterEvent("reverseTrigger", state.onCounterReverseTrigger);
const modActionsEvents = pluginData.getPlugin(ModActionsPlugin).getEventEmitter();
@ -303,14 +305,11 @@ export const AutomodPlugin = zeppelinGuildPlugin<AutomodPluginType>()({
async beforeUnload(pluginData) {
const { state, guild } = pluginData;
// @ts-expect-error
const countersPlugin = pluginData.getPlugin(CountersPlugin);
if (state.onCounterTrigger) {
// @ts-expect-error
countersPlugin.offCounterEvent("trigger", state.onCounterTrigger);
}
if (state.onCounterReverseTrigger) {
// @ts-expect-error
countersPlugin.offCounterEvent("reverseTrigger", state.onCounterReverseTrigger);
}

View file

@ -12,9 +12,7 @@ export const AddToCounterAction = automodAction({
defaultConfig: {},
async apply({ pluginData, contexts, actionConfig, matchResult, ruleName }) {
// @ts-expect-error
const countersPlugin = pluginData.getPlugin(CountersPlugin);
// @ts-expect-error
if (!countersPlugin.counterExists(actionConfig.counter)) {
pluginData.getPlugin(LogsPlugin).logBotAlert({
body: `Unknown counter \`${actionConfig.counter}\` in \`add_to_counter\` action of Automod rule \`${ruleName}\``,
@ -22,7 +20,6 @@ export const AddToCounterAction = automodAction({
return;
}
// @ts-expect-error
countersPlugin.changeCounterValue(
actionConfig.counter,
contexts[0].message?.channel_id || null,

View file

@ -1,8 +1,7 @@
import { PermissionsBitField, PermissionsString } from "discord.js";
import * as t from "io-ts";
import { noop } from "knub/dist/utils";
import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter";
import { isValidSnowflake, tNullable, tPartialDictionary } from "../../../utils";
import { isValidSnowflake, noop, tNullable, tPartialDictionary } from "../../../utils";
import {
guildToTemplateSafeGuild,
savedMessageToTemplateSafeSavedMessage,

View file

@ -12,9 +12,7 @@ export const SetCounterAction = automodAction({
defaultConfig: {},
async apply({ pluginData, contexts, actionConfig, matchResult, ruleName }) {
// @ts-expect-error
const countersPlugin = pluginData.getPlugin(CountersPlugin);
// @ts-expect-error
if (!countersPlugin.counterExists(actionConfig.counter)) {
pluginData.getPlugin(LogsPlugin).logBotAlert({
body: `Unknown counter \`${actionConfig.counter}\` in \`add_to_counter\` action of Automod rule \`${ruleName}\``,
@ -22,7 +20,6 @@ export const SetCounterAction = automodAction({
return;
}
// @ts-expect-error
countersPlugin.setCounterValue(
actionConfig.counter,
contexts[0].message?.channel_id || null,

View file

@ -14,11 +14,8 @@ export async function runAutomodOnCounterTrigger(
) {
const user = userId ? await resolveUser(pluginData.client, userId) : undefined;
const member = (userId && (await resolveMember(pluginData.client, pluginData.guild, userId))) || undefined;
// @ts-expect-error
const prettyCounterName = pluginData.getPlugin(CountersPlugin).getPrettyNameForCounter(counterName);
// @ts-expect-error
const prettyTriggerName = pluginData
// @ts-expect-error
.getPlugin(CountersPlugin)
.getPrettyNameForCounterTrigger(counterName, triggerName);

View file

@ -1,6 +1,6 @@
import * as t from "io-ts";
import { GuildPluginData } from "knub";
import { Awaitable } from "knub/dist/utils";
import { Awaitable } from "../../utils/typeUtils";
import { AutomodContext, AutomodPluginType } from "./types";
interface BaseAutomodTriggerMatchResult {

View file

@ -1,5 +1,6 @@
import { trimPluginDescription } from "../../utils";
import { ZeppelinGuildPluginBlueprint } from "../ZeppelinPluginBlueprint";
import { ConfigSchema } from "./types";
export const pluginInfo: ZeppelinGuildPluginBlueprint["info"] = {
prettyName: "Automod",
@ -99,4 +100,5 @@ export const pluginInfo: ZeppelinGuildPluginBlueprint["info"] = {
{matchSummary}
~~~
`),
configSchema: ConfigSchema,
};

View file

@ -3,7 +3,7 @@ import { AllowedGuilds } from "../../data/AllowedGuilds";
import { ApiPermissionAssignments } from "../../data/ApiPermissionAssignments";
import { Configs } from "../../data/Configs";
import { GuildArchives } from "../../data/GuildArchives";
import { sendSuccessMessage } from "../../pluginUtils";
import { makeIoTsConfigParser, sendSuccessMessage } from "../../pluginUtils";
import { zeppelinGlobalPlugin } from "../ZeppelinPluginBlueprint";
import { getActiveReload, resetActiveReload } from "./activeReload";
import { AddDashboardUserCmd } from "./commands/AddDashboardUserCmd";
@ -37,7 +37,7 @@ const defaultOptions = {
export const BotControlPlugin = zeppelinGlobalPlugin<BotControlPluginType>()({
name: "bot_control",
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -82,7 +82,4 @@ export const BotControlPlugin = zeppelinGlobalPlugin<BotControlPluginType>()({
}
}
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -3,7 +3,7 @@ import { Case } from "../../data/entities/Case";
import { GuildArchives } from "../../data/GuildArchives";
import { GuildCases } from "../../data/GuildCases";
import { GuildLogs } from "../../data/GuildLogs";
import { mapToPublicFn } from "../../pluginUtils";
import { makeIoTsConfigParser, mapToPublicFn } from "../../pluginUtils";
import { trimPluginDescription } from "../../utils";
import { InternalPosterPlugin } from "../InternalPoster/InternalPosterPlugin";
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
@ -18,6 +18,11 @@ import { getTotalCasesByMod } from "./functions/getTotalCasesByMod";
import { postCaseToCaseLogChannel } from "./functions/postToCaseLogChannel";
import { CaseArgs, CaseNoteArgs, CasesPluginType, ConfigSchema } from "./types";
// The `any` cast here is to prevent TypeScript from locking up from the circular dependency
function getLogsPlugin(): Promise<any> {
return import("../Logs/LogsPlugin.js") as Promise<any>;
}
const defaultOptions = {
config: {
log_automatic_actions: true,
@ -37,15 +42,11 @@ export const CasesPlugin = zeppelinGuildPlugin<CasesPluginType>()({
description: trimPluginDescription(`
This plugin contains basic configuration for cases created by other plugins
`),
configSchema: ConfigSchema,
},
dependencies: async () => [
TimeAndDatePlugin,
InternalPosterPlugin,
// The `as any` cast here is to prevent TypeScript from locking up from the circular dependency
((await import("../Logs/LogsPlugin")) as any).LogsPlugin,
],
configSchema: ConfigSchema,
dependencies: async () => [TimeAndDatePlugin, InternalPosterPlugin, (await getLogsPlugin()).LogsPlugin],
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
public: {
@ -87,7 +88,4 @@ export const CasesPlugin = zeppelinGuildPlugin<CasesPluginType>()({
state.archives = GuildArchives.getGuildInstance(guild.id);
state.cases = GuildCases.getGuildInstance(guild.id);
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,5 +1,5 @@
import { GuildPluginData } from "knub";
import { splitMessageIntoChunks } from "knub/dist/helpers";
import { splitMessageIntoChunks } from "knub/helpers";
import moment from "moment-timezone";
import { Case } from "../../../data/entities/Case";
import { convertDelayStringToMS, DAYS, DBDateFormat, disableLinkPreviews, messageLink } from "../../../utils";

View file

@ -1,6 +1,7 @@
import { PluginOptions } from "knub";
import { GuildLogs } from "../../data/GuildLogs";
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners";
import { trimPluginDescription } from "../../utils";
import { LogsPlugin } from "../Logs/LogsPlugin";
@ -53,10 +54,11 @@ export const CensorPlugin = zeppelinGuildPlugin<CensorPluginType>()({
For more advanced filtering, check out the Automod plugin!
`),
legacy: true,
configSchema: ConfigSchema,
},
dependencies: () => [LogsPlugin],
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
beforeLoad(pluginData) {
@ -86,7 +88,4 @@ export const CensorPlugin = zeppelinGuildPlugin<CensorPluginType>()({
state.savedMessages.events.off("create", state.onMessageCreateFn);
state.savedMessages.events.off("update", state.onMessageUpdateFn);
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,21 +1,21 @@
import * as t from "io-ts";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { ArchiveChannelCmd } from "./commands/ArchiveChannelCmd";
import { ChannelArchiverPluginType } from "./types";
const ConfigSchema = t.type({});
export const ChannelArchiverPlugin = zeppelinGuildPlugin<ChannelArchiverPluginType>()({
name: "channel_archiver",
showInDocs: false,
dependencies: () => [TimeAndDatePlugin],
configSchema: t.type({}),
configParser: makeIoTsConfigParser(ConfigSchema),
// prettier-ignore
messageCommands: [
ArchiveChannelCmd,
],
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,5 +1,6 @@
import { CooldownManager } from "knub";
import { GuildLogs } from "../../data/GuildLogs";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { trimPluginDescription } from "../../utils";
import { LogsPlugin } from "../Logs/LogsPlugin";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
@ -22,10 +23,11 @@ export const CompanionChannelsPlugin = zeppelinGuildPlugin<CompanionChannelsPlug
Once set up, any time a user joins one of the specified voice channels,
they'll get channel permissions applied to them for the text channels.
`),
configSchema: ConfigSchema,
},
dependencies: () => [LogsPlugin],
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
events: [VoiceStateUpdateEvt],
@ -37,7 +39,4 @@ export const CompanionChannelsPlugin = zeppelinGuildPlugin<CompanionChannelsPlug
afterLoad(pluginData) {
pluginData.state.serverLogs = new GuildLogs(pluginData.guild.id);
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,5 +1,6 @@
import { PluginOptions } from "knub";
import { GuildContextMenuLinks } from "../../data/GuildContextMenuLinks";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { LogsPlugin } from "../Logs/LogsPlugin";
import { MutesPlugin } from "../Mutes/MutesPlugin";
import { UtilityPlugin } from "../Utility/UtilityPlugin";
@ -35,8 +36,8 @@ export const ContextMenuPlugin = zeppelinGuildPlugin<ContextMenuPluginType>()({
name: "context_menu",
showInDocs: false,
configSchema: ConfigSchema,
dependencies: () => [MutesPlugin, LogsPlugin, UtilityPlugin],
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -53,7 +54,4 @@ export const ContextMenuPlugin = zeppelinGuildPlugin<ContextMenuPluginType>()({
afterLoad(pluginData) {
loadAllCommands(pluginData);
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,4 +1,5 @@
import { EventEmitter } from "events";
import * as t from "io-ts";
import { PluginOptions } from "knub";
import {
buildCounterConditionString,
@ -9,7 +10,7 @@ import {
import { GuildCounters } from "../../data/GuildCounters";
import { mapToPublicFn } from "../../pluginUtils";
import { convertDelayStringToMS, MINUTES } from "../../utils";
import { StrictValidationError } from "../../validatorUtils";
import { StrictValidationError, validate } from "../../validatorUtils";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { AddCounterCmd } from "./commands/AddCounterCmd";
import { CountersListCmd } from "./commands/CountersListCmd";
@ -72,12 +73,13 @@ export const CountersPlugin = zeppelinGuildPlugin<CountersPluginType>()({
description:
"Keep track of per-user, per-channel, or global numbers and trigger specific actions based on this number",
configurationGuide: "See <a href='/docs/setup-guides/counters'>Counters setup guide</a>",
configSchema: ConfigSchema,
},
configSchema: ConfigSchema,
defaultOptions,
configParser: (options) => {
for (const [counterName, counter] of Object.entries(options.counters || {})) {
// TODO: Separate input and output types
configParser: (input) => {
for (const [counterName, counter] of Object.entries<any>((input as any).counters || {})) {
counter.name = counterName;
counter.per_user = counter.per_user ?? false;
counter.per_channel = counter.per_channel ?? false;
@ -90,7 +92,7 @@ export const CountersPlugin = zeppelinGuildPlugin<CountersPluginType>()({
// Normalize triggers
for (const [triggerName, trigger] of Object.entries(counter.triggers)) {
const triggerObj: Partial<TTrigger> = typeof trigger === "string" ? { condition: trigger } : trigger;
const triggerObj = (typeof trigger === "string" ? { condition: trigger } : trigger) as Partial<TTrigger>;
triggerObj.name = triggerName;
const parsedCondition = parseCounterConditionString(triggerObj.condition || "");
@ -109,12 +111,16 @@ export const CountersPlugin = zeppelinGuildPlugin<CountersPluginType>()({
}
}
if (Object.values(options.counters || {}).length > MAX_COUNTERS) {
if (Object.values((input as any).counters || {}).length > MAX_COUNTERS) {
throw new StrictValidationError([`You can only have at most ${MAX_COUNTERS} counters`]);
}
// FIXME: Any typing
return <any>options;
const error = validate(ConfigSchema, input);
if (error) {
throw error;
}
return input as t.TypeOf<typeof ConfigSchema>;
},
public: {

View file

@ -1,6 +1,6 @@
import { Snowflake, TextChannel } from "discord.js";
import { guildPluginMessageCommand } from "knub";
import { waitForReply } from "knub/dist/helpers";
import { waitForReply } from "knub/helpers";
import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage } from "../../../pluginUtils";
import { resolveUser, UnknownUser } from "../../../utils";

View file

@ -1,6 +1,6 @@
import { Snowflake, TextChannel } from "discord.js";
import { guildPluginMessageCommand } from "knub";
import { waitForReply } from "knub/dist/helpers";
import { waitForReply } from "knub/helpers";
import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage } from "../../../pluginUtils";
import { resolveUser, UnknownUser } from "../../../utils";

View file

@ -1,6 +1,6 @@
import { Snowflake, TextChannel } from "discord.js";
import { guildPluginMessageCommand } from "knub";
import { waitForReply } from "knub/dist/helpers";
import { waitForReply } from "knub/helpers";
import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage } from "../../../pluginUtils";
import { resolveUser, UnknownUser } from "../../../utils";

View file

@ -1,6 +1,6 @@
import { Snowflake } from "discord.js";
import { guildPluginMessageCommand } from "knub";
import { waitForReply } from "knub/dist/helpers";
import { waitForReply } from "knub/helpers";
import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage } from "../../../pluginUtils";
import { resolveUser, UnknownUser } from "../../../utils";

View file

@ -1,6 +1,7 @@
import { GuildChannel, GuildMember, User } from "discord.js";
import { guildPluginMessageCommand, parseSignature } from "knub";
import { commandTypes } from "../../commandTypes";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { createTypedTemplateSafeValueContainer, TemplateSafeValueContainer } from "../../templateFormatter";
import { UnknownUser } from "../../utils";
import { isScalar } from "../../utils/isScalar";
@ -24,7 +25,7 @@ export const CustomEventsPlugin = zeppelinGuildPlugin<CustomEventsPluginType>()(
name: "custom_events",
showInDocs: false,
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
afterLoad(pluginData) {
@ -67,7 +68,4 @@ export const CustomEventsPlugin = zeppelinGuildPlugin<CustomEventsPluginType>()(
beforeUnload() {
// TODO: Run clearTriggers() once we actually have something there
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -4,6 +4,7 @@ import { BasePluginType, GlobalPluginData, globalPluginEventListener } from "knu
import { AllowedGuilds } from "../../data/AllowedGuilds";
import { Configs } from "../../data/Configs";
import { env } from "../../env";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { zeppelinGlobalPlugin } from "../ZeppelinPluginBlueprint";
interface GuildAccessMonitorPluginType extends BasePluginType {
@ -26,7 +27,7 @@ async function checkGuild(pluginData: GlobalPluginData<GuildAccessMonitorPluginT
*/
export const GuildAccessMonitorPlugin = zeppelinGlobalPlugin<GuildAccessMonitorPluginType>()({
name: "guild_access_monitor",
configSchema: t.type({}),
configParser: makeIoTsConfigParser(t.type({})),
events: [
globalPluginEventListener<GuildAccessMonitorPluginType>()({
@ -59,7 +60,4 @@ export const GuildAccessMonitorPlugin = zeppelinGlobalPlugin<GuildAccessMonitorP
checkGuild(pluginData, guild);
}
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,5 +1,6 @@
import * as t from "io-ts";
import { Configs } from "../../data/Configs";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { zeppelinGlobalPlugin } from "../ZeppelinPluginBlueprint";
import { reloadChangedGuilds } from "./functions/reloadChangedGuilds";
import { GuildConfigReloaderPluginType } from "./types";
@ -8,7 +9,7 @@ export const GuildConfigReloaderPlugin = zeppelinGlobalPlugin<GuildConfigReloade
name: "guild_config_reloader",
showInDocs: false,
configSchema: t.type({}),
configParser: makeIoTsConfigParser(t.type({})),
async beforeLoad(pluginData) {
const { state } = pluginData;
@ -25,7 +26,4 @@ export const GuildConfigReloaderPlugin = zeppelinGlobalPlugin<GuildConfigReloade
clearTimeout(pluginData.state.nextCheckTimeout);
pluginData.state.unloaded = true;
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,10 +1,9 @@
import { BasePluginType } from "knub";
import { Configs } from "../../data/Configs";
import { TConfigSchema } from "../Mutes/types";
import Timeout = NodeJS.Timeout;
export interface GuildConfigReloaderPluginType extends BasePluginType {
config: TConfigSchema;
config: {};
state: {
guildConfigs: Configs;
unloaded: boolean;

View file

@ -3,6 +3,7 @@ import * as t from "io-ts";
import { guildPluginEventListener } from "knub";
import { AllowedGuilds } from "../../data/AllowedGuilds";
import { ApiPermissionAssignments } from "../../data/ApiPermissionAssignments";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { MINUTES } from "../../utils";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { GuildInfoSaverPluginType } from "./types";
@ -11,7 +12,7 @@ export const GuildInfoSaverPlugin = zeppelinGuildPlugin<GuildInfoSaverPluginType
name: "guild_info_saver",
showInDocs: false,
configSchema: t.type({}),
configParser: makeIoTsConfigParser(t.type({})),
events: [
guildPluginEventListener({
@ -30,9 +31,6 @@ export const GuildInfoSaverPlugin = zeppelinGuildPlugin<GuildInfoSaverPluginType
beforeUnload(pluginData) {
clearInterval(pluginData.state.updateInterval);
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});
async function updateGuildInfo(guild: Guild) {

View file

@ -1,6 +1,6 @@
import { PluginOptions } from "knub";
import { Webhooks } from "../../data/Webhooks";
import { mapToPublicFn } from "../../pluginUtils";
import { makeIoTsConfigParser, mapToPublicFn } from "../../pluginUtils";
import { Queue } from "../../Queue";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { editMessage } from "./functions/editMessage";
@ -16,7 +16,7 @@ export const InternalPosterPlugin = zeppelinGuildPlugin<InternalPosterPluginType
name: "internal_poster",
showInDocs: false,
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -33,7 +33,4 @@ export const InternalPosterPlugin = zeppelinGuildPlugin<InternalPosterPluginType
state.missingPermissions = false;
state.webhookClientCache = new Map();
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,6 +1,7 @@
import { PluginOptions } from "knub";
import { onGuildEvent } from "../../data/GuildEvents";
import { GuildVCAlerts } from "../../data/GuildVCAlerts";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { trimPluginDescription } from "../../utils";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { FollowCmd } from "./commands/FollowCmd";
@ -38,9 +39,10 @@ export const LocateUserPlugin = zeppelinGuildPlugin<LocateUserPluginType>()({
* Instantly receive an invite to the voice channel of a user
* Be notified as soon as a user switches or joins a voice channel
`),
configSchema: ConfigSchema,
},
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -78,7 +80,4 @@ export const LocateUserPlugin = zeppelinGuildPlugin<LocateUserPluginType>()({
state.unregisterGuildEventListener?.();
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,6 +1,6 @@
import { GuildMember, GuildTextBasedChannel, Invite, VoiceChannel } from "discord.js";
import { GuildPluginData } from "knub";
import { getInviteLink } from "knub/dist/helpers";
import { getInviteLink } from "knub/helpers";
import { sendErrorMessage } from "../../../pluginUtils";
import { LocateUserPluginType } from "../types";
import { createOrReuseInvite } from "./createOrReuseInvite";

View file

@ -6,7 +6,7 @@ import { GuildLogs } from "../../data/GuildLogs";
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
import { LogType } from "../../data/LogType";
import { logger } from "../../logger";
import { mapToPublicFn } from "../../pluginUtils";
import { makeIoTsConfigParser, mapToPublicFn } from "../../pluginUtils";
import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners";
import { createTypedTemplateSafeValueContainer, TypedTemplateSafeValueContainer } from "../../templateFormatter";
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
@ -110,6 +110,11 @@ import { logVoiceChannelJoin } from "./logFunctions/logVoiceChannelJoin";
import { logVoiceChannelLeave } from "./logFunctions/logVoiceChannelLeave";
import { logVoiceChannelMove } from "./logFunctions/logVoiceChannelMove";
// The `any` cast here is to prevent TypeScript from locking up from the circular dependency
function getCasesPlugin(): Promise<any> {
return import("../Cases/CasesPlugin.js") as Promise<any>;
}
const defaultOptions: PluginOptions<LogsPluginType> = {
config: {
channels: {},
@ -138,15 +143,11 @@ export const LogsPlugin = zeppelinGuildPlugin<LogsPluginType>()({
showInDocs: true,
info: {
prettyName: "Logs",
configSchema: ConfigSchema,
},
dependencies: async () => [
TimeAndDatePlugin,
InternalPosterPlugin,
// The `as any` cast here is to prevent TypeScript from locking up from the circular dependency
((await import("../Cases/CasesPlugin")) as any).CasesPlugin,
],
configSchema: ConfigSchema,
dependencies: async () => [TimeAndDatePlugin, InternalPosterPlugin, (await getCasesPlugin()).CasesPlugin],
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
events: [
@ -326,7 +327,4 @@ export const LogsPlugin = zeppelinGuildPlugin<LogsPluginType>()({
}
discardRegExpRunner(`guild-${guild.id}`);
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,6 +1,6 @@
import { GuildTextBasedChannel, User } from "discord.js";
import { GuildPluginData } from "knub";
import { deactivateMentions, disableCodeBlocks } from "knub/dist/helpers";
import { deactivateMentions, disableCodeBlocks } from "knub/helpers";
import { resolveChannelIds } from "src/utils/resolveChannelIds";
import { SavedMessage } from "../../../data/entities/SavedMessage";
import { LogType } from "../../../data/LogType";

View file

@ -1,5 +1,6 @@
import { PluginOptions } from "knub";
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { SaveMessagesToDBCmd } from "./commands/SaveMessagesToDB";
import { SavePinsToDBCmd } from "./commands/SavePinsToDB";
@ -24,7 +25,7 @@ export const MessageSaverPlugin = zeppelinGuildPlugin<MessageSaverPluginType>()(
name: "message_saver",
showInDocs: false,
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -45,7 +46,4 @@ export const MessageSaverPlugin = zeppelinGuildPlugin<MessageSaverPluginType>()(
const { state, guild } = pluginData;
state.savedMessages = GuildSavedMessages.getGuildInstance(guild.id);
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -5,7 +5,7 @@ import { onGuildEvent } from "../../data/GuildEvents";
import { GuildLogs } from "../../data/GuildLogs";
import { GuildMutes } from "../../data/GuildMutes";
import { GuildTempbans } from "../../data/GuildTempbans";
import { mapToPublicFn } from "../../pluginUtils";
import { makeIoTsConfigParser, mapToPublicFn } from "../../pluginUtils";
import { Queue } from "../../Queue";
import { MINUTES, trimPluginDescription } from "../../utils";
import { CasesPlugin } from "../Cases/CasesPlugin";
@ -120,10 +120,11 @@ export const ModActionsPlugin = zeppelinGuildPlugin<ModActionsPluginType>()({
description: trimPluginDescription(`
This plugin contains the 'typical' mod actions such as warning, muting, kicking, banning, etc.
`),
configSchema: ConfigSchema,
},
dependencies: () => [TimeAndDatePlugin, CasesPlugin, MutesPlugin, LogsPlugin],
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
events: [CreateBanCaseOnManualBanEvt, CreateUnbanCaseOnManualUnbanEvt, PostAlertOnMemberJoinEvt],
@ -223,7 +224,4 @@ export const ModActionsPlugin = zeppelinGuildPlugin<ModActionsPluginType>()({
state.unregisterGuildEventListener?.();
state.events.removeAllListeners();
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,5 +1,5 @@
import humanizeDuration from "humanize-duration";
import { getMemberLevel } from "knub/dist/helpers";
import { getMemberLevel } from "knub/helpers";
import { commandTypeHelpers as ct } from "../../../commandTypes";
import { CaseTypes } from "../../../data/CaseTypes";
import { clearExpiringTempban, registerExpiringTempban } from "../../../data/loops/expiringTempbansLoop";

View file

@ -1,5 +1,5 @@
import { Snowflake } from "discord.js";
import { waitForReply } from "knub/dist/helpers";
import { waitForReply } from "knub/helpers";
import { performance } from "perf_hooks";
import { commandTypeHelpers as ct } from "../../../commandTypes";
import { CaseTypes } from "../../../data/CaseTypes";

View file

@ -1,5 +1,5 @@
import { Snowflake } from "discord.js";
import { waitForReply } from "knub/dist/helpers";
import { waitForReply } from "knub/helpers";
import { commandTypeHelpers as ct } from "../../../commandTypes";
import { CaseTypes } from "../../../data/CaseTypes";
import { LogType } from "../../../data/LogType";

View file

@ -1,5 +1,5 @@
import { Snowflake } from "discord.js";
import { waitForReply } from "knub/dist/helpers";
import { waitForReply } from "knub/helpers";
import { commandTypeHelpers as ct } from "../../../commandTypes";
import { LogType } from "../../../data/LogType";
import { logger } from "../../../logger";

View file

@ -1,6 +1,6 @@
import { GuildMember, GuildTextBasedChannel } from "discord.js";
import { GuildPluginData } from "knub";
import { hasPermission } from "knub/dist/helpers";
import { hasPermission } from "knub/helpers";
import { LogType } from "../../../data/LogType";
import { canActOn, sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
import { DAYS, errorMessage, resolveMember, resolveUser, SECONDS } from "../../../utils";

View file

@ -5,7 +5,7 @@ import { GuildCases } from "../../data/GuildCases";
import { onGuildEvent } from "../../data/GuildEvents";
import { GuildLogs } from "../../data/GuildLogs";
import { GuildMutes } from "../../data/GuildMutes";
import { mapToPublicFn } from "../../pluginUtils";
import { makeIoTsConfigParser, mapToPublicFn } from "../../pluginUtils";
import { CasesPlugin } from "../Cases/CasesPlugin";
import { LogsPlugin } from "../Logs/LogsPlugin";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
@ -65,10 +65,11 @@ export const MutesPlugin = zeppelinGuildPlugin<MutesPluginType>()({
showInDocs: true,
info: {
prettyName: "Mutes",
configSchema: ConfigSchema,
},
configSchema: ConfigSchema,
dependencies: () => [CasesPlugin, LogsPlugin],
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -126,7 +127,4 @@ export const MutesPlugin = zeppelinGuildPlugin<MutesPluginType>()({
state.unregisterGuildEventListener?.();
state.events.removeAllListeners();
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,6 +1,7 @@
import { PluginOptions } from "knub";
import { GuildNicknameHistory } from "../../data/GuildNicknameHistory";
import { UsernameHistory } from "../../data/UsernameHistory";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { Queue } from "../../Queue";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { NamesCmd } from "./commands/NamesCmd";
@ -24,7 +25,7 @@ export const NameHistoryPlugin = zeppelinGuildPlugin<NameHistoryPluginType>()({
name: "name_history",
showInDocs: false,
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -46,7 +47,4 @@ export const NameHistoryPlugin = zeppelinGuildPlugin<NameHistoryPluginType>()({
state.usernameHistory = new UsernameHistory();
state.updateQueue = new Queue();
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,5 +1,5 @@
import { Snowflake } from "discord.js";
import { createChunkedMessage, disableCodeBlocks } from "knub/dist/helpers";
import { createChunkedMessage, disableCodeBlocks } from "knub/helpers";
import { commandTypeHelpers as ct } from "../../../commandTypes";
import { NICKNAME_RETENTION_PERIOD } from "../../../data/cleanup/nicknames";
import { MAX_NICKNAME_ENTRIES_PER_USER } from "../../../data/GuildNicknameHistory";

View file

@ -1,6 +1,7 @@
import { PluginOptions } from "knub";
import { GuildLogs } from "../../data/GuildLogs";
import { GuildPersistedData } from "../../data/GuildPersistedData";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { trimPluginDescription } from "../../utils";
import { LogsPlugin } from "../Logs/LogsPlugin";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
@ -25,10 +26,11 @@ export const PersistPlugin = zeppelinGuildPlugin<PersistPluginType>()({
Re-apply roles or nicknames for users when they rejoin the server.
Mute roles are re-applied automatically, this plugin is not required for that.
`),
configSchema: ConfigSchema,
},
dependencies: () => [LogsPlugin],
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -43,7 +45,4 @@ export const PersistPlugin = zeppelinGuildPlugin<PersistPluginType>()({
state.persistedData = GuildPersistedData.getGuildInstance(guild.id);
state.logs = new GuildLogs(guild.id);
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,6 +1,6 @@
import { PluginOptions } from "knub";
import { hasPhishermanMasterAPIKey, phishermanApiKeyIsValid } from "../../data/Phisherman";
import { mapToPublicFn } from "../../pluginUtils";
import { makeIoTsConfigParser, mapToPublicFn } from "../../pluginUtils";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { getDomainInfo } from "./functions/getDomainInfo";
import { pluginInfo } from "./info";
@ -18,7 +18,7 @@ export const PhishermanPlugin = zeppelinGuildPlugin<PhishermanPluginType>()({
showInDocs: true,
info: pluginInfo,
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -49,7 +49,4 @@ export const PhishermanPlugin = zeppelinGuildPlugin<PhishermanPluginType>()({
}
}
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,5 +1,6 @@
import { trimPluginDescription } from "../../utils";
import { ZeppelinGuildPluginBlueprint } from "../ZeppelinPluginBlueprint";
import { ConfigSchema } from "./types";
export const pluginInfo: ZeppelinGuildPluginBlueprint["info"] = {
prettyName: "Phisherman",
@ -38,4 +39,5 @@ export const pluginInfo: ZeppelinGuildPluginBlueprint["info"] = {
clean: true
~~~
`),
configSchema: ConfigSchema,
};

View file

@ -1,5 +1,6 @@
import { PluginOptions } from "knub";
import { GuildPingableRoles } from "../../data/GuildPingableRoles";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { PingableRoleDisableCmd } from "./commands/PingableRoleDisableCmd";
import { PingableRoleEnableCmd } from "./commands/PingableRoleEnableCmd";
@ -24,9 +25,10 @@ export const PingableRolesPlugin = zeppelinGuildPlugin<PingableRolesPluginType>(
showInDocs: true,
info: {
prettyName: "Pingable roles",
configSchema: ConfigSchema,
},
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -49,7 +51,4 @@ export const PingableRolesPlugin = zeppelinGuildPlugin<PingableRolesPluginType>(
state.cache = new Map();
state.timeouts = new Map();
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -3,6 +3,7 @@ import { onGuildEvent } from "../../data/GuildEvents";
import { GuildLogs } from "../../data/GuildLogs";
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
import { GuildScheduledPosts } from "../../data/GuildScheduledPosts";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { LogsPlugin } from "../Logs/LogsPlugin";
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
@ -35,10 +36,11 @@ export const PostPlugin = zeppelinGuildPlugin<PostPluginType>()({
showInDocs: true,
info: {
prettyName: "Post",
configSchema: ConfigSchema,
},
dependencies: () => [TimeAndDatePlugin, LogsPlugin],
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -73,7 +75,4 @@ export const PostPlugin = zeppelinGuildPlugin<PostPluginType>()({
state.unregisterGuildEventListener?.();
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,6 +1,7 @@
import { PluginOptions } from "knub";
import { GuildReactionRoles } from "../../data/GuildReactionRoles";
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { Queue } from "../../Queue";
import { LogsPlugin } from "../Logs/LogsPlugin";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
@ -39,10 +40,11 @@ export const ReactionRolesPlugin = zeppelinGuildPlugin<ReactionRolesPluginType>(
info: {
prettyName: "Reaction roles",
legacy: "Consider using the [Role buttons](/docs/plugins/role_buttons) plugin instead.",
configSchema: ConfigSchema,
},
dependencies: () => [LogsPlugin],
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -85,7 +87,4 @@ export const ReactionRolesPlugin = zeppelinGuildPlugin<ReactionRolesPluginType>(
clearTimeout(state.autoRefreshTimeout);
}
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,6 +1,7 @@
import { PluginOptions } from "knub";
import { onGuildEvent } from "../../data/GuildEvents";
import { GuildReminders } from "../../data/GuildReminders";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { RemindCmd } from "./commands/RemindCmd";
@ -28,10 +29,11 @@ export const RemindersPlugin = zeppelinGuildPlugin<RemindersPluginType>()({
showInDocs: true,
info: {
prettyName: "Reminders",
configSchema: ConfigSchema,
},
dependencies: () => [TimeAndDatePlugin],
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -63,7 +65,4 @@ export const RemindersPlugin = zeppelinGuildPlugin<RemindersPluginType>()({
state.unregisterGuildEventListener?.();
state.unloaded = true;
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,6 +1,6 @@
import { HTTPError, Snowflake } from "discord.js";
import { GuildPluginData } from "knub";
import { disableLinkPreviews } from "knub/dist/helpers";
import { disableLinkPreviews } from "knub/helpers";
import moment from "moment-timezone";
import { Reminder } from "../../../data/entities/Reminder";
import { DBDateFormat } from "../../../utils";

View file

@ -1,5 +1,6 @@
import * as t from "io-ts";
import { GuildRoleButtons } from "../../data/GuildRoleButtons";
import { StrictValidationError } from "../../validatorUtils";
import { StrictValidationError, validate } from "../../validatorUtils";
import { LogsPlugin } from "../Logs/LogsPlugin";
import { RoleManagerPlugin } from "../RoleManager/RoleManagerPlugin";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
@ -13,7 +14,6 @@ import { ConfigSchema, RoleButtonsPluginType } from "./types";
export const RoleButtonsPlugin = zeppelinGuildPlugin<RoleButtonsPluginType>()({
name: "role_buttons",
configSchema: ConfigSchema,
info: pluginInfo,
showInDocs: true,
@ -32,11 +32,10 @@ export const RoleButtonsPlugin = zeppelinGuildPlugin<RoleButtonsPluginType>()({
],
},
configParser(options) {
configParser(input) {
// Auto-fill "name" property for buttons based on the object key
const buttonsArray = Array.isArray(options.buttons) ? options.buttons : [];
const seenMessages = new Set();
for (const [name, buttonsConfig] of Object.entries(options.buttons ?? {})) {
for (const [name, buttonsConfig] of Object.entries<any>((input as any).buttons ?? {})) {
if (name.length > 16) {
throw new StrictValidationError(["Name for role buttons can be at most 16 characters long"]);
}
@ -66,8 +65,12 @@ export const RoleButtonsPlugin = zeppelinGuildPlugin<RoleButtonsPluginType>()({
}
}
// FIXME: any typing lol
return <any>options;
const error = validate(ConfigSchema, input);
if (error) {
throw error;
}
return input as t.TypeOf<typeof ConfigSchema>;
},
dependencies: () => [LogsPlugin, RoleManagerPlugin],

View file

@ -1,5 +1,6 @@
import { trimPluginDescription } from "../../utils";
import { ZeppelinGuildPluginBlueprint } from "../ZeppelinPluginBlueprint";
import { ConfigSchema } from "./types";
export const pluginInfo: ZeppelinGuildPluginBlueprint["info"] = {
prettyName: "Role buttons",
@ -77,4 +78,5 @@ export const pluginInfo: ZeppelinGuildPluginBlueprint["info"] = {
... # See above for examples for options
~~~
`),
configSchema: ConfigSchema,
};

View file

@ -1,5 +1,5 @@
import { GuildRoleQueue } from "../../data/GuildRoleQueue";
import { mapToPublicFn } from "../../pluginUtils";
import { makeIoTsConfigParser, mapToPublicFn } from "../../pluginUtils";
import { LogsPlugin } from "../Logs/LogsPlugin";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { addPriorityRole } from "./functions/addPriorityRole";
@ -11,10 +11,10 @@ import { ConfigSchema, RoleManagerPluginType } from "./types";
export const RoleManagerPlugin = zeppelinGuildPlugin<RoleManagerPluginType>()({
name: "role_manager",
configSchema: ConfigSchema,
showInDocs: false,
dependencies: () => [LogsPlugin],
configParser: makeIoTsConfigParser(ConfigSchema),
public: {
addRole: mapToPublicFn(addRole),
@ -40,7 +40,4 @@ export const RoleManagerPlugin = zeppelinGuildPlugin<RoleManagerPluginType>()({
state.abortRoleAssignmentLoop = true;
await state.pendingRoleAssignmentPromise;
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,5 +1,6 @@
import { PluginOptions } from "knub";
import { GuildLogs } from "../../data/GuildLogs";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { trimPluginDescription } from "../../utils";
import { LogsPlugin } from "../Logs/LogsPlugin";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
@ -39,10 +40,11 @@ export const RolesPlugin = zeppelinGuildPlugin<RolesPluginType>()({
description: trimPluginDescription(`
Enables authorised users to add and remove whitelisted roles with a command.
`),
configSchema: ConfigSchema,
},
configSchema: ConfigSchema,
dependencies: () => [LogsPlugin],
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -58,7 +60,4 @@ export const RolesPlugin = zeppelinGuildPlugin<RolesPluginType>()({
state.logs = new GuildLogs(guild.id);
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,5 +1,7 @@
import * as t from "io-ts";
import { CooldownManager, PluginOptions } from "knub";
import { trimPluginDescription } from "../../utils";
import { validate } from "../../validatorUtils";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { RoleAddCmd } from "./commands/RoleAddCmd";
import { RoleHelpCmd } from "./commands/RoleHelpCmd";
@ -17,9 +19,6 @@ export const SelfGrantableRolesPlugin = zeppelinGuildPlugin<SelfGrantableRolesPl
name: "self_grantable_roles",
showInDocs: true,
configSchema: ConfigSchema,
defaultOptions,
info: {
prettyName: "Self-grantable roles",
description: trimPluginDescription(`
@ -68,24 +67,31 @@ export const SelfGrantableRolesPlugin = zeppelinGuildPlugin<SelfGrantableRolesPl
can_use: true
~~~
`),
configSchema: ConfigSchema,
},
configParser: (options) => {
const config = options;
for (const [key, entry] of Object.entries(config.entries)) {
configParser: (input) => {
const entries = (input as any).entries;
for (const [key, entry] of Object.entries<any>(entries)) {
// Apply default entry config
config.entries[key] = { ...defaultSelfGrantableRoleEntry, ...entry };
entries[key] = { ...defaultSelfGrantableRoleEntry, ...entry };
// Normalize alias names
if (entry.roles) {
for (const [roleId, aliases] of Object.entries(entry.roles)) {
for (const [roleId, aliases] of Object.entries<string[]>(entry.roles)) {
entry.roles[roleId] = aliases.map((a) => a.toLowerCase());
}
}
}
return { ...options, config };
const error = validate(ConfigSchema, input);
if (error) {
throw error;
}
return input as t.TypeOf<typeof ConfigSchema>;
},
defaultOptions,
// prettier-ignore
messageCommands: [

View file

@ -2,6 +2,7 @@ import { PluginOptions } from "knub";
import { GuildLogs } from "../../data/GuildLogs";
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
import { GuildSlowmodes } from "../../data/GuildSlowmodes";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { SECONDS } from "../../utils";
import { LogsPlugin } from "../Logs/LogsPlugin";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
@ -40,6 +41,7 @@ export const SlowmodePlugin = zeppelinGuildPlugin<SlowmodePluginType>()({
showInDocs: true,
info: {
prettyName: "Slowmode",
configSchema: ConfigSchema,
},
// prettier-ignore
@ -47,7 +49,7 @@ export const SlowmodePlugin = zeppelinGuildPlugin<SlowmodePluginType>()({
LogsPlugin,
],
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -84,7 +86,4 @@ export const SlowmodePlugin = zeppelinGuildPlugin<SlowmodePluginType>()({
state.savedMessages.events.off("create", state.onMessageCreateFn);
clearInterval(state.clearInterval);
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,6 +1,6 @@
import { GuildChannel, TextChannel } from "discord.js";
import humanizeDuration from "humanize-duration";
import { createChunkedMessage } from "knub/dist/helpers";
import { createChunkedMessage } from "knub/helpers";
import { errorMessage } from "../../../utils";
import { slowmodeCmd } from "../types";

View file

@ -3,6 +3,7 @@ import { GuildArchives } from "../../data/GuildArchives";
import { GuildLogs } from "../../data/GuildLogs";
import { GuildMutes } from "../../data/GuildMutes";
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { trimPluginDescription } from "../../utils";
import { LogsPlugin } from "../Logs/LogsPlugin";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
@ -52,11 +53,11 @@ export const SpamPlugin = zeppelinGuildPlugin<SpamPluginType>()({
For more advanced spam filtering, check out the Automod plugin!
`),
legacy: true,
configSchema: ConfigSchema,
},
dependencies: () => [LogsPlugin],
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -92,7 +93,4 @@ export const SpamPlugin = zeppelinGuildPlugin<SpamPluginType>()({
state.savedMessages.events.off("create", state.onMessageCreateFn);
clearInterval(state.expiryInterval);
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,8 +1,10 @@
import * as t from "io-ts";
import { PluginOptions } from "knub";
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
import { GuildStarboardMessages } from "../../data/GuildStarboardMessages";
import { GuildStarboardReactions } from "../../data/GuildStarboardReactions";
import { trimPluginDescription } from "../../utils";
import { validate } from "../../validatorUtils";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { MigratePinsCmd } from "./commands/MigratePinsCmd";
import { StarboardReactionAddEvt } from "./events/StarboardReactionAddEvt";
@ -30,9 +32,6 @@ export const StarboardPlugin = zeppelinGuildPlugin<StarboardPluginType>()({
name: "starboard",
showInDocs: true,
configSchema: ConfigSchema,
defaultOptions,
info: {
prettyName: "Starboard",
description: trimPluginDescription(`
@ -122,18 +121,25 @@ export const StarboardPlugin = zeppelinGuildPlugin<StarboardPluginType>()({
enabled: true
~~~
`),
configSchema: ConfigSchema,
},
configParser(options) {
if (options.boards) {
for (const [name, opts] of Object.entries(options.boards)) {
options.boards[name] = Object.assign({}, defaultStarboardOpts, options.boards[name]);
configParser(input) {
const boards = (input as any).boards;
if (boards) {
for (const [name, opts] of Object.entries(boards)) {
boards[name] = Object.assign({}, defaultStarboardOpts, boards[name]);
}
}
// FIXME: any typing lol
return <any>options;
const error = validate(ConfigSchema, input);
if (error) {
throw error;
}
return input as t.TypeOf<typeof ConfigSchema>;
},
defaultOptions,
// prettier-ignore
messageCommands: [

View file

@ -1,8 +1,9 @@
import { Snowflake } from "discord.js";
import humanizeDuration from "humanize-duration";
import * as t from "io-ts";
import { PluginOptions } from "knub";
import moment from "moment-timezone";
import { StrictValidationError } from "src/validatorUtils";
import { StrictValidationError, validate } from "src/validatorUtils";
import { GuildArchives } from "../../data/GuildArchives";
import { GuildLogs } from "../../data/GuildLogs";
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
@ -71,9 +72,9 @@ export const TagsPlugin = zeppelinGuildPlugin<TagsPluginType>()({
${generateTemplateMarkdown(TemplateFunctions)}
`),
configSchema: ConfigSchema,
},
configSchema: ConfigSchema,
dependencies: () => [LogsPlugin],
defaultOptions,
@ -96,17 +97,19 @@ export const TagsPlugin = zeppelinGuildPlugin<TagsPluginType>()({
findTagByName: mapToPublicFn(findTagByName),
},
configParser(options) {
if (options.delete_with_command && options.auto_delete_command) {
configParser(_input) {
const input = _input as any;
if (input.delete_with_command && input.auto_delete_command) {
throw new StrictValidationError([
`Cannot have both (global) delete_with_command and global_delete_invoke enabled`,
]);
}
// Check each category for conflicting options
if (options.categories) {
for (const [name, opts] of Object.entries(options.categories)) {
const cat = options.categories[name];
if (input.categories) {
for (const [name, opts] of Object.entries(input.categories)) {
const cat = input.categories[name];
if (cat.delete_with_command && cat.auto_delete_command) {
throw new StrictValidationError([
`Cannot have both (category specific) delete_with_command and category_delete_invoke enabled at <categories/${name}>`,
@ -115,8 +118,12 @@ export const TagsPlugin = zeppelinGuildPlugin<TagsPluginType>()({
}
}
// FIXME: any typing lol
return <any>options;
const error = validate(ConfigSchema, input);
if (error) {
throw error;
}
return input as t.TypeOf<typeof ConfigSchema>;
},
beforeLoad(pluginData) {

View file

@ -1,6 +1,5 @@
import * as t from "io-ts";
import { GuildPluginData } from "knub";
import { ExtendedMatchParams } from "knub/dist/config/PluginConfigManager";
import { ExtendedMatchParams, GuildPluginData } from "knub";
import { Tag, TagsPluginType } from "../types";
export async function findTagByName(

View file

@ -1,7 +1,6 @@
import { GuildMember } from "discord.js";
import escapeStringRegexp from "escape-string-regexp";
import { GuildPluginData } from "knub";
import { ExtendedMatchParams } from "knub/dist/config/PluginConfigManager";
import { ExtendedMatchParams, GuildPluginData } from "knub";
import { StrictMessageContent } from "../../../utils";
import { TagsPluginType, TTagCategory } from "../types";
import { renderTagFromString } from "./renderTagFromString";

View file

@ -1,5 +1,4 @@
import { GuildPluginData } from "knub";
import { ExtendedMatchParams } from "knub/dist/config/PluginConfigManager";
import { ExtendedMatchParams, GuildPluginData } from "knub";
import { renderTemplate, TemplateSafeValue, TemplateSafeValueContainer } from "../../../templateFormatter";
import { renderRecursively, StrictMessageContent } from "../../../utils";
import { TagsPluginType, TTag } from "../types";

View file

@ -1,6 +1,6 @@
import { PluginOptions } from "knub";
import { GuildMemberTimezones } from "../../data/GuildMemberTimezones";
import { mapToPublicFn } from "../../pluginUtils";
import { makeIoTsConfigParser, mapToPublicFn } from "../../pluginUtils";
import { trimPluginDescription } from "../../utils";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { ResetTimezoneCmd } from "./commands/ResetTimezoneCmd";
@ -39,9 +39,10 @@ export const TimeAndDatePlugin = zeppelinGuildPlugin<TimeAndDatePluginType>()({
description: trimPluginDescription(`
Allows controlling the displayed time/date formats and timezones
`),
configSchema: ConfigSchema,
},
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -64,7 +65,4 @@ export const TimeAndDatePlugin = zeppelinGuildPlugin<TimeAndDatePluginType>()({
state.memberTimezones = GuildMemberTimezones.getGuildInstance(guild.id);
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,5 +1,6 @@
import * as t from "io-ts";
import { UsernameHistory } from "../../data/UsernameHistory";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { Queue } from "../../Queue";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { MessageCreateUpdateUsernameEvt, VoiceChannelJoinUpdateUsernameEvt } from "./events/UpdateUsernameEvts";
@ -9,7 +10,7 @@ export const UsernameSaverPlugin = zeppelinGuildPlugin<UsernameSaverPluginType>(
name: "username_saver",
showInDocs: false,
configSchema: t.type({}),
configParser: makeIoTsConfigParser(t.type({})),
// prettier-ignore
events: [
@ -23,7 +24,4 @@ export const UsernameSaverPlugin = zeppelinGuildPlugin<UsernameSaverPluginType>(
state.usernameHistory = new UsernameHistory();
state.updateQueue = new Queue();
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -5,7 +5,7 @@ import { GuildCases } from "../../data/GuildCases";
import { GuildLogs } from "../../data/GuildLogs";
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
import { Supporters } from "../../data/Supporters";
import { sendSuccessMessage } from "../../pluginUtils";
import { makeIoTsConfigParser, sendSuccessMessage } from "../../pluginUtils";
import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners";
import { LogsPlugin } from "../Logs/LogsPlugin";
import { ModActionsPlugin } from "../ModActions/ModActionsPlugin";
@ -117,10 +117,11 @@ export const UtilityPlugin = zeppelinGuildPlugin<UtilityPluginType>()({
showInDocs: true,
info: {
prettyName: "Utility",
configSchema: ConfigSchema,
},
dependencies: () => [TimeAndDatePlugin, ModActionsPlugin, LogsPlugin],
configSchema: ConfigSchema,
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -221,7 +222,4 @@ export const UtilityPlugin = zeppelinGuildPlugin<UtilityPluginType>()({
beforeUnload(pluginData) {
discardRegExpRunner(`guild-${pluginData.guild.id}`);
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -1,5 +1,4 @@
import { LoadedGuildPlugin } from "knub";
import { PluginCommandDefinition } from "knub/dist/commands/commandUtils";
import { LoadedGuildPlugin, PluginCommandDefinition } from "knub";
import { commandTypeHelpers as ct } from "../../../commandTypes";
import { createChunkedMessage } from "../../../utils";
import { utilityCmd } from "../types";
@ -32,7 +31,6 @@ export const HelpCmd = utilityCmd({
if (strTrigger.startsWith(searchStr)) {
matchingCommands.push({
plugin,
// @ts-expect-error
command: registeredCommand,
});
break;

View file

@ -1,5 +1,5 @@
import { Snowflake } from "discord.js";
import { getChannelId, getRoleId } from "knub/dist/utils";
import { getChannelId, getRoleId } from "knub/helpers";
import { commandTypeHelpers as ct } from "../../../commandTypes";
import { sendErrorMessage } from "../../../pluginUtils";
import { isValidSnowflake, noop, parseInviteCodeInput, resolveInvite, resolveUser } from "../../../utils";

View file

@ -1,7 +1,6 @@
import { APIEmbed, MessageType, Snowflake, TextChannel } from "discord.js";
import humanizeDuration from "humanize-duration";
import { GuildPluginData } from "knub";
import { getDefaultPrefix } from "knub/dist/commands/commandUtils";
import { getDefaultMessageCommandPrefix, GuildPluginData } from "knub";
import moment from "moment-timezone";
import { chunkMessageLines, EmbedWith, messageLink, preEmbedPadding, trimEmptyLines, trimLines } from "../../../utils";
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
@ -136,8 +135,7 @@ export async function getMessageInfoEmbed(
}
if (message.embeds.length) {
// @ts-expect-error
const prefix = pluginData.fullConfig.prefix || getDefaultPrefix(pluginData.client);
const prefix = pluginData.fullConfig.prefix || getDefaultMessageCommandPrefix(pluginData.client);
embed.fields.push({
name: preEmbedPadding + "Embeds",
value: `Message contains an embed, use \`${prefix}source\` to see the embed source`,

View file

@ -10,8 +10,7 @@ import {
User,
} from "discord.js";
import escapeStringRegexp from "escape-string-regexp";
import { GuildPluginData } from "knub";
import { ArgsFromSignatureOrArray } from "knub/dist/commands/commandUtils";
import { ArgsFromSignatureOrArray, GuildPluginData } from "knub";
import moment from "moment-timezone";
import { getBaseUrl, sendErrorMessage } from "../../pluginUtils";
import { allowTimeout, RegExpRunner } from "../../RegExpRunner";
@ -192,6 +191,7 @@ export async function displaySearch(
if (msg.author.id !== interaction.user.id) {
interaction
.reply({ content: `You are not permitted to use these buttons.`, ephemeral: true })
// tslint:disable-next-line no-console
.catch((err) => console.trace(err.message));
} else {
if (interaction.customId === `previousButton:${idMod}` && currentPage > 1) {

View file

@ -1,5 +1,6 @@
import { PluginOptions } from "knub";
import { GuildLogs } from "../../data/GuildLogs";
import { makeIoTsConfigParser } from "../../pluginUtils";
import { LogsPlugin } from "../Logs/LogsPlugin";
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
import { SendWelcomeMessageEvt } from "./events/SendWelcomeMessageEvt";
@ -18,10 +19,11 @@ export const WelcomeMessagePlugin = zeppelinGuildPlugin<WelcomeMessagePluginType
showInDocs: true,
info: {
prettyName: "Welcome message",
configSchema: ConfigSchema,
},
configSchema: ConfigSchema,
dependencies: () => [LogsPlugin],
configParser: makeIoTsConfigParser(ConfigSchema),
defaultOptions,
// prettier-ignore
@ -35,7 +37,4 @@ export const WelcomeMessagePlugin = zeppelinGuildPlugin<WelcomeMessagePluginType
state.logs = new GuildLogs(guild.id);
state.sentWelcomeMessages = new Set();
},
// FIXME: Proper inherittance from ZeppelinPluginBlueprint
configParser: (o: any) => o,
});

View file

@ -8,9 +8,6 @@ import {
GuildPluginBlueprint,
GuildPluginData,
} from "knub";
import { PluginOptions } from "knub/dist/config/configTypes";
import { Awaitable } from "knub/dist/utils";
import { getPluginConfigParser } from "../pluginUtils";
import { TMarkdown } from "../types";
/**
@ -19,42 +16,30 @@ import { TMarkdown } from "../types";
export interface ZeppelinGuildPluginBlueprint<TPluginData extends GuildPluginData<any> = GuildPluginData<any>>
extends GuildPluginBlueprint<TPluginData> {
configSchema: t.TypeC<any>;
showInDocs?: boolean;
info?: {
prettyName: string;
description?: TMarkdown;
usageGuide?: TMarkdown;
configurationGuide?: TMarkdown;
legacy?: boolean | string;
configSchema?: t.Type<any>;
};
// FIXME: need proper typings here
configParser: (
options: TPluginData["_pluginType"]["config"],
strict?: boolean,
) => Awaitable<PluginOptions<TPluginData["_pluginType"]>>;
}
export function zeppelinGuildPlugin<TBlueprint extends ZeppelinGuildPluginBlueprint>(
blueprint: TBlueprint,
): TBlueprint & { configParser: ZeppelinGuildPluginBlueprint["configParser"] };
export function zeppelinGuildPlugin<TBlueprint extends ZeppelinGuildPluginBlueprint>(blueprint: TBlueprint): TBlueprint;
export function zeppelinGuildPlugin<TPluginType extends BasePluginType>(): <
TBlueprint extends ZeppelinGuildPluginBlueprint<GuildPluginData<TPluginType>>,
>(
blueprint: TBlueprint,
) => TBlueprint & {
configParser: ZeppelinGuildPluginBlueprint<GuildPluginData<TPluginType>>["configParser"];
};
) => TBlueprint;
export function zeppelinGuildPlugin(...args) {
if (args.length) {
const blueprint = guildPlugin(
...(args as Parameters<typeof guildPlugin>),
) as unknown as ZeppelinGuildPluginBlueprint;
blueprint.configParser = <any>getPluginConfigParser(blueprint, blueprint.configParser);
return blueprint;
} else {
return zeppelinGuildPlugin as (name, blueprint) => ZeppelinGuildPluginBlueprint;
@ -66,31 +51,23 @@ export function zeppelinGuildPlugin(...args) {
*/
export interface ZeppelinGlobalPluginBlueprint<TPluginType extends BasePluginType = BasePluginType>
extends GlobalPluginBlueprint<GlobalPluginData<TPluginType>> {
configSchema: t.TypeC<any>;
// FIXME: need proper typings here
configParser: (options: TPluginType["config"], strict?: boolean) => Awaitable<PluginOptions<TPluginType>>;
}
extends GlobalPluginBlueprint<GlobalPluginData<TPluginType>> {}
export function zeppelinGlobalPlugin<TBlueprint extends ZeppelinGlobalPluginBlueprint>(
blueprint: TBlueprint,
): TBlueprint & { configParser: ZeppelinGlobalPluginBlueprint["configParser"] };
): TBlueprint;
export function zeppelinGlobalPlugin<TPluginType extends BasePluginType>(): <
TBlueprint extends ZeppelinGlobalPluginBlueprint<TPluginType>,
>(
blueprint: TBlueprint,
) => TBlueprint & {
configParser: ZeppelinGlobalPluginBlueprint<TPluginType>["configParser"];
};
) => TBlueprint;
export function zeppelinGlobalPlugin(...args) {
if (args.length) {
const blueprint = globalPlugin(
...(args as Parameters<typeof globalPlugin>),
) as unknown as ZeppelinGlobalPluginBlueprint;
// @ts-expect-error FIXME: Check the types here
blueprint.configParser = getPluginConfigParser(blueprint, blueprint.configParser);
return blueprint;
} else {
return zeppelinGlobalPlugin as (name, blueprint) => ZeppelinGlobalPluginBlueprint;

View file

@ -1,5 +1,6 @@
import { Profiler } from "knub/dist/Profiler";
import type { Knub } from "knub";
type Profiler = Knub["profiler"];
let profiler: Profiler | null = null;
export function getProfiler() {

View file

@ -1,4 +1,4 @@
import { Awaitable } from "knub/dist/utils";
import { Awaitable } from "./typeUtils";
export async function asyncReduce<T, V>(
arr: T[],

View file

@ -9,8 +9,8 @@ import {
TextBasedChannel,
User,
} from "discord.js";
import { Awaitable } from "knub/dist/utils";
import { MINUTES, noop } from "../utils";
import { Awaitable } from "./typeUtils";
import Timeout = NodeJS.Timeout;
export type LoadPageFn = (page: number) => Awaitable<MessageCreateOptions & MessageEditOptions>;

View file

@ -1,7 +1,9 @@
import { Profiler } from "knub/dist/Profiler";
import type { Knub } from "knub";
import { performance } from "perf_hooks";
import { noop, SECONDS } from "../utils";
type Profiler = Knub["profiler"];
let _profilingEnabled = false;
export const profilingEnabled = () => {

View file

@ -1,7 +1,5 @@
import { GuildPluginData } from "knub";
import { getDefaultPrefix } from "knub/dist/commands/commandUtils";
import { getDefaultMessageCommandPrefix, GuildPluginData } from "knub";
export function getGuildPrefix(pluginData: GuildPluginData<any>) {
// @ts-expect-error: discord.js version mismatch
return pluginData.fullConfig.prefix || getDefaultPrefix(pluginData.client);
return pluginData.fullConfig.prefix || getDefaultMessageCommandPrefix(pluginData.client);
}

View file

@ -9,6 +9,8 @@ export declare type WithRequiredProps<T, K extends keyof T> = T & {
// https://devblogs.microsoft.com/typescript/announcing-typescript-4-1/
export type Awaited<T> = T extends PromiseLike<infer U> ? Awaited<U> : T;
export type Awaitable<T = unknown> = T | Promise<T>;
export type DeepMutable<T> = {
-readonly [P in keyof T]: DeepMutable<T[P]>;
};

View file

@ -7,9 +7,9 @@ import {
MessageComponentInteraction,
MessageCreateOptions,
} from "discord.js";
import { noop } from "knub/dist/utils";
import moment from "moment";
import uuidv4 from "uuid/v4";
import { noop } from "../utils";
export async function waitForButtonConfirm(
channel: GuildTextBasedChannel,
@ -37,6 +37,7 @@ export async function waitForButtonConfirm(
if (options?.restrictToId && options.restrictToId !== interaction.user.id) {
interaction
.reply({ content: `You are not permitted to use these buttons.`, ephemeral: true })
// tslint:disable-next-line no-console
.catch((err) => console.trace(err.message));
} else {
if (interaction.customId.startsWith(`confirmButton:${idMod}:`)) {