Skip to content

Commit

Permalink
Add command metadata decorators
Browse files Browse the repository at this point in the history
Can be used in place of a constructor with a CommandInfo object when creating commands with TypeScript. Not sure if these decorators are Babel compatible or not. The bare minimum metadata a command needs to function is @name, @description, and @Usage. I will likely apply this to CommandInfo as well later on.
  • Loading branch information
zajrik committed Mar 17, 2017
1 parent ca0becd commit 32c0949
Show file tree
Hide file tree
Showing 3 changed files with 260 additions and 79 deletions.
91 changes: 46 additions & 45 deletions src/lib/command/Command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,29 +34,6 @@ export class Command<T extends Bot>

public constructor(bot: T, info: CommandInfo = null)
{
// Assert necessary command information
const name: string = this.constructor.name;
if (!info) throw new Error(`You must provide an info object for command: ${name}`);
if (!info.name) throw new Error(`You must provide a name for command: ${name}`);
if (!info.description) throw new Error(`You must provide a description for command: ${name}`);
if (!info.usage) throw new Error(`You must provide usage information for command: ${name}`);
if (!info.group) throw new Error(`You must provide a group for command: ${name}`);
if (info.aliases && !Array.isArray(info.aliases)) throw new Error(`Aliases for command ${name} must be an array`);
if (info.permissions && !Array.isArray(info.permissions)) throw new Error(`Permissions for command ${name} must be an array`);
if (info.permissions && info.permissions.length > 0)
info.permissions.forEach((perm: PermissionResolvable, index: number) =>
{
try
{
(<any> bot).resolver.resolvePermission(perm);
}
catch (err)
{
throw new Error(`Command#${name} permission "${info.permissions[index]}" at ${name}.permissions[${index}] is not a valid permission.\n\n${err}`);
}
});
if (info.roles && !Array.isArray(info.roles)) throw new Error(`Roles for command ${name} must be an array`);

/**
* Bot instance
* @memberof Command
Expand All @@ -74,7 +51,6 @@ export class Command<T extends Bot>
* @name name
* @instance
*/
this.name = info.name;

/**
* A brief description of the command, displayed
Expand All @@ -84,7 +60,6 @@ export class Command<T extends Bot>
* @name description
* @instance
*/
this.description = info.description;

/**
* An example of command usage. The token '&lt;prefix&gt;' will
Expand All @@ -95,7 +70,6 @@ export class Command<T extends Bot>
* @name usage
* @instance
*/
this.usage = info.usage;

/**
* Extra information about the command to be displayed
Expand All @@ -105,7 +79,6 @@ export class Command<T extends Bot>
* @name extraHelp
* @instance
*/
this.extraHelp = info.extraHelp;

/**
* The command group that the command belongs to. Allows commands to be
Expand All @@ -115,7 +88,6 @@ export class Command<T extends Bot>
* @name group
* @instance
*/
this.group = info.group;

/**
* Aliases the command can be called by other than its name
Expand All @@ -124,7 +96,6 @@ export class Command<T extends Bot>
* @name aliases
* @instance
*/
this.aliases = info.aliases || [];

/**
* Whether or not a command can only be used within a
Expand All @@ -134,13 +105,15 @@ export class Command<T extends Bot>
* @name guildOnly
* @instance
*/
this.guildOnly = info.guildOnly || false;

/**
* Whether or not the command is to be hidden from the
* commands list via the default help command
* @memberof Command
* @type {boolean}
* @name hidden
* @instance
*/
this.hidden = info.hidden || false;

/**
* Options for how arguments should be parsed. See: {@link ArgOpts}
Expand All @@ -149,8 +122,6 @@ export class Command<T extends Bot>
* @name argOpts
* @instance
*/
this.argOpts = info.argOpts || {};
this.argOpts.separator = this.argOpts.separator || ' ';

/**
* Array of permissions required by the command
Expand All @@ -162,7 +133,6 @@ export class Command<T extends Bot>
* @name permissions
* @instance
*/
this.permissions = info.permissions || [];

/**
* Array of roles required to use the command. If the command caller
Expand All @@ -174,7 +144,6 @@ export class Command<T extends Bot>
* @name roles
* @instance
*/
this.roles = info.roles || [];

/**
* Whether or not the command can be used by the bot owner(s).
Expand All @@ -184,7 +153,6 @@ export class Command<T extends Bot>
* @instance
* @see [Bot#config.owner]{@link Bot#config}
*/
this.ownerOnly = info.ownerOnly || false;

/**
* The name of a base command to overload. Commands may only overload
Expand All @@ -195,19 +163,15 @@ export class Command<T extends Bot>
* @name overloads
* @instance
*/
this.overloads = info.overloads || null;

// Create the RateLimiter instance if a ratelimit is specified
if (info.ratelimit)
this._rateLimiter = new RateLimiter(info.ratelimit, false);

// 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"');
if (info) Object.assign(this, info);

// Default guildOnly to true if permissions/roles are given
if (this.permissions.length > 0 || this.roles.length > 0) this.guildOnly = true;
// Create the RateLimiter instance if a ratelimit is specified
if (info && info.ratelimit)
this._rateLimiter = new RateLimiter(info.ratelimit, false);
}

/**
Expand All @@ -234,7 +198,44 @@ export class Command<T extends Bot>
*/
public register(): void
{
let name: string = this.constructor.name;
const name: string = this.constructor.name;

// Set defaults if not present
if (!this.aliases) this.aliases = [];
if (!this.group) this.group = 'base';
if (!this.guildOnly) this.guildOnly = false;
if (!this.hidden) this.hidden = false;
if (!this.argOpts) this.argOpts = {};
if (!this.argOpts.separator) this.argOpts.separator = ' ';
if (!this.permissions) this.permissions = [];
if (!this.roles) this.roles = [];
if (!this.ownerOnly) this.ownerOnly = false;

// Make necessary asserts
if (!this.name) throw new Error(`You must provide a name for command: ${name}`);
if (!this.description) throw new Error(`You must provide a description for command: ${name}`);
if (!this.usage) throw new Error(`You must provide usage information for command: ${name}`);
if (!this.group) throw new Error(`You must provide a group for command: ${name}`);
if (this.aliases && !Array.isArray(this.aliases)) throw new Error(`Aliases for command ${name} must be an array`);
if (this.permissions && !Array.isArray(this.permissions)) throw new Error(`Permissions for command ${name} must be an array`);
if (this.permissions && this.permissions.length > 0)
this.permissions.forEach((perm: PermissionResolvable, index: number) =>
{
try
{
(<any> this.bot).resolver.resolvePermission(perm);
}
catch (err)
{
throw new Error(`Command#${name} permission "${this.permissions[index]}" at ${name}.permissions[${index}] is not a valid permission.\n\n${err}`);
}
});
if (this.roles && !Array.isArray(this.roles)) throw new Error(`Roles for command ${name} must be an array`);
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
if (this.permissions.length > 0 || this.roles.length > 0) this.guildOnly = true;

if (!this.action) throw new Error(`Command#${name}.action: expected Function, got: ${typeof this.action}`);
if (!(this.action instanceof Function)) throw new Error(`Command#${name}.action: expected Function, got: ${typeof this.action}`);
}
Expand Down
Loading

0 comments on commit 32c0949

Please sign in to comment.