UNPKG

frozor-commands

Version:
100 lines (77 loc) 3.31 kB
const { Command } = require('./Command'); const Collection = require('djs-collection'); class CommandParent extends Command { /** * Create a CommandParent instance. This can be used to run sub-commands. * @param data {object} - Data to instantiate the command and parent with. * @Param data.children {Array.<Command|CommandParent>} - Command instances to use as subcommands for the parent. */ constructor(data) { if (!data.children || data.children.length === 0) { throw new Error('Children must be provided to CommandParent'); } if (!Array.isArray(data.children)) { throw new TypeError('Expected type Array in data.children'); } super(data); let depth = 0; const children = new Collection(); for (const child of data.children) { if (!(child instanceof Command)) { throw new TypeError('Expected type Command in children. Did you forget to instantiate it?'); } child.parent = this; for (const name of child.names()) { children.set(name, child); } if (child instanceof CommandParent) { depth = Math.max(depth, child.depth); } } depth += 1; this.maxArgs = Number.POSITIVE_INFINITY; this.depth = depth; this.children = children; } getUsageStatement() { return `${this.name} [${Array.from(this).map(child => child.name).join('|')}]`; } subCommandNotProvided(msg, bot, extra) { return 'Please provide a sub-command to run.'; } subCommandFail(subCommand, msg, bot, extra) { return `Hmm, the sub-command *${subCommand}* doesn't seem to exist.`; } /** * Act on a message's intended action. * If overriding, use this whenever you want to run a sub-command. * Don't forget to strip unnecessary args. * @param action {string} - An action to act upon... this is effectively just a sub-command. * @param msg {object} - The message to act upon. Requires args property and reply method. * @param {object} [bot] - The bot to pass. * @param {object} [extra] - The object to pass. * @return {Promise} - The children's run result. */ act(action, msg, bot, extra) { if (!this.children.has(action)) { return msg.reply(this.subCommandFail(action, msg, bot, extra)); } // Get the child and run it, returning the promise since this is an AsyncFunction return this.children.get(action).run(msg, bot, extra); } async run(msg, bot, extra) { if (msg.args.length === 0) { return msg.reply(this.subCommandNotProvided(msg, bot, extra)); } const subCommand = msg.args[0].toLowerCase(); // Remove the first arg since the next command doesn't care about its own arg. msg.args = msg.args.slice(1); return this.act(subCommand, msg, bot, extra); } *[Symbol.iterator]() { for (const command of new Set(this.children.values())) { yield command; } } } module.exports = CommandParent;