diff --git a/package-lock.json b/package-lock.json index f728fad7..9788ade9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2560,9 +2560,9 @@ } }, "@types/node": { - "version": "10.12.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.0.tgz", - "integrity": "sha512-3TUHC3jsBAB7qVRGxT6lWyYo2v96BMmD2PTcl47H25Lu7UXtFH/2qqmKiVrnel6Ne//0TFYf6uvNX+HW2FRkLQ==" + "version": "12.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.5.tgz", + "integrity": "sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w==" }, "@types/oauth": { "version": "0.9.1", @@ -8299,16 +8299,49 @@ "dev": true }, "knub": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/knub/-/knub-22.0.0.tgz", - "integrity": "sha512-QHMqSS8eVBVX0vMff8lEkWhO7mOVXdobUrNOuAMI7ldto0Aakf0oNdDnwRXFj0yNb5Sp1fvzYFt35nsx/ORqkw==", + "version": "24.0.0", + "resolved": "https://registry.npmjs.org/knub/-/knub-24.0.0.tgz", + "integrity": "sha512-qQimi9L3p1kVV08TI3MeSN8J2CzjrYwGLVpN8IiwBvvbRFPJcVcSzvw3CSTbs594m6Zr8/MnXdh5fDQBGuMI6Q==", "requires": { - "escape-string-regexp": "^1.0.5", - "lodash.at": "^4.6.0", - "lodash.difference": "^4.5.0", - "lodash.merge": "^4.6.2", - "reflect-metadata": "^0.1.10", - "ts-essentials": "^2.0.3" + "escape-string-regexp": "^2.0.0", + "knub-command-manager": "^5.1.0", + "reflect-metadata": "^0.1.13", + "ts-essentials": "^2.0.12" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "knub-command-manager": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/knub-command-manager/-/knub-command-manager-5.1.0.tgz", + "integrity": "sha512-zxYwglsdAVbskoU0WYc6nB9+nJVYQIhwLz0olvQyYprV0EIU0Wo7QDeAHbcEQUMDZEmJ1jfVAEzGGwvSHItIpA==", + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + } + } + }, + "knub-command-manager": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/knub-command-manager/-/knub-command-manager-5.1.0.tgz", + "integrity": "sha512-zxYwglsdAVbskoU0WYc6nB9+nJVYQIhwLz0olvQyYprV0EIU0Wo7QDeAHbcEQUMDZEmJ1jfVAEzGGwvSHItIpA==", + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + } } }, "last-commit-log": { @@ -8561,11 +8594,6 @@ "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, - "lodash.at": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.at/-/lodash.at-4.6.0.tgz", - "integrity": "sha1-k83OZk8KGZTqM9181A4jr9EbD/g=" - }, "lodash.chunk": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz", @@ -8597,11 +8625,6 @@ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, "lodash.pick": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", diff --git a/package.json b/package.json index 9b9cc694..0f87827c 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,8 @@ "humanize-duration": "^3.15.0", "io-ts": "^2.0.0", "js-yaml": "^3.13.1", - "knub": "^22.0.0", + "knub": "^24.0.0", + "knub-command-manager": "^5.1.0", "last-commit-log": "^2.1.0", "lodash.chunk": "^4.2.0", "lodash.clonedeep": "^4.5.0", @@ -63,7 +64,7 @@ "@types/js-yaml": "^3.12.1", "@types/lodash.at": "^4.6.3", "@types/moment-timezone": "^0.5.6", - "@types/node": "^10.12.0", + "@types/node": "^12.7.5", "@types/passport": "^1.0.0", "@types/passport-oauth2": "^1.4.8", "@types/tmp": "0.0.33", diff --git a/src/PluginRuntimeError.ts b/src/PluginRuntimeError.ts index b5364c70..ce84b83c 100644 --- a/src/PluginRuntimeError.ts +++ b/src/PluginRuntimeError.ts @@ -11,7 +11,7 @@ export class PluginRuntimeError { this.guildId = guildId; } - [util.inspect.custom](depth, options) { + [util.inspect.custom](depth?, options?) { return `PRE [${this.pluginName}] [${this.guildId}] ${this.message}`; } diff --git a/src/api/docs.ts b/src/api/docs.ts index 324a1079..09b57185 100644 --- a/src/api/docs.ts +++ b/src/api/docs.ts @@ -2,10 +2,9 @@ import express from "express"; import { availablePlugins } from "../plugins/availablePlugins"; import { ZeppelinPlugin } from "../plugins/ZeppelinPlugin"; import { notFound } from "./responses"; -import { CommandManager, ICommandConfig } from "knub/dist/CommandManager"; import { dropPropertiesByName, indentLines } from "../utils"; - -const commandManager = new CommandManager(); +import { IPluginCommandConfig, Plugin, pluginUtils } from "knub"; +import { parseParameters } from "knub-command-manager"; function formatConfigSchema(schema) { if (schema._tag === "InterfaceType" || schema._tag === "PartialType") { @@ -79,20 +78,20 @@ export function initDocs(app: express.Express) { const props = Reflect.ownKeys(pluginClass.prototype); const commands = props.reduce((arr, prop) => { if (typeof prop !== "string") return arr; - const propCommands = Reflect.getMetadata("commands", pluginClass.prototype, prop); - if (propCommands) { + const decoratorCommands = pluginUtils.getPluginDecoratorCommands(pluginClass as typeof Plugin); + if (decoratorCommands) { arr.push( - ...propCommands.map(cmd => { - const trigger = typeof cmd.command === "string" ? cmd.command : cmd.command.source; + ...decoratorCommands.map(cmd => { + const trigger = typeof cmd.trigger === "string" ? cmd.trigger : cmd.trigger.source; const parameters = cmd.parameters ? typeof cmd.parameters === "string" - ? commandManager.parseParameterString(cmd.parameters) + ? parseParameters(cmd.parameters) : cmd.parameters : []; - const config: ICommandConfig = cmd.options || {}; + const config: IPluginCommandConfig = cmd.config || {}; if (config.overloads) { config.overloads = config.overloads.map(overload => { - return typeof overload === "string" ? commandManager.parseParameterString(overload) : overload; + return typeof overload === "string" ? parseParameters(overload) : overload; }); } diff --git a/src/customArgumentTypes.ts b/src/customArgumentTypes.ts index 47869fbf..22d85cf1 100644 --- a/src/customArgumentTypes.ts +++ b/src/customArgumentTypes.ts @@ -6,41 +6,42 @@ import { resolveUser, UnknownUser, } from "./utils"; -import { CommandArgumentTypeError } from "knub"; import { Client, GuildChannel, Message } from "eris"; +import { TypeConversionError } from "knub-command-manager"; +import { ICommandContext } from "knub"; export const customArgumentTypes = { delay(value) { const result = convertDelayStringToMS(value); if (result == null) { - throw new CommandArgumentTypeError(`Could not convert ${value} to a delay`); + throw new TypeConversionError(`Could not convert ${value} to a delay`); } return result; }, - async resolvedUser(value, msg, bot: Client) { - const result = await resolveUser(bot, value); + async resolvedUser(value, context: ICommandContext) { + const result = await resolveUser(context.bot, value); if (result == null || result instanceof UnknownUser) { - throw new CommandArgumentTypeError(`User \`${disableCodeBlocks(value)}\` was not found`); + throw new TypeConversionError(`User \`${disableCodeBlocks(value)}\` was not found`); } return result; }, - async resolvedUserLoose(value, msg, bot: Client) { - const result = await resolveUser(bot, value); + async resolvedUserLoose(value, context: ICommandContext) { + const result = await resolveUser(context.bot, value); if (result == null) { - throw new CommandArgumentTypeError(`Invalid user: \`${disableCodeBlocks(value)}\``); + throw new TypeConversionError(`Invalid user: \`${disableCodeBlocks(value)}\``); } return result; }, - async resolvedMember(value, msg: Message, bot: Client) { - if (!(msg.channel instanceof GuildChannel)) return null; + async resolvedMember(value, context: ICommandContext) { + if (!(context.message.channel instanceof GuildChannel)) return null; - const result = await resolveMember(bot, msg.channel.guild, value); + const result = await resolveMember(context.bot, context.message.channel.guild, value); if (result == null) { - throw new CommandArgumentTypeError( + throw new TypeConversionError( `Member \`${disableCodeBlocks(value)}\` was not found or they have left the server`, ); } diff --git a/src/plugins/ChannelArchiver.ts b/src/plugins/ChannelArchiver.ts index 93af4cc5..421604af 100644 --- a/src/plugins/ChannelArchiver.ts +++ b/src/plugins/ChannelArchiver.ts @@ -1,4 +1,4 @@ -import { decorators as d, logger } from "knub"; +import { decorators as d, ICommandContext, logger } from "knub"; import { GlobalZeppelinPlugin } from "./GlobalZeppelinPlugin"; import { Attachment, GuildChannel, Message, TextChannel } from "eris"; import { confirm, downloadFile, errorMessage, noop, SECONDS, trimLines } from "../utils"; @@ -57,8 +57,8 @@ export class ChannelArchiverPlugin extends ZeppelinPlugin { }, ], preFilters: [ - (msg, command, plugin: ChannelArchiverPlugin) => { - return plugin.isOwner(msg.author.id); + (command, context: ICommandContext) => { + return (context.plugin as ChannelArchiverPlugin).isOwner(context.message.author.id); }, ], }) diff --git a/src/plugins/CustomEvents.ts b/src/plugins/CustomEvents.ts index d2e8281d..84e82bec 100644 --- a/src/plugins/CustomEvents.ts +++ b/src/plugins/CustomEvents.ts @@ -87,7 +87,7 @@ export class CustomEventsPlugin extends ZeppelinPlugin { onLoad() { for (const [key, event] of Object.entries(this.getConfig().events)) { if (event.trigger.type === "command") { - this.commands.add( + this.addCommand( event.trigger.name, event.trigger.params, (msg, args) => { @@ -95,8 +95,9 @@ export class CustomEventsPlugin extends ZeppelinPlugin { this.runEvent(event, { msg, args }, { args, msg: strippedMsg }); }, { - requiredPermission: `events.${key}.trigger.can_use`, - locks: [], + extra: { + requiredPermission: `events.${key}.trigger.can_use`, + }, }, ); } diff --git a/src/plugins/LocateUser.ts b/src/plugins/LocateUser.ts index d859f17c..ed946baf 100644 --- a/src/plugins/LocateUser.ts +++ b/src/plugins/LocateUser.ts @@ -78,8 +78,10 @@ export class LocatePlugin extends ZeppelinPlugin { } @d.command("where", "", { - info: { - description: "Posts an instant invite to the voice channel that `` is in", + extra: { + info: { + description: "Posts an instant invite to the voice channel that `` is in", + }, }, }) @d.permission("can_where") @@ -90,8 +92,10 @@ export class LocatePlugin extends ZeppelinPlugin { @d.command("vcalert", " [duration:delay] [reminder:string$]", { aliases: ["vca"], - info: { - description: "Sets up an alert that notifies you any time `` switches or joins voice channels", + extra: { + info: { + description: "Sets up an alert that notifies you any time `` switches or joins voice channels", + }, }, }) @d.permission("can_alert") diff --git a/src/plugins/ModActions.ts b/src/plugins/ModActions.ts index 093e9629..de1d1dea 100644 --- a/src/plugins/ModActions.ts +++ b/src/plugins/ModActions.ts @@ -483,9 +483,11 @@ export class ModActionsPlugin extends ZeppelinPlugin { @d.command("update", " [note:string$]", { overloads: ["[note:string$]"], - info: { - description: - "Update the specified case (or, if case number is omitted, your latest case) by adding more notes/details to it", + extra: { + info: { + description: + "Update the specified case (or, if case number is omitted, your latest case) by adding more notes/details to it", + }, }, }) @d.permission("can_note") @@ -527,8 +529,10 @@ export class ModActionsPlugin extends ZeppelinPlugin { } @d.command("note", " ", { - info: { - description: "Add a note to the specified user", + extra: { + info: { + description: "Add a note to the specified user", + }, }, }) @d.permission("can_note") @@ -552,8 +556,10 @@ export class ModActionsPlugin extends ZeppelinPlugin { @d.command("warn", " ", { options: [{ name: "mod", type: "member" }], - info: { - description: "Send a warning to the specified user", + extra: { + info: { + description: "Send a warning to the specified user", + }, }, }) @d.permission("can_warn") @@ -757,8 +763,10 @@ export class ModActionsPlugin extends ZeppelinPlugin { @d.command("mute", " ", { overloads: [" ", " [reason:string$]"], options: [{ name: "mod", type: "member" }], - info: { - description: "Mute the specified member", + extra: { + info: { + description: "Mute the specified member", + }, }, }) @d.permission("can_mute") @@ -798,8 +806,10 @@ export class ModActionsPlugin extends ZeppelinPlugin { @d.command("forcemute", " ", { overloads: [" ", " [reason:string$]"], options: [{ name: "mod", type: "member" }], - info: { - description: "Force-mute the specified user, even if they're not on the server", + extra: { + info: { + description: "Force-mute the specified user, even if they're not on the server", + }, }, }) @d.permission("can_mute") @@ -876,8 +886,10 @@ export class ModActionsPlugin extends ZeppelinPlugin { @d.command("unmute", " ", { overloads: [" ", " [reason:string$]"], options: [{ name: "mod", type: "member" }], - info: { - description: "Unmute the specified member", + extra: { + info: { + description: "Unmute the specified member", + }, }, }) @d.permission("can_mute") @@ -921,8 +933,10 @@ export class ModActionsPlugin extends ZeppelinPlugin { @d.command("forceunmute", " ", { overloads: [" ", " [reason:string$]"], options: [{ name: "mod", type: "member" }], - info: { - description: "Force-unmute the specified user, even if they're not on the server", + extra: { + info: { + description: "Force-unmute the specified user, even if they're not on the server", + }, }, }) @d.permission("can_mute") @@ -950,8 +964,10 @@ export class ModActionsPlugin extends ZeppelinPlugin { @d.command("kick", " [reason:string$]", { options: [{ name: "mod", type: "member" }], - info: { - description: "Kick the specified member", + extra: { + info: { + description: "Kick the specified member", + }, }, }) @d.permission("can_kick") @@ -1011,8 +1027,10 @@ export class ModActionsPlugin extends ZeppelinPlugin { @d.command("ban", " [reason:string$]", { options: [{ name: "mod", type: "member" }], - info: { - description: "Ban the specified member", + extra: { + info: { + description: "Ban the specified member", + }, }, }) @d.permission("can_ban") @@ -1072,9 +1090,11 @@ export class ModActionsPlugin extends ZeppelinPlugin { @d.command("softban", " [reason:string$]", { options: [{ name: "mod", type: "member" }], - info: { - description: - '"Softban" the specified user by banning and immediately unbanning them. Effectively a kick with message deletions.', + extra: { + info: { + description: + '"Softban" the specified user by banning and immediately unbanning them. Effectively a kick with message deletions.', + }, }, }) @d.permission("can_ban") @@ -1162,8 +1182,10 @@ export class ModActionsPlugin extends ZeppelinPlugin { @d.command("unban", " [reason:string$]", { options: [{ name: "mod", type: "member" }], - info: { - description: "Unban the specified member", + extra: { + info: { + description: "Unban the specified member", + }, }, }) @d.permission("can_ban") @@ -1216,8 +1238,10 @@ export class ModActionsPlugin extends ZeppelinPlugin { @d.command("forceban", " [reason:string$]", { options: [{ name: "mod", type: "member" }], - info: { - description: "Force-ban the specified user, even if they aren't on the server", + extra: { + info: { + description: "Force-ban the specified user, even if they aren't on the server", + }, }, }) @d.permission("can_ban") @@ -1283,8 +1307,10 @@ export class ModActionsPlugin extends ZeppelinPlugin { } @d.command("massban", "", { - info: { - description: "Mass-ban a list of user IDs", + extra: { + info: { + description: "Mass-ban a list of user IDs", + }, }, }) @d.permission("can_massban") @@ -1370,8 +1396,10 @@ export class ModActionsPlugin extends ZeppelinPlugin { @d.command("addcase", " [reason:string$]", { options: [{ name: "mod", type: "member" }], - info: { - description: "Add an arbitrary case to the specified user without taking any action", + extra: { + info: { + description: "Add an arbitrary case to the specified user without taking any action", + }, }, }) @d.permission("can_addcase") @@ -1434,8 +1462,10 @@ export class ModActionsPlugin extends ZeppelinPlugin { } @d.command("case", "", { - info: { - description: "Show information about a specific case", + extra: { + info: { + description: "Show information about a specific case", + }, }, }) @d.permission("can_view") @@ -1465,8 +1495,10 @@ export class ModActionsPlugin extends ZeppelinPlugin { shortcut: "h", }, ], - info: { - description: "Show a list of cases the specified user has", + extra: { + info: { + description: "Show a list of cases the specified user has", + }, }, }) @d.permission("can_view") @@ -1532,8 +1564,10 @@ export class ModActionsPlugin extends ZeppelinPlugin { @d.command("cases", null, { options: [{ name: "mod", type: "Member" }], - info: { - description: "Show the most recent 5 cases by the specified --mod", + extra: { + info: { + description: "Show the most recent 5 cases by the specified --mod", + }, }, }) @d.permission("can_view") @@ -1561,8 +1595,10 @@ export class ModActionsPlugin extends ZeppelinPlugin { } @d.command("hidecase", "", { - info: { - description: "Hide the specified case so it doesn't appear in !cases or !info", + extra: { + info: { + description: "Hide the specified case so it doesn't appear in !cases or !info", + }, }, }) @d.permission("can_hidecase") @@ -1580,8 +1616,10 @@ export class ModActionsPlugin extends ZeppelinPlugin { } @d.command("unhidecase", "", { - info: { - description: "Un-hide the specified case, making it appear in !cases and !info again", + extra: { + info: { + description: "Un-hide the specified case, making it appear in !cases and !info again", + }, }, }) @d.permission("can_hidecase") diff --git a/src/plugins/Tags.ts b/src/plugins/Tags.ts index a6570600..742bbc26 100644 --- a/src/plugins/Tags.ts +++ b/src/plugins/Tags.ts @@ -10,6 +10,7 @@ import { ZeppelinPlugin } from "./ZeppelinPlugin"; import { parseTemplate, renderTemplate, TemplateParseError } from "../templateFormatter"; import { GuildArchives } from "../data/GuildArchives"; import * as t from "io-ts"; +import { parseArguments } from "knub-command-manager"; const ConfigSchema = t.type({ prefix: t.string, @@ -233,7 +234,7 @@ export class TagsPlugin extends ZeppelinPlugin { // Substitute variables (matched with Knub's argument parser -> supports quotes etc.) const variableStr = msg.data.content.slice(prefix.length + tagName.length).trim(); - const tagArgs = this.commands.parseArguments(variableStr).map(v => v.value); + const tagArgs = parseArguments(variableStr).map(v => v.value); // Format the string try { diff --git a/src/plugins/Utility.ts b/src/plugins/Utility.ts index ae4037e4..b736a7d2 100644 --- a/src/plugins/Utility.ts +++ b/src/plugins/Utility.ts @@ -1,4 +1,11 @@ -import { decorators as d, getCommandSignature, IPluginOptions, ICommandDefinition, waitForReaction } from "knub"; +import { + decorators as d, + getCommandSignature, + ICommandContext, + ICommandExtraData, + IPluginOptions, + waitForReaction, +} from "knub"; import { CategoryChannel, Channel, @@ -45,6 +52,7 @@ import { ZeppelinPlugin } from "./ZeppelinPlugin"; import { getCurrentUptime } from "../uptime"; import LCL from "last-commit-log"; import * as t from "io-ts"; +import { ICommandDefinition } from "knub-command-manager"; const ConfigSchema = t.type({ can_roles: t.boolean, @@ -959,17 +967,18 @@ export class UtilityPlugin extends ZeppelinPlugin { helpCmd(msg: Message, args: { command: string }) { const searchStr = args.command.toLowerCase(); - const matchingCommands: ICommandDefinition[] = []; + const matchingCommands: Array> = []; const guildData = this.knub.getGuildData(this.guildId); for (const plugin of guildData.loadedPlugins.values()) { if (!(plugin instanceof ZeppelinPlugin)) continue; - const commands = plugin.getRegisteredCommands(); - for (const command of commands) { - const trigger = command.trigger.source.toLowerCase(); - if (trigger.startsWith(searchStr)) { - matchingCommands.push(command); + const registeredCommands = plugin.getRegisteredCommands(); + for (const registeredCommand of registeredCommands) { + for (const trigger of registeredCommand.command.triggers) { + if (trigger.source.startsWith(searchStr)) { + matchingCommands.push(registeredCommand.command); + } } } } @@ -977,16 +986,7 @@ export class UtilityPlugin extends ZeppelinPlugin { const totalResults = matchingCommands.length; const limitedResults = matchingCommands.slice(0, 15); const signatures = limitedResults.map(command => { - return ( - "`" + - getCommandSignature( - guildData.config.prefix, - command.trigger.source, - command.parameters, - command.config.options, - ) + - "`" - ); + return "`" + getCommandSignature(command) + "`"; }); if (totalResults === 0) { diff --git a/src/plugins/ZeppelinPlugin.ts b/src/plugins/ZeppelinPlugin.ts index db16e904..2c891503 100644 --- a/src/plugins/ZeppelinPlugin.ts +++ b/src/plugins/ZeppelinPlugin.ts @@ -184,13 +184,6 @@ export class ZeppelinPlugin extends Plug } } - /** - * Intended for cross-plugin functionality - */ - public getRegisteredCommands() { - return this.commands.commands; - } - /** * Intended for cross-plugin functionality */