Skip to content

Commit

Permalink
Add command middleware function functionality
Browse files Browse the repository at this point in the history
That `Command#use` doc is ridiculous. I will definitely need to write a detailed help page for it and outsource that info there eventually.
  • Loading branch information
zajrik committed Feb 22, 2017
1 parent 9cf0f95 commit 9beb59b
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 2 deletions.
41 changes: 41 additions & 0 deletions src/lib/command/Command.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ export default class Command
*/
this.overloads = info.overloads || null;

// Middleware function storage for the Command instance
this._middleware = [];

if (this.overloads && this.group !== 'base') throw new Error('Commands may only overload commands in group "base"');

// Default guildOnly to true if permissions/roles are given
Expand Down Expand Up @@ -217,6 +220,44 @@ export default class Command
if (!(this.action instanceof Function)) throw new Error(`Command#${name}.action: expected Function, got: ${typeof this.action}`);
}

/**
* Adds a middleware function to be used when the command is run
* to make modifications to args or determine if the command can
* be run. Takes a function that will receive the message object
* and the array of args.
*
* A middleware function must return an array where the first item
* is the message object and the second item is the args array.
* If a middleware function returns a string, or throws a string/error,
* it will be sent to the calling channel as a message and the command
* execution will be aborted. If a middleware function does not return
* anything or returns something other than an array or string, it will
* fail silently.
*
* Example:
* ```js
* this.use((message, args) => [message, args.map(a => a.toUpperCase())]);
* ```
* This will add a middleware function to the command that will attempt
* to transform all args to uppercase. This will of course fail if any
* of the args are not a string. This could be ensured with the `stringArgs`
* `argOpts` flag, or via another middleware function added before this one
* that converts all args to strings.
*
* Note: Middleware functions should only be added to a command one time each,
* and thus should be added in the Command's constructor. Multiple middleware
* functions can be added to a command via multiple calls to this method
* @memberof Command
* @instance
* @param {Function} fn - Middleware function. `(message, args) => [message, args]`
* @returns {Command} This command instance
*/
use(fn)
{
this._middleware.push(fn);
return this;
}

// Send provided response text to the command's calling channel
// via edit, editCode, sendMessage, or sendCode depending on Whether
// or not the bot is a selfbot and/or a codeblock language is given
Expand Down
26 changes: 24 additions & 2 deletions src/lib/command/CommandDispatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,29 @@ export default class CommandDispatcher
if (!this.hasRoles(dm, message, command)) return this.missingRolesError(message, command);
if (guildStorage) message.guild.storage = guildStorage;

await this.dispatch(command, message, args, mentions, original).catch(console.error);
let middlewarePassed = true;
for (const middleware of command._middleware)
try
{
let result = middleware(message, args);
if (!(result instanceof Array))
{
if (typeof result === 'string') message.channel.send(result);
middlewarePassed = false;
break;
}
[message, args] = result;
}
catch (err)
{
middlewarePassed = false;
message.channel.send(err.toString());
break;
}

if (middlewarePassed)
await this.dispatch(command, message, args, mentions, original).catch(console.error);

const dispatchEnd = now() - dispatchStart;

/**
Expand Down Expand Up @@ -147,7 +169,7 @@ export default class CommandDispatcher
.map(a => typeof a === 'string' ? a.trim() : a)
.filter(a => a !== '' && !(typeof a !== 'string' && isNaN(a)));

return { command: command, mentions: mentions, args: args, content: content, dm: dm };
return { command, mentions, args, content, dm };
}

/**
Expand Down

0 comments on commit 9beb59b

Please sign in to comment.