cumsystem
Version:
simple command system and command handler
446 lines (445 loc) • 16.9 kB
JavaScript
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
var Discord = __importStar(require("discord.js"));
var System_1 = require("./System");
System_1.System; // eslint .. ./.,,,, ,
function parseUser(bot, parse, guild) {
if (parse.startsWith('<@') && parse.startsWith('>')) {
parse = parse.substr(2, parse.length - 3);
}
if (!isNaN(Number(parse))) {
var user = bot.users.cache.get(parse);
if (user !== undefined)
return user;
}
else {
if (parse.split('#').length === 2) {
var name_1 = parse.split('#')[0];
var discrim_1 = parse.split('#')[1];
var users = bot.users.cache.filter(function (u) { return u.username === name_1 && u.discriminator === discrim_1; });
if (users.size === 1) {
return users.first() || null;
}
}
if (guild) {
var users = guild.members.cache.filter(function (u) { var _a; return u.nickname !== null && ((_a = u.nickname) === null || _a === void 0 ? void 0 : _a.toLowerCase().startsWith(parse.toLowerCase())); });
if (users.size > 0) {
var user = users.first();
if (user)
return user.user;
}
users = guild.members.cache.filter(function (u) { var _a; return u.nickname !== null && ((_a = u.nickname) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === parse.toLowerCase(); });
if (users.size > 0) {
var user = users.first();
if (user)
return user.user;
}
users = guild.members.cache.filter(function (u) { return u.user.username.toLowerCase() === parse.toLowerCase(); });
if (users.size > 0) {
var user = users.first();
if (user)
return user.user;
}
users = guild.members.cache.filter(function (u) { return u.user.username.toLowerCase().startsWith(parse.toLowerCase()); });
if (users.size > 0) {
var user = users.first();
if (user)
return user.user;
}
}
}
return null;
}
/**
* Represents a command the bot can run (for example, a help command)
*
* `content` is a variable that is the message's content without the prefix. For example:
*
* `msg.content`: `!say abcdefg aa aa`
*
* `content`: `abcdefg aa aa`
*/
var Command = /** @class */ (function () {
/**
* Create a command
* @example
* ```typescript
* let command = new CommandSystem.Command('test', msg => {
* msg.channel.send('Testing!');
* });
* ```
* @param {string} name The name, also what invokes the command
* @param {function} cfunction The function to run after the command is ran
*/
function Command(name, cfunction) {
this.globalCooldowns = 0;
this.userCooldowns = {};
this.name = name;
this.cfunc = cfunction;
this.category = 'uncategorized';
this.usage = '';
this.displayUsage = '';
this.clientPermissions = [];
this.userPermissions = [];
this.needsDM = false;
this.needsGuild = false;
this.hidden = false;
this.ignorePrefix = false;
this.ownerOnly = false;
this.nsfwOnly = false;
this.description = '';
this.aliases = [];
this.examples = [];
this.globalCooldown = 0;
this.userCooldown = 0;
return this;
}
/**
* Change the command name
* @param {string} name The name to use for the command
* @returns {Command} Itself
*/
Command.prototype.setName = function (name) {
this.name = name;
return this;
};
/**
* Sets the usage of the command. Will be used for checking the syntax!!, use `Command#setDisplayUsage` to set a display usage.
*
* Types available:
* - `user`
* - `number`
* - `id`
* - `url`
* - `string` / `any`
*
* @example
* ```typescript
* new Command('', message => {
* message.channel.send('usage test passed!');
* })
* .setUsage('(string) (number) (user)')
* .setDisplayUsage('(parameter 1) (parameter 2) (parameter 3)');
* ```
* @param {string} usage the usage, use () for necessary and [] for optional arguments
* @returns {Command} Itself
*/
Command.prototype.setUsage = function (usage) {
this.usage = usage;
this.displayUsage = usage;
return this;
};
/**
* Changes the usage in the help command. Isn't parsed
* @param {string} usage the usage
* @returns {Command} Itself
*/
Command.prototype.setDisplayUsage = function (usage) {
this.displayUsage = usage;
return this;
};
/**
* Add an example usage to the command
* @example
* ```typescript
* new Command('', message => {
* message.channel.send('usage test passed!');
* })
* .setUsage('(string) (number) (user)')
* .setDisplayUsage('(parameter 1) (parameter 2) (parameter 3)')
* .addExample('text 1 551929694019256333');
* ```
* @param {string} example an example usage of the command
* @returns {Command} Itself
*/
Command.prototype.addExample = function (example) {
this.examples.push(example);
return this;
};
/**
* Adds an alias which the command can be invoked with
* @param {string} alias the name of the alias
* @returns {Command} Itself
*/
Command.prototype.addAlias = function (alias) {
this.aliases.push(alias);
return this;
};
/**
* Adds aliases which the command can be invoked with
* @param {string[]} aliases an array of alias names
* @returns {Command} Itself
*/
Command.prototype.addAliases = function (aliases) {
var _this = this;
aliases.forEach(function (alias) {
_this.addAlias(alias);
});
return this;
};
/**
* Sets the command's decription, display only
* @param {string} desc the description, leave empty to remove
* @returns {Command} Itself
*/
Command.prototype.setDescription = function (desc) {
this.description = desc === undefined ? 'No description provided' : desc;
return this;
};
/**
* Sets the command's category, display only
* @param {string} category the category, leave empty to remove
* @returns {Command} Itself
*/
Command.prototype.setCategory = function (category) {
this.category = (category === null || category === void 0 ? void 0 : category.toLowerCase()) || 'uncategorized';
return this;
};
/**
* Change the command's visibility in the help command
* @param {boolean} hide
* @returns {Command} Itself
*/
Command.prototype.setHidden = function (hide) {
this.hidden = hide === undefined ? true : hide;
return this;
};
/**
* Set the command to be ran as owner only
* @param {boolean} owner
* @returns {Command} Itself
*/
Command.prototype.setOwnerOnly = function (owner) {
this.ownerOnly = owner === undefined ? true : owner;
return this;
};
/**
* Set whether the command is able to be ran outside dms or not
* @param {boolean} needs
* @returns {Command} Itself
*/
Command.prototype.setDMOnly = function (needs) {
this.needsDM = needs === undefined ? true : needs;
this.needsGuild = !this.needsDM;
return this;
};
/**
* Set whether the command is able to be ran outside servers or not
* @param {boolean} needs
* @returns {Command} Itself
*/
Command.prototype.setGuildOnly = function (needs) {
this.needsGuild = needs === undefined ? true : needs;
this.needsDM = !this.needsGuild;
return this;
};
/**
* Set whether the command can only be ran in an NSFW channel or a DM
* @param {boolean} needs
* @returns {Command} Itself
*/
Command.prototype.setNSFW = function (needs) {
this.nsfwOnly = needs === undefined ? true : needs;
return this;
};
/**
* Set whether the command ignores any given custom prefixes (only really useful for commands that change the prefix)
* @param {boolean} needs
* @returns {Command} Itself
*/
Command.prototype.setIgnorePrefix = function (needs) {
this.ignorePrefix = needs === undefined ? true : needs;
return this;
};
/**
* Add a permission required for the client to run the command
* @param {Discord.PermissionResolvable} perm The permission to add
* @returns {Command} Itself
*/
Command.prototype.addClientPermission = function (perm) {
if (Object.keys(Discord.Permissions.FLAGS).includes(perm.toString())) {
this.clientPermissions.push(perm);
}
else {
process.emitWarning("Unknown permission: " + perm);
}
return this;
};
/**
* add a permission required for the user to invoke the command
* @param {Discord.PermissionResolvable} perm the permission to add
* @returns {Command} Itself
*/
Command.prototype.addUserPermission = function (perm) {
if (Object.keys(Discord.Permissions.FLAGS).includes(perm.toString())) {
this.userPermissions.push(perm);
}
else {
process.emitWarning("Unknown permission: " + perm);
}
return this;
};
/**
* add multiple permissions required for the client to run the command
* @param {Discord.PermissionResolvable[]} perms an array of permissions to add
* @returns {Command} Itself
*/
Command.prototype.addClientPermissions = function (perms) {
var _this = this;
perms.forEach(function (perm) {
_this.addClientPermission(perm);
});
return this;
};
/**
* add multiple permissions required for the user to invoke the command
* @param {Discord.PermissionResolvable[]} perms an array of permissions to add
* @returns {Command} Itself
*/
Command.prototype.addUserPermissions = function (perms) {
var _this = this;
perms.forEach(function (perm) {
_this.addUserPermission(perm);
});
return this;
};
/**
* Set a per-user cooldown on the command to prevent it from being spammed
* @param {number} time the cooldown in ms
* @returns {Command} Itself
*/
Command.prototype.setUserCooldown = function (time) {
this.userCooldown = time;
return this;
};
/**
* Set a global cooldown on the command to prevent it from being spammed
* @param {number} time the cooldown in ms
* @returns {Command} Itself
*/
Command.prototype.setGlobalCooldown = function (time) {
this.globalCooldown = time;
return this;
};
/**
* check if you can run the command with a message, and if so run it
* @param {Discord.Message} message the message that invoked the command
* @param {Discord.Client} client the client of the bot that recieved the command
*/
Command.prototype.runCommand = function (message, system) {
var params = message.content.split(' ').slice(1);
var owner = message.author.id === system.ownerID;
if (this.ownerOnly && !owner)
return message.channel.send('This command can only be ran by the owner!');
if (this.needsGuild && !message.guild)
return message.channel.send('This command needs to be ran in a server!');
if (this.needsDM && message.guild)
return message.channel.send('This command needs to be ran in a DM!');
// permission checking
if (this.clientPermissions.length > 0 && message.guild) {
var missingpermissions_1 = [];
this.clientPermissions.forEach(function (perm) {
if (message.guild && message.guild.me && !message.guild.me.hasPermission(perm)) {
missingpermissions_1.push(perm);
}
});
if (missingpermissions_1.length > 0) {
return message.channel.send("**I can't run this command!** This bot need these permissions to run this command: `" + missingpermissions_1.join(', ') + "`");
}
}
if (this.userPermissions.length > 0 && message.guild) {
var missingPermissions_1 = [];
this.userPermissions.forEach(function (perm) {
if (message.member !== null && !message.member.hasPermission(perm)) {
missingPermissions_1.push(perm);
}
});
if (missingPermissions_1.length > 0) {
return message.channel.send("**You can't run this command!** You need these permissions to use this command: `" + missingPermissions_1.join(', ') + "`");
}
}
// nsfw command checking
if (this.nsfwOnly) {
// only check if ran inside a guild
if (message.guild && message.channel instanceof Discord.TextChannel) {
// nsfw off check
if (!message.channel.nsfw)
return message.channel.send('This command needs to be ran in an NSFW channel or DM!');
// check for no nsfw tag in topic
if (message.channel.topic !== null && message.channel.topic.includes('[no_nsfw]'))
return message.channel.send('This command needs to be ran in an NSFW channel, but this channel has a [no_nsfw] tag in the topic.');
}
}
// argument checking
// TODO: redo this entire thing. like the entire thing
var argumentsValid = [];
if (this.usage && !this.usageCheck) {
var argument = this.usage.split(' ');
argument.forEach(function (arg, i) {
if (params[i] !== undefined) {
switch (arg.slice(1, arg.length - 1)) {
case 'any':
case 'string':
argumentsValid[i] = true;
break;
case 'user':
argumentsValid[i] = parseUser(message.client, params[i], message.guild === null ? undefined : message.guild) !== null;
break;
case 'url':
argumentsValid[i] = params[i].startsWith('http://') || params[i].startsWith('https://');
break;
case 'number':
argumentsValid[i] = !isNaN(Number(params[i]));
break;
case 'id':
argumentsValid[i] = message.client ? Boolean((message.client.guilds.cache.get(params[i]) || message.client.users.cache.get(params[i]) || message.client.channels.cache.get(params[i]))) : true;
}
}
else {
argumentsValid[i] = arg.startsWith('[') && arg.endsWith(']');
}
});
}
else {
argumentsValid = this.usageCheck ? [this.usageCheck(message.content)] : [true];
}
if (argumentsValid !== null) {
if (argumentsValid.includes(false)) {
return message.channel.send("Invalid syntax! `" + (this.name + ' ' + this.displayUsage) + "`");
}
}
// cooldowns
if (this.userCooldown > 0 && !owner) {
if (this.userCooldowns[message.author.id] === undefined || Date.now() - this.userCooldowns[message.author.id] > 0) {
this.userCooldowns[message.author.id] = this.userCooldown;
}
else {
return message.react('⏱️');
}
}
if (this.globalCooldown > 0 && !owner) {
if ((Date.now() - this.globalCooldowns) > 0) {
this.globalCooldowns = Date.now() + this.globalCooldown;
}
else {
return message.react('⏱️');
}
}
// then run the command
try {
this.cfunc(message, params.join(' '));
}
catch (err) {
system.emit('error', err, message, this);
}
};
return Command;
}());
exports.Command = Command;