3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-03-15 05:41:51 +00:00

Add io-ts config schemas to all guild plugins

This commit is contained in:
Dragory 2019-07-21 21:15:52 +03:00
parent 2f3dfa96db
commit 74c78f51ce
23 changed files with 373 additions and 294 deletions

View file

@ -7,14 +7,14 @@ import { customEmojiRegex, errorMessage, isEmoji, successMessage } from "../util
import { ZeppelinPlugin } from "./ZeppelinPlugin"; import { ZeppelinPlugin } from "./ZeppelinPlugin";
import * as t from "io-ts"; import * as t from "io-ts";
const configSchema = t.type({ const ConfigSchema = t.type({
can_manage: t.boolean, can_manage: t.boolean,
}); });
type TConfigSchema = t.TypeOf<typeof configSchema>; type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
export class AutoReactionsPlugin extends ZeppelinPlugin<TConfigSchema> { export class AutoReactionsPlugin extends ZeppelinPlugin<TConfigSchema> {
public static pluginName = "auto_reactions"; public static pluginName = "auto_reactions";
protected static configSchema = configSchema; protected static configSchema = ConfigSchema;
protected savedMessages: GuildSavedMessages; protected savedMessages: GuildSavedMessages;
protected autoReactions: GuildAutoReactions; protected autoReactions: GuildAutoReactions;

View file

@ -9,11 +9,13 @@ import { GuildArchives } from "../data/GuildArchives";
import { IPluginOptions } from "knub"; import { IPluginOptions } from "knub";
import { GuildLogs } from "../data/GuildLogs"; import { GuildLogs } from "../data/GuildLogs";
import { LogType } from "../data/LogType"; import { LogType } from "../data/LogType";
import * as t from "io-ts";
interface ICasesPluginConfig { const ConfigSchema = t.type({
log_automatic_actions: boolean; log_automatic_actions: t.boolean,
case_log_channel: string; case_log_channel: t.string,
} });
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
/** /**
* Can also be used as a config object for functions that create cases * Can also be used as a config object for functions that create cases
@ -40,14 +42,15 @@ export type CaseNoteArgs = {
noteDetails?: string[]; noteDetails?: string[];
}; };
export class CasesPlugin extends ZeppelinPlugin<ICasesPluginConfig> { export class CasesPlugin extends ZeppelinPlugin<TConfigSchema> {
public static pluginName = "cases"; public static pluginName = "cases";
protected static configSchema = ConfigSchema;
protected cases: GuildCases; protected cases: GuildCases;
protected archives: GuildArchives; protected archives: GuildArchives;
protected logs: GuildLogs; protected logs: GuildLogs;
getDefaultOptions(): IPluginOptions<ICasesPluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
log_automatic_actions: true, log_automatic_actions: true,

View file

@ -15,26 +15,26 @@ import { GuildSavedMessages } from "../data/GuildSavedMessages";
import { SavedMessage } from "../data/entities/SavedMessage"; import { SavedMessage } from "../data/entities/SavedMessage";
import { ZeppelinPlugin } from "./ZeppelinPlugin"; import { ZeppelinPlugin } from "./ZeppelinPlugin";
import cloneDeep from "lodash.clonedeep"; import cloneDeep from "lodash.clonedeep";
import * as t from "io-ts";
interface ICensorPluginConfig { const ConfigSchema = t.type({
filter_zalgo: boolean; filter_zalgo: t.boolean,
filter_invites: boolean; filter_invites: t.boolean,
invite_guild_whitelist: string[]; invite_guild_whitelist: t.array(t.string),
invite_guild_blacklist: string[]; invite_guild_blacklist: t.array(t.string),
invite_code_whitelist: string[]; invite_code_whitelist: t.array(t.string),
invite_code_blacklist: string[]; invite_code_blacklist: t.array(t.string),
allow_group_dm_invites: boolean; allow_group_dm_invites: t.boolean,
filter_domains: t.boolean,
domain_whitelist: t.array(t.string),
domain_blacklist: t.array(t.string),
blocked_tokens: t.array(t.string),
blocked_words: t.array(t.string),
blocked_regex: t.array(t.string),
});
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
filter_domains: boolean; export class CensorPlugin extends ZeppelinPlugin<TConfigSchema> {
domain_whitelist: string[];
domain_blacklist: string[];
blocked_tokens: string[];
blocked_words: string[];
blocked_regex: string[];
}
export class CensorPlugin extends ZeppelinPlugin<ICensorPluginConfig> {
public static pluginName = "censor"; public static pluginName = "censor";
protected serverLogs: GuildLogs; protected serverLogs: GuildLogs;
@ -43,7 +43,7 @@ export class CensorPlugin extends ZeppelinPlugin<ICensorPluginConfig> {
private onMessageCreateFn; private onMessageCreateFn;
private onMessageUpdateFn; private onMessageUpdateFn;
getDefaultOptions(): IPluginOptions<ICensorPluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
filter_zalgo: false, filter_zalgo: false,

View file

@ -1,29 +1,31 @@
import { decorators as d, IPluginOptions, logger } from "knub"; import { decorators as d, IPluginOptions, logger } from "knub";
import { ZeppelinPlugin } from "./ZeppelinPlugin"; import { ZeppelinPlugin } from "./ZeppelinPlugin";
import { Member, Channel, GuildChannel, PermissionOverwrite, Permission, Message } from "eris"; import { Member, Channel, GuildChannel, PermissionOverwrite, Permission, Message } from "eris";
import * as t from "io-ts";
// Permissions using these numbers: https://abal.moe/Eris/docs/reference (add all allowed/denied ones up) // Permissions using these numbers: https://abal.moe/Eris/docs/reference (add all allowed/denied ones up)
interface ICompanionChannel { const CompanionChannel = t.type({
channelIds: string[]; channelIds: t.array(t.string),
permissions: number; permissions: t.number,
} });
type TCompanionChannel = t.TypeOf<typeof CompanionChannel>;
const ConfigSchema = t.type({
channels: t.record(t.string, CompanionChannel),
});
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
interface ICompanionChannelMap { interface ICompanionChannelMap {
[channelId: string]: ICompanionChannel; [channelId: string]: TCompanionChannel;
} }
interface ICompanionChannelPluginConfig { export class CompanionChannelPlugin extends ZeppelinPlugin<TConfigSchema> {
channels: {
[key: string]: ICompanionChannel;
};
}
export class CompanionChannelPlugin extends ZeppelinPlugin<ICompanionChannelPluginConfig> {
public static pluginName = "companion_channels"; public static pluginName = "companion_channels";
protected static configSchema = ConfigSchema;
companionChannels: Map<string, ICompanionChannel> = new Map(); companionChannels: Map<string, TCompanionChannel> = new Map();
getDefaultOptions(): IPluginOptions<ICompanionChannelPluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
channels: {}, channels: {},

View file

@ -5,68 +5,77 @@ import { renderTemplate } from "../templateFormatter";
import { stripObjectToScalars } from "../utils"; import { stripObjectToScalars } from "../utils";
import { CasesPlugin } from "./Cases"; import { CasesPlugin } from "./Cases";
import { CaseTypes } from "../data/CaseTypes"; import { CaseTypes } from "../data/CaseTypes";
import * as t from "io-ts";
// Triggers // Triggers
type CommandTrigger = { const CommandTrigger = t.type({
type: "command"; type: t.literal("command"),
name: string; name: t.string,
params: string; params: t.string,
can_use: boolean; can_use: t.boolean,
}; });
type TCommandTrigger = t.TypeOf<typeof CommandTrigger>;
type AnyTrigger = CommandTrigger; const AnyTrigger = CommandTrigger; // TODO: Make into a union once we have more triggers
type TAnyTrigger = t.TypeOf<typeof AnyTrigger>;
// Actions // Actions
type AddRoleAction = { const AddRoleAction = t.type({
type: "add_role"; type: t.literal("add_role"),
target: string; target: t.string,
role: string | string[]; role: t.union([t.string, t.array(t.string)]),
}; });
type TAddRoleAction = t.TypeOf<typeof AddRoleAction>;
type CreateCaseAction = { const CreateCaseAction = t.type({
type: "create_case"; type: t.literal("create_case"),
case_type: string; case_type: t.string,
mod: string; mod: t.string,
target: string; target: t.string,
reason: string; reason: t.string,
}; });
type TCreateCaseAction = t.TypeOf<typeof CreateCaseAction>;
type MoveToVoiceChannelAction = { const MoveToVoiceChannelAction = t.type({
type: "move_to_vc"; type: t.literal("move_to_vc"),
target: string; target: t.string,
channel: string; channel: t.string,
}; });
type TMoveToVoiceChannelAction = t.TypeOf<typeof MoveToVoiceChannelAction>;
type MessageAction = { const MessageAction = t.type({
type: "message"; type: t.literal("message"),
channel: string; channel: t.string,
content: string; content: t.string,
}; });
type TMessageAction = t.TypeOf<typeof MessageAction>;
type AnyAction = AddRoleAction | CreateCaseAction | MoveToVoiceChannelAction | MessageAction; const AnyAction = t.union([AddRoleAction, CreateCaseAction, MoveToVoiceChannelAction, MessageAction]);
type TAnyAction = t.TypeOf<typeof AnyAction>;
// Event // Full config schema
type CustomEvent = { const CustomEvent = t.type({
name: string; name: t.string,
trigger: AnyTrigger; trigger: AnyTrigger,
actions: AnyAction[]; actions: t.array(AnyAction),
}; });
type TCustomEvent = t.TypeOf<typeof CustomEvent>;
interface ICustomEventsPluginConfig { const ConfigSchema = t.type({
events: { events: t.record(t.string, CustomEvent),
[key: string]: CustomEvent; });
}; type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
}
class ActionError extends Error {} class ActionError extends Error {}
export class CustomEventsPlugin extends ZeppelinPlugin<ICustomEventsPluginConfig> { export class CustomEventsPlugin extends ZeppelinPlugin<TConfigSchema> {
public static pluginName = "custom_events"; public static pluginName = "custom_events";
public static dependencies = ["cases"];
protected static configSchema = ConfigSchema;
private clearTriggers: () => void; private clearTriggers: () => void;
public static dependencies = ["cases"]; getDefaultOptions(): IPluginOptions<TConfigSchema> {
getDefaultOptions(): IPluginOptions<ICustomEventsPluginConfig> {
return { return {
config: { config: {
events: {}, events: {},
@ -97,7 +106,7 @@ export class CustomEventsPlugin extends ZeppelinPlugin<ICustomEventsPluginConfig
// TODO: Run this.clearTriggers() once we actually have something there // TODO: Run this.clearTriggers() once we actually have something there
} }
async runEvent(event: CustomEvent, eventData: any, values: any) { async runEvent(event: TCustomEvent, eventData: any, values: any) {
try { try {
for (const action of event.actions) { for (const action of event.actions) {
if (action.type === "add_role") { if (action.type === "add_role") {
@ -125,7 +134,7 @@ export class CustomEventsPlugin extends ZeppelinPlugin<ICustomEventsPluginConfig
} }
} }
async addRoleAction(action: AddRoleAction, values: any, event: CustomEvent, eventData: any) { async addRoleAction(action: TAddRoleAction, values: any, event: TCustomEvent, eventData: any) {
const targetId = await renderTemplate(action.target, values, false); const targetId = await renderTemplate(action.target, values, false);
const target = await this.getMember(targetId); const target = await this.getMember(targetId);
if (!target) throw new ActionError(`Unknown target member: ${targetId}`); if (!target) throw new ActionError(`Unknown target member: ${targetId}`);
@ -140,7 +149,7 @@ export class CustomEventsPlugin extends ZeppelinPlugin<ICustomEventsPluginConfig
}); });
} }
async createCaseAction(action: CreateCaseAction, values: any, event: CustomEvent, eventData: any) { async createCaseAction(action: TCreateCaseAction, values: any, event: TCustomEvent, eventData: any) {
const modId = await renderTemplate(action.mod, values, false); const modId = await renderTemplate(action.mod, values, false);
const targetId = await renderTemplate(action.target, values, false); const targetId = await renderTemplate(action.target, values, false);
@ -159,7 +168,7 @@ export class CustomEventsPlugin extends ZeppelinPlugin<ICustomEventsPluginConfig
}); });
} }
async moveToVoiceChannelAction(action: MoveToVoiceChannelAction, values: any, event: CustomEvent, eventData: any) { async moveToVoiceChannelAction(action: TMoveToVoiceChannelAction, values: any, event: TCustomEvent, eventData: any) {
const targetId = await renderTemplate(action.target, values, false); const targetId = await renderTemplate(action.target, values, false);
const target = await this.getMember(targetId); const target = await this.getMember(targetId);
if (!target) throw new ActionError("Unknown target member"); if (!target) throw new ActionError("Unknown target member");
@ -179,7 +188,7 @@ export class CustomEventsPlugin extends ZeppelinPlugin<ICustomEventsPluginConfig
}); });
} }
async messageAction(action: MessageAction, values: any) { async messageAction(action: TMessageAction, values: any) {
const targetChannelId = await renderTemplate(action.channel, values, false); const targetChannelId = await renderTemplate(action.channel, values, false);
const targetChannel = this.guild.channels.get(targetChannelId); const targetChannel = this.guild.channels.get(targetChannelId);
if (!targetChannel) throw new ActionError("Unknown target channel"); if (!targetChannel) throw new ActionError("Unknown target channel");

View file

@ -5,22 +5,25 @@ import { Message, Member, Guild, TextableChannel, VoiceChannel, Channel, User }
import { GuildVCAlerts } from "../data/GuildVCAlerts"; import { GuildVCAlerts } from "../data/GuildVCAlerts";
import moment = require("moment"); import moment = require("moment");
import { resolveMember, sorter, createChunkedMessage, errorMessage, successMessage } from "../utils"; import { resolveMember, sorter, createChunkedMessage, errorMessage, successMessage } from "../utils";
import * as t from "io-ts";
const ConfigSchema = t.type({
can_where: t.boolean,
can_alert: t.boolean,
});
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
const ALERT_LOOP_TIME = 30 * 1000; const ALERT_LOOP_TIME = 30 * 1000;
interface ILocatePluginConfig { export class LocatePlugin extends ZeppelinPlugin<TConfigSchema> {
can_where: boolean;
can_alert: boolean;
}
export class LocatePlugin extends ZeppelinPlugin<ILocatePluginConfig> {
public static pluginName = "locate_user"; public static pluginName = "locate_user";
protected static configSchema = ConfigSchema;
private alerts: GuildVCAlerts; private alerts: GuildVCAlerts;
private outdatedAlertsTimeout; private outdatedAlertsTimeout;
private usersWithAlerts: string[] = []; private usersWithAlerts: string[] = [];
getDefaultOptions(): IPluginOptions<ILocatePluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
can_where: false, can_where: false,

View file

@ -26,33 +26,35 @@ import { GuildCases } from "../data/GuildCases";
import { ZeppelinPlugin } from "./ZeppelinPlugin"; import { ZeppelinPlugin } from "./ZeppelinPlugin";
import { renderTemplate, TemplateParseError } from "../templateFormatter"; import { renderTemplate, TemplateParseError } from "../templateFormatter";
import cloneDeep from "lodash.clonedeep"; import cloneDeep from "lodash.clonedeep";
import * as t from "io-ts";
interface ILogChannel { const LogChannel = t.partial({
include?: string[]; include: t.array(t.string),
exclude?: string[]; exclude: t.array(t.string),
batched?: boolean; batched: t.boolean,
batch_time?: number; batch_time: t.number,
excluded_users?: string[]; excluded_users: t.array(t.string),
} });
type TLogChannel = t.TypeOf<typeof LogChannel>;
interface ILogChannelMap { const LogChannelMap = t.record(t.string, LogChannel);
[channelId: string]: ILogChannel; type TLogChannelMap = t.TypeOf<typeof LogChannelMap>;
}
interface ILogsPluginConfig { const ConfigSchema = t.type({
channels: { channels: LogChannelMap,
[key: string]: ILogChannel; format: t.intersection([
}; t.record(t.string, t.string),
format: { t.type({
[key: string]: string; timestamp: t.string,
timestamp: string; }),
}; ]),
ping_user: t.boolean,
});
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
ping_user: boolean; export class LogsPlugin extends ZeppelinPlugin<TConfigSchema> {
}
export class LogsPlugin extends ZeppelinPlugin<ILogsPluginConfig> {
public static pluginName = "logs"; public static pluginName = "logs";
protected static configSchema = ConfigSchema;
protected guildLogs: GuildLogs; protected guildLogs: GuildLogs;
protected savedMessages: GuildSavedMessages; protected savedMessages: GuildSavedMessages;
@ -69,7 +71,7 @@ export class LogsPlugin extends ZeppelinPlugin<ILogsPluginConfig> {
private excludedUserProps = ["user", "member", "mod"]; private excludedUserProps = ["user", "member", "mod"];
getDefaultOptions(): IPluginOptions<ILogsPluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
channels: {}, channels: {},
@ -121,7 +123,7 @@ export class LogsPlugin extends ZeppelinPlugin<ILogsPluginConfig> {
} }
async log(type, data) { async log(type, data) {
const logChannels: ILogChannelMap = this.getConfig().channels; const logChannels: TLogChannelMap = this.getConfig().channels;
const typeStr = LogType[type]; const typeStr = LogType[type];
logChannelLoop: for (const [channelId, opts] of Object.entries(logChannels)) { logChannelLoop: for (const [channelId, opts] of Object.entries(logChannels)) {

View file

@ -3,17 +3,20 @@ import { GuildChannel, Message, TextChannel } from "eris";
import { GuildSavedMessages } from "../data/GuildSavedMessages"; import { GuildSavedMessages } from "../data/GuildSavedMessages";
import { successMessage } from "../utils"; import { successMessage } from "../utils";
import { ZeppelinPlugin } from "./ZeppelinPlugin"; import { ZeppelinPlugin } from "./ZeppelinPlugin";
import * as t from "io-ts";
interface IMessageSaverPluginConfig { const ConfigSchema = t.type({
can_manage: boolean; can_manage: t.boolean,
} });
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
export class MessageSaverPlugin extends ZeppelinPlugin<IMessageSaverPluginConfig> { export class MessageSaverPlugin extends ZeppelinPlugin<TConfigSchema> {
public static pluginName = "message_saver"; public static pluginName = "message_saver";
protected static configSchema = ConfigSchema;
protected savedMessages: GuildSavedMessages; protected savedMessages: GuildSavedMessages;
getDefaultOptions(): IPluginOptions<IMessageSaverPluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
can_manage: false, can_manage: false,

View file

@ -26,6 +26,33 @@ import { Case } from "../data/entities/Case";
import { renderTemplate } from "../templateFormatter"; import { renderTemplate } from "../templateFormatter";
import { CasesPlugin } from "./Cases"; import { CasesPlugin } from "./Cases";
import { MuteResult, MutesPlugin } from "./Mutes"; import { MuteResult, MutesPlugin } from "./Mutes";
import * as t from "io-ts";
const ConfigSchema = t.type({
dm_on_warn: t.boolean,
dm_on_kick: t.boolean,
dm_on_ban: t.boolean,
message_on_warn: t.boolean,
message_on_kick: t.boolean,
message_on_ban: t.boolean,
message_channel: t.string,
warn_message: t.string,
kick_message: t.string,
ban_message: t.string,
alert_on_rejoin: t.boolean,
alert_channel: t.string,
can_note: t.boolean,
can_warn: t.boolean,
can_mute: t.boolean,
can_kick: t.boolean,
can_ban: t.boolean,
can_view: t.boolean,
can_addcase: t.boolean,
can_massban: t.boolean,
can_hidecase: t.boolean,
can_act_as_other: t.boolean,
});
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
enum IgnoredEventType { enum IgnoredEventType {
Ban = 1, Ban = 1,
@ -38,35 +65,10 @@ interface IIgnoredEvent {
userId: string; userId: string;
} }
interface IModActionsPluginConfig { export class ModActionsPlugin extends ZeppelinPlugin<TConfigSchema> {
dm_on_warn: boolean;
dm_on_kick: boolean;
dm_on_ban: boolean;
message_on_warn: boolean;
message_on_kick: boolean;
message_on_ban: boolean;
message_channel: string;
warn_message: string;
kick_message: string;
ban_message: string;
alert_on_rejoin: boolean;
alert_channel: string;
can_note: boolean;
can_warn: boolean;
can_mute: boolean;
can_kick: boolean;
can_ban: boolean;
can_view: boolean;
can_addcase: boolean;
can_massban: boolean;
can_hidecase: boolean;
can_act_as_other: boolean;
}
export class ModActionsPlugin extends ZeppelinPlugin<IModActionsPluginConfig> {
public static pluginName = "mod_actions"; public static pluginName = "mod_actions";
public static dependencies = ["cases", "mutes"]; public static dependencies = ["cases", "mutes"];
protected static configSchema = ConfigSchema;
protected mutes: GuildMutes; protected mutes: GuildMutes;
protected cases: GuildCases; protected cases: GuildCases;
@ -82,7 +84,7 @@ export class ModActionsPlugin extends ZeppelinPlugin<IModActionsPluginConfig> {
this.ignoredEvents = []; this.ignoredEvents = [];
} }
getDefaultOptions(): IPluginOptions<IModActionsPluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
dm_on_warn: true, dm_on_warn: true,

View file

@ -25,26 +25,28 @@ import { renderTemplate } from "../templateFormatter";
import { CaseTypes } from "../data/CaseTypes"; import { CaseTypes } from "../data/CaseTypes";
import { CaseArgs, CasesPlugin } from "./Cases"; import { CaseArgs, CasesPlugin } from "./Cases";
import { Case } from "../data/entities/Case"; import { Case } from "../data/entities/Case";
import * as t from "io-ts";
const ConfigSchema = t.type({
mute_role: t.string,
move_to_voice_channel: t.string,
dm_on_mute: t.boolean,
message_on_mute: t.boolean,
message_channel: t.string,
mute_message: t.string,
timed_mute_message: t.string,
can_view_list: t.boolean,
can_cleanup: t.boolean,
});
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
interface IMuteWithDetails extends Mute { interface IMuteWithDetails extends Mute {
member?: Member; member?: Member;
banned?: boolean; banned?: boolean;
} }
interface IMutesPluginConfig {
mute_role: string;
move_to_voice_channel: string;
dm_on_mute: boolean;
message_on_mute: boolean;
message_channel: string;
mute_message: string;
timed_mute_message: string;
can_view_list: boolean;
can_cleanup: boolean;
}
export type MuteResult = { export type MuteResult = {
case: Case; case: Case;
notifyResult: INotifyUserResult; notifyResult: INotifyUserResult;
@ -59,15 +61,16 @@ const EXPIRED_MUTE_CHECK_INTERVAL = 60 * 1000;
let FIRST_CHECK_TIME = Date.now(); let FIRST_CHECK_TIME = Date.now();
const FIRST_CHECK_INCREMENT = 5 * 1000; const FIRST_CHECK_INCREMENT = 5 * 1000;
export class MutesPlugin extends ZeppelinPlugin<IMutesPluginConfig> { export class MutesPlugin extends ZeppelinPlugin<TConfigSchema> {
public static pluginName = "mutes"; public static pluginName = "mutes";
protected static configSchema = ConfigSchema;
protected mutes: GuildMutes; protected mutes: GuildMutes;
protected cases: GuildCases; protected cases: GuildCases;
protected serverLogs: GuildLogs; protected serverLogs: GuildLogs;
private muteClearIntervalId: NodeJS.Timer; private muteClearIntervalId: NodeJS.Timer;
getDefaultOptions(): IPluginOptions<IMutesPluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
mute_role: null, mute_role: null,

View file

@ -4,18 +4,21 @@ import { Member, Message } from "eris";
import { createChunkedMessage, disableCodeBlocks } from "../utils"; import { createChunkedMessage, disableCodeBlocks } from "../utils";
import { ZeppelinPlugin } from "./ZeppelinPlugin"; import { ZeppelinPlugin } from "./ZeppelinPlugin";
import { MAX_USERNAME_ENTRIES_PER_USER, UsernameHistory } from "../data/UsernameHistory"; import { MAX_USERNAME_ENTRIES_PER_USER, UsernameHistory } from "../data/UsernameHistory";
import * as t from "io-ts";
interface INameHistoryPluginConfig { const ConfigSchema = t.type({
can_view: boolean; can_view: t.boolean,
} });
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
export class NameHistoryPlugin extends ZeppelinPlugin<INameHistoryPluginConfig> { export class NameHistoryPlugin extends ZeppelinPlugin<TConfigSchema> {
public static pluginName = "name_history"; public static pluginName = "name_history";
protected static configSchema = ConfigSchema;
protected nicknameHistory: GuildNicknameHistory; protected nicknameHistory: GuildNicknameHistory;
protected usernameHistory: UsernameHistory; protected usernameHistory: UsernameHistory;
getDefaultOptions(): IPluginOptions<INameHistoryPluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
can_view: false, can_view: false,

View file

@ -6,20 +6,23 @@ import { GuildLogs } from "../data/GuildLogs";
import { LogType } from "../data/LogType"; import { LogType } from "../data/LogType";
import { stripObjectToScalars } from "../utils"; import { stripObjectToScalars } from "../utils";
import { ZeppelinPlugin } from "./ZeppelinPlugin"; import { ZeppelinPlugin } from "./ZeppelinPlugin";
import * as t from "io-ts";
interface IPersistPluginConfig { const ConfigSchema = t.type({
persisted_roles: string[]; persisted_roles: t.array(t.string),
persist_nicknames: boolean; persist_nicknames: t.boolean,
persist_voice_mutes: boolean; persist_voice_mutes: t.boolean,
} });
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
export class PersistPlugin extends ZeppelinPlugin<IPersistPluginConfig> { export class PersistPlugin extends ZeppelinPlugin<TConfigSchema> {
public static pluginName = "persist"; public static pluginName = "persist";
protected static configSchema = ConfigSchema;
protected persistedData: GuildPersistedData; protected persistedData: GuildPersistedData;
protected logs: GuildLogs; protected logs: GuildLogs;
getDefaultOptions(): IPluginOptions<IPersistPluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
persisted_roles: [], persisted_roles: [],

View file

@ -4,21 +4,24 @@ import { GuildPingableRoles } from "../data/GuildPingableRoles";
import { PingableRole } from "../data/entities/PingableRole"; import { PingableRole } from "../data/entities/PingableRole";
import { errorMessage, successMessage } from "../utils"; import { errorMessage, successMessage } from "../utils";
import { ZeppelinPlugin } from "./ZeppelinPlugin"; import { ZeppelinPlugin } from "./ZeppelinPlugin";
import * as t from "io-ts";
const ConfigSchema = t.type({
can_manage: t.boolean,
});
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
const TIMEOUT = 10 * 1000; const TIMEOUT = 10 * 1000;
interface IPingableRolesPluginConfig { export class PingableRolesPlugin extends ZeppelinPlugin<TConfigSchema> {
can_manage: boolean;
}
export class PingableRolesPlugin extends ZeppelinPlugin<IPingableRolesPluginConfig> {
public static pluginName = "pingable_roles"; public static pluginName = "pingable_roles";
protected static configSchema = ConfigSchema;
protected pingableRoles: GuildPingableRoles; protected pingableRoles: GuildPingableRoles;
protected cache: Map<string, PingableRole[]>; protected cache: Map<string, PingableRole[]>;
protected timeouts: Map<string, any>; protected timeouts: Map<string, any>;
getDefaultOptions(): IPluginOptions<IPingableRolesPluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
can_manage: false, can_manage: false,

View file

@ -22,6 +22,13 @@ import { GuildScheduledPosts } from "../data/GuildScheduledPosts";
import moment, { Moment } from "moment-timezone"; import moment, { Moment } from "moment-timezone";
import { GuildLogs } from "../data/GuildLogs"; import { GuildLogs } from "../data/GuildLogs";
import { LogType } from "../data/LogType"; import { LogType } from "../data/LogType";
import * as t from "io-ts";
const ConfigSchema = t.type({
can_post: t.boolean,
});
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
const fsp = fs.promises; const fsp = fs.promises;
const COLOR_MATCH_REGEX = /^#?([0-9a-f]{6})$/; const COLOR_MATCH_REGEX = /^#?([0-9a-f]{6})$/;
@ -29,12 +36,9 @@ const COLOR_MATCH_REGEX = /^#?([0-9a-f]{6})$/;
const SCHEDULED_POST_CHECK_INTERVAL = 15 * SECONDS; const SCHEDULED_POST_CHECK_INTERVAL = 15 * SECONDS;
const SCHEDULED_POST_PREVIEW_TEXT_LENGTH = 50; const SCHEDULED_POST_PREVIEW_TEXT_LENGTH = 50;
interface IPostPluginConfig { export class PostPlugin extends ZeppelinPlugin<TConfigSchema> {
can_post: boolean;
}
export class PostPlugin extends ZeppelinPlugin<IPostPluginConfig> {
public static pluginName = "post"; public static pluginName = "post";
protected static configSchema = ConfigSchema;
protected savedMessages: GuildSavedMessages; protected savedMessages: GuildSavedMessages;
protected scheduledPosts: GuildScheduledPosts; protected scheduledPosts: GuildScheduledPosts;
@ -54,7 +58,7 @@ export class PostPlugin extends ZeppelinPlugin<IPostPluginConfig> {
clearTimeout(this.scheduledPostLoopTimeout); clearTimeout(this.scheduledPostLoopTimeout);
} }
getDefaultOptions(): IPluginOptions<IPostPluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
can_post: false, can_post: false,

View file

@ -8,6 +8,22 @@ import { Queue } from "../Queue";
import { ReactionRole } from "../data/entities/ReactionRole"; import { ReactionRole } from "../data/entities/ReactionRole";
import Timeout = NodeJS.Timeout; import Timeout = NodeJS.Timeout;
import DiscordRESTError from "eris/lib/errors/DiscordRESTError"; // tslint:disable-line import DiscordRESTError from "eris/lib/errors/DiscordRESTError"; // tslint:disable-line
import * as t from "io-ts";
/**
* Either of:
* [emojiId, roleId]
* [emojiId, roleId, emojiName]
* Where emojiId is either the snowflake of a custom emoji, or the actual unicode emoji
*/
const ReactionRolePair = t.union([t.tuple([t.string, t.string, t.string]), t.tuple([t.string, t.string])]);
type TReactionRolePair = t.TypeOf<typeof ReactionRolePair>;
const ConfigSchema = t.type({
auto_refresh_interval: t.number,
can_manage: t.boolean,
});
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
type ReactionRolePair = [string, string, string?]; type ReactionRolePair = [string, string, string?];
@ -26,14 +42,9 @@ type PendingMemberRoleChanges = {
}>; }>;
}; };
interface IReactionRolesPluginConfig { export class ReactionRolesPlugin extends ZeppelinPlugin<TConfigSchema> {
auto_refresh_interval: number;
can_manage: boolean;
}
export class ReactionRolesPlugin extends ZeppelinPlugin<IReactionRolesPluginConfig> {
public static pluginName = "reaction_roles"; public static pluginName = "reaction_roles";
protected static configSchema = ConfigSchema;
protected reactionRoles: GuildReactionRoles; protected reactionRoles: GuildReactionRoles;
protected savedMessages: GuildSavedMessages; protected savedMessages: GuildSavedMessages;
@ -44,7 +55,7 @@ export class ReactionRolesPlugin extends ZeppelinPlugin<IReactionRolesPluginConf
private autoRefreshTimeout; private autoRefreshTimeout;
getDefaultOptions(): IPluginOptions<IReactionRolesPluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
auto_refresh_interval: null, auto_refresh_interval: null,
@ -279,17 +290,17 @@ export class ReactionRolesPlugin extends ZeppelinPlugin<IReactionRolesPluginConf
// Turn "emoji = role" pairs into an array of tuples of the form [emoji, roleId] // Turn "emoji = role" pairs into an array of tuples of the form [emoji, roleId]
// Emoji is either a unicode emoji or the snowflake of a custom emoji // Emoji is either a unicode emoji or the snowflake of a custom emoji
const emojiRolePairs: ReactionRolePair[] = args.reactionRolePairs const emojiRolePairs: TReactionRolePair[] = args.reactionRolePairs
.trim() .trim()
.split("\n") .split("\n")
.map(v => v.split("=").map(v => v.trim())) // tslint:disable-line .map(v => v.split("=").map(v => v.trim())) // tslint:disable-line
.map( .map(
(pair): ReactionRolePair => { (pair): TReactionRolePair => {
const customEmojiMatch = pair[0].match(/^<a?:(.*?):(\d+)>$/); const customEmojiMatch = pair[0].match(/^<a?:(.*?):(\d+)>$/);
if (customEmojiMatch) { if (customEmojiMatch) {
return [customEmojiMatch[2], pair[1], customEmojiMatch[1]]; return [customEmojiMatch[2], pair[1], customEmojiMatch[1]];
} else { } else {
return pair as ReactionRolePair; return pair as TReactionRolePair;
} }
}, },
); );

View file

@ -12,16 +12,19 @@ import {
sorter, sorter,
successMessage, successMessage,
} from "../utils"; } from "../utils";
import * as t from "io-ts";
const ConfigSchema = t.type({
can_use: t.boolean,
});
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
const REMINDER_LOOP_TIME = 10 * 1000; const REMINDER_LOOP_TIME = 10 * 1000;
const MAX_TRIES = 3; const MAX_TRIES = 3;
interface IRemindersPluginConfig { export class RemindersPlugin extends ZeppelinPlugin<TConfigSchema> {
can_use: boolean;
}
export class RemindersPlugin extends ZeppelinPlugin<IRemindersPluginConfig> {
public static pluginName = "reminders"; public static pluginName = "reminders";
protected static configSchema = ConfigSchema;
protected reminders: GuildReminders; protected reminders: GuildReminders;
protected tries: Map<number, number>; protected tries: Map<number, number>;
@ -29,7 +32,7 @@ export class RemindersPlugin extends ZeppelinPlugin<IRemindersPluginConfig> {
private postRemindersTimeout; private postRemindersTimeout;
private unloaded = false; private unloaded = false;
getDefaultOptions(): IPluginOptions<IRemindersPluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
can_use: false, can_use: false,

View file

@ -3,19 +3,22 @@ import { GuildSelfGrantableRoles } from "../data/GuildSelfGrantableRoles";
import { GuildChannel, Message, Role, TextChannel } from "eris"; import { GuildChannel, Message, Role, TextChannel } from "eris";
import { asSingleLine, chunkArray, errorMessage, sorter, successMessage, trimLines } from "../utils"; import { asSingleLine, chunkArray, errorMessage, sorter, successMessage, trimLines } from "../utils";
import { ZeppelinPlugin } from "./ZeppelinPlugin"; import { ZeppelinPlugin } from "./ZeppelinPlugin";
import * as t from "io-ts";
interface ISelfGrantableRolesPluginConfig { const ConfigSchema = t.type({
can_manage: boolean; can_manage: t.boolean,
can_use: boolean; can_use: t.boolean,
can_ignore_cooldown: boolean; can_ignore_cooldown: t.boolean,
} });
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
export class SelfGrantableRolesPlugin extends ZeppelinPlugin<ISelfGrantableRolesPluginConfig> { export class SelfGrantableRolesPlugin extends ZeppelinPlugin<TConfigSchema> {
public static pluginName = "self_grantable_roles"; public static pluginName = "self_grantable_roles";
protected static configSchema = ConfigSchema;
protected selfGrantableRoles: GuildSelfGrantableRoles; protected selfGrantableRoles: GuildSelfGrantableRoles;
getDefaultOptions(): IPluginOptions<ISelfGrantableRolesPluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
can_manage: false, can_manage: false,

View file

@ -17,20 +17,23 @@ import { GuildSavedMessages } from "../data/GuildSavedMessages";
import DiscordRESTError from "eris/lib/errors/DiscordRESTError"; // tslint:disable-line import DiscordRESTError from "eris/lib/errors/DiscordRESTError"; // tslint:disable-line
import { GuildLogs } from "../data/GuildLogs"; import { GuildLogs } from "../data/GuildLogs";
import { LogType } from "../data/LogType"; import { LogType } from "../data/LogType";
import * as t from "io-ts";
const ConfigSchema = t.type({
use_native_slowmode: t.boolean,
can_manage: t.boolean,
is_affected: t.boolean,
});
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
const NATIVE_SLOWMODE_LIMIT = 6 * 60 * 60; // 6 hours const NATIVE_SLOWMODE_LIMIT = 6 * 60 * 60; // 6 hours
const MAX_SLOWMODE = 60 * 60 * 24 * 365 * 100; // 100 years const MAX_SLOWMODE = 60 * 60 * 24 * 365 * 100; // 100 years
const BOT_SLOWMODE_CLEAR_INTERVAL = 60 * 1000; const BOT_SLOWMODE_CLEAR_INTERVAL = 60 * 1000;
interface ISlowmodePluginConfig { export class SlowmodePlugin extends ZeppelinPlugin<TConfigSchema> {
use_native_slowmode: boolean;
can_manage: boolean;
is_affected: boolean;
}
export class SlowmodePlugin extends ZeppelinPlugin<ISlowmodePluginConfig> {
public static pluginName = "slowmode"; public static pluginName = "slowmode";
protected static configSchema = ConfigSchema;
protected slowmodes: GuildSlowmodes; protected slowmodes: GuildSlowmodes;
protected savedMessages: GuildSavedMessages; protected savedMessages: GuildSavedMessages;
@ -39,7 +42,7 @@ export class SlowmodePlugin extends ZeppelinPlugin<ISlowmodePluginConfig> {
private onMessageCreateFn; private onMessageCreateFn;
getDefaultOptions(): IPluginOptions<ISlowmodePluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
use_native_slowmode: true, use_native_slowmode: true,

View file

@ -21,6 +21,34 @@ import { GuildMutes } from "../data/GuildMutes";
import { ZeppelinPlugin } from "./ZeppelinPlugin"; import { ZeppelinPlugin } from "./ZeppelinPlugin";
import { MuteResult, MutesPlugin } from "./Mutes"; import { MuteResult, MutesPlugin } from "./Mutes";
import { CasesPlugin } from "./Cases"; import { CasesPlugin } from "./Cases";
import * as t from "io-ts";
const BaseSingleSpamConfig = t.intersection([
t.type({
interval: t.number,
count: t.number,
}),
t.partial({
mute: t.boolean,
mute_time: t.number,
clean: t.boolean,
}),
]);
type TBaseSingleSpamConfig = t.TypeOf<typeof BaseSingleSpamConfig>;
const ConfigSchema = t.type({
max_censor: BaseSingleSpamConfig,
max_messages: BaseSingleSpamConfig,
max_mentions: BaseSingleSpamConfig,
max_links: BaseSingleSpamConfig,
max_attachments: BaseSingleSpamConfig,
max_emojis: BaseSingleSpamConfig,
max_newlines: BaseSingleSpamConfig,
max_duplicates: BaseSingleSpamConfig,
max_characters: BaseSingleSpamConfig,
max_voice_moves: BaseSingleSpamConfig,
});
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
enum RecentActionType { enum RecentActionType {
Message = 1, Message = 1,
@ -47,29 +75,9 @@ const MAX_INTERVAL = 300;
const SPAM_ARCHIVE_EXPIRY_DAYS = 90; const SPAM_ARCHIVE_EXPIRY_DAYS = 90;
interface IBaseSingleSpamConfig { export class SpamPlugin extends ZeppelinPlugin<TConfigSchema> {
interval: number;
count: number;
mute?: boolean;
mute_time?: number;
clean?: boolean;
}
interface ISpamPluginConfig {
max_censor: IBaseSingleSpamConfig;
max_messages: IBaseSingleSpamConfig;
max_mentions: IBaseSingleSpamConfig;
max_links: IBaseSingleSpamConfig;
max_attachments: IBaseSingleSpamConfig;
max_emojis: IBaseSingleSpamConfig;
max_newlines: IBaseSingleSpamConfig;
max_duplicates: IBaseSingleSpamConfig;
max_characters: IBaseSingleSpamConfig;
max_voice_moves: IBaseSingleSpamConfig;
}
export class SpamPlugin extends ZeppelinPlugin<ISpamPluginConfig> {
public static pluginName = "spam"; public static pluginName = "spam";
protected static configSchema = ConfigSchema;
protected logs: GuildLogs; protected logs: GuildLogs;
protected archives: GuildArchives; protected archives: GuildArchives;
@ -91,7 +99,7 @@ export class SpamPlugin extends ZeppelinPlugin<ISpamPluginConfig> {
private expiryInterval; private expiryInterval;
getDefaultOptions(): IPluginOptions<ISpamPluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
max_censor: null, max_censor: null,
@ -201,7 +209,7 @@ export class SpamPlugin extends ZeppelinPlugin<ISpamPluginConfig> {
async logAndDetectMessageSpam( async logAndDetectMessageSpam(
savedMessage: SavedMessage, savedMessage: SavedMessage,
type: RecentActionType, type: RecentActionType,
spamConfig: IBaseSingleSpamConfig, spamConfig: TBaseSingleSpamConfig,
actionCount: number, actionCount: number,
description: string, description: string,
) { ) {

View file

@ -16,20 +16,23 @@ import path from "path";
import moment from "moment-timezone"; import moment from "moment-timezone";
import { GuildSavedMessages } from "../data/GuildSavedMessages"; import { GuildSavedMessages } from "../data/GuildSavedMessages";
import { SavedMessage } from "../data/entities/SavedMessage"; import { SavedMessage } from "../data/entities/SavedMessage";
import * as t from "io-ts";
interface IStarboardPluginConfig { const ConfigSchema = t.type({
can_manage: boolean; can_manage: t.boolean,
} });
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
export class StarboardPlugin extends ZeppelinPlugin<IStarboardPluginConfig> { export class StarboardPlugin extends ZeppelinPlugin<TConfigSchema> {
public static pluginName = "starboard"; public static pluginName = "starboard";
protected static configSchema = ConfigSchema;
protected starboards: GuildStarboards; protected starboards: GuildStarboards;
protected savedMessages: GuildSavedMessages; protected savedMessages: GuildSavedMessages;
private onMessageDeleteFn; private onMessageDeleteFn;
getDefaultOptions(): IPluginOptions<IStarboardPluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
can_manage: false, can_manage: false,

View file

@ -9,18 +9,21 @@ import humanizeDuration from "humanize-duration";
import { ZeppelinPlugin } from "./ZeppelinPlugin"; import { ZeppelinPlugin } from "./ZeppelinPlugin";
import { parseTemplate, renderTemplate, TemplateParseError } from "../templateFormatter"; import { parseTemplate, renderTemplate, TemplateParseError } from "../templateFormatter";
import { GuildArchives } from "../data/GuildArchives"; import { GuildArchives } from "../data/GuildArchives";
import * as t from "io-ts";
interface ITagsPluginConfig { const ConfigSchema = t.type({
prefix: string; prefix: t.string,
delete_with_command: boolean; delete_with_command: t.boolean,
can_create: boolean; can_create: t.boolean,
can_use: boolean; can_use: t.boolean,
can_list: boolean; can_list: t.boolean,
} });
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
export class TagsPlugin extends ZeppelinPlugin<ITagsPluginConfig> { export class TagsPlugin extends ZeppelinPlugin<TConfigSchema> {
public static pluginName = "tags"; public static pluginName = "tags";
protected static configSchema = ConfigSchema;
protected archives: GuildArchives; protected archives: GuildArchives;
protected tags: GuildTags; protected tags: GuildTags;
@ -31,7 +34,7 @@ export class TagsPlugin extends ZeppelinPlugin<ITagsPluginConfig> {
protected tagFunctions; protected tagFunctions;
getDefaultOptions(): IPluginOptions<ITagsPluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
prefix: "!!", prefix: "!!",

View file

@ -43,8 +43,25 @@ import { GuildSavedMessages } from "../data/GuildSavedMessages";
import { GuildArchives } from "../data/GuildArchives"; import { GuildArchives } from "../data/GuildArchives";
import { ZeppelinPlugin } from "./ZeppelinPlugin"; import { ZeppelinPlugin } from "./ZeppelinPlugin";
import { getCurrentUptime } from "../uptime"; import { getCurrentUptime } from "../uptime";
import LCL from "last-commit-log"; import LCL from "last-commit-log";
import * as t from "io-ts";
const ConfigSchema = t.type({
can_roles: t.boolean,
can_level: t.boolean,
can_search: t.boolean,
can_clean: t.boolean,
can_info: t.boolean,
can_server: t.boolean,
can_reload_guild: t.boolean,
can_nickname: t.boolean,
can_ping: t.boolean,
can_source: t.boolean,
can_vcmove: t.boolean,
can_help: t.boolean,
can_about: t.boolean,
});
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
const { performance } = require("perf_hooks"); const { performance } = require("perf_hooks");
@ -63,24 +80,9 @@ type MemberSearchParams = {
"case-sensitive"?: boolean; "case-sensitive"?: boolean;
}; };
interface IUtilityPluginConfig { export class UtilityPlugin extends ZeppelinPlugin<TConfigSchema> {
can_roles: boolean;
can_level: boolean;
can_search: boolean;
can_clean: boolean;
can_info: boolean;
can_server: boolean;
can_reload_guild: boolean;
can_nickname: boolean;
can_ping: boolean;
can_source: boolean;
can_vcmove: boolean;
can_help: boolean;
can_about: boolean;
}
export class UtilityPlugin extends ZeppelinPlugin<IUtilityPluginConfig> {
public static pluginName = "utility"; public static pluginName = "utility";
protected static configSchema = ConfigSchema;
protected logs: GuildLogs; protected logs: GuildLogs;
protected cases: GuildCases; protected cases: GuildCases;
@ -89,7 +91,7 @@ export class UtilityPlugin extends ZeppelinPlugin<IUtilityPluginConfig> {
protected lastFullMemberRefresh = 0; protected lastFullMemberRefresh = 0;
getDefaultOptions(): IPluginOptions<IUtilityPluginConfig> { getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
can_roles: false, can_roles: false,
@ -834,7 +836,7 @@ export class UtilityPlugin extends ZeppelinPlugin<IUtilityPluginConfig> {
const highest = Math.round(Math.max(...times)); const highest = Math.round(Math.max(...times));
const lowest = Math.round(Math.min(...times)); const lowest = Math.round(Math.min(...times));
const mean = Math.round(times.reduce((t, v) => t + v, 0) / times.length); const mean = Math.round(times.reduce((total, ms) => total + ms, 0) / times.length);
const shard = this.bot.shards.get(this.bot.guildShardMap[this.guildId]); const shard = this.bot.shards.get(this.bot.guildShardMap[this.guildId]);

View file

@ -5,19 +5,22 @@ import { renderTemplate } from "../templateFormatter";
import { createChunkedMessage, stripObjectToScalars } from "../utils"; import { createChunkedMessage, stripObjectToScalars } from "../utils";
import { LogType } from "../data/LogType"; import { LogType } from "../data/LogType";
import { GuildLogs } from "../data/GuildLogs"; import { GuildLogs } from "../data/GuildLogs";
import * as t from "io-ts";
interface IWelcomeMessageConfig { const ConfigSchema = t.type({
send_dm: boolean; send_dm: t.boolean,
send_to_channel: string; send_to_channel: t.string,
message: string; message: t.string,
} });
type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
export class WelcomeMessagePlugin extends ZeppelinPlugin<IWelcomeMessageConfig> { export class WelcomeMessagePlugin extends ZeppelinPlugin<TConfigSchema> {
public static pluginName = "welcome_message"; public static pluginName = "welcome_message";
protected static configSchema = ConfigSchema;
protected logs: GuildLogs; protected logs: GuildLogs;
protected getDefaultOptions(): IPluginOptions<IWelcomeMessageConfig> { protected getDefaultOptions(): IPluginOptions<TConfigSchema> {
return { return {
config: { config: {
send_dm: false, send_dm: false,