UNPKG

cumsystem

Version:

simple command system and command handler

446 lines (445 loc) 16.9 kB
"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;