diff --git a/.gitignore b/.gitignore index b512c09..04c01ba 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -node_modules \ No newline at end of file +node_modules/ +dist/ \ No newline at end of file diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..5c5532a --- /dev/null +++ b/.npmignore @@ -0,0 +1,2 @@ +src/ +tsconfig.json \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..8d7b4cd --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,4 @@ +{ + "printWidth": 80, + "tabWidth": 2 +} diff --git a/dist/Command.js b/dist/Command.js deleted file mode 100644 index 11efc3c..0000000 --- a/dist/Command.js +++ /dev/null @@ -1,372 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -const cooldown_1 = __importDefault(require("./models/cooldown")); -class Command { - instance; - client; - _names = []; - _category = ''; - _minArgs = 0; - _maxArgs = -1; - _syntaxError; - _expectedArgs; - _description; - _requiredPermissions; - _requiredRoles = new Map(); // - _callback = () => { }; - _error = null; - _disabled = []; - _cooldownDuration = 0; - _cooldownChar = ''; - _cooldown; - _userCooldowns = new Map(); // OR - _globalCooldown; - _guildCooldowns = new Map(); // - _databaseCooldown = false; - _ownerOnly = false; - _hidden = false; - _guildOnly = false; - _testOnly = false; - _slash = false; - _requireRoles = false; - _requiredChannels = new Map(); // - constructor(instance, client, names, callback, error, { category, minArgs, maxArgs, syntaxError, expectedArgs, description, requiredPermissions, permissions, cooldown, globalCooldown, ownerOnly = false, hidden = false, guildOnly = false, testOnly = false, slash = false, requireRoles = false, }) { - this.instance = instance; - this.client = client; - this._names = typeof names === 'string' ? [names] : names; - this._category = category; - this._minArgs = minArgs || 0; - this._maxArgs = maxArgs === undefined ? -1 : maxArgs; - this._syntaxError = syntaxError; - this._expectedArgs = expectedArgs; - this._description = description; - this._requiredPermissions = requiredPermissions || permissions; - this._cooldown = cooldown || ''; - this._globalCooldown = globalCooldown || ''; - this._ownerOnly = ownerOnly; - this._hidden = hidden; - this._guildOnly = guildOnly; - this._testOnly = testOnly; - this._callback = callback; - this._error = error; - this._slash = slash; - this._requireRoles = requireRoles; - if (this.cooldown && this.globalCooldown) { - throw new Error(`Command "${names[0]}" has both a global and per-user cooldown. Commands can only have up to one of these properties.`); - } - if (requiredPermissions && permissions) { - throw new Error(`Command "${names[0]}" has both requiredPermissions and permissions fields. These are interchangeable but only one should be provided.`); - } - if (this.cooldown) { - this.verifyCooldown(this._cooldown, 'cooldown'); - } - if (this.globalCooldown) { - this.verifyCooldown(this._globalCooldown, 'global cooldown'); - } - if (this._minArgs < 0) { - throw new Error(`Command "${names[0]}" has a minimum argument count less than 0!`); - } - if (this._maxArgs < -1) { - throw new Error(`Command "${names[0]}" has a maximum argument count less than -1!`); - } - if (this._maxArgs !== -1 && this._maxArgs < this._minArgs) { - throw new Error(`Command "${names[0]}" has a maximum argument count less than it's minimum argument count!`); - } - } - async execute(message, args) { - const reply = await this._callback({ - message, - channel: message.channel, - args, - text: args.join(' '), - client: this.client, - prefix: this.instance.getPrefix(message.guild), - instance: this.instance, - user: message.author, - member: message.member, - guild: message.guild, - cancelCoolDown: () => { - this.decrementCooldowns(message.guild?.id, message.author.id); - }, - }); - if (!reply) { - return; - } - if (typeof reply === 'string') { - message.reply({ - content: reply, - }); - } - else if (typeof reply === 'object') { - if (reply.custom) { - message.reply(reply); - } - else { - let embeds = []; - if (Array.isArray(reply)) { - embeds = reply; - } - else { - embeds.push(reply); - } - message.reply({ - embeds, - }); - } - } - } - get names() { - return this._names; - } - get category() { - return this._category; - } - get description() { - return this._description; - } - get minArgs() { - return this._minArgs; - } - get maxArgs() { - return this._maxArgs; - } - get syntaxError() { - return this._syntaxError || {}; - } - get expectedArgs() { - return this._expectedArgs; - } - get requiredPermissions() { - return this._requiredPermissions; - } - get cooldownDuration() { - return this._cooldownDuration; - } - get cooldownChar() { - return this._cooldownChar; - } - get cooldown() { - return this._cooldown; - } - get globalCooldown() { - return this._globalCooldown; - } - get testOnly() { - return this._testOnly; - } - verifyCooldown(cooldown, type) { - if (typeof cooldown !== 'string') { - throw new Error(`Invalid ${type} format! Must be a string, examples: "10s" "5m" etc.`); - } - const results = cooldown.match(/[a-z]+|[^a-z]+/gi) || []; - if (results.length !== 2) { - throw new Error(`Invalid ${type} format! Please provide "", examples: "10s" "5m" etc.`); - } - this._cooldownDuration = +results[0]; - if (isNaN(this._cooldownDuration)) { - throw new Error(`Invalid ${type} format! Number is invalid.`); - } - this._cooldownChar = results[1]; - if (this._cooldownChar !== 's' && - this._cooldownChar !== 'm' && - this._cooldownChar !== 'h' && - this._cooldownChar !== 'd') { - throw new Error(`Invalid ${type} format! Unknown type. Please provide 's', 'm', 'h', or 'd' for seconds, minutes, hours, or days respectively.`); - } - if (type === 'global cooldown' && - this._cooldownChar === 's' && - this._cooldownDuration < 60) { - throw new Error(`Invalid ${type} format! The minimum duration for a global cooldown is 1m.`); - } - const moreInfo = ' For more information please see https://docs.wornoffkeys.com/commands/command-cooldowns'; - if (this._cooldownDuration < 1) { - throw new Error(`Invalid ${type} format! Durations must be at least 1.${moreInfo}`); - } - if ((this._cooldownChar === 's' || this._cooldownChar === 'm') && - this._cooldownDuration > 60) { - throw new Error(`Invalid ${type} format! Second or minute durations cannot exceed 60.${moreInfo}`); - } - if (this._cooldownChar === 'h' && this._cooldownDuration > 24) { - throw new Error(`Invalid ${type} format! Hour durations cannot exceed 24.${moreInfo}`); - } - if (this._cooldownChar === 'd' && this._cooldownDuration > 365) { - throw new Error(`Invalid ${type} format! Day durations cannot exceed 365.${moreInfo}`); - } - } - get hidden() { - return this._hidden; - } - get guildOnly() { - return this._guildOnly; - } - get ownerOnly() { - return this._ownerOnly; - } - verifyDatabaseCooldowns() { - if (this._cooldownChar === 'd' || - this._cooldownChar === 'h' || - (this._cooldownChar === 'm' && this._cooldownDuration >= 5)) { - this._databaseCooldown = true; - if (!this.instance.isDBConnected()) { - console.warn(`WOKCommands > A database connection is STRONGLY RECOMMENDED for cooldowns of 5 minutes or more.`); - } - } - } - /** - * Decrements per-user and global cooldowns - * Deletes expired cooldowns - */ - decrementCooldowns(guildId, userId) { - for (const map of [this._userCooldowns, this._guildCooldowns]) { - if (typeof map !== 'string') { - map.forEach((value, key) => { - if (key === `${guildId}-${userId}`) { - value = 0; - } - if (--value <= 0) { - map.delete(key); - } - else { - map.set(key, value); - } - if (this._databaseCooldown && this.instance.isDBConnected()) { - this.updateDatabaseCooldowns(`${this.names[0]}-${key}`, value); - } - }); - } - } - } - async updateDatabaseCooldowns(_id, cooldown) { - // Only update every 20s - if (cooldown % 20 === 0 && this.instance.isDBConnected()) { - const type = this.globalCooldown ? 'global' : 'per-user'; - if (cooldown <= 0) { - await cooldown_1.default.deleteOne({ _id, name: this.names[0], type }); - } - else { - await cooldown_1.default.findOneAndUpdate({ - _id, - name: this.names[0], - type, - }, { - _id, - name: this.names[0], - type, - cooldown, - }, { upsert: true }); - } - } - } - setCooldown(guildId, userId, customCooldown) { - const target = this.globalCooldown || this.cooldown; - if (target) { - let seconds = customCooldown || this._cooldownDuration; - const durationType = customCooldown ? 's' : this._cooldownChar; - switch (durationType) { - case 'm': - seconds *= 60; - break; - case 'h': - seconds *= 60 * 60; - break; - case 'd': - seconds *= 60 * 60 * 24; - break; - } - // Increment to ensure we save it to the database when it is divisible by 20 - ++seconds; - if (this.globalCooldown) { - this._guildCooldowns.set(guildId, seconds); - } - else { - this._userCooldowns.set(`${guildId}-${userId}`, seconds); - } - } - } - getCooldownSeconds(guildId, userId) { - let seconds = this.globalCooldown - ? this._guildCooldowns.get(guildId) - : this._userCooldowns.get(`${guildId}-${userId}`); - if (!seconds) { - return ''; - } - const days = Math.floor(seconds / (3600 * 24)); - const hours = Math.floor((seconds % (3600 * 24)) / 3600); - const minutes = Math.floor((seconds % 3600) / 60); - seconds = Math.floor(seconds % 60); - let result = ''; - if (days) { - result += `${days}d `; - } - if (hours) { - result += `${hours}h `; - } - if (minutes) { - result += `${minutes}m `; - } - if (seconds) { - result += `${seconds}s `; - } - return result.substring(0, result.length - 1); - } - addRequiredRole(guildId, roleId) { - const array = this._requiredRoles?.get(guildId) || []; - if (!array.includes(roleId)) { - array.push(roleId); - this._requiredRoles?.set(guildId, array); - } - } - removeRequiredRole(guildId, roleId) { - if (roleId === 'none') { - this._requiredRoles?.delete(guildId); - return; - } - const array = this._requiredRoles?.get(guildId) || []; - const index = array ? array.indexOf(roleId) : -1; - if (array && index >= 0) { - array.splice(index, 1); - } - } - getRequiredRoles(guildId) { - const map = this._requiredRoles || new Map(); - return map.get(guildId) || []; - } - get callback() { - return this._callback; - } - disable(guildId) { - if (!this._disabled.includes(guildId)) { - this._disabled.push(guildId); - } - } - enable(guildId) { - const index = this._disabled.indexOf(guildId); - if (index >= 0) { - this._disabled.splice(index, 1); - } - } - isDisabled(guildId) { - return this._disabled.includes(guildId); - } - get error() { - return this._error; - } - get slash() { - return this._slash; - } - get doesRequireRoles() { - return this._requireRoles; - } - get requiredChannels() { - return this._requiredChannels; - } - setRequiredChannels(guild, command, channels) { - if (!guild) { - return; - } - this.requiredChannels.set(`${guild.id}-${command}`, channels); - } -} -module.exports = Command; diff --git a/dist/CommandHandler.js b/dist/CommandHandler.js deleted file mode 100644 index 9a4a261..0000000 --- a/dist/CommandHandler.js +++ /dev/null @@ -1,339 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const fs_1 = __importDefault(require("fs")); -const path_1 = __importDefault(require("path")); -const Command_1 = __importDefault(require("./Command")); -const get_all_files_1 = __importDefault(require("./get-all-files")); -const disabled_commands_1 = __importDefault(require("./models/disabled-commands")); -const required_roles_1 = __importDefault(require("./models/required-roles")); -const cooldown_1 = __importDefault(require("./models/cooldown")); -const channel_commands_1 = __importDefault(require("./models/channel-commands")); -const permissions_1 = require("./permissions"); -const CommandErrors_1 = __importDefault(require("./enums/CommandErrors")); -const Events_1 = __importDefault(require("./enums/Events")); -const replyFromCheck = async (reply, message) => { - if (!reply) { - return new Promise((resolve) => { - resolve('No reply provided.'); - }); - } - if (typeof reply === 'string') { - return message.reply({ - content: reply, - }); - } - else { - let embeds = []; - if (Array.isArray(reply)) { - embeds = reply; - } - else { - embeds.push(reply); - } - return message.reply({ - embeds, - }); - } -}; -class CommandHandler { - _commands = new Map(); - _client = null; - _commandChecks = new Map(); - constructor(instance, client, dir, disabledDefaultCommands, typeScript = false) { - this._client = client; - this.setUp(instance, client, dir, disabledDefaultCommands, typeScript); - } - async setUp(instance, client, dir, disabledDefaultCommands, typeScript = false) { - // Do not pass in TS here because this should always compiled to JS - for (const [file, fileName] of get_all_files_1.default(path_1.default.join(__dirname, 'commands'))) { - if (disabledDefaultCommands.includes(fileName)) { - continue; - } - await this.registerCommand(instance, client, file, fileName, true); - } - // Do not pass in TS here because this should always compiled to JS - for (const [file, fileName] of get_all_files_1.default(path_1.default.join(__dirname, 'command-checks'))) { - this._commandChecks.set(fileName, require(file)); - } - if (dir) { - if (!fs_1.default.existsSync(dir)) { - throw new Error(`Commands directory "${dir}" doesn't exist!`); - } - const files = get_all_files_1.default(dir, typeScript ? '.ts' : ''); - const amount = files.length; - console.log(`WOKCommands > Loaded ${amount} command${amount === 1 ? '' : 's'}.`); - for (const [file, fileName] of files) { - await this.registerCommand(instance, client, file, fileName); - } - if (instance.isDBConnected()) { - await this.fetchDisabledCommands(); - await this.fetchRequiredRoles(); - await this.fetchChannelOnly(); - } - this._commands.forEach(async (command) => { - command.verifyDatabaseCooldowns(); - if (instance.isDBConnected()) { - const results = await cooldown_1.default.find({ - name: command.names[0], - type: command.globalCooldown ? 'global' : 'per-user', - }); - for (const { _id, cooldown } of results) { - const [name, guildId, userId] = _id.split('-'); - command.setCooldown(guildId, userId, cooldown); - } - } - }); - client.on('messageCreate', async (message) => { - const guild = message.guild; - let content = message.content; - const prefix = instance.getPrefix(guild).toLowerCase(); - if (!content.toLowerCase().startsWith(prefix)) { - return; - } - if (instance.ignoreBots && message.author.bot) { - return; - } - // Remove the prefix - content = content.substring(prefix.length); - const args = content.split(/[ ]+/g); - // Remove the "command", leaving just the arguments - const firstElement = args.shift(); - if (!firstElement) { - return; - } - // Ensure the user input is lower case because it is stored as lower case in the map - const name = firstElement.toLowerCase(); - const command = this._commands.get(name); - if (!command) { - return; - } - const { error, slash } = command; - if (slash === true) { - return; - } - const { member, author: user, channel } = message; - for (const [checkName, checkFunction,] of this._commandChecks.entries()) { - if (!(await checkFunction(guild, command, instance, member, user, (reply) => { - return replyFromCheck(reply, message); - }, args, name, channel))) { - return; - } - } - try { - command.execute(message, args); - } - catch (e) { - if (error) { - error({ - error: CommandErrors_1.default.EXCEPTION, - command, - message, - info: { - error: e, - }, - }); - } - else { - message.reply(instance.messageHandler.get(guild, 'EXCEPTION')); - console.error(e); - } - instance.emit(Events_1.default.COMMAND_EXCEPTION, command, message, e); - } - }); - } - const decrementCountdown = () => { - this._commands.forEach((command) => { - command.decrementCooldowns(); - }); - setTimeout(decrementCountdown, 1000); - }; - decrementCountdown(); - } - async registerCommand(instance, client, file, fileName, builtIn = false) { - let configuration = await require(file); - // person is using 'export default' so we import the default instead - if (configuration.default && Object.keys(configuration).length === 1) { - configuration = configuration.default; - } - const { name = fileName, category, commands, aliases, init, callback, run, execute, error, description, requiredPermissions, permissions, slash, expectedArgs, expectedArgsTypes, minArgs, options = [], } = configuration; - const { testOnly } = configuration; - if (run || execute) { - throw new Error(`Command located at "${file}" has either a "run" or "execute" function. Please rename that function to "callback".`); - } - let names = commands || aliases || []; - if (!name && (!names || names.length === 0)) { - throw new Error(`Command located at "${file}" does not have a name, commands array, or aliases array set. Please set at lease one property to specify the command name.`); - } - if (typeof names === 'string') { - names = [names]; - } - if (typeof name !== 'string') { - throw new Error(`Command located at "${file}" does not have a string as a name.`); - } - if (name && !names.includes(name.toLowerCase())) { - names.unshift(name.toLowerCase()); - } - if (requiredPermissions || permissions) { - for (const perm of requiredPermissions || permissions) { - if (!permissions_1.permissionList.includes(perm)) { - throw new Error(`Command located at "${file}" has an invalid permission node: "${perm}". Permissions must be all upper case and be one of the following: "${[ - ...permissions_1.permissionList, - ].join('", "')}"`); - } - } - } - const missing = []; - if (!category) { - missing.push('Category'); - } - if (!description) { - missing.push('Description'); - } - if (missing.length && instance.showWarns) { - console.warn(`WOKCommands > Command "${names[0]}" does not have the following properties: ${missing}.`); - } - if (testOnly && !instance.testServers.length) { - console.warn(`WOKCommands > Command "${names[0]}" has "testOnly" set to true, but no test servers are defined.`); - } - if (slash !== undefined && typeof slash !== 'boolean' && slash !== 'both') { - throw new Error(`WOKCommands > Command "${names[0]}" has a "slash" property that is not boolean "true" or string "both".`); - } - if (!slash && options.length) { - throw new Error(`WOKCommands > Command "${names[0]}" has an "options" property but is not a slash command.`); - } - if (slash && !(builtIn && !instance.isDBConnected())) { - if (!description) { - throw new Error(`WOKCommands > A description is required for command "${names[0]}" because it is a slash command.`); - } - if (minArgs !== undefined && !expectedArgs) { - throw new Error(`WOKCommands > Command "${names[0]}" has "minArgs" property defined without "expectedArgs" property as a slash command.`); - } - if (options.length) { - for (const key in options) { - const name = options[key].name; - let lowerCase = name.toLowerCase(); - if (name !== lowerCase && instance.showWarns) { - console.log(`WOKCommands > Command "${names[0]}" has an option of "${name}". All option names must be lower case for slash commands. WOKCommands will modify this for you.`); - } - if (lowerCase.match(/\s/g)) { - lowerCase = lowerCase.replace(/\s/g, '_'); - console.log(`WOKCommands > Command "${names[0]}" has an option of "${name}" with a white space in it. It is a best practice for option names to only be one word. WOKCommands will modify this for you.`); - } - options[key].name = lowerCase; - } - } - else if (expectedArgs) { - const split = expectedArgs - .substring(1, expectedArgs.length - 1) - .split(/[>\]] [<\[]/); - for (let a = 0; a < split.length; ++a) { - const item = split[a]; - options.push({ - name: item.replace(/ /g, '-').toLowerCase(), - description: item, - type: expectedArgsTypes && expectedArgsTypes.length >= a - ? expectedArgsTypes[a] - : 'STRING', - required: a < minArgs, - }); - } - } - const slashCommands = instance.slashCommands; - if (testOnly) { - for (const id of instance.testServers) { - await slashCommands.create(names[0], description, options, id); - } - } - else { - await slashCommands.create(names[0], description, options); - } - } - if (callback) { - if (init) { - init(client, instance); - } - const command = new Command_1.default(instance, client, names, callback, error, configuration); - for (const name of names) { - // Ensure the alias is lower case because we read as lower case later on - this._commands.set(name.toLowerCase(), command); - } - } - } - get commands() { - const results = []; - const added = []; - this._commands.forEach(({ names, category = '', description = '', expectedArgs = '', hidden = false, testOnly = false, }) => { - if (!added.includes(names[0])) { - results.push({ - names: [...names], - category, - description, - syntax: expectedArgs, - hidden, - testOnly, - }); - added.push(names[0]); - } - }); - return results; - } - getCommandsByCategory(category, visibleOnly) { - const results = []; - for (const command of this.commands) { - if (visibleOnly && command.hidden) { - continue; - } - if (command.category === category) { - results.push(command); - } - } - return results; - } - getCommand(name) { - return this._commands.get(name); - } - getICommand(name) { - return this.commands.find((command) => command.names?.includes(name)); - } - async fetchDisabledCommands() { - const results = await disabled_commands_1.default.find({}); - for (const result of results) { - const { guildId, command } = result; - this._commands.get(command)?.disable(guildId); - } - } - async fetchRequiredRoles() { - const results = await required_roles_1.default.find({}); - for (const result of results) { - const { guildId, command, requiredRoles } = result; - const cmd = this._commands.get(command); - if (cmd) { - for (const roleId of requiredRoles) { - cmd.addRequiredRole(guildId, roleId); - } - } - } - } - async fetchChannelOnly() { - const results = await channel_commands_1.default.find({}); - for (const result of results) { - const { command, guildId, channels } = result; - const cmd = this._commands.get(command); - if (!cmd) { - continue; - } - const guild = this._client?.guilds.cache.get(guildId); - if (!guild) { - continue; - } - cmd.setRequiredChannels(guild, command, channels - .toString() - .replace(/\"\[\]/g, '') - .split(',')); - } - } -} -exports.default = CommandHandler; diff --git a/dist/FeatureHandler.js b/dist/FeatureHandler.js deleted file mode 100644 index b6b77d1..0000000 --- a/dist/FeatureHandler.js +++ /dev/null @@ -1,89 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -const fs_1 = __importDefault(require("fs")); -const path_1 = __importDefault(require("path")); -const get_all_files_1 = __importDefault(require("./get-all-files")); -class FeatureHandler { - _features = new Map(); // - _client; - _instance; - constructor(client, instance, dir, typeScript = false) { - this._client = client; - this._instance = instance; - this.setup(dir, typeScript); - } - setup = async (dir, typeScript) => { - // Register built in features - for (const [file, fileName] of get_all_files_1.default(path_1.default.join(__dirname, 'features'), typeScript ? '.ts' : '')) { - this.registerFeature(require(file), fileName); - } - if (!dir) { - return; - } - if (!fs_1.default.existsSync(dir)) { - throw new Error(`Listeners directory "${dir}" doesn't exist!`); - } - const files = get_all_files_1.default(dir, typeScript ? '.ts' : ''); - const amount = files.length; - if (amount > 0) { - console.log(`WOKCommands > Loading ${amount} listener${amount === 1 ? '' : 's'}...`); - for (const [file, fileName] of files) { - const debug = `WOKCommands DEBUG > Feature "${fileName}" load time`; - if (this._instance.debug) { - console.time(debug); - } - this.registerFeature(require(file), fileName); - if (this._instance.debug) { - console.timeEnd(debug); - } - } - } - else { - console.log(`WOKCommands > Loaded ${amount} listener${amount === 1 ? '' : 's'}.`); - } - }; - registerFeature = (file, fileName) => { - let func = file; - const { config } = file; - if (file.default) { - func = file.default; - } - let testOnly = false; - if (config) { - const { displayName, dbName } = config; - if (config.testOnly) { - testOnly = true; - } - const missing = []; - if (!displayName) - missing.push('displayName'); - if (!dbName) - missing.push('dbName'); - if (missing.length && this._instance.showWarns) { - console.warn(`WOKCommands > Feature "${fileName}" has a config file that doesn't contain the following properties: ${missing}`); - } - } - else if (this._instance.showWarns) { - console.warn(`WOKCommands > Feature "${fileName}" does not export a config object.`); - } - if (typeof func !== 'function') { - return; - } - const isEnabled = (guildId) => { - if (testOnly && !this._instance.testServers.includes(guildId)) { - return false; - } - return this.isEnabled(guildId, file); - }; - if (config && config.loadDBFirst === true) { - console.warn(`WOKCommands > config.loadDBFirst in features is no longer required. MongoDB is now connected to before any features or commands are loaded.`); - } - func(this._client, this._instance, isEnabled); - }; - isEnabled = (guildId, feature) => { - return !(this._features.get(feature) || []).includes(guildId); - }; -} -module.exports = FeatureHandler; diff --git a/dist/SlashCommands.js b/dist/SlashCommands.js deleted file mode 100644 index 9771410..0000000 --- a/dist/SlashCommands.js +++ /dev/null @@ -1,191 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -const path_1 = __importDefault(require("path")); -const get_all_files_1 = __importDefault(require("./get-all-files")); -class SlashCommands { - _client; - _instance; - _commandChecks = new Map(); - constructor(instance, listen, typeScript) { - this._instance = instance; - this._client = instance.client; - this.setUp(listen, typeScript); - } - async setUp(listen, typeScript = false) { - // Do not pass in TS here because this should always compiled to JS - for (const [file, fileName] of get_all_files_1.default(path_1.default.join(__dirname, 'command-checks'))) { - this._commandChecks.set(fileName, require(file)); - } - const replyFromCheck = async (reply, interaction) => { - if (!reply) { - return new Promise((resolve) => { - resolve('No reply provided.'); - }); - } - if (typeof reply === 'string') { - return interaction.reply({ - content: reply, - ephemeral: this._instance.ephemeral, - }); - } - else { - let embeds = []; - if (Array.isArray(reply)) { - embeds = reply; - } - else { - embeds.push(reply); - } - return interaction.reply({ - embeds, - ephemeral: this._instance.ephemeral, - }); - } - }; - if (listen) { - this._client.on('interactionCreate', async (interaction) => { - if (!interaction.isCommand()) { - return; - } - const { user, commandName, options, guild, channelId } = interaction; - const member = interaction.member; - const channel = guild?.channels.cache.get(channelId) || null; - const command = this._instance.commandHandler.getCommand(commandName); - if (!command) { - interaction.reply({ - content: this._instance.messageHandler.get(guild, 'INVALID_SLASH_COMMAND'), - ephemeral: this._instance.ephemeral, - }); - return; - } - const args = []; - options.data.forEach(({ value }) => { - args.push(String(value)); - }); - for (const [checkName, checkFunction,] of this._commandChecks.entries()) { - if (!(await checkFunction(guild, command, this._instance, member, user, (reply) => { - return replyFromCheck(reply, interaction); - }, args, commandName, channel))) { - return; - } - } - this.invokeCommand(interaction, commandName, options, args); - }); - } - } - getCommands(guildId) { - if (guildId) { - return this._client.guilds.cache.get(guildId)?.commands; - } - return this._client.application?.commands; - } - async get(guildId) { - const commands = this.getCommands(guildId); - if (commands) { - // @ts-ignore - await commands.fetch(); - return commands.cache; - } - return new Map(); - } - didOptionsChange(command, options) { - return (command.options?.filter((opt, index) => { - return (opt?.required !== options[index]?.required && - opt?.name !== options[index]?.name && - opt?.options?.length !== options.length); - }).length !== 0); - } - async create(name, description, options, guildId) { - let commands; - if (guildId) { - commands = this._client.guilds.cache.get(guildId)?.commands; - } - else { - commands = this._client.application?.commands; - } - if (!commands) { - return; - } - // @ts-ignore - await commands.fetch(); - const cmd = commands.cache.find((cmd) => cmd.name === name); - if (cmd) { - const optionsChanged = this.didOptionsChange(cmd, options); - if (cmd.description !== description || - cmd.options.length !== options.length || - optionsChanged) { - console.log(`WOKCommands > Updating${guildId ? ' guild' : ''} slash command "${name}"`); - return commands?.edit(cmd.id, { - name, - description, - options, - }); - } - return Promise.resolve(cmd); - } - if (commands) { - console.log(`WOKCommands > Creating${guildId ? ' guild' : ''} slash command "${name}"`); - const newCommand = await commands.create({ - name, - description, - options, - }); - return newCommand; - } - return Promise.resolve(undefined); - } - async delete(commandId, guildId) { - const commands = this.getCommands(guildId); - if (commands) { - const cmd = commands.cache.get(commandId); - if (cmd) { - console.log(`WOKCommands > Deleting${guildId ? ' guild' : ''} slash command "${cmd.name}"`); - cmd.delete(); - } - } - return Promise.resolve(undefined); - } - async invokeCommand(interaction, commandName, options, args) { - const command = this._instance.commandHandler.getCommand(commandName); - if (!command || !command.callback) { - return; - } - const reply = await command.callback({ - member: interaction.member, - guild: interaction.guild, - channel: interaction.channel, - args, - text: args.join(' '), - client: this._client, - instance: this._instance, - interaction, - options, - user: interaction.user, - }); - if (reply) { - if (typeof reply === 'string') { - interaction.reply({ - content: reply, - }); - } - else if (typeof reply === 'object') { - if (reply.custom) { - interaction.reply(reply); - } - else { - let embeds = []; - if (Array.isArray(reply)) { - embeds = reply; - } - else { - embeds.push(reply); - } - interaction.reply({ embeds }); - } - } - } - } -} -module.exports = SlashCommands; diff --git a/dist/command-checks/channel-specific.js b/dist/command-checks/channel-specific.js deleted file mode 100644 index eecbeb5..0000000 --- a/dist/command-checks/channel-specific.js +++ /dev/null @@ -1,30 +0,0 @@ -"use strict"; -module.exports = (guild, command, instance, member, user, reply, args, name, channel) => { - if (!guild || !command || !command.names) { - return true; - } - const key = `${guild.id}-${command.names[0]}`; - const channels = command.requiredChannels.get(key); - if (channels && channels.length && !channels.includes(channel.id)) { - let channelList = ''; - for (const channel of channels) { - channelList += `<#${channel}>, `; - } - channelList = channelList.substring(0, channelList.length - 2); - reply(instance.messageHandler.get(guild, 'ALLOWED_CHANNELS', { - CHANNELS: channelList, - })).then((message) => { - if (!message) { - return; - } - if (instance.delErrMsgCooldown === -1 || !message.deletable) { - return; - } - setTimeout(() => { - message.delete(); - }, 1000 * instance.delErrMsgCooldown); - }); - return false; - } - return true; -}; diff --git a/dist/command-checks/guild-only-check.js b/dist/command-checks/guild-only-check.js deleted file mode 100644 index 06a8426..0000000 --- a/dist/command-checks/guild-only-check.js +++ /dev/null @@ -1,24 +0,0 @@ -"use strict"; -module.exports = (guild, command, instance, member, user, reply) => { - const { guildOnly } = command; - // If this command doesn't care if it's in a guild or not then just simply return true - if (!guildOnly) { - return true; - } - if (!guild) { - reply(instance.messageHandler.get(guild, 'GUILD_ONLY_COMMAND')).then((message) => { - if (!message) { - return; - } - if (instance.delErrMsgCooldown === -1 || !message.deletable) { - return; - } - setTimeout(() => { - message.delete(); - }, 1000 * instance.delErrMsgCooldown); - }); - return false; - } - // The guild exists - return true; -}; diff --git a/dist/command-checks/has-permissions.js b/dist/command-checks/has-permissions.js deleted file mode 100644 index 82ab18a..0000000 --- a/dist/command-checks/has-permissions.js +++ /dev/null @@ -1,39 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -const CommandErrors_1 = __importDefault(require("../enums/CommandErrors")); -module.exports = (guild, command, instance, member, user, reply) => { - if (!guild || !member) { - return true; - } - const { requiredPermissions, error } = command; - for (const perm of requiredPermissions || []) { - // @ts-ignore - if (!member.permissions.has(perm)) { - if (error) { - error({ - error: CommandErrors_1.default.MISSING_PERMISSIONS, - command, - }); - } - else { - reply(instance.messageHandler.get(guild, 'MISSING_PERMISSION', { - PERM: perm, - })).then((message) => { - if (!message) { - return; - } - if (instance.delErrMsgCooldown === -1 || !message.deletable) { - return; - } - setTimeout(() => { - message.delete(); - }, 1000 * instance.delErrMsgCooldown); - }); - } - return false; - } - } - return true; -}; diff --git a/dist/command-checks/has-roles.js b/dist/command-checks/has-roles.js deleted file mode 100644 index 0029ba2..0000000 --- a/dist/command-checks/has-roles.js +++ /dev/null @@ -1,69 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -const CommandErrors_1 = __importDefault(require("../enums/CommandErrors")); -module.exports = async (guild, command, instance, member, user, reply) => { - if (!guild || !member) { - return true; - } - const { error } = command; - const roles = command.getRequiredRoles(guild.id); - if (roles && roles.length) { - const missingRoles = []; - const missingRolesNames = []; - for (const role of roles) { - const realRole = await guild.roles.fetch(role); - if (realRole !== null && !member.roles.cache.has(role)) { - missingRoles.push(role); - missingRolesNames.push(realRole.name); - } - } - if (missingRoles.length) { - if (error) { - error({ - error: CommandErrors_1.default.MISSING_ROLES, - command, - message: null, - info: { - missingRoles, - }, - }); - } - else { - reply(instance.messageHandler.get(guild, 'MISSING_ROLES', { - ROLES: missingRolesNames.join(', '), - })).then((message) => { - if (!message) { - return; - } - if (instance.delErrMsgCooldown === -1 || !message.deletable) { - return; - } - setTimeout(() => { - message.delete(); - }, 1000 * instance.delErrMsgCooldown); - }); - } - return false; - } - } - else if (command.doesRequireRoles) { - reply(instance.messageHandler.get(guild, 'REQUIRE_ROLES', { - PREFIX: instance.getPrefix(guild), - COMMAND: command.names[0], - })).then((message) => { - if (!message) { - return; - } - if (instance.delErrMsgCooldown === -1 || !message.deletable) { - return; - } - setTimeout(() => { - message.delete(); - }, 1000 * instance.delErrMsgCooldown); - }); - return false; - } - return true; -}; diff --git a/dist/command-checks/has-valid-arguments.js b/dist/command-checks/has-valid-arguments.js deleted file mode 100644 index eee3e66..0000000 --- a/dist/command-checks/has-valid-arguments.js +++ /dev/null @@ -1,54 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -const CommandErrors_1 = __importDefault(require("../enums/CommandErrors")); -module.exports = (guild, command, instance, member, user, reply, args, name) => { - const { minArgs, maxArgs, expectedArgs, error } = command; - const prefix = instance.getPrefix(guild).toLowerCase(); - if ((minArgs !== undefined && args.length < minArgs) || - (maxArgs !== undefined && maxArgs !== -1 && args.length > maxArgs)) { - const syntaxError = command.syntaxError || {}; - const { messageHandler } = instance; - let errorMsg = syntaxError[messageHandler.getLanguage(guild)] || - instance.messageHandler.get(guild, 'SYNTAX_ERROR'); - // Replace {PREFIX} with the actual prefix - if (errorMsg) { - errorMsg = errorMsg.replace(/{PREFIX}/g, prefix); - // Replace {COMMAND} with the name of the command that was ran - errorMsg = errorMsg.replace(/{COMMAND}/g, name); - // Replace {ARGUMENTS} with the expectedArgs property from the command - // If one was not provided then replace {ARGUMENTS} with an empty string - errorMsg = errorMsg.replace(/ {ARGUMENTS}/g, expectedArgs ? ` ${expectedArgs}` : ''); - } - if (error) { - error({ - error: CommandErrors_1.default.INVALID_ARGUMENTS, - command, - message: null, - info: { - minArgs, - maxArgs, - length: args.length, - errorMsg, - }, - }); - } - else { - // Reply with the local or global syntax error - reply(errorMsg).then((message) => { - if (!message) { - return; - } - if (instance.delErrMsgCooldown === -1 || !message.deletable) { - return; - } - setTimeout(() => { - message.delete(); - }, 1000 * instance.delErrMsgCooldown); - }); - } - return false; - } - return true; -}; diff --git a/dist/command-checks/in-cooldown.js b/dist/command-checks/in-cooldown.js deleted file mode 100644 index c90097e..0000000 --- a/dist/command-checks/in-cooldown.js +++ /dev/null @@ -1,42 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -const CommandErrors_1 = __importDefault(require("../enums/CommandErrors")); -module.exports = (guild, command, instance, member, user, reply) => { - const { cooldown, globalCooldown, error } = command; - if ((cooldown || globalCooldown) && user) { - const guildId = guild ? guild.id : 'dm'; - const timeLeft = command.getCooldownSeconds(guildId, user.id); - if (timeLeft) { - if (error) { - error({ - error: CommandErrors_1.default.COOLDOWN, - command, - message: null, - info: { - timeLeft, - }, - }); - } - else { - reply(instance.messageHandler.get(guild, 'COOLDOWN', { - COOLDOWN: timeLeft, - })).then((message) => { - if (!message) { - return; - } - if (instance.delErrMsgCooldown === -1 || !message.deletable) { - return; - } - setTimeout(() => { - message.delete(); - }, 1000 * instance.delErrMsgCooldown); - }); - } - return false; - } - command.setCooldown(guildId, user.id); - } - return true; -}; diff --git a/dist/command-checks/is-enabled.js b/dist/command-checks/is-enabled.js deleted file mode 100644 index 56f7fee..0000000 --- a/dist/command-checks/is-enabled.js +++ /dev/null @@ -1,31 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -const CommandErrors_1 = __importDefault(require("../enums/CommandErrors")); -module.exports = (guild, command, instance, member, user, reply) => { - if (!guild || !command.isDisabled(guild.id)) { - return true; - } - const { error } = command; - if (error) { - error({ - error: CommandErrors_1.default.COMMAND_DISABLED, - command, - }); - } - else { - reply(instance.messageHandler.get(guild, 'DISABLED_COMMAND')).then((message) => { - if (!message) { - return; - } - if (instance.delErrMsgCooldown === -1 || !message.deletable) { - return; - } - setTimeout(() => { - message.delete(); - }, 1000 * instance.delErrMsgCooldown); - }); - } - return false; -}; diff --git a/dist/command-checks/is-not-test-only.js b/dist/command-checks/is-not-test-only.js deleted file mode 100644 index 72bd471..0000000 --- a/dist/command-checks/is-not-test-only.js +++ /dev/null @@ -1,8 +0,0 @@ -"use strict"; -module.exports = (guild, command, instance) => { - const { testOnly } = command; - if (!testOnly) { - return true; - } - return guild && instance.testServers.includes(guild.id); -}; diff --git a/dist/command-checks/owner-only-check.js b/dist/command-checks/owner-only-check.js deleted file mode 100644 index 3cfe416..0000000 --- a/dist/command-checks/owner-only-check.js +++ /dev/null @@ -1,22 +0,0 @@ -"use strict"; -module.exports = (guild, command, instance, member, user, reply) => { - const { ownerOnly } = command; - if (!ownerOnly) { - return true; - } - if (!instance.botOwner.includes(user.id)) { - reply(instance.messageHandler.get(guild, 'BOT_OWNERS_ONLY')).then((message) => { - if (!message) { - return; - } - if (instance.delErrMsgCooldown === -1 || !message.deletable) { - return; - } - setTimeout(() => { - message.delete(); - }, 1000 * instance.delErrMsgCooldown); - }); - return false; - } - return true; -}; diff --git a/dist/commands/channelonly.js b/dist/commands/channelonly.js deleted file mode 100644 index ad7a9dd..0000000 --- a/dist/commands/channelonly.js +++ /dev/null @@ -1,88 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -const channel_commands_1 = __importDefault(require("../models/channel-commands")); -module.exports = { - description: 'Makes a command only work in some channels.', - category: 'Configuration', - permissions: ['ADMINISTRATOR'], - minArgs: 1, - maxArgs: 2, - expectedArgs: ' [Channel tag]', - cooldown: '2s', - guildOnly: true, - slash: 'both', - options: [ - { - name: 'command', - description: 'The command name', - type: 'STRING', - required: true, - }, - { - name: 'channel', - description: 'The tag of the channel', - type: 'CHANNEL', - required: false, - }, - ], - callback: async (options) => { - const { message, channel, args, instance, interaction } = options; - const { guild } = channel; - const { messageHandler } = instance; - let commandName = (args.shift() || '').toLowerCase(); - const command = instance.commandHandler.getCommand(commandName); - if (!instance.isDBConnected()) { - return messageHandler.get(guild, 'NO_DATABASE_FOUND'); - } - if (!command || !command.names) { - return messageHandler.get(guild, 'UNKNOWN_COMMAND', { - COMMAND: commandName, - }); - } - commandName = command.names[0]; - if (args.length === 0) { - const results = await channel_commands_1.default.deleteMany({ - guildId: guild?.id, - command: commandName, - }); - // @ts-ignore - if (results.n === 0) { - return messageHandler.get(guild, 'NOT_CHANNEL_COMMAND'); - } - command.setRequiredChannels(guild, commandName, []); - return messageHandler.get(guild, 'NO_LONGER_CHANNEL_COMMAND'); - } - if (message?.mentions.channels.size === 0) { - return messageHandler.get(guild, 'NO_TAGGED_CHANNELS'); - } - let channels; - if (message) { - channels = Array.from(message.mentions.channels.keys()); - } - else { - channels = [interaction.options.getChannel('channel')]; - } - const results = await channel_commands_1.default.findOneAndUpdate({ - guildId: guild?.id, - command: commandName, - }, { - guildId: guild?.id, - command: commandName, - $addToSet: { - channels, - }, - }, { - upsert: true, - new: true, - }); - if (results) { - command.setRequiredChannels(guild, commandName, results.channels); - } - return messageHandler.get(guild, 'NOW_CHANNEL_COMMAND', { - COMMAND: commandName, - CHANNELS: args.join(' '), - }); - }, -}; diff --git a/dist/commands/command.js b/dist/commands/command.js deleted file mode 100644 index 242867a..0000000 --- a/dist/commands/command.js +++ /dev/null @@ -1,86 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -const disabled_commands_1 = __importDefault(require("../models/disabled-commands")); -module.exports = { - description: 'Enables or disables a command for this guild', - category: 'Configuration', - permissions: ['ADMINISTRATOR'], - minArgs: 2, - maxArgs: 2, - expectedArgs: '<"enable" or "disable"> ', - cooldown: '2s', - slash: 'both', - options: [ - { - name: 'action', - description: 'Either "enable" or "disable"', - required: true, - type: 'STRING', - choices: [ - { - name: 'Enable', - value: 'enable', - }, - { name: 'Disable', value: 'disable' }, - ], - }, - { - name: 'command', - description: 'The name of the command', - required: true, - type: 'STRING', - }, - ], - callback: async (options) => { - const { channel, args, instance } = options; - const { guild } = channel; - const newState = args.shift()?.toLowerCase(); - const name = (args.shift() || '').toLowerCase(); - if (!guild) { - return instance.messageHandler.get(guild, 'CANNOT_ENABLE_DISABLE_IN_DMS'); - } - if (!instance.isDBConnected()) { - return instance.messageHandler.get(guild, 'NO_DATABASE_FOUND'); - } - if (newState !== 'enable' && newState !== 'disable') { - return instance.messageHandler.get(guild, 'ENABLE_DISABLE_STATE'); - } - const command = instance.commandHandler.getCommand(name); - if (command) { - const mainCommand = command.names[0]; - if (mainCommand === 'command') { - return instance.messageHandler.get(guild, 'CANNOT_DISABLE_THIS_COMMAND'); - } - const isDisabled = command.isDisabled(guild.id); - if (newState === 'enable') { - if (!isDisabled) { - return instance.messageHandler.get(guild, 'COMMAND_ALREADY_ENABLED'); - } - await disabled_commands_1.default.deleteOne({ - guildId: guild.id, - command: mainCommand, - }); - command.enable(guild.id); - return instance.messageHandler.get(guild, 'COMMAND_NOW_ENABLED', { - COMMAND: mainCommand, - }); - } - if (isDisabled) { - return instance.messageHandler.get(guild, 'COMMAND_ALREADY_DISABLED'); - } - await new disabled_commands_1.default({ - guildId: guild.id, - command: mainCommand, - }).save(); - command.disable(guild.id); - return instance.messageHandler.get(guild, 'COMMAND_NOW_DISABLED', { - COMMAND: mainCommand, - }); - } - return instance.messageHandler.get(guild, 'UNKNOWN_COMMAND', { - COMMAND: name, - }); - }, -}; diff --git a/dist/commands/help/!ReactionListener.js b/dist/commands/help/!ReactionListener.js deleted file mode 100644 index cf1a2d7..0000000 --- a/dist/commands/help/!ReactionListener.js +++ /dev/null @@ -1,217 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.addReactions = void 0; -const _get_first_embed_1 = __importDefault(require("./!get-first-embed")); -const /** - * Recursively adds reactions to the message - * @param message The message to react to - * @param reactions A list of reactions to add - */ addReactions = (message, reactions) => { - const emoji = reactions.shift(); - if (emoji) { - message.react(emoji); - addReactions(message, reactions); - } -}; -exports.addReactions = addReactions; -class ReactionHandler { - instance; - reaction; - user; - message; - embed; - guild = null; - emojiName = ''; - emojiId = ''; - door = '🚪'; - pageLimit = 3; - constructor(instance, reaction, user) { - this.instance = instance; - this.reaction = reaction; - this.user = user; - this.message = reaction.message; - this.init(); - } - init = async () => { - if (this.message.partial) { - await this.message.fetch(); - } - const { embeds, guild } = this.message; - if (this.user.bot || !embeds || embeds.length !== 1) { - return; - } - this.embed = embeds[0]; - this.guild = guild; - if (!this.canUserInteract()) { - return; - } - this.emojiName = this.reaction.emoji.name; - this.emojiId = this.reaction.emoji.id || ''; - this.handleEmoji(); - }; - /** - * @returns If the bot has access to remove reactions from the help menu - */ - canBotRemoveReaction = () => { - return (this.message.channel.type !== 'DM' && - this.message.member?.permissions.has('MANAGE_MESSAGES')); - }; - /** - * @returns If the user is allowed to interact with this help menu - */ - canUserInteract = () => { - // Check if the title of the embed is correct - const displayName = this.instance.displayName - ? this.instance.displayName + ' ' - : ''; - const isSameTitle = this.embed.title === - `${displayName}${this.instance.messageHandler.getEmbed(this.guild, 'HELP_MENU', 'TITLE')}`; - if (!isSameTitle) { - return false; - } - // Check if the user's ID is in the footer - if (this.embed.footer) { - const { text } = this.embed.footer; - const id = text?.split('#')[1]; - if (id !== this.user.id) { - if (this.canBotRemoveReaction()) { - this.reaction.users.remove(this.user.id); - } - return false; - } - } - return true; - }; - /** - * Invoked when the user returns to the main menu - */ - returnToMainMenu = () => { - const { embed: newEmbed, reactions } = _get_first_embed_1.default(this.message, this.instance); - this.embed.setDescription(newEmbed.description || ''); - this.message.edit({ embeds: [this.embed] }); - if (this.canBotRemoveReaction()) { - this.message.reactions.removeAll(); - } - addReactions(this.message, reactions); - }; - /** - * @param commandLength How many commands are in the category - * @returns An array of [page, maxPages] - */ - getMaxPages = (commandLength) => { - let page = 1; - if (this.embed && this.embed.description) { - const split = this.embed.description.split('\n'); - const lastLine = split[split.length - 1]; - if (lastLine.startsWith('Page ')) { - page = parseInt(lastLine.split(' ')[1]); - } - } - return [page, Math.ceil(commandLength / this.pageLimit)]; - }; - /** - * @returns An object containing information regarding the commands - */ - getCommands = () => { - let category = this.instance.getCategory(this.emojiId || this.emojiName); - const commandsString = this.instance.messageHandler.getEmbed(this.guild, 'HELP_MENU', 'COMMANDS'); - if (this.embed.description) { - const split = this.embed.description.split('\n'); - const cmdStr = ' ' + commandsString; - if (split[0].endsWith(cmdStr)) { - category = split[0].replace(cmdStr, ''); - } - } - const commands = this.instance.commandHandler.getCommandsByCategory(category); - return { - length: commands.length, - commands, - commandsString, - category, - }; - }; - static getHelp = (command, instance, guild) => { - const { description, syntax, names } = command; - if (names === undefined) { - console.error('WOKCommands > A command does not have a name assigned to it.'); - return ''; - } - const mainName = typeof names === 'string' ? names : names.shift(); - let desc = `**${mainName}**${description ? ' - ' : ''}${description}`; - if (names.length && typeof names !== 'string') { - desc += `\n${instance.messageHandler.getEmbed(guild, 'HELP_MENU', 'ALIASES')}: "${names.join('", "')}"`; - } - desc += `\n${instance.messageHandler.getEmbed(guild, 'HELP_MENU', 'SYNTAX')}: "${instance.getPrefix(guild)}${mainName}${syntax ? ' ' : ''}${syntax || ''}"`; - return desc; - }; - /** - * Generates the actual menu - */ - generateMenu = (page, maxPages) => { - const { length, commands, commandsString, category } = this.getCommands(); - const hasMultiplePages = length > this.pageLimit; - let desc = `${category} ${commandsString}\n\n${this.instance.messageHandler.getEmbed(this.guild, 'HELP_MENU', 'DESCRIPTION_FIRST_LINE')}`; - if (hasMultiplePages) { - desc += `\n\n${this.instance.messageHandler.getEmbed(this.guild, 'HELP_MENU', 'DESCRIPTION_SECOND_LINE')}`; - } - const start = (page - 1) * this.pageLimit; - for (let a = start, counter = a; a < commands.length && a < start + this.pageLimit; ++a) { - const command = commands[a]; - let { hidden, category, names } = command; - if (!hidden && category === category) { - if (typeof names === 'string') { - // @ts-ignore - names = [...names]; - } - desc += `\n\n#${++counter}) ${ReactionHandler.getHelp(command, this.instance, this.guild)}`; - } - } - desc += `\n\nPage ${page} / ${maxPages}.`; - this.embed.setDescription(desc); - this.message.edit({ embeds: [this.embed] }); - if (this.canBotRemoveReaction()) { - this.message.reactions.removeAll(); - } - const reactions = []; - if (hasMultiplePages) { - reactions.push('⬅'); - reactions.push('➡'); - } - reactions.push('🚪'); - addReactions(this.message, reactions); - }; - /** - * Handles the input from the emoji - */ - handleEmoji = () => { - if (this.emojiName === this.door) { - this.returnToMainMenu(); - return; - } - const { length } = this.getCommands(); - let [page, maxPages] = this.getMaxPages(length); - if (this.emojiName === '⬅') { - if (page <= 1) { - if (this.canBotRemoveReaction()) { - this.reaction.users.remove(this.user.id); - } - return; - } - --page; - } - else if (this.emojiName === '➡') { - if (page >= maxPages) { - if (this.canBotRemoveReaction()) { - this.reaction.users.remove(this.user.id); - } - return; - } - ++page; - } - this.generateMenu(page, maxPages); - }; -} -exports.default = ReactionHandler; diff --git a/dist/commands/help/!get-first-embed.js b/dist/commands/help/!get-first-embed.js deleted file mode 100644 index 08e82be..0000000 --- a/dist/commands/help/!get-first-embed.js +++ /dev/null @@ -1,56 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const getFirstEmbed = (message, instance) => { - const { guild, member } = message; - const { commandHandler: { commands }, messageHandler, } = instance; - const embed = new discord_js_1.MessageEmbed() - .setTitle(`${instance.displayName} ${messageHandler.getEmbed(guild, 'HELP_MENU', 'TITLE')}`) - .setDescription(messageHandler.getEmbed(guild, 'HELP_MENU', 'SELECT_A_CATEGORY')) - .setFooter(`ID #${message.author?.id}`); - if (instance.color) { - embed.setColor(instance.color); - } - const categories = {}; - const isAdmin = member && member.permissions.has('ADMINISTRATOR'); - for (const { category, testOnly } of commands) { - if (!category || - (testOnly && guild && !instance.testServers.includes(guild.id)) || - (!isAdmin && instance.hiddenCategories.includes(category))) { - continue; - } - if (categories[category]) { - ++categories[category].amount; - } - else { - categories[category] = { - amount: 1, - emoji: instance.getEmoji(category), - }; - } - } - const reactions = []; - const keys = Object.keys(categories); - for (let a = 0; a < keys.length; ++a) { - const key = keys[a]; - const { emoji } = categories[key]; - if (!emoji) { - console.warn(`WOKCommands > Category "${key}" does not have an emoji icon.`); - continue; - } - const visibleCommands = instance.commandHandler.getCommandsByCategory(key, true); - const amount = visibleCommands.length; - if (amount === 0) { - continue; - } - const reaction = emoji; - reactions.push(reaction); - embed.setDescription(embed.description + - `\n\n**${reaction} - ${key}** - ${amount} command${amount === 1 ? '' : 's'}`); - } - return { - embed, - reactions, - }; -}; -exports.default = getFirstEmbed; diff --git a/dist/commands/help/help.js b/dist/commands/help/help.js deleted file mode 100644 index 793c2ae..0000000 --- a/dist/commands/help/help.js +++ /dev/null @@ -1,82 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const discord_js_1 = require("discord.js"); -const _get_first_embed_1 = __importDefault(require("./!get-first-embed")); -const _ReactionListener_1 = __importStar(require("./!ReactionListener")); -const sendHelpMenu = (message, instance) => { - const { embed, reactions } = _get_first_embed_1.default(message, instance); - message.channel - .send({ - embeds: [embed], - }) - .then((message) => { - _ReactionListener_1.addReactions(message, reactions); - }); -}; -module.exports = { - description: "Displays this bot's commands", - category: 'Help', - aliases: 'commands', - maxArgs: 1, - expectedArgs: '[command]', - init: (client, instance) => { - client.on('messageReactionAdd', async (reaction, user) => { - new _ReactionListener_1.default(instance, reaction, user); - }); - }, - callback: (options) => { - const { message, channel, instance, args } = options; - const { guild } = channel; - if (guild && !guild.me?.permissions.has('SEND_MESSAGES')) { - console.warn(`WOKCommands > Could not send message due to no permissions in channel for ${guild.name}`); - return; - } - if (guild && !guild.me?.permissions.has('ADD_REACTIONS')) { - return instance.messageHandler.get(guild, 'NO_REACT_PERMS'); - } - // Typical "!help" syntax for the menu - if (args.length === 0) { - sendHelpMenu(message, instance); - return; - } - // If the user is looking for info on a specific command - // Ex: "!help prefix" - const arg = args.shift()?.toLowerCase(); - const command = instance.commandHandler.getICommand(arg); - if (!command) { - return instance.messageHandler.get(guild, 'UNKNOWN_COMMAND', { - COMMAND: arg, - }); - } - const description = _ReactionListener_1.default.getHelp(command, instance, guild); - const embed = new discord_js_1.MessageEmbed() - .setTitle(`${instance.displayName} ${instance.messageHandler.getEmbed(guild, 'HELP_MENU', 'TITLE')} - ${arg}`) - .setDescription(description); - if (instance.color) { - embed.setColor(instance.color); - } - return embed; - }, -}; diff --git a/dist/commands/language.js b/dist/commands/language.js deleted file mode 100644 index 7d86fd4..0000000 --- a/dist/commands/language.js +++ /dev/null @@ -1,51 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -const languages_1 = __importDefault(require("../models/languages")); -const Events_1 = __importDefault(require("../enums/Events")); -module.exports = { - description: 'Displays or sets the language for this Discord server', - category: 'Configuration', - aliases: ['lang'], - permissions: ['ADMINISTRATOR'], - maxArgs: 1, - expectedArgs: '[language]', - cooldown: '2s', - slash: 'both', - callback: async (options) => { - const { channel, text, instance } = options; - const { guild } = channel; - if (!guild) { - return; - } - const { messageHandler } = instance; - if (!instance.isDBConnected()) { - return instance.messageHandler.get(guild, 'NO_DATABASE_FOUND'); - } - const lang = text.toLowerCase(); - if (!lang) { - return instance.messageHandler.get(guild, 'CURRENT_LANGUAGE', { - LANGUAGE: instance.messageHandler.getLanguage(guild), - }); - } - if (!messageHandler.languages().includes(lang)) { - instance.emit(Events_1.default.LANGUAGE_NOT_SUPPORTED, guild, lang); - return messageHandler.get(guild, 'LANGUAGE_NOT_SUPPORTED', { - LANGUAGE: lang, - }); - } - instance.messageHandler.setLanguage(guild, lang); - await languages_1.default.findOneAndUpdate({ - _id: guild.id, - }, { - _id: guild.id, - language: lang, - }, { - upsert: true, - }); - return instance.messageHandler.get(guild, 'NEW_LANGUAGE', { - LANGUAGE: lang, - }); - }, -}; diff --git a/dist/commands/prefix.js b/dist/commands/prefix.js deleted file mode 100644 index 1b06f8a..0000000 --- a/dist/commands/prefix.js +++ /dev/null @@ -1,42 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -const prefixes_1 = __importDefault(require("../models/prefixes")); -module.exports = { - description: 'Displays or sets the prefix for the current guild', - category: 'Configuration', - permissions: ['ADMINISTRATOR'], - maxArgs: 1, - expectedArgs: '[prefix]', - cooldown: '2s', - slash: 'both', - callback: async (options) => { - const { channel, args, text, instance } = options; - const { guild } = channel; - if (args.length === 0) { - return instance.messageHandler.get(guild, 'CURRENT_PREFIX', { - PREFIX: instance.getPrefix(guild), - }); - } - if (guild) { - const { id } = guild; - if (!instance.isDBConnected()) { - return instance.messageHandler.get(guild, 'NO_DATABASE_FOUND'); - } - await prefixes_1.default.findOneAndUpdate({ - _id: id, - }, { - _id: id, - prefix: text, - }, { - upsert: true, - }); - instance.setPrefix(guild, text); - return instance.messageHandler.get(guild, 'SET_PREFIX', { - PREFIX: text, - }); - } - return instance.messageHandler.get(guild, 'CANNOT_SET_PREFIX_IN_DMS'); - }, -}; diff --git a/dist/commands/requiredrole.js b/dist/commands/requiredrole.js deleted file mode 100644 index 1d8892f..0000000 --- a/dist/commands/requiredrole.js +++ /dev/null @@ -1,61 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -const required_roles_1 = __importDefault(require("../models/required-roles")); -module.exports = { - description: 'Specifies what role each command requires.', - category: 'Configuration', - permissions: ['ADMINISTRATOR'], - aliases: ['requiredroles', 'requirerole', 'requireroles'], - minArgs: 2, - maxArgs: 2, - expectedArgs: ' ', - cooldown: '2s', - slash: 'both', - callback: async (options) => { - const { channel, args, instance } = options; - const name = (args.shift() || '').toLowerCase(); - const roleId = (args.shift() || '').toLowerCase(); - const { guild } = channel; - if (!guild) { - return instance.messageHandler.get(guild, 'CANNOT_CHANGE_REQUIRED_ROLES_IN_DMS'); - } - if (!instance.isDBConnected()) { - return instance.messageHandler.get(guild, 'NO_DATABASE_FOUND'); - } - const command = instance.commandHandler.getCommand(name); - if (command) { - if (roleId === 'none') { - command.removeRequiredRole(guild.id, roleId); - await required_roles_1.default.deleteOne({ - guildId: guild.id, - command: command.names[0], - }); - return instance.messageHandler.get(guild, 'REMOVED_ALL_REQUIRED_ROLES', { - COMMAND: command.names[0], - }); - } - command.addRequiredRole(guild.id, roleId); - await required_roles_1.default.findOneAndUpdate({ - guildId: guild.id, - command: command.names[0], - }, { - guildId: guild.id, - command: command.names[0], - $addToSet: { - requiredRoles: roleId, - }, - }, { - upsert: true, - }); - return instance.messageHandler.get(guild, 'ADDED_REQUIRED_ROLE', { - ROLE: roleId, - COMMAND: command.names[0], - }); - } - return instance.messageHandler.get(guild, 'UNKNOWN_COMMAND', { - COMMAND: name, - }); - }, -}; diff --git a/dist/commands/slash.js b/dist/commands/slash.js deleted file mode 100644 index 9200f13..0000000 --- a/dist/commands/slash.js +++ /dev/null @@ -1,93 +0,0 @@ -"use strict"; -const discord_js_1 = require("discord.js"); -module.exports = { - description: 'Allows the bot developers to manage existing slash commands', - category: 'Configuration', - permissions: ['ADMINISTRATOR'], - maxArgs: 1, - expectedArgs: '[command-id]', - ownerOnly: true, - hidden: true, - slash: 'both', - callback: async (options) => { - const { channel, instance, text } = options; - const { guild } = channel; - const { slashCommands } = instance; - const global = await slashCommands.get(); - if (text) { - let useGuild = true; - try { - global?.forEach((cmd) => { - if (cmd.id === text) { - useGuild = false; - throw new Error(''); - } - }); - } - catch (ignored) { } - slashCommands.delete(text, useGuild ? guild.id : undefined); - if (useGuild) { - return `Slash command with the ID "${text}" has been deleted from guild "${guild.id}".`; - } - return `Slash command with the ID "${text}" has been deleted. This may take up to 1 hour to be seen on all servers using your bot.`; - } - let counter = 0; - let allSlashCommands = []; - if (global.size) { - global.forEach((cmd) => { - if (cmd && cmd.name) { - const newString = `${cmd.name}: ${cmd.id}\n`; - if ((allSlashCommands[counter] || []).length + newString.length < - 1024) { - allSlashCommands[counter] ??= ''; - allSlashCommands[counter] += newString; - } - else { - ++counter; - allSlashCommands[counter] ??= ''; - allSlashCommands[counter] += newString; - } - } - }); - } - else { - allSlashCommands.push('None'); - } - const embed = new discord_js_1.MessageEmbed().addField('How to delete a slash command:', `${instance.getPrefix(guild)}slash `); - for (let a = 0; a < allSlashCommands.length; ++a) { - embed.addField(`Global slash commands:${a === 0 ? '' : ' (Continued)'}`, allSlashCommands[a]); - } - if (guild) { - const guildOnly = await slashCommands.get(guild.id); - counter = 0; - let guildOnlyCommands = []; - if (guildOnly.size) { - guildOnly.forEach((cmd) => { - if (cmd && cmd.name) { - const newString = `${cmd.name}: ${cmd.id}\n`; - if ((guildOnlyCommands[counter] || []).length + newString.length < - 1024) { - guildOnlyCommands[counter] ??= ''; - guildOnlyCommands[counter] += newString; - } - else { - ++counter; - guildOnlyCommands[counter] ??= ''; - guildOnlyCommands[counter] += newString; - } - } - }); - } - else { - guildOnlyCommands[0] = 'None'; - } - for (let a = 0; a < guildOnlyCommands.length; ++a) { - embed.addField(`Guild slash commands:${a === 0 ? '' : ' (Continued)'}`, guildOnlyCommands[a]); - } - } - if (instance.color) { - embed.setColor(instance.color); - } - return embed; - }, -}; diff --git a/dist/enums/CommandErrors.js b/dist/enums/CommandErrors.js deleted file mode 100644 index 761e1de..0000000 --- a/dist/enums/CommandErrors.js +++ /dev/null @@ -1,12 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var CommandErrors; -(function (CommandErrors) { - CommandErrors["EXCEPTION"] = "EXCEPTION"; - CommandErrors["COOLDOWN"] = "COOLDOWN"; - CommandErrors["INVALID_ARGUMENTS"] = "INVALID ARGUMENTS"; - CommandErrors["MISSING_PERMISSIONS"] = "MISSING PERMISSIONS"; - CommandErrors["MISSING_ROLES"] = "MISSING ROLES"; - CommandErrors["COMMAND_DISABLED"] = "COMMAND DISABLED"; -})(CommandErrors || (CommandErrors = {})); -exports.default = CommandErrors; diff --git a/dist/enums/Events.js b/dist/enums/Events.js deleted file mode 100644 index 48cd972..0000000 --- a/dist/enums/Events.js +++ /dev/null @@ -1,9 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var Events; -(function (Events) { - Events["DATABASE_CONNECTED"] = "databaseConnected"; - Events["LANGUAGE_NOT_SUPPORTED"] = "languageNotSupported"; - Events["COMMAND_EXCEPTION"] = "commandException"; -})(Events || (Events = {})); -exports.default = Events; diff --git a/dist/features/message-upsert.js b/dist/features/message-upsert.js deleted file mode 100644 index 127c4fd..0000000 --- a/dist/features/message-upsert.js +++ /dev/null @@ -1,15 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.config = void 0; -exports.default = (client) => { - client.on('messageCreate', (message) => { - client.emit('messageUpsert', message); - }); - client.on('messageUpdate', (oldMessage, newMessage) => { - client.emit('messageUpsert', newMessage, oldMessage); - }); -}; -exports.config = { - displayName: 'Message Upsert', - dbName: 'MESSAGE-UPSERT', -}; diff --git a/dist/get-all-files.js b/dist/get-all-files.js deleted file mode 100644 index e2dd73d..0000000 --- a/dist/get-all-files.js +++ /dev/null @@ -1,25 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -const fs_1 = __importDefault(require("fs")); -const getAllFiles = (dir, extension) => { - const files = fs_1.default.readdirSync(dir, { - withFileTypes: true, - }); - let jsFiles = []; - for (const file of files) { - if (file.isDirectory()) { - jsFiles = [...jsFiles, ...getAllFiles(`${dir}/${file.name}`, extension)]; - } - else if (file.name.endsWith(extension || '.js') && - !file.name.startsWith('!')) { - let fileName = file.name.replace(/\\/g, '/').split('/'); - fileName = fileName[fileName.length - 1]; - fileName = fileName.split('.')[0].toLowerCase(); - jsFiles.push([`${dir}/${file.name}`, fileName]); - } - } - return jsFiles; -}; -module.exports = getAllFiles; diff --git a/dist/index.js b/dist/index.js deleted file mode 100644 index bb8f71c..0000000 --- a/dist/index.js +++ /dev/null @@ -1,289 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const events_1 = require("events"); -const FeatureHandler_1 = __importDefault(require("./FeatureHandler")); -const mongo_1 = __importStar(require("./mongo")); -const prefixes_1 = __importDefault(require("./models/prefixes")); -const message_handler_1 = __importDefault(require("./message-handler")); -const SlashCommands_1 = __importDefault(require("./SlashCommands")); -const Events_1 = __importDefault(require("./enums/Events")); -const CommandHandler_1 = __importDefault(require("./CommandHandler")); -class WOKCommands extends events_1.EventEmitter { - _client; - _defaultPrefix = '!'; - _commandsDir = 'commands'; - _featuresDir = ''; - _mongoConnection = null; - _displayName = ''; - _prefixes = {}; - _categories = new Map(); // - _hiddenCategories = []; - _color = null; - _commandHandler = null; - _featureHandler = null; - _tagPeople = true; - _showWarns = true; - _delErrMsgCooldown = -1; - _ignoreBots = true; - _botOwner = []; - _testServers = []; - _defaultLanguage = 'english'; - _ephemeral = true; - _debug = false; - _messageHandler = null; - _slashCommand = null; - constructor(client, options) { - super(); - this._client = client; - this.setUp(client, options); - } - async setUp(client, options) { - if (!client) { - throw new Error('No Discord JS Client provided as first argument!'); - } - let { commandsDir = '', commandDir = '', featuresDir = '', featureDir = '', messagesPath, mongoUri, showWarns = true, delErrMsgCooldown = -1, defaultLanguage = 'english', ignoreBots = true, dbOptions, testServers, botOwners, disabledDefaultCommands = [], typeScript = false, ephemeral = true, debug = false, } = options || {}; - if (mongoUri) { - await mongo_1.default(mongoUri, this, dbOptions); - this._mongoConnection = mongo_1.getMongoConnection(); - const results = await prefixes_1.default.find({}); - for (const result of results) { - const { _id, prefix } = result; - this._prefixes[_id] = prefix; - } - } - else { - if (showWarns) { - console.warn('WOKCommands > No MongoDB connection URI provided. Some features might not work! See this for more details:\nhttps://docs.wornoffkeys.com/databases/mongodb'); - } - this.emit(Events_1.default.DATABASE_CONNECTED, null, ''); - } - this._commandsDir = commandsDir || commandDir || this._commandsDir; - this._featuresDir = featuresDir || featureDir || this._featuresDir; - this._ephemeral = ephemeral; - this._debug = debug; - if (this._commandsDir && - !(this._commandsDir.includes('/') || this._commandsDir.includes('\\'))) { - throw new Error("WOKCommands > The 'commands' directory must be an absolute path. This can be done by using the 'path' module. More info: https://docs.wornoffkeys.com/setup-and-options-object"); - } - if (this._featuresDir && - !(this._featuresDir.includes('/') || this._featuresDir.includes('\\'))) { - throw new Error("WOKCommands > The 'features' directory must be an absolute path. This can be done by using the 'path' module. More info: https://docs.wornoffkeys.com/setup-and-options-object"); - } - if (testServers) { - if (typeof testServers === 'string') { - testServers = [testServers]; - } - this._testServers = testServers; - } - if (botOwners) { - if (typeof botOwners === 'string') { - botOwners = [botOwners]; - } - this._botOwner = botOwners; - } - this._showWarns = showWarns; - this._delErrMsgCooldown = delErrMsgCooldown; - this._defaultLanguage = defaultLanguage.toLowerCase(); - this._ignoreBots = ignoreBots; - if (typeof disabledDefaultCommands === 'string') { - disabledDefaultCommands = [disabledDefaultCommands]; - } - this._commandHandler = new CommandHandler_1.default(this, client, this._commandsDir, disabledDefaultCommands, typeScript); - this._slashCommand = new SlashCommands_1.default(this, true, typeScript); - this._messageHandler = new message_handler_1.default(this, messagesPath || ''); - this.setCategorySettings([ - { - name: 'Configuration', - emoji: '⚙', - }, - { - name: 'Help', - emoji: '❓', - }, - ]); - this._featureHandler = new FeatureHandler_1.default(client, this, this._featuresDir, typeScript); - console.log('WOKCommands > Your bot is now running.'); - } - setMongoPath(mongoPath) { - console.warn('WOKCommands > .setMongoPath() no longer works as expected. Please pass in your mongo URI as a "mongoUri" property using the options object. For more information: https://docs.wornoffkeys.com/databases/mongodb'); - return this; - } - get client() { - return this._client; - } - get displayName() { - return this._displayName; - } - setDisplayName(displayName) { - this._displayName = displayName; - return this; - } - get prefixes() { - return this._prefixes; - } - get defaultPrefix() { - return this._defaultPrefix; - } - setDefaultPrefix(defaultPrefix) { - this._defaultPrefix = defaultPrefix; - return this; - } - getPrefix(guild) { - return this._prefixes[guild ? guild.id : ''] || this._defaultPrefix; - } - setPrefix(guild, prefix) { - if (guild) { - this._prefixes[guild.id] = prefix; - } - return this; - } - get categories() { - return this._categories; - } - get hiddenCategories() { - return this._hiddenCategories; - } - get color() { - return this._color; - } - setColor(color) { - this._color = color; - return this; - } - getEmoji(category) { - const emoji = this._categories.get(category) || ''; - if (typeof emoji === 'object') { - // @ts-ignore - return `<:${emoji.name}:${emoji.id}>`; - } - return emoji; - } - getCategory(emoji) { - let result = ''; - this._categories.forEach((value, key) => { - // == is intended here - if (emoji == value) { - // @ts-ignore - result = key; - return false; - } - }); - return result; - } - setCategorySettings(category) { - for (let { emoji, name, hidden, customEmoji } of category) { - if (emoji.startsWith('<:') && emoji.endsWith('>')) { - customEmoji = true; - emoji = emoji.split(':')[2]; - emoji = emoji.substring(0, emoji.length - 1); - } - let targetEmoji = emoji; - if (customEmoji) { - targetEmoji = this._client.emojis.cache.get(emoji); - } - if (this.isEmojiUsed(targetEmoji)) { - console.warn(`WOKCommands > The emoji "${targetEmoji}" for category "${name}" is already used.`); - } - this._categories.set(name, targetEmoji || this.categories.get(name) || ''); - if (hidden) { - this._hiddenCategories.push(name); - } - } - return this; - } - isEmojiUsed(emoji) { - if (!emoji) { - return false; - } - let isUsed = false; - this._categories.forEach((value) => { - if (value === emoji) { - isUsed = true; - } - }); - return isUsed; - } - get commandHandler() { - return this._commandHandler; - } - get mongoConnection() { - return this._mongoConnection; - } - isDBConnected() { - const connection = this.mongoConnection; - return !!(connection && connection.readyState === 1); - } - setTagPeople(tagPeople) { - this._tagPeople = tagPeople; - return this; - } - get tagPeople() { - return this._tagPeople; - } - get showWarns() { - return this._showWarns; - } - get delErrMsgCooldown() { - return this._delErrMsgCooldown; - } - get ignoreBots() { - return this._ignoreBots; - } - get botOwner() { - return this._botOwner; - } - setBotOwner(botOwner) { - console.log('WOKCommands > setBotOwner() is deprecated. Please specify your bot owners in the object constructor instead. See https://docs.wornoffkeys.com/setup-and-options-object'); - if (typeof botOwner === 'string') { - botOwner = [botOwner]; - } - this._botOwner = botOwner; - return this; - } - get testServers() { - return this._testServers; - } - get defaultLanguage() { - return this._defaultLanguage; - } - setDefaultLanguage(defaultLanguage) { - this._defaultLanguage = defaultLanguage; - return this; - } - get ephemeral() { - return this._ephemeral; - } - get debug() { - return this._debug; - } - get messageHandler() { - return this._messageHandler; - } - get slashCommands() { - return this._slashCommand; - } -} -exports.default = WOKCommands; -module.exports = WOKCommands; diff --git a/dist/message-handler.js b/dist/message-handler.js deleted file mode 100644 index e7425d1..0000000 --- a/dist/message-handler.js +++ /dev/null @@ -1,104 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const languages_1 = __importDefault(require("./models/languages")); -const defualtMessages = require('../messages.json'); -class MessageHandler { - _instance; - _guildLanguages = new Map(); // - _languages = []; - _messages = {}; - constructor(instance, messagePath) { - this._instance = instance; - (async () => { - this._messages = messagePath ? await Promise.resolve().then(() => __importStar(require(messagePath))) : defualtMessages; - for (const messageId of Object.keys(this._messages)) { - for (const language of Object.keys(this._messages[messageId])) { - this._languages.push(language.toLowerCase()); - } - } - if (!this._languages.includes(instance.defaultLanguage)) { - throw new Error(`The current default language defined is not supported.`); - } - if (instance.isDBConnected()) { - const results = await languages_1.default.find(); - // @ts-ignore - for (const { _id: guildId, language } of results) { - this._guildLanguages.set(guildId, language); - } - } - })(); - } - languages() { - return this._languages; - } - async setLanguage(guild, language) { - if (guild) { - this._guildLanguages.set(guild.id, language); - } - } - getLanguage(guild) { - if (guild) { - const result = this._guildLanguages.get(guild.id); - if (result) { - return result; - } - } - return this._instance.defaultLanguage; - } - get(guild, messageId, args = {}) { - const language = this.getLanguage(guild); - const translations = this._messages[messageId]; - if (!translations) { - console.error(`WOKCommands > Could not find the correct message to send for "${messageId}"`); - return 'Could not find the correct message to send. Please report this to the bot developer.'; - } - let result = translations[language]; - for (const key of Object.keys(args)) { - const expression = new RegExp(`{${key}}`, 'g'); - result = result.replace(expression, args[key]); - } - return result; - } - getEmbed(guild, embedId, itemId, args = {}) { - const language = this.getLanguage(guild); - const items = this._messages[embedId]; - if (!items) { - console.error(`WOKCommands > Could not find the correct item to send for "${embedId}" -> "${itemId}"`); - return 'Could not find the correct message to send. Please report this to the bot developer.'; - } - const translations = items[itemId]; - if (!translations) { - console.error(`WOKCommands > Could not find the correct message to send for "${embedId}"`); - return 'Could not find the correct message to send. Please report this to the bot developer.'; - } - let result = translations[language]; - for (const key of Object.keys(args)) { - const expression = new RegExp(`{${key}}`, 'g'); - result = result.replace(expression, args[key]); - } - return result; - } -} -exports.default = MessageHandler; diff --git a/dist/models/channel-commands.js b/dist/models/channel-commands.js deleted file mode 100644 index 5afb61d..0000000 --- a/dist/models/channel-commands.js +++ /dev/null @@ -1,35 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -const mongoose_1 = __importStar(require("mongoose")); -const reqString = { - type: String, - required: true, -}; -const schema = new mongoose_1.Schema({ - guildId: reqString, - command: reqString, - channels: { - type: [String], - required: true, - }, -}); -const name = 'wokcommands-channel-commands'; -module.exports = mongoose_1.default.models[name] || mongoose_1.default.model(name, schema, name); diff --git a/dist/models/cooldown.js b/dist/models/cooldown.js deleted file mode 100644 index adc211e..0000000 --- a/dist/models/cooldown.js +++ /dev/null @@ -1,37 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -const mongoose_1 = __importStar(require("mongoose")); -const reqString = { - type: String, - required: true, -}; -const schema = new mongoose_1.Schema({ - // Command-GuildID or Command-GuildID-UserID - _id: reqString, - name: reqString, - type: reqString, - cooldown: { - type: Number, - required: true, - }, -}); -const name = 'wokcommands-cooldowns'; -module.exports = mongoose_1.default.models[name] || mongoose_1.default.model(name, schema, name); diff --git a/dist/models/disabled-commands.js b/dist/models/disabled-commands.js deleted file mode 100644 index 6470b41..0000000 --- a/dist/models/disabled-commands.js +++ /dev/null @@ -1,31 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -const mongoose_1 = __importStar(require("mongoose")); -const reqString = { - type: String, - required: true, -}; -const schema = new mongoose_1.Schema({ - guildId: reqString, - command: reqString, -}); -const name = 'wokcommands-disabled-commands'; -module.exports = mongoose_1.default.models[name] || mongoose_1.default.model(name, schema, name); diff --git a/dist/models/languages.js b/dist/models/languages.js deleted file mode 100644 index a7a6017..0000000 --- a/dist/models/languages.js +++ /dev/null @@ -1,32 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -const mongoose_1 = __importStar(require("mongoose")); -const reqString = { - type: String, - required: true, -}; -const schema = new mongoose_1.Schema({ - // GuildID - _id: reqString, - language: reqString, -}); -const name = 'wokcommands-languages'; -module.exports = mongoose_1.default.models[name] || mongoose_1.default.model(name, schema, name); diff --git a/dist/models/prefixes.js b/dist/models/prefixes.js deleted file mode 100644 index bf0c204..0000000 --- a/dist/models/prefixes.js +++ /dev/null @@ -1,32 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -const mongoose_1 = __importStar(require("mongoose")); -const reqString = { - type: String, - required: true, -}; -const schema = new mongoose_1.Schema({ - // Guild ID - _id: reqString, - prefix: reqString, -}); -const name = 'wokcommands-prefixes'; -module.exports = mongoose_1.default.models[name] || mongoose_1.default.model(name, schema, name); diff --git a/dist/models/required-roles.js b/dist/models/required-roles.js deleted file mode 100644 index 1ef5a06..0000000 --- a/dist/models/required-roles.js +++ /dev/null @@ -1,35 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -const mongoose_1 = __importStar(require("mongoose")); -const reqString = { - type: String, - required: true, -}; -const schema = new mongoose_1.Schema({ - guildId: reqString, - command: reqString, - requiredRoles: { - type: [String], - required: true, - }, -}); -const name = 'wokcommands-required-roles'; -module.exports = mongoose_1.default.models[name] || mongoose_1.default.model(name, schema, name); diff --git a/dist/mongo.js b/dist/mongo.js deleted file mode 100644 index 308eb7c..0000000 --- a/dist/mongo.js +++ /dev/null @@ -1,28 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.getMongoConnection = void 0; -const mongoose_1 = __importDefault(require("mongoose")); -const Events_1 = __importDefault(require("./enums/Events")); -const results = { - 0: 'Disconnected', - 1: 'Connected', - 2: 'Connecting', - 3: 'Disconnecting', -}; -exports.default = async (mongoPath, instance, dbOptions = {}) => { - const options = { - keepAlive: true, - ...dbOptions, - }; - await mongoose_1.default.connect(mongoPath, options); - const { connection } = mongoose_1.default; - const state = results[connection.readyState] || 'Unknown'; - instance.emit(Events_1.default.DATABASE_CONNECTED, connection, state); -}; -const getMongoConnection = () => { - return mongoose_1.default.connection; -}; -exports.getMongoConnection = getMongoConnection; diff --git a/dist/permissions.js b/dist/permissions.js deleted file mode 100644 index 3f1577e..0000000 --- a/dist/permissions.js +++ /dev/null @@ -1,37 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.permissionList = void 0; -const permissionList = [ - 'CREATE_INSTANT_INVITE', - 'KICK_MEMBERS', - 'BAN_MEMBERS', - 'ADMINISTRATOR', - 'MANAGE_CHANNELS', - 'MANAGE_GUILD', - 'ADD_REACTIONS', - 'VIEW_AUDIT_LOG', - 'PRIORITY_SPEAKER', - 'STREAM', - 'VIEW_CHANNEL', - 'SEND_MESSAGES', - 'SEND_TTS_MESSAGES', - 'MANAGE_MESSAGES', - 'EMBED_LINKS', - 'ATTACH_FILES', - 'READ_MESSAGE_HISTORY', - 'MENTION_EVERYONE', - 'USE_EXTERNAL_EMOJIS', - 'VIEW_GUILD_INSIGHTS', - 'CONNECT', - 'SPEAK', - 'MUTE_MEMBERS', - 'DEAFEN_MEMBERS', - 'MOVE_MEMBERS', - 'USE_VAD', - 'CHANGE_NICKNAME', - 'MANAGE_NICKNAMES', - 'MANAGE_ROLES', - 'MANAGE_WEBHOOKS', - 'MANAGE_EMOJIS', -]; -exports.permissionList = permissionList; diff --git a/index.js b/index.js deleted file mode 100644 index bb16aa2..0000000 --- a/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import WOKCommands from './src' - -export default WOKCommands diff --git a/package-lock.json b/package-lock.json index ac8d953..d29ba5b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,12 @@ { "name": "wokcommands", - "version": "1.5.0", + "version": "1.5.3", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "1.5.0", + "name": "wokcommands", + "version": "1.5.3", "license": "ISC", "dependencies": { "discord.js": "^13.1.0", diff --git a/package.json b/package.json index 2d6fc79..f50e71a 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,6 @@ "name": "wokcommands", "version": "1.5.3", "main": "dist/index.js", - "typings": "./typings.d.ts", "scripts": { "tsc": "tsc -w --outDir dist --rootDir src --skipLibCheck", "compile": "tsc && node index.js", diff --git a/src/Command.ts b/src/Command.ts index beb62ac..ef5461c 100644 --- a/src/Command.ts +++ b/src/Command.ts @@ -1,39 +1,38 @@ -import { Client, Guild, Message, MessageEmbed } from 'discord.js' -import WOKCommands from '.' - -import permissions from './permissions' -import cooldownSchema from './models/cooldown' -import { ICommand } from '../typings' +import { Client, Guild, Message } from "discord.js"; +import WOKCommands from "."; +import cooldownSchema from "./models/cooldown"; +import permissions from "./permissions"; +import { ICommand } from "./types"; class Command { - private instance: WOKCommands - private client: Client - private _names: string[] = [] - private _category = '' - private _minArgs: number = 0 - private _maxArgs: number = -1 - private _syntaxError?: { [key: string]: string } - private _expectedArgs?: string - private _description?: string - private _requiredPermissions?: permissions | undefined - private _requiredRoles?: Map = new Map() // - private _callback: Function = () => {} - private _error: Function | null = null - private _disabled: string[] = [] - private _cooldownDuration = 0 - private _cooldownChar = '' - private _cooldown: string - private _userCooldowns: Map = new Map() // OR - private _globalCooldown: string - private _guildCooldowns: Map = new Map() // - private _databaseCooldown = false - private _ownerOnly = false - private _hidden = false - private _guildOnly = false - private _testOnly = false - private _slash: boolean | string = false - private _requireRoles = false - private _requiredChannels: Map = new Map() // + private instance: WOKCommands; + private client: Client; + private _names: string[] = []; + private _category = ""; + private _minArgs: number = 0; + private _maxArgs: number = -1; + private _syntaxError?: { [key: string]: string }; + private _expectedArgs?: string; + private _description?: string; + private _requiredPermissions?: permissions | undefined; + private _requiredRoles?: Map = new Map(); // + private _callback: Function = () => {}; + private _error: Function | null = null; + private _disabled: string[] = []; + private _cooldownDuration = 0; + private _cooldownChar = ""; + private _cooldown: string; + private _userCooldowns: Map = new Map(); // OR + private _globalCooldown: string; + private _guildCooldowns: Map = new Map(); // + private _databaseCooldown = false; + private _ownerOnly = false; + private _hidden = false; + private _guildOnly = false; + private _testOnly = false; + private _slash: boolean | string = false; + private _requireRoles = false; + private _requiredChannels: Map = new Map(); // constructor( instance: WOKCommands, @@ -60,63 +59,63 @@ class Command { requireRoles = false, }: ICommand ) { - this.instance = instance - this.client = client - this._names = typeof names === 'string' ? [names] : names - this._category = category - this._minArgs = minArgs || 0 - this._maxArgs = maxArgs === undefined ? -1 : maxArgs - this._syntaxError = syntaxError - this._expectedArgs = expectedArgs - this._description = description - this._requiredPermissions = requiredPermissions || permissions - this._cooldown = cooldown || '' - this._globalCooldown = globalCooldown || '' - this._ownerOnly = ownerOnly - this._hidden = hidden - this._guildOnly = guildOnly - this._testOnly = testOnly - this._callback = callback - this._error = error - this._slash = slash - this._requireRoles = requireRoles + this.instance = instance; + this.client = client; + this._names = typeof names === "string" ? [names] : names; + this._category = category; + this._minArgs = minArgs || 0; + this._maxArgs = maxArgs === undefined ? -1 : maxArgs; + this._syntaxError = syntaxError; + this._expectedArgs = expectedArgs; + this._description = description; + this._requiredPermissions = requiredPermissions || permissions; + this._cooldown = cooldown || ""; + this._globalCooldown = globalCooldown || ""; + this._ownerOnly = ownerOnly; + this._hidden = hidden; + this._guildOnly = guildOnly; + this._testOnly = testOnly; + this._callback = callback; + this._error = error; + this._slash = slash; + this._requireRoles = requireRoles; if (this.cooldown && this.globalCooldown) { throw new Error( `Command "${names[0]}" has both a global and per-user cooldown. Commands can only have up to one of these properties.` - ) + ); } if (requiredPermissions && permissions) { throw new Error( `Command "${names[0]}" has both requiredPermissions and permissions fields. These are interchangeable but only one should be provided.` - ) + ); } if (this.cooldown) { - this.verifyCooldown(this._cooldown, 'cooldown') + this.verifyCooldown(this._cooldown, "cooldown"); } if (this.globalCooldown) { - this.verifyCooldown(this._globalCooldown, 'global cooldown') + this.verifyCooldown(this._globalCooldown, "global cooldown"); } if (this._minArgs < 0) { throw new Error( `Command "${names[0]}" has a minimum argument count less than 0!` - ) + ); } if (this._maxArgs < -1) { throw new Error( `Command "${names[0]}" has a maximum argument count less than -1!` - ) + ); } if (this._maxArgs !== -1 && this._maxArgs < this._minArgs) { throw new Error( `Command "${names[0]}" has a maximum argument count less than it's minimum argument count!` - ) + ); } } @@ -125,7 +124,7 @@ class Command { message, channel: message.channel, args, - text: args.join(' '), + text: args.join(" "), client: this.client, prefix: this.instance.getPrefix(message.guild), instance: this.instance, @@ -133,185 +132,185 @@ class Command { member: message.member, guild: message.guild, cancelCoolDown: () => { - this.decrementCooldowns(message.guild?.id, message.author.id) + this.decrementCooldowns(message.guild?.id, message.author.id); }, - }) + }); if (!reply) { - return + return; } - if (typeof reply === 'string') { + if (typeof reply === "string") { message.reply({ content: reply, - }) - } else if (typeof reply === 'object') { + }); + } else if (typeof reply === "object") { if (reply.custom) { - message.reply(reply) + message.reply(reply); } else { - let embeds = [] + let embeds = []; if (Array.isArray(reply)) { - embeds = reply + embeds = reply; } else { - embeds.push(reply) + embeds.push(reply); } message.reply({ embeds, - }) + }); } } } public get names(): string[] { - return this._names + return this._names; } public get category(): string { - return this._category + return this._category; } public get description(): string | undefined { - return this._description + return this._description; } public get minArgs(): number { - return this._minArgs + return this._minArgs; } public get maxArgs(): number { - return this._maxArgs + return this._maxArgs; } public get syntaxError(): { [key: string]: string } { - return this._syntaxError || {} + return this._syntaxError || {}; } public get expectedArgs(): string | undefined { - return this._expectedArgs + return this._expectedArgs; } public get requiredPermissions(): permissions | undefined { - return this._requiredPermissions + return this._requiredPermissions; } public get cooldownDuration(): number { - return this._cooldownDuration + return this._cooldownDuration; } public get cooldownChar(): string { - return this._cooldownChar + return this._cooldownChar; } public get cooldown(): string { - return this._cooldown + return this._cooldown; } public get globalCooldown(): string { - return this._globalCooldown + return this._globalCooldown; } public get testOnly(): boolean { - return this._testOnly + return this._testOnly; } public verifyCooldown(cooldown: string, type: string) { - if (typeof cooldown !== 'string') { + if (typeof cooldown !== "string") { throw new Error( `Invalid ${type} format! Must be a string, examples: "10s" "5m" etc.` - ) + ); } - const results = cooldown.match(/[a-z]+|[^a-z]+/gi) || [] + const results = cooldown.match(/[a-z]+|[^a-z]+/gi) || []; if (results.length !== 2) { throw new Error( `Invalid ${type} format! Please provide "", examples: "10s" "5m" etc.` - ) + ); } - this._cooldownDuration = +results[0] + this._cooldownDuration = +results[0]; if (isNaN(this._cooldownDuration)) { - throw new Error(`Invalid ${type} format! Number is invalid.`) + throw new Error(`Invalid ${type} format! Number is invalid.`); } - this._cooldownChar = results[1] + this._cooldownChar = results[1]; if ( - this._cooldownChar !== 's' && - this._cooldownChar !== 'm' && - this._cooldownChar !== 'h' && - this._cooldownChar !== 'd' + this._cooldownChar !== "s" && + this._cooldownChar !== "m" && + this._cooldownChar !== "h" && + this._cooldownChar !== "d" ) { throw new Error( `Invalid ${type} format! Unknown type. Please provide 's', 'm', 'h', or 'd' for seconds, minutes, hours, or days respectively.` - ) + ); } if ( - type === 'global cooldown' && - this._cooldownChar === 's' && + type === "global cooldown" && + this._cooldownChar === "s" && this._cooldownDuration < 60 ) { throw new Error( `Invalid ${type} format! The minimum duration for a global cooldown is 1m.` - ) + ); } const moreInfo = - ' For more information please see https://docs.wornoffkeys.com/commands/command-cooldowns' + " For more information please see https://docs.wornoffkeys.com/commands/command-cooldowns"; if (this._cooldownDuration < 1) { throw new Error( `Invalid ${type} format! Durations must be at least 1.${moreInfo}` - ) + ); } if ( - (this._cooldownChar === 's' || this._cooldownChar === 'm') && + (this._cooldownChar === "s" || this._cooldownChar === "m") && this._cooldownDuration > 60 ) { throw new Error( `Invalid ${type} format! Second or minute durations cannot exceed 60.${moreInfo}` - ) + ); } - if (this._cooldownChar === 'h' && this._cooldownDuration > 24) { + if (this._cooldownChar === "h" && this._cooldownDuration > 24) { throw new Error( `Invalid ${type} format! Hour durations cannot exceed 24.${moreInfo}` - ) + ); } - if (this._cooldownChar === 'd' && this._cooldownDuration > 365) { + if (this._cooldownChar === "d" && this._cooldownDuration > 365) { throw new Error( `Invalid ${type} format! Day durations cannot exceed 365.${moreInfo}` - ) + ); } } public get hidden(): boolean { - return this._hidden + return this._hidden; } public get guildOnly(): boolean { - return this._guildOnly + return this._guildOnly; } public get ownerOnly(): boolean { - return this._ownerOnly + return this._ownerOnly; } public verifyDatabaseCooldowns() { if ( - this._cooldownChar === 'd' || - this._cooldownChar === 'h' || - (this._cooldownChar === 'm' && this._cooldownDuration >= 5) + this._cooldownChar === "d" || + this._cooldownChar === "h" || + (this._cooldownChar === "m" && this._cooldownDuration >= 5) ) { - this._databaseCooldown = true + this._databaseCooldown = true; if (!this.instance.isDBConnected()) { console.warn( `WOKCommands > A database connection is STRONGLY RECOMMENDED for cooldowns of 5 minutes or more.` - ) + ); } } } @@ -322,22 +321,22 @@ class Command { */ public decrementCooldowns(guildId?: string, userId?: string) { for (const map of [this._userCooldowns, this._guildCooldowns]) { - if (typeof map !== 'string') { + if (typeof map !== "string") { map.forEach((value, key) => { if (key === `${guildId}-${userId}`) { - value = 0 + value = 0; } if (--value <= 0) { - map.delete(key) + map.delete(key); } else { - map.set(key, value) + map.set(key, value); } if (this._databaseCooldown && this.instance.isDBConnected()) { - this.updateDatabaseCooldowns(`${this.names[0]}-${key}`, value) + this.updateDatabaseCooldowns(`${this.names[0]}-${key}`, value); } - }) + }); } } } @@ -345,10 +344,10 @@ class Command { public async updateDatabaseCooldowns(_id: String, cooldown: number) { // Only update every 20s if (cooldown % 20 === 0 && this.instance.isDBConnected()) { - const type = this.globalCooldown ? 'global' : 'per-user' + const type = this.globalCooldown ? "global" : "per-user"; if (cooldown <= 0) { - await cooldownSchema.deleteOne({ _id, name: this.names[0], type }) + await cooldownSchema.deleteOne({ _id, name: this.names[0], type }); } else { await cooldownSchema.findOneAndUpdate( { @@ -363,39 +362,39 @@ class Command { cooldown, }, { upsert: true } - ) + ); } } } public setCooldown(guildId: string, userId: string, customCooldown?: number) { - const target = this.globalCooldown || this.cooldown + const target = this.globalCooldown || this.cooldown; if (target) { - let seconds = customCooldown || this._cooldownDuration - const durationType = customCooldown ? 's' : this._cooldownChar + let seconds = customCooldown || this._cooldownDuration; + const durationType = customCooldown ? "s" : this._cooldownChar; switch (durationType) { - case 'm': - seconds *= 60 - break + case "m": + seconds *= 60; + break; - case 'h': - seconds *= 60 * 60 - break + case "h": + seconds *= 60 * 60; + break; - case 'd': - seconds *= 60 * 60 * 24 - break + case "d": + seconds *= 60 * 60 * 24; + break; } // Increment to ensure we save it to the database when it is divisible by 20 - ++seconds + ++seconds; if (this.globalCooldown) { - this._guildCooldowns.set(guildId, seconds) + this._guildCooldowns.set(guildId, seconds); } else { - this._userCooldowns.set(`${guildId}-${userId}`, seconds) + this._userCooldowns.set(`${guildId}-${userId}`, seconds); } } } @@ -403,99 +402,99 @@ class Command { public getCooldownSeconds(guildId: string, userId: string): string { let seconds = this.globalCooldown ? this._guildCooldowns.get(guildId) - : this._userCooldowns.get(`${guildId}-${userId}`) + : this._userCooldowns.get(`${guildId}-${userId}`); if (!seconds) { - return '' + return ""; } - const days = Math.floor(seconds / (3600 * 24)) - const hours = Math.floor((seconds % (3600 * 24)) / 3600) - const minutes = Math.floor((seconds % 3600) / 60) - seconds = Math.floor(seconds % 60) + const days = Math.floor(seconds / (3600 * 24)); + const hours = Math.floor((seconds % (3600 * 24)) / 3600); + const minutes = Math.floor((seconds % 3600) / 60); + seconds = Math.floor(seconds % 60); - let result = '' + let result = ""; if (days) { - result += `${days}d ` + result += `${days}d `; } if (hours) { - result += `${hours}h ` + result += `${hours}h `; } if (minutes) { - result += `${minutes}m ` + result += `${minutes}m `; } if (seconds) { - result += `${seconds}s ` + result += `${seconds}s `; } - return result.substring(0, result.length - 1) + return result.substring(0, result.length - 1); } public addRequiredRole(guildId: string, roleId: string) { - const array = this._requiredRoles?.get(guildId) || [] + const array = this._requiredRoles?.get(guildId) || []; if (!array.includes(roleId)) { - array.push(roleId) - this._requiredRoles?.set(guildId, array) + array.push(roleId); + this._requiredRoles?.set(guildId, array); } } public removeRequiredRole(guildId: string, roleId: string) { - if (roleId === 'none') { - this._requiredRoles?.delete(guildId) - return + if (roleId === "none") { + this._requiredRoles?.delete(guildId); + return; } - const array = this._requiredRoles?.get(guildId) || [] - const index = array ? array.indexOf(roleId) : -1 + const array = this._requiredRoles?.get(guildId) || []; + const index = array ? array.indexOf(roleId) : -1; if (array && index >= 0) { - array.splice(index, 1) + array.splice(index, 1); } } public getRequiredRoles(guildId: string): string[] { - const map = this._requiredRoles || new Map() - return map.get(guildId) || [] + const map = this._requiredRoles || new Map(); + return map.get(guildId) || []; } public get callback(): Function { - return this._callback + return this._callback; } public disable(guildId: string) { if (!this._disabled.includes(guildId)) { - this._disabled.push(guildId) + this._disabled.push(guildId); } } public enable(guildId: string) { - const index = this._disabled.indexOf(guildId) + const index = this._disabled.indexOf(guildId); if (index >= 0) { - this._disabled.splice(index, 1) + this._disabled.splice(index, 1); } } public isDisabled(guildId: string) { - return this._disabled.includes(guildId) + return this._disabled.includes(guildId); } public get error(): Function | null { - return this._error + return this._error; } public get slash(): boolean | string { - return this._slash + return this._slash; } public get doesRequireRoles(): boolean { - return this._requireRoles + return this._requireRoles; } public get requiredChannels(): Map { - return this._requiredChannels + return this._requiredChannels; } public setRequiredChannels( @@ -504,11 +503,11 @@ class Command { channels: String[] ) { if (!guild) { - return + return; } - this.requiredChannels.set(`${guild.id}-${command}`, channels) + this.requiredChannels.set(`${guild.id}-${command}`, channels); } } -export = Command +export = Command; diff --git a/src/CommandHandler.ts b/src/CommandHandler.ts index 749744c..7ee9ca1 100644 --- a/src/CommandHandler.ts +++ b/src/CommandHandler.ts @@ -1,18 +1,17 @@ -import { Client, Guild, Message, MessageEmbed } from 'discord.js' -import fs from 'fs' -import WOKCommands from '.' -import path from 'path' - -import Command from './Command' -import getAllFiles from './get-all-files' -import disabledCommands from './models/disabled-commands' -import requiredRoles from './models/required-roles' -import cooldown from './models/cooldown' -import channelCommands from './models/channel-commands' -import { permissionList } from './permissions' -import { ICommand } from '../typings' -import CommandErrors from './enums/CommandErrors' -import Events from './enums/Events' +import { Client, Guild, Message, MessageEmbed } from "discord.js"; +import fs from "fs"; +import path from "path"; +import WOKCommands from "."; +import Command from "./Command"; +import CommandErrors from "./enums/CommandErrors"; +import Events from "./enums/Events"; +import getAllFiles from "./get-all-files"; +import channelCommands from "./models/channel-commands"; +import cooldown from "./models/cooldown"; +import disabledCommands from "./models/disabled-commands"; +import requiredRoles from "./models/required-roles"; +import { permissionList } from "./permissions"; +import { ICommand } from "./types"; const replyFromCheck = async ( reply: string | MessageEmbed | MessageEmbed[], @@ -20,33 +19,33 @@ const replyFromCheck = async ( ) => { if (!reply) { return new Promise((resolve) => { - resolve('No reply provided.') - }) + resolve("No reply provided."); + }); } - if (typeof reply === 'string') { + if (typeof reply === "string") { return message.reply({ content: reply, - }) + }); } else { - let embeds = [] + let embeds = []; if (Array.isArray(reply)) { - embeds = reply + embeds = reply; } else { - embeds.push(reply) + embeds.push(reply); } return message.reply({ embeds, - }) + }); } -} +}; export default class CommandHandler { - private _commands: Map = new Map() - private _client: Client | null = null - private _commandChecks: Map = new Map() + private _commands: Map = new Map(); + private _client: Client | null = null; + private _commandChecks: Map = new Map(); constructor( instance: WOKCommands, @@ -55,9 +54,9 @@ export default class CommandHandler { disabledDefaultCommands: string[], typeScript = false ) { - this._client = client + this._client = client; - this.setUp(instance, client, dir, disabledDefaultCommands, typeScript) + this.setUp(instance, client, dir, disabledDefaultCommands, typeScript); } private async setUp( @@ -69,99 +68,99 @@ export default class CommandHandler { ) { // Do not pass in TS here because this should always compiled to JS for (const [file, fileName] of getAllFiles( - path.join(__dirname, 'commands') + path.join(__dirname, "commands") )) { if (disabledDefaultCommands.includes(fileName)) { - continue + continue; } - await this.registerCommand(instance, client, file, fileName, true) + await this.registerCommand(instance, client, file, fileName, true); } // Do not pass in TS here because this should always compiled to JS for (const [file, fileName] of getAllFiles( - path.join(__dirname, 'command-checks') + path.join(__dirname, "command-checks") )) { - this._commandChecks.set(fileName, require(file)) + this._commandChecks.set(fileName, require(file)); } if (dir) { if (!fs.existsSync(dir)) { - throw new Error(`Commands directory "${dir}" doesn't exist!`) + throw new Error(`Commands directory "${dir}" doesn't exist!`); } - const files = getAllFiles(dir, typeScript ? '.ts' : '') - const amount = files.length + const files = getAllFiles(dir, typeScript ? ".ts" : ""); + const amount = files.length; console.log( - `WOKCommands > Loaded ${amount} command${amount === 1 ? '' : 's'}.` - ) + `WOKCommands > Loaded ${amount} command${amount === 1 ? "" : "s"}.` + ); for (const [file, fileName] of files) { - await this.registerCommand(instance, client, file, fileName) + await this.registerCommand(instance, client, file, fileName); } if (instance.isDBConnected()) { - await this.fetchDisabledCommands() - await this.fetchRequiredRoles() - await this.fetchChannelOnly() + await this.fetchDisabledCommands(); + await this.fetchRequiredRoles(); + await this.fetchChannelOnly(); } this._commands.forEach(async (command) => { - command.verifyDatabaseCooldowns() + command.verifyDatabaseCooldowns(); if (instance.isDBConnected()) { const results = await cooldown.find({ name: command.names[0], - type: command.globalCooldown ? 'global' : 'per-user', - }) + type: command.globalCooldown ? "global" : "per-user", + }); for (const { _id, cooldown } of results) { - const [name, guildId, userId] = _id.split('-') - command.setCooldown(guildId, userId, cooldown) + const [name, guildId, userId] = _id.split("-"); + command.setCooldown(guildId, userId, cooldown); } } - }) + }); - client.on('messageCreate', async (message) => { - const guild: Guild | null = message.guild - let content: string = message.content - const prefix = instance.getPrefix(guild).toLowerCase() + client.on("messageCreate", async (message) => { + const guild: Guild | null = message.guild; + let content: string = message.content; + const prefix = instance.getPrefix(guild).toLowerCase(); if (!content.toLowerCase().startsWith(prefix)) { - return + return; } if (instance.ignoreBots && message.author.bot) { - return + return; } // Remove the prefix - content = content.substring(prefix.length) + content = content.substring(prefix.length); - const args = content.split(/[ ]+/g) + const args = content.split(/[ ]+/g); // Remove the "command", leaving just the arguments - const firstElement = args.shift() + const firstElement = args.shift(); if (!firstElement) { - return + return; } // Ensure the user input is lower case because it is stored as lower case in the map - const name = firstElement.toLowerCase() + const name = firstElement.toLowerCase(); - const command = this._commands.get(name) + const command = this._commands.get(name); if (!command) { - return + return; } - const { error, slash } = command + const { error, slash } = command; if (slash === true) { - return + return; } - const { member, author: user, channel } = message + const { member, author: user, channel } = message; for (const [ checkName, @@ -175,19 +174,19 @@ export default class CommandHandler { member, user, (reply: string | MessageEmbed) => { - return replyFromCheck(reply, message) + return replyFromCheck(reply, message); }, args, name, channel )) ) { - return + return; } } try { - command.execute(message, args) + command.execute(message, args); } catch (e) { if (error) { error({ @@ -197,25 +196,25 @@ export default class CommandHandler { info: { error: e, }, - }) + }); } else { - message.reply(instance.messageHandler.get(guild, 'EXCEPTION')) - console.error(e) + message.reply(instance.messageHandler.get(guild, "EXCEPTION")); + console.error(e); } - instance.emit(Events.COMMAND_EXCEPTION, command, message, e) + instance.emit(Events.COMMAND_EXCEPTION, command, message, e); } - }) + }); } const decrementCountdown = () => { this._commands.forEach((command) => { - command.decrementCooldowns() - }) + command.decrementCooldowns(); + }); - setTimeout(decrementCountdown, 1000) - } - decrementCountdown() + setTimeout(decrementCountdown, 1000); + }; + decrementCountdown(); } public async registerCommand( @@ -225,11 +224,11 @@ export default class CommandHandler { fileName: string, builtIn = false ) { - let configuration = await require(file) + let configuration = await require(file); // person is using 'export default' so we import the default instead if (configuration.default && Object.keys(configuration).length === 1) { - configuration = configuration.default + configuration = configuration.default; } const { @@ -250,36 +249,36 @@ export default class CommandHandler { expectedArgsTypes, minArgs, options = [], - } = configuration + } = configuration; - const { testOnly } = configuration + const { testOnly } = configuration; if (run || execute) { throw new Error( `Command located at "${file}" has either a "run" or "execute" function. Please rename that function to "callback".` - ) + ); } - let names = commands || aliases || [] + let names = commands || aliases || []; if (!name && (!names || names.length === 0)) { throw new Error( `Command located at "${file}" does not have a name, commands array, or aliases array set. Please set at lease one property to specify the command name.` - ) + ); } - if (typeof names === 'string') { - names = [names] + if (typeof names === "string") { + names = [names]; } - if (typeof name !== 'string') { + if (typeof name !== "string") { throw new Error( `Command located at "${file}" does not have a string as a name.` - ) + ); } if (name && !names.includes(name.toLowerCase())) { - names.unshift(name.toLowerCase()) + names.unshift(name.toLowerCase()); } if (requiredPermissions || permissions) { @@ -289,111 +288,111 @@ export default class CommandHandler { `Command located at "${file}" has an invalid permission node: "${perm}". Permissions must be all upper case and be one of the following: "${[ ...permissionList, ].join('", "')}"` - ) + ); } } } - const missing = [] + const missing = []; if (!category) { - missing.push('Category') + missing.push("Category"); } if (!description) { - missing.push('Description') + missing.push("Description"); } if (missing.length && instance.showWarns) { console.warn( `WOKCommands > Command "${names[0]}" does not have the following properties: ${missing}.` - ) + ); } if (testOnly && !instance.testServers.length) { console.warn( `WOKCommands > Command "${names[0]}" has "testOnly" set to true, but no test servers are defined.` - ) + ); } - if (slash !== undefined && typeof slash !== 'boolean' && slash !== 'both') { + if (slash !== undefined && typeof slash !== "boolean" && slash !== "both") { throw new Error( `WOKCommands > Command "${names[0]}" has a "slash" property that is not boolean "true" or string "both".` - ) + ); } if (!slash && options.length) { throw new Error( `WOKCommands > Command "${names[0]}" has an "options" property but is not a slash command.` - ) + ); } if (slash && !(builtIn && !instance.isDBConnected())) { if (!description) { throw new Error( `WOKCommands > A description is required for command "${names[0]}" because it is a slash command.` - ) + ); } if (minArgs !== undefined && !expectedArgs) { throw new Error( `WOKCommands > Command "${names[0]}" has "minArgs" property defined without "expectedArgs" property as a slash command.` - ) + ); } if (options.length) { for (const key in options) { - const name = options[key].name - let lowerCase = name.toLowerCase() + const name = options[key].name; + let lowerCase = name.toLowerCase(); if (name !== lowerCase && instance.showWarns) { console.log( `WOKCommands > Command "${names[0]}" has an option of "${name}". All option names must be lower case for slash commands. WOKCommands will modify this for you.` - ) + ); } if (lowerCase.match(/\s/g)) { - lowerCase = lowerCase.replace(/\s/g, '_') + lowerCase = lowerCase.replace(/\s/g, "_"); console.log( `WOKCommands > Command "${names[0]}" has an option of "${name}" with a white space in it. It is a best practice for option names to only be one word. WOKCommands will modify this for you.` - ) + ); } - options[key].name = lowerCase + options[key].name = lowerCase; } } else if (expectedArgs) { const split = expectedArgs .substring(1, expectedArgs.length - 1) - .split(/[>\]] [<\[]/) + .split(/[>\]] [<\[]/); for (let a = 0; a < split.length; ++a) { - const item = split[a] + const item = split[a]; options.push({ - name: item.replace(/ /g, '-').toLowerCase(), + name: item.replace(/ /g, "-").toLowerCase(), description: item, type: expectedArgsTypes && expectedArgsTypes.length >= a ? expectedArgsTypes[a] - : 'STRING', + : "STRING", required: a < minArgs, - }) + }); } } - const slashCommands = instance.slashCommands + const slashCommands = instance.slashCommands; if (testOnly) { for (const id of instance.testServers) { - await slashCommands.create(names[0], description, options, id) + await slashCommands.create(names[0], description, options, id); } } else { - await slashCommands.create(names[0], description, options) + await slashCommands.create(names[0], description, options); } } if (callback) { if (init) { - init(client, instance) + init(client, instance); } const command = new Command( @@ -403,25 +402,25 @@ export default class CommandHandler { callback, error, configuration - ) + ); for (const name of names) { // Ensure the alias is lower case because we read as lower case later on - this._commands.set(name.toLowerCase(), command) + this._commands.set(name.toLowerCase(), command); } } } public get commands(): ICommand[] { - const results: ICommand[] = [] - const added: string[] = [] + const results: ICommand[] = []; + const added: string[] = []; this._commands.forEach( ({ names, - category = '', - description = '', - expectedArgs = '', + category = "", + description = "", + expectedArgs = "", hidden = false, testOnly = false, }) => { @@ -433,82 +432,82 @@ export default class CommandHandler { syntax: expectedArgs, hidden, testOnly, - }) + }); - added.push(names[0]) + added.push(names[0]); } } - ) + ); - return results + return results; } public getCommandsByCategory( category: string, visibleOnly?: boolean ): ICommand[] { - const results: ICommand[] = [] + const results: ICommand[] = []; for (const command of this.commands) { if (visibleOnly && command.hidden) { - continue + continue; } if (command.category === category) { - results.push(command) + results.push(command); } } - return results + return results; } public getCommand(name: string): Command | undefined { - return this._commands.get(name) + return this._commands.get(name); } public getICommand(name: string): ICommand | undefined { - return this.commands.find((command) => command.names?.includes(name)) + return this.commands.find((command) => command.names?.includes(name)); } public async fetchDisabledCommands() { - const results: any[] = await disabledCommands.find({}) + const results: any[] = await disabledCommands.find({}); for (const result of results) { - const { guildId, command } = result + const { guildId, command } = result; - this._commands.get(command)?.disable(guildId) + this._commands.get(command)?.disable(guildId); } } public async fetchRequiredRoles() { - const results: any[] = await requiredRoles.find({}) + const results: any[] = await requiredRoles.find({}); for (const result of results) { - const { guildId, command, requiredRoles } = result + const { guildId, command, requiredRoles } = result; - const cmd = this._commands.get(command) + const cmd = this._commands.get(command); if (cmd) { for (const roleId of requiredRoles) { - cmd.addRequiredRole(guildId, roleId) + cmd.addRequiredRole(guildId, roleId); } } } } public async fetchChannelOnly() { - const results: any[] = await channelCommands.find({}) + const results: any[] = await channelCommands.find({}); for (const result of results) { - const { command, guildId, channels } = result + const { command, guildId, channels } = result; - const cmd = this._commands.get(command) + const cmd = this._commands.get(command); if (!cmd) { - continue + continue; } - const guild = this._client?.guilds.cache.get(guildId) + const guild = this._client?.guilds.cache.get(guildId); if (!guild) { - continue + continue; } cmd.setRequiredChannels( @@ -516,9 +515,9 @@ export default class CommandHandler { command, channels .toString() - .replace(/\"\[\]/g, '') - .split(',') - ) + .replace(/\"\[\]/g, "") + .split(",") + ); } } } diff --git a/src/FeatureHandler.ts b/src/FeatureHandler.ts index a2f4662..a8cc2ef 100644 --- a/src/FeatureHandler.ts +++ b/src/FeatureHandler.ts @@ -1,14 +1,14 @@ -import { Client } from 'discord.js' -import fs from 'fs' -import WOKCommands from '.' -import path from 'path' +import { Client } from "discord.js"; +import fs from "fs"; +import WOKCommands from "."; +import path from "path"; -import getAllFiles from './get-all-files' +import getAllFiles from "./get-all-files"; class FeatureHandler { - private _features: Map = new Map() // - private _client: Client - private _instance: WOKCommands + private _features: Map = new Map(); // + private _client: Client; + private _instance: WOKCommands; constructor( client: Client, @@ -16,109 +16,109 @@ class FeatureHandler { dir: string, typeScript = false ) { - this._client = client - this._instance = instance - this.setup(dir, typeScript) + this._client = client; + this._instance = instance; + this.setup(dir, typeScript); } private setup = async (dir: string, typeScript: boolean) => { // Register built in features for (const [file, fileName] of getAllFiles( - path.join(__dirname, 'features'), - typeScript ? '.ts' : '' + path.join(__dirname, "features"), + typeScript ? ".ts" : "" )) { - this.registerFeature(require(file), fileName) + this.registerFeature(require(file), fileName); } if (!dir) { - return + return; } if (!fs.existsSync(dir)) { - throw new Error(`Listeners directory "${dir}" doesn't exist!`) + throw new Error(`Listeners directory "${dir}" doesn't exist!`); } - const files = getAllFiles(dir, typeScript ? '.ts' : '') + const files = getAllFiles(dir, typeScript ? ".ts" : ""); - const amount = files.length + const amount = files.length; if (amount > 0) { console.log( - `WOKCommands > Loading ${amount} listener${amount === 1 ? '' : 's'}...` - ) + `WOKCommands > Loading ${amount} listener${amount === 1 ? "" : "s"}...` + ); for (const [file, fileName] of files) { - const debug = `WOKCommands DEBUG > Feature "${fileName}" load time` + const debug = `WOKCommands DEBUG > Feature "${fileName}" load time`; if (this._instance.debug) { - console.time(debug) + console.time(debug); } - this.registerFeature(require(file), fileName) + this.registerFeature(require(file), fileName); if (this._instance.debug) { - console.timeEnd(debug) + console.timeEnd(debug); } } } else { console.log( - `WOKCommands > Loaded ${amount} listener${amount === 1 ? '' : 's'}.` - ) + `WOKCommands > Loaded ${amount} listener${amount === 1 ? "" : "s"}.` + ); } - } + }; private registerFeature = (file: any, fileName: string) => { - let func = file - const { config } = file + let func = file; + const { config } = file; if (file.default) { - func = file.default + func = file.default; } - let testOnly = false + let testOnly = false; if (config) { - const { displayName, dbName } = config + const { displayName, dbName } = config; if (config.testOnly) { - testOnly = true + testOnly = true; } - const missing = [] - if (!displayName) missing.push('displayName') - if (!dbName) missing.push('dbName') + const missing = []; + if (!displayName) missing.push("displayName"); + if (!dbName) missing.push("dbName"); if (missing.length && this._instance.showWarns) { console.warn( `WOKCommands > Feature "${fileName}" has a config file that doesn't contain the following properties: ${missing}` - ) + ); } } else if (this._instance.showWarns) { console.warn( `WOKCommands > Feature "${fileName}" does not export a config object.` - ) + ); } - if (typeof func !== 'function') { - return + if (typeof func !== "function") { + return; } const isEnabled = (guildId: string) => { if (testOnly && !this._instance.testServers.includes(guildId)) { - return false + return false; } - return this.isEnabled(guildId, file) - } + return this.isEnabled(guildId, file); + }; if (config && config.loadDBFirst === true) { console.warn( `WOKCommands > config.loadDBFirst in features is no longer required. MongoDB is now connected to before any features or commands are loaded.` - ) + ); } - func(this._client, this._instance, isEnabled) - } + func(this._client, this._instance, isEnabled); + }; private isEnabled = (guildId: string, feature: string): boolean => { - return !(this._features.get(feature) || []).includes(guildId) - } + return !(this._features.get(feature) || []).includes(guildId); + }; } -export = FeatureHandler +export = FeatureHandler; diff --git a/src/SlashCommands.ts b/src/SlashCommands.ts index e23f8dc..61efe11 100644 --- a/src/SlashCommands.ts +++ b/src/SlashCommands.ts @@ -9,30 +9,30 @@ import { GuildMember, MessageEmbed, User, -} from 'discord.js' -import path from 'path' +} from "discord.js"; +import path from "path"; -import getAllFiles from './get-all-files' -import WOKCommands from '.' +import getAllFiles from "./get-all-files"; +import WOKCommands from "."; class SlashCommands { - private _client: Client - private _instance: WOKCommands - private _commandChecks: Map = new Map() + private _client: Client; + private _instance: WOKCommands; + private _commandChecks: Map = new Map(); constructor(instance: WOKCommands, listen: boolean, typeScript?: boolean) { - this._instance = instance - this._client = instance.client + this._instance = instance; + this._client = instance.client; - this.setUp(listen, typeScript) + this.setUp(listen, typeScript); } private async setUp(listen: boolean, typeScript = false) { // Do not pass in TS here because this should always compiled to JS for (const [file, fileName] of getAllFiles( - path.join(__dirname, 'command-checks') + path.join(__dirname, "command-checks") )) { - this._commandChecks.set(fileName, require(file)) + this._commandChecks.set(fileName, require(file)); } const replyFromCheck = async ( @@ -41,58 +41,58 @@ class SlashCommands { ) => { if (!reply) { return new Promise((resolve) => { - resolve('No reply provided.') - }) + resolve("No reply provided."); + }); } - if (typeof reply === 'string') { + if (typeof reply === "string") { return interaction.reply({ content: reply, ephemeral: this._instance.ephemeral, - }) + }); } else { - let embeds = [] + let embeds = []; if (Array.isArray(reply)) { - embeds = reply + embeds = reply; } else { - embeds.push(reply) + embeds.push(reply); } return interaction.reply({ embeds, ephemeral: this._instance.ephemeral, - }) + }); } - } + }; if (listen) { - this._client.on('interactionCreate', async (interaction) => { + this._client.on("interactionCreate", async (interaction) => { if (!interaction.isCommand()) { - return + return; } - const { user, commandName, options, guild, channelId } = interaction - const member = interaction.member as GuildMember - const channel = guild?.channels.cache.get(channelId) || null - const command = this._instance.commandHandler.getCommand(commandName) + const { user, commandName, options, guild, channelId } = interaction; + const member = interaction.member as GuildMember; + const channel = guild?.channels.cache.get(channelId) || null; + const command = this._instance.commandHandler.getCommand(commandName); if (!command) { interaction.reply({ content: this._instance.messageHandler.get( guild, - 'INVALID_SLASH_COMMAND' + "INVALID_SLASH_COMMAND" ), ephemeral: this._instance.ephemeral, - }) - return + }); + return; } - const args: string[] = [] + const args: string[] = []; options.data.forEach(({ value }) => { - args.push(String(value)) - }) + args.push(String(value)); + }); for (const [ checkName, @@ -106,39 +106,39 @@ class SlashCommands { member, user, (reply: string | MessageEmbed) => { - return replyFromCheck(reply, interaction) + return replyFromCheck(reply, interaction); }, args, commandName, channel )) ) { - return + return; } } - this.invokeCommand(interaction, commandName, options, args) - }) + this.invokeCommand(interaction, commandName, options, args); + }); } } public getCommands(guildId?: string) { if (guildId) { - return this._client.guilds.cache.get(guildId)?.commands + return this._client.guilds.cache.get(guildId)?.commands; } - return this._client.application?.commands + return this._client.application?.commands; } public async get(guildId?: string): Promise> { - const commands = this.getCommands(guildId) + const commands = this.getCommands(guildId); if (commands) { // @ts-ignore - await commands.fetch() - return commands.cache + await commands.fetch(); + return commands.cache; } - return new Map() + return new Map(); } private didOptionsChange( @@ -151,9 +151,9 @@ class SlashCommands { opt?.required !== options[index]?.required && opt?.name !== options[index]?.name && opt?.options?.length !== options.length - ) + ); }).length !== 0 - ) + ); } public async create( @@ -162,27 +162,27 @@ class SlashCommands { options: ApplicationCommandOptionData[], guildId?: string ): Promise | undefined> { - let commands + let commands; if (guildId) { - commands = this._client.guilds.cache.get(guildId)?.commands + commands = this._client.guilds.cache.get(guildId)?.commands; } else { - commands = this._client.application?.commands + commands = this._client.application?.commands; } if (!commands) { - return + return; } // @ts-ignore - await commands.fetch() + await commands.fetch(); const cmd = commands.cache.find( (cmd) => cmd.name === name - ) as ApplicationCommand + ) as ApplicationCommand; if (cmd) { - const optionsChanged = this.didOptionsChange(cmd, options) + const optionsChanged = this.didOptionsChange(cmd, options); if ( cmd.description !== description || @@ -191,58 +191,58 @@ class SlashCommands { ) { console.log( `WOKCommands > Updating${ - guildId ? ' guild' : '' + guildId ? " guild" : "" } slash command "${name}"` - ) + ); return commands?.edit(cmd.id, { name, description, options, - }) + }); } - return Promise.resolve(cmd) + return Promise.resolve(cmd); } if (commands) { console.log( `WOKCommands > Creating${ - guildId ? ' guild' : '' + guildId ? " guild" : "" } slash command "${name}"` - ) + ); const newCommand = await commands.create({ name, description, options, - }) + }); - return newCommand + return newCommand; } - return Promise.resolve(undefined) + return Promise.resolve(undefined); } public async delete( commandId: string, guildId?: string ): Promise | undefined> { - const commands = this.getCommands(guildId) + const commands = this.getCommands(guildId); if (commands) { - const cmd = commands.cache.get(commandId) + const cmd = commands.cache.get(commandId); if (cmd) { console.log( - `WOKCommands > Deleting${guildId ? ' guild' : ''} slash command "${ + `WOKCommands > Deleting${guildId ? " guild" : ""} slash command "${ cmd.name }"` - ) + ); - cmd.delete() + cmd.delete(); } } - return Promise.resolve(undefined) + return Promise.resolve(undefined); } public async invokeCommand( @@ -251,10 +251,10 @@ class SlashCommands { options: CommandInteractionOptionResolver, args: string[] ) { - const command = this._instance.commandHandler.getCommand(commandName) + const command = this._instance.commandHandler.getCommand(commandName); if (!command || !command.callback) { - return + return; } const reply = await command.callback({ @@ -262,36 +262,36 @@ class SlashCommands { guild: interaction.guild, channel: interaction.channel, args, - text: args.join(' '), + text: args.join(" "), client: this._client, instance: this._instance, interaction, options, user: interaction.user, - }) + }); if (reply) { - if (typeof reply === 'string') { + if (typeof reply === "string") { interaction.reply({ content: reply, - }) - } else if (typeof reply === 'object') { + }); + } else if (typeof reply === "object") { if (reply.custom) { - interaction.reply(reply) + interaction.reply(reply); } else { - let embeds = [] + let embeds = []; if (Array.isArray(reply)) { - embeds = reply + embeds = reply; } else { - embeds.push(reply) + embeds.push(reply); } - interaction.reply({ embeds }) + interaction.reply({ embeds }); } } } } } -export = SlashCommands +export = SlashCommands; diff --git a/src/command-checks/channel-specific.ts b/src/command-checks/channel-specific.ts index 35c3db7..f4ff92e 100644 --- a/src/command-checks/channel-specific.ts +++ b/src/command-checks/channel-specific.ts @@ -1,6 +1,6 @@ -import { Guild, GuildChannel, GuildMember, Message, User } from 'discord.js' -import WOKCommands from '..' -import Command from '../Command' +import { Guild, GuildChannel, GuildMember, Message, User } from "discord.js"; +import WOKCommands from ".."; +import Command from "../Command"; export = ( guild: Guild | null, @@ -14,39 +14,39 @@ export = ( channel: GuildChannel ) => { if (!guild || !command || !command.names) { - return true + return true; } - const key = `${guild.id}-${command.names[0]}` + const key = `${guild.id}-${command.names[0]}`; - const channels = command.requiredChannels.get(key) + const channels = command.requiredChannels.get(key); if (channels && channels.length && !channels.includes(channel.id)) { - let channelList = '' + let channelList = ""; for (const channel of channels) { - channelList += `<#${channel}>, ` + channelList += `<#${channel}>, `; } - channelList = channelList.substring(0, channelList.length - 2) + channelList = channelList.substring(0, channelList.length - 2); reply( - instance.messageHandler.get(guild, 'ALLOWED_CHANNELS', { + instance.messageHandler.get(guild, "ALLOWED_CHANNELS", { CHANNELS: channelList, }) ).then((message: Message | null) => { if (!message) { - return + return; } if (instance.delErrMsgCooldown === -1 || !message.deletable) { - return + return; } setTimeout(() => { - message.delete() - }, 1000 * instance.delErrMsgCooldown) - }) + message.delete(); + }, 1000 * instance.delErrMsgCooldown); + }); - return false + return false; } - return true -} + return true; +}; diff --git a/src/command-checks/guild-only-check.ts b/src/command-checks/guild-only-check.ts index d85ed2b..2170049 100644 --- a/src/command-checks/guild-only-check.ts +++ b/src/command-checks/guild-only-check.ts @@ -1,6 +1,6 @@ -import { Guild, GuildMember, Message, User } from 'discord.js' -import WOKCommands from '..' -import Command from '../Command' +import { Guild, GuildMember, Message, User } from "discord.js"; +import WOKCommands from ".."; +import Command from "../Command"; export = ( guild: Guild | null, @@ -10,32 +10,32 @@ export = ( user: User, reply: Function ) => { - const { guildOnly } = command + const { guildOnly } = command; // If this command doesn't care if it's in a guild or not then just simply return true if (!guildOnly) { - return true + return true; } if (!guild) { - reply(instance.messageHandler.get(guild, 'GUILD_ONLY_COMMAND')).then( + reply(instance.messageHandler.get(guild, "GUILD_ONLY_COMMAND")).then( (message: Message | null) => { if (!message) { - return + return; } if (instance.delErrMsgCooldown === -1 || !message.deletable) { - return + return; } setTimeout(() => { - message.delete() - }, 1000 * instance.delErrMsgCooldown) + message.delete(); + }, 1000 * instance.delErrMsgCooldown); } - ) - return false + ); + return false; } // The guild exists - return true -} + return true; +}; diff --git a/src/command-checks/has-permissions.ts b/src/command-checks/has-permissions.ts index d2826bf..d09b313 100644 --- a/src/command-checks/has-permissions.ts +++ b/src/command-checks/has-permissions.ts @@ -1,7 +1,7 @@ -import { Guild, GuildMember, Message, User } from 'discord.js' -import WOKCommands from '..' -import Command from '../Command' -import CommandErrors from '../enums/CommandErrors' +import { Guild, GuildMember, Message, User } from "discord.js"; +import WOKCommands from ".."; +import Command from "../Command"; +import CommandErrors from "../enums/CommandErrors"; export = ( guild: Guild | null, @@ -12,10 +12,10 @@ export = ( reply: Function ) => { if (!guild || !member) { - return true + return true; } - const { requiredPermissions, error } = command + const { requiredPermissions, error } = command; for (const perm of requiredPermissions || []) { // @ts-ignore @@ -24,30 +24,30 @@ export = ( error({ error: CommandErrors.MISSING_PERMISSIONS, command, - }) + }); } else { reply( - instance.messageHandler.get(guild, 'MISSING_PERMISSION', { + instance.messageHandler.get(guild, "MISSING_PERMISSION", { PERM: perm, }) ).then((message: Message | null) => { if (!message) { - return + return; } if (instance.delErrMsgCooldown === -1 || !message.deletable) { - return + return; } setTimeout(() => { - message.delete() - }, 1000 * instance.delErrMsgCooldown) - }) + message.delete(); + }, 1000 * instance.delErrMsgCooldown); + }); } - return false + return false; } } - return true -} + return true; +}; diff --git a/src/command-checks/has-roles.ts b/src/command-checks/has-roles.ts index 0984f64..b97df99 100644 --- a/src/command-checks/has-roles.ts +++ b/src/command-checks/has-roles.ts @@ -1,8 +1,8 @@ -import { Guild, GuildMember, Message, User } from 'discord.js' +import { Guild, GuildMember, Message, User } from "discord.js"; -import WOKCommands from '..' -import Command from '../Command' -import CommandErrors from '../enums/CommandErrors' +import WOKCommands from ".."; +import Command from "../Command"; +import CommandErrors from "../enums/CommandErrors"; export = async ( guild: Guild | null, @@ -13,23 +13,23 @@ export = async ( reply: Function ) => { if (!guild || !member) { - return true + return true; } - const { error } = command + const { error } = command; - const roles = command.getRequiredRoles(guild.id) + const roles = command.getRequiredRoles(guild.id); if (roles && roles.length) { - const missingRoles = [] - const missingRolesNames = [] + const missingRoles = []; + const missingRolesNames = []; for (const role of roles) { - const realRole = await guild.roles.fetch(role) + const realRole = await guild.roles.fetch(role); if (realRole !== null && !member.roles.cache.has(role)) { - missingRoles.push(role) - missingRolesNames.push(realRole.name) + missingRoles.push(role); + missingRolesNames.push(realRole.name); } } @@ -42,50 +42,50 @@ export = async ( info: { missingRoles, }, - }) + }); } else { reply( - instance.messageHandler.get(guild, 'MISSING_ROLES', { - ROLES: missingRolesNames.join(', '), + instance.messageHandler.get(guild, "MISSING_ROLES", { + ROLES: missingRolesNames.join(", "), }) ).then((message: Message | null) => { if (!message) { - return + return; } if (instance.delErrMsgCooldown === -1 || !message.deletable) { - return + return; } setTimeout(() => { - message.delete() - }, 1000 * instance.delErrMsgCooldown) - }) + message.delete(); + }, 1000 * instance.delErrMsgCooldown); + }); } - return false + return false; } } else if (command.doesRequireRoles) { reply( - instance.messageHandler.get(guild, 'REQUIRE_ROLES', { + instance.messageHandler.get(guild, "REQUIRE_ROLES", { PREFIX: instance.getPrefix(guild), COMMAND: command.names[0], }) ).then((message: Message | null) => { if (!message) { - return + return; } if (instance.delErrMsgCooldown === -1 || !message.deletable) { - return + return; } setTimeout(() => { - message.delete() - }, 1000 * instance.delErrMsgCooldown) - }) - return false + message.delete(); + }, 1000 * instance.delErrMsgCooldown); + }); + return false; } - return true -} + return true; +}; diff --git a/src/command-checks/has-valid-arguments.ts b/src/command-checks/has-valid-arguments.ts index 8da23aa..ffdf8d3 100644 --- a/src/command-checks/has-valid-arguments.ts +++ b/src/command-checks/has-valid-arguments.ts @@ -1,7 +1,7 @@ -import { Guild, GuildMember, Message, User } from 'discord.js' -import WOKCommands from '..' -import Command from '../Command' -import CommandErrors from '../enums/CommandErrors' +import { Guild, GuildMember, Message, User } from "discord.js"; +import WOKCommands from ".."; +import Command from "../Command"; +import CommandErrors from "../enums/CommandErrors"; export = ( guild: Guild | null, @@ -13,33 +13,33 @@ export = ( args: string[], name: string ) => { - const { minArgs, maxArgs, expectedArgs, error } = command - const prefix = instance.getPrefix(guild).toLowerCase() + const { minArgs, maxArgs, expectedArgs, error } = command; + const prefix = instance.getPrefix(guild).toLowerCase(); if ( (minArgs !== undefined && args.length < minArgs) || (maxArgs !== undefined && maxArgs !== -1 && args.length > maxArgs) ) { - const syntaxError = command.syntaxError || {} - const { messageHandler } = instance + const syntaxError = command.syntaxError || {}; + const { messageHandler } = instance; let errorMsg = syntaxError[messageHandler.getLanguage(guild)] || - instance.messageHandler.get(guild, 'SYNTAX_ERROR') + instance.messageHandler.get(guild, "SYNTAX_ERROR"); // Replace {PREFIX} with the actual prefix if (errorMsg) { - errorMsg = errorMsg.replace(/{PREFIX}/g, prefix) + errorMsg = errorMsg.replace(/{PREFIX}/g, prefix); // Replace {COMMAND} with the name of the command that was ran - errorMsg = errorMsg.replace(/{COMMAND}/g, name) + errorMsg = errorMsg.replace(/{COMMAND}/g, name); // Replace {ARGUMENTS} with the expectedArgs property from the command // If one was not provided then replace {ARGUMENTS} with an empty string errorMsg = errorMsg.replace( / {ARGUMENTS}/g, - expectedArgs ? ` ${expectedArgs}` : '' - ) + expectedArgs ? ` ${expectedArgs}` : "" + ); } if (error) { @@ -53,26 +53,26 @@ export = ( length: args.length, errorMsg, }, - }) + }); } else { // Reply with the local or global syntax error reply(errorMsg).then((message: Message | null) => { if (!message) { - return + return; } if (instance.delErrMsgCooldown === -1 || !message.deletable) { - return + return; } setTimeout(() => { - message.delete() - }, 1000 * instance.delErrMsgCooldown) - }) + message.delete(); + }, 1000 * instance.delErrMsgCooldown); + }); } - return false + return false; } - return true -} + return true; +}; diff --git a/src/command-checks/in-cooldown.ts b/src/command-checks/in-cooldown.ts index b0dd664..9b07543 100644 --- a/src/command-checks/in-cooldown.ts +++ b/src/command-checks/in-cooldown.ts @@ -1,7 +1,7 @@ -import { Guild, GuildMember, Message, User } from 'discord.js' -import WOKCommands from '..' -import Command from '../Command' -import CommandErrors from '../enums/CommandErrors' +import { Guild, GuildMember, Message, User } from "discord.js"; +import WOKCommands from ".."; +import Command from "../Command"; +import CommandErrors from "../enums/CommandErrors"; export = ( guild: Guild | null, @@ -11,12 +11,12 @@ export = ( user: User, reply: Function ) => { - const { cooldown, globalCooldown, error } = command + const { cooldown, globalCooldown, error } = command; if ((cooldown || globalCooldown) && user) { - const guildId = guild ? guild.id : 'dm' + const guildId = guild ? guild.id : "dm"; - const timeLeft = command.getCooldownSeconds(guildId, user.id) + const timeLeft = command.getCooldownSeconds(guildId, user.id); if (timeLeft) { if (error) { error({ @@ -26,32 +26,32 @@ export = ( info: { timeLeft, }, - }) + }); } else { reply( - instance.messageHandler.get(guild, 'COOLDOWN', { + instance.messageHandler.get(guild, "COOLDOWN", { COOLDOWN: timeLeft, }) ).then((message: Message | null) => { if (!message) { - return + return; } if (instance.delErrMsgCooldown === -1 || !message.deletable) { - return + return; } setTimeout(() => { - message.delete() - }, 1000 * instance.delErrMsgCooldown) - }) + message.delete(); + }, 1000 * instance.delErrMsgCooldown); + }); } - return false + return false; } - command.setCooldown(guildId, user.id) + command.setCooldown(guildId, user.id); } - return true -} + return true; +}; diff --git a/src/command-checks/is-enabled.ts b/src/command-checks/is-enabled.ts index 8407c8f..a2d05b9 100644 --- a/src/command-checks/is-enabled.ts +++ b/src/command-checks/is-enabled.ts @@ -1,7 +1,7 @@ -import { Guild, GuildMember, Message, User } from 'discord.js' -import WOKCommands from '..' -import Command from '../Command' -import CommandErrors from '../enums/CommandErrors' +import { Guild, GuildMember, Message, User } from "discord.js"; +import WOKCommands from ".."; +import Command from "../Command"; +import CommandErrors from "../enums/CommandErrors"; /** * Checks if the given command is enabled in the current guild @@ -15,33 +15,33 @@ export = ( reply: Function ) => { if (!guild || !command.isDisabled(guild.id)) { - return true + return true; } - const { error } = command + const { error } = command; if (error) { error({ error: CommandErrors.COMMAND_DISABLED, command, - }) + }); } else { - reply(instance.messageHandler.get(guild, 'DISABLED_COMMAND')).then( + reply(instance.messageHandler.get(guild, "DISABLED_COMMAND")).then( (message: Message | null) => { if (!message) { - return + return; } if (instance.delErrMsgCooldown === -1 || !message.deletable) { - return + return; } setTimeout(() => { - message.delete() - }, 1000 * instance.delErrMsgCooldown) + message.delete(); + }, 1000 * instance.delErrMsgCooldown); } - ) + ); } - return false -} + return false; +}; diff --git a/src/command-checks/is-not-test-only.ts b/src/command-checks/is-not-test-only.ts index f820d6b..685d66b 100644 --- a/src/command-checks/is-not-test-only.ts +++ b/src/command-checks/is-not-test-only.ts @@ -1,13 +1,13 @@ -import { Guild } from 'discord.js' -import WOKCommands from '..' -import Command from '../Command' +import { Guild } from "discord.js"; +import WOKCommands from ".."; +import Command from "../Command"; export = (guild: Guild | null, command: Command, instance: WOKCommands) => { - const { testOnly } = command + const { testOnly } = command; if (!testOnly) { - return true + return true; } - return guild && instance.testServers.includes(guild.id) -} + return guild && instance.testServers.includes(guild.id); +}; diff --git a/src/command-checks/owner-only-check.ts b/src/command-checks/owner-only-check.ts index 9060dbf..307ec29 100644 --- a/src/command-checks/owner-only-check.ts +++ b/src/command-checks/owner-only-check.ts @@ -1,6 +1,6 @@ -import { Guild, GuildMember, Message, User } from 'discord.js' -import WOKCommands from '..' -import Command from '../Command' +import { Guild, GuildMember, Message, User } from "discord.js"; +import WOKCommands from ".."; +import Command from "../Command"; export = ( guild: Guild | null, @@ -10,31 +10,31 @@ export = ( user: User, reply: Function ) => { - const { ownerOnly } = command + const { ownerOnly } = command; if (!ownerOnly) { - return true + return true; } if (!instance.botOwner.includes(user.id)) { - reply(instance.messageHandler.get(guild, 'BOT_OWNERS_ONLY')).then( + reply(instance.messageHandler.get(guild, "BOT_OWNERS_ONLY")).then( (message: Message | null) => { if (!message) { - return + return; } if (instance.delErrMsgCooldown === -1 || !message.deletable) { - return + return; } setTimeout(() => { - message.delete() - }, 1000 * instance.delErrMsgCooldown) + message.delete(); + }, 1000 * instance.delErrMsgCooldown); } - ) + ); - return false + return false; } - return true -} + return true; +}; diff --git a/src/commands/channelonly.ts b/src/commands/channelonly.ts index 2bc67d1..dda2786 100644 --- a/src/commands/channelonly.ts +++ b/src/commands/channelonly.ts @@ -1,83 +1,83 @@ -import { ICallbackObject, ICommand } from '../..' -import channelCommandSchema from '../models/channel-commands' +import channelCommandSchema from "../models/channel-commands"; +import { ICallbackObject, ICommand } from "../types"; export = { - description: 'Makes a command only work in some channels.', - category: 'Configuration', + description: "Makes a command only work in some channels.", + category: "Configuration", - permissions: ['ADMINISTRATOR'], + permissions: ["ADMINISTRATOR"], minArgs: 1, maxArgs: 2, - expectedArgs: ' [Channel tag]', + expectedArgs: " [Channel tag]", - cooldown: '2s', + cooldown: "2s", guildOnly: true, - slash: 'both', + slash: "both", options: [ { - name: 'command', - description: 'The command name', - type: 'STRING', + name: "command", + description: "The command name", + type: "STRING", required: true, }, { - name: 'channel', - description: 'The tag of the channel', - type: 'CHANNEL', + name: "channel", + description: "The tag of the channel", + type: "CHANNEL", required: false, }, ], callback: async (options: ICallbackObject) => { - const { message, channel, args, instance, interaction } = options - const { guild } = channel + const { message, channel, args, instance, interaction } = options; + const { guild } = channel; - const { messageHandler } = instance + const { messageHandler } = instance; - let commandName = (args.shift() || '').toLowerCase() - const command = instance.commandHandler.getCommand(commandName) + let commandName = (args.shift() || "").toLowerCase(); + const command = instance.commandHandler.getCommand(commandName); if (!instance.isDBConnected()) { - return messageHandler.get(guild, 'NO_DATABASE_FOUND') + return messageHandler.get(guild, "NO_DATABASE_FOUND"); } if (!command || !command.names) { - return messageHandler.get(guild, 'UNKNOWN_COMMAND', { + return messageHandler.get(guild, "UNKNOWN_COMMAND", { COMMAND: commandName, - }) + }); } - commandName = command.names[0] + commandName = command.names[0]; if (args.length === 0) { const results = await channelCommandSchema.deleteMany({ guildId: guild?.id, command: commandName, - }) + }); // @ts-ignore if (results.n === 0) { - return messageHandler.get(guild, 'NOT_CHANNEL_COMMAND') + return messageHandler.get(guild, "NOT_CHANNEL_COMMAND"); } - command.setRequiredChannels(guild, commandName, []) + command.setRequiredChannels(guild, commandName, []); - return messageHandler.get(guild, 'NO_LONGER_CHANNEL_COMMAND') + return messageHandler.get(guild, "NO_LONGER_CHANNEL_COMMAND"); } if (message?.mentions.channels.size === 0) { - return messageHandler.get(guild, 'NO_TAGGED_CHANNELS') + return messageHandler.get(guild, "NO_TAGGED_CHANNELS"); } - let channels + let channels; if (message) { - channels = Array.from(message.mentions.channels.keys()) + channels = Array.from(message.mentions.channels.keys()); } else { - channels = [interaction.options.getChannel('channel')] + channels = [interaction.options.getChannel("channel")]; } const results = await channelCommandSchema.findOneAndUpdate( @@ -96,15 +96,15 @@ export = { upsert: true, new: true, } - ) + ); if (results) { - command.setRequiredChannels(guild, commandName, results.channels) + command.setRequiredChannels(guild, commandName, results.channels); } - return messageHandler.get(guild, 'NOW_CHANNEL_COMMAND', { + return messageHandler.get(guild, "NOW_CHANNEL_COMMAND", { COMMAND: commandName, - CHANNELS: args.join(' '), - }) + CHANNELS: args.join(" "), + }); }, -} as ICommand +} as ICommand; diff --git a/src/commands/command.ts b/src/commands/command.ts index e70e7cd..9e727fc 100644 --- a/src/commands/command.ts +++ b/src/commands/command.ts @@ -1,106 +1,109 @@ -import disabledCommands from '../models/disabled-commands' -import { ICallbackObject, ICommand } from '../..' +import disabledCommands from "../models/disabled-commands"; +import { ICallbackObject, ICommand } from "../types"; export = { - description: 'Enables or disables a command for this guild', - category: 'Configuration', + description: "Enables or disables a command for this guild", + category: "Configuration", - permissions: ['ADMINISTRATOR'], + permissions: ["ADMINISTRATOR"], minArgs: 2, maxArgs: 2, expectedArgs: '<"enable" or "disable"> ', - cooldown: '2s', + cooldown: "2s", - slash: 'both', + slash: "both", options: [ { - name: 'action', + name: "action", description: 'Either "enable" or "disable"', required: true, - type: 'STRING', + type: "STRING", choices: [ { - name: 'Enable', - value: 'enable', + name: "Enable", + value: "enable", }, - { name: 'Disable', value: 'disable' }, + { name: "Disable", value: "disable" }, ], }, { - name: 'command', - description: 'The name of the command', + name: "command", + description: "The name of the command", required: true, - type: 'STRING', + type: "STRING", }, ], callback: async (options: ICallbackObject) => { - const { channel, args, instance } = options + const { channel, args, instance } = options; - const { guild } = channel - const newState = args.shift()?.toLowerCase() - const name = (args.shift() || '').toLowerCase() + const { guild } = channel; + const newState = args.shift()?.toLowerCase(); + const name = (args.shift() || "").toLowerCase(); if (!guild) { - return instance.messageHandler.get(guild, 'CANNOT_ENABLE_DISABLE_IN_DMS') + return instance.messageHandler.get(guild, "CANNOT_ENABLE_DISABLE_IN_DMS"); } if (!instance.isDBConnected()) { - return instance.messageHandler.get(guild, 'NO_DATABASE_FOUND') + return instance.messageHandler.get(guild, "NO_DATABASE_FOUND"); } - if (newState !== 'enable' && newState !== 'disable') { - return instance.messageHandler.get(guild, 'ENABLE_DISABLE_STATE') + if (newState !== "enable" && newState !== "disable") { + return instance.messageHandler.get(guild, "ENABLE_DISABLE_STATE"); } - const command = instance.commandHandler.getCommand(name) + const command = instance.commandHandler.getCommand(name); if (command) { - const mainCommand = command.names[0] - if (mainCommand === 'command') { - return instance.messageHandler.get(guild, 'CANNOT_DISABLE_THIS_COMMAND') + const mainCommand = command.names[0]; + if (mainCommand === "command") { + return instance.messageHandler.get( + guild, + "CANNOT_DISABLE_THIS_COMMAND" + ); } - const isDisabled = command.isDisabled(guild.id) + const isDisabled = command.isDisabled(guild.id); - if (newState === 'enable') { + if (newState === "enable") { if (!isDisabled) { - return instance.messageHandler.get(guild, 'COMMAND_ALREADY_ENABLED') + return instance.messageHandler.get(guild, "COMMAND_ALREADY_ENABLED"); } await disabledCommands.deleteOne({ guildId: guild.id, command: mainCommand, - }) + }); - command.enable(guild.id) + command.enable(guild.id); - return instance.messageHandler.get(guild, 'COMMAND_NOW_ENABLED', { + return instance.messageHandler.get(guild, "COMMAND_NOW_ENABLED", { COMMAND: mainCommand, - }) + }); } if (isDisabled) { - return instance.messageHandler.get(guild, 'COMMAND_ALREADY_DISABLED') + return instance.messageHandler.get(guild, "COMMAND_ALREADY_DISABLED"); } await new disabledCommands({ guildId: guild.id, command: mainCommand, - }).save() + }).save(); - command.disable(guild.id) + command.disable(guild.id); - return instance.messageHandler.get(guild, 'COMMAND_NOW_DISABLED', { + return instance.messageHandler.get(guild, "COMMAND_NOW_DISABLED", { COMMAND: mainCommand, - }) + }); } - return instance.messageHandler.get(guild, 'UNKNOWN_COMMAND', { + return instance.messageHandler.get(guild, "UNKNOWN_COMMAND", { COMMAND: name, - }) + }); }, -} as ICommand +} as ICommand; diff --git a/src/commands/help/!ReactionListener.ts b/src/commands/help/!ReactionListener.ts index ef2db71..9973c48 100644 --- a/src/commands/help/!ReactionListener.ts +++ b/src/commands/help/!ReactionListener.ts @@ -7,10 +7,10 @@ import { PartialMessageReaction, PartialUser, User, -} from 'discord.js' -import WOKCommands from '../..' -import { ICommand } from '../../../typings' -import getFirstEmbed from './!get-first-embed' +} from "discord.js"; +import WOKCommands from "../.."; +import { ICommand } from "../../types"; +import getFirstEmbed from "./!get-first-embed"; const /** * Recursively adds reactions to the message @@ -18,71 +18,71 @@ const /** * @param reactions A list of reactions to add */ addReactions = (message: Message | PartialMessage, reactions: string[]) => { - const emoji = reactions.shift() + const emoji = reactions.shift(); if (emoji) { - message.react(emoji) - addReactions(message, reactions) + message.react(emoji); + addReactions(message, reactions); } - } + }; class ReactionHandler { - instance: WOKCommands - reaction: MessageReaction | PartialMessageReaction - user: PartialUser | User - message: Message | PartialMessage - embed!: MessageEmbed - guild: Guild | null = null - emojiName: string | null = '' - emojiId = '' - door = '🚪' - pageLimit = 3 + instance: WOKCommands; + reaction: MessageReaction | PartialMessageReaction; + user: PartialUser | User; + message: Message | PartialMessage; + embed!: MessageEmbed; + guild: Guild | null = null; + emojiName: string | null = ""; + emojiId = ""; + door = "🚪"; + pageLimit = 3; constructor( instance: WOKCommands, reaction: MessageReaction | PartialMessageReaction, user: PartialUser | User ) { - this.instance = instance - this.reaction = reaction - this.user = user - this.message = reaction.message + this.instance = instance; + this.reaction = reaction; + this.user = user; + this.message = reaction.message; - this.init() + this.init(); } init = async () => { if (this.message.partial) { - await this.message.fetch() + await this.message.fetch(); } - const { embeds, guild } = this.message + const { embeds, guild } = this.message; if (this.user.bot || !embeds || embeds.length !== 1) { - return + return; } - this.embed = embeds[0] - this.guild = guild + this.embed = embeds[0]; + this.guild = guild; if (!this.canUserInteract()) { - return + return; } - this.emojiName = this.reaction.emoji.name - this.emojiId = this.reaction.emoji.id || '' - this.handleEmoji() - } + this.emojiName = this.reaction.emoji.name; + this.emojiId = this.reaction.emoji.id || ""; + this.handleEmoji(); + }; /** * @returns If the bot has access to remove reactions from the help menu */ canBotRemoveReaction = () => { return ( - this.message.channel.type !== 'DM' && - this.message.member?.permissions.has('MANAGE_MESSAGES') - ) - } + this.message.channel.type !== "DM" && + this.message.member?.permissions.has("MANAGE_MESSAGES") + ); + }; /** * @returns If the user is allowed to interact with this help menu @@ -90,34 +90,34 @@ class ReactionHandler { canUserInteract = () => { // Check if the title of the embed is correct const displayName = this.instance.displayName - ? this.instance.displayName + ' ' - : '' + ? this.instance.displayName + " " + : ""; const isSameTitle = this.embed.title === `${displayName}${this.instance.messageHandler.getEmbed( this.guild, - 'HELP_MENU', - 'TITLE' - )}` + "HELP_MENU", + "TITLE" + )}`; if (!isSameTitle) { - return false + return false; } // Check if the user's ID is in the footer if (this.embed.footer) { - const { text } = this.embed.footer - const id = text?.split('#')[1] + const { text } = this.embed.footer; + const id = text?.split("#")[1]; if (id !== this.user.id) { if (this.canBotRemoveReaction()) { - this.reaction.users.remove(this.user.id) + this.reaction.users.remove(this.user.id); } - return false + return false; } } - return true - } + return true; + }; /** * Invoked when the user returns to the main menu @@ -126,202 +126,202 @@ class ReactionHandler { const { embed: newEmbed, reactions } = getFirstEmbed( this.message, this.instance - ) + ); - this.embed.setDescription(newEmbed.description || '') - this.message.edit({ embeds: [this.embed] }) + this.embed.setDescription(newEmbed.description || ""); + this.message.edit({ embeds: [this.embed] }); if (this.canBotRemoveReaction()) { - this.message.reactions.removeAll() + this.message.reactions.removeAll(); } - addReactions(this.message, reactions) - } + addReactions(this.message, reactions); + }; /** * @param commandLength How many commands are in the category * @returns An array of [page, maxPages] */ getMaxPages = (commandLength: number) => { - let page = 1 + let page = 1; if (this.embed && this.embed.description) { - const split = this.embed.description.split('\n') - const lastLine = split[split.length - 1] - if (lastLine.startsWith('Page ')) { - page = parseInt(lastLine.split(' ')[1]) + const split = this.embed.description.split("\n"); + const lastLine = split[split.length - 1]; + if (lastLine.startsWith("Page ")) { + page = parseInt(lastLine.split(" ")[1]); } } - return [page, Math.ceil(commandLength / this.pageLimit)] - } + return [page, Math.ceil(commandLength / this.pageLimit)]; + }; /** * @returns An object containing information regarding the commands */ getCommands = () => { - let category = this.instance.getCategory(this.emojiId || this.emojiName) + let category = this.instance.getCategory(this.emojiId || this.emojiName); const commandsString = this.instance.messageHandler.getEmbed( this.guild, - 'HELP_MENU', - 'COMMANDS' - ) + "HELP_MENU", + "COMMANDS" + ); if (this.embed.description) { - const split = this.embed.description.split('\n') - const cmdStr = ' ' + commandsString + const split = this.embed.description.split("\n"); + const cmdStr = " " + commandsString; if (split[0].endsWith(cmdStr)) { - category = split[0].replace(cmdStr, '') + category = split[0].replace(cmdStr, ""); } } const commands = - this.instance.commandHandler.getCommandsByCategory(category) + this.instance.commandHandler.getCommandsByCategory(category); return { length: commands.length, commands, commandsString, category, - } - } + }; + }; static getHelp = ( command: ICommand, instance: WOKCommands, guild: Guild | null ) => { - const { description, syntax, names } = command + const { description, syntax, names } = command; if (names === undefined) { console.error( - 'WOKCommands > A command does not have a name assigned to it.' - ) - return '' + "WOKCommands > A command does not have a name assigned to it." + ); + return ""; } - const mainName = typeof names === 'string' ? names : names.shift() + const mainName = typeof names === "string" ? names : names.shift(); - let desc = `**${mainName}**${description ? ' - ' : ''}${description}` + let desc = `**${mainName}**${description ? " - " : ""}${description}`; - if (names.length && typeof names !== 'string') { + if (names.length && typeof names !== "string") { desc += `\n${instance.messageHandler.getEmbed( guild, - 'HELP_MENU', - 'ALIASES' - )}: "${names.join('", "')}"` + "HELP_MENU", + "ALIASES" + )}: "${names.join('", "')}"`; } desc += `\n${instance.messageHandler.getEmbed( guild, - 'HELP_MENU', - 'SYNTAX' - )}: "${instance.getPrefix(guild)}${mainName}${syntax ? ' ' : ''}${ - syntax || '' - }"` + "HELP_MENU", + "SYNTAX" + )}: "${instance.getPrefix(guild)}${mainName}${syntax ? " " : ""}${ + syntax || "" + }"`; - return desc - } + return desc; + }; /** * Generates the actual menu */ generateMenu = (page: number, maxPages: number) => { - const { length, commands, commandsString, category } = this.getCommands() + const { length, commands, commandsString, category } = this.getCommands(); - const hasMultiplePages = length > this.pageLimit + const hasMultiplePages = length > this.pageLimit; let desc = `${category} ${commandsString}\n\n${this.instance.messageHandler.getEmbed( this.guild, - 'HELP_MENU', - 'DESCRIPTION_FIRST_LINE' - )}` + "HELP_MENU", + "DESCRIPTION_FIRST_LINE" + )}`; if (hasMultiplePages) { desc += `\n\n${this.instance.messageHandler.getEmbed( this.guild, - 'HELP_MENU', - 'DESCRIPTION_SECOND_LINE' - )}` + "HELP_MENU", + "DESCRIPTION_SECOND_LINE" + )}`; } - const start = (page - 1) * this.pageLimit + const start = (page - 1) * this.pageLimit; for ( let a = start, counter = a; a < commands.length && a < start + this.pageLimit; ++a ) { - const command = commands[a] + const command = commands[a]; - let { hidden, category, names } = command + let { hidden, category, names } = command; if (!hidden && category === category) { - if (typeof names === 'string') { + if (typeof names === "string") { // @ts-ignore - names = [...names] + names = [...names]; } desc += `\n\n#${++counter}) ${ReactionHandler.getHelp( command, this.instance, this.guild - )}` + )}`; } } - desc += `\n\nPage ${page} / ${maxPages}.` + desc += `\n\nPage ${page} / ${maxPages}.`; - this.embed.setDescription(desc) - this.message.edit({ embeds: [this.embed] }) + this.embed.setDescription(desc); + this.message.edit({ embeds: [this.embed] }); if (this.canBotRemoveReaction()) { - this.message.reactions.removeAll() + this.message.reactions.removeAll(); } - const reactions = [] + const reactions = []; if (hasMultiplePages) { - reactions.push('⬅') - reactions.push('➡') + reactions.push("⬅"); + reactions.push("➡"); } - reactions.push('🚪') - addReactions(this.message, reactions) - } + reactions.push("🚪"); + addReactions(this.message, reactions); + }; /** * Handles the input from the emoji */ handleEmoji = () => { if (this.emojiName === this.door) { - this.returnToMainMenu() - return + this.returnToMainMenu(); + return; } - const { length } = this.getCommands() + const { length } = this.getCommands(); - let [page, maxPages] = this.getMaxPages(length) + let [page, maxPages] = this.getMaxPages(length); - if (this.emojiName === '⬅') { + if (this.emojiName === "⬅") { if (page <= 1) { if (this.canBotRemoveReaction()) { - this.reaction.users.remove(this.user.id) + this.reaction.users.remove(this.user.id); } - return + return; } - --page - } else if (this.emojiName === '➡') { + --page; + } else if (this.emojiName === "➡") { if (page >= maxPages) { if (this.canBotRemoveReaction()) { - this.reaction.users.remove(this.user.id) + this.reaction.users.remove(this.user.id); } - return + return; } - ++page + ++page; } - this.generateMenu(page, maxPages) - } + this.generateMenu(page, maxPages); + }; } -export default ReactionHandler -export { addReactions } +export default ReactionHandler; +export { addReactions }; diff --git a/src/commands/help/!get-first-embed.ts b/src/commands/help/!get-first-embed.ts index 03920fc..2976af4 100644 --- a/src/commands/help/!get-first-embed.ts +++ b/src/commands/help/!get-first-embed.ts @@ -1,42 +1,42 @@ -import { Message, MessageEmbed, PartialMessage } from 'discord.js' -import WOKCommands from '../../' +import { Message, MessageEmbed, PartialMessage } from "discord.js"; +import WOKCommands from "../../"; const getFirstEmbed = ( message: Message | PartialMessage, instance: WOKCommands ) => { - const { guild, member } = message + const { guild, member } = message; const { commandHandler: { commands }, messageHandler, - } = instance + } = instance; const embed = new MessageEmbed() .setTitle( `${instance.displayName} ${messageHandler.getEmbed( guild, - 'HELP_MENU', - 'TITLE' + "HELP_MENU", + "TITLE" )}` ) .setDescription( - messageHandler.getEmbed(guild, 'HELP_MENU', 'SELECT_A_CATEGORY') + messageHandler.getEmbed(guild, "HELP_MENU", "SELECT_A_CATEGORY") ) - .setFooter(`ID #${message.author?.id}`) + .setFooter(`ID #${message.author?.id}`); if (instance.color) { - embed.setColor(instance.color) + embed.setColor(instance.color); } const categories: { [key: string]: { - amount: number - emoji: string - } - } = {} + amount: number; + emoji: string; + }; + } = {}; - const isAdmin = member && member.permissions.has('ADMINISTRATOR') + const isAdmin = member && member.permissions.has("ADMINISTRATOR"); for (const { category, testOnly } of commands) { if ( @@ -44,59 +44,59 @@ const getFirstEmbed = ( (testOnly && guild && !instance.testServers.includes(guild.id)) || (!isAdmin && instance.hiddenCategories.includes(category)) ) { - continue + continue; } if (categories[category]) { - ++categories[category].amount + ++categories[category].amount; } else { categories[category] = { amount: 1, emoji: instance.getEmoji(category), - } + }; } } - const reactions: string[] = [] + const reactions: string[] = []; - const keys = Object.keys(categories) + const keys = Object.keys(categories); for (let a = 0; a < keys.length; ++a) { - const key = keys[a] - const { emoji } = categories[key] + const key = keys[a]; + const { emoji } = categories[key]; if (!emoji) { console.warn( `WOKCommands > Category "${key}" does not have an emoji icon.` - ) + ); - continue + continue; } const visibleCommands = instance.commandHandler.getCommandsByCategory( key, true - ) - const amount = visibleCommands.length + ); + const amount = visibleCommands.length; if (amount === 0) { - continue + continue; } - const reaction = emoji - reactions.push(reaction) + const reaction = emoji; + reactions.push(reaction); embed.setDescription( embed.description + `\n\n**${reaction} - ${key}** - ${amount} command${ - amount === 1 ? '' : 's' + amount === 1 ? "" : "s" }` - ) + ); } return { embed, reactions, - } -} + }; +}; -export default getFirstEmbed +export default getFirstEmbed; diff --git a/src/commands/help/help.ts b/src/commands/help/help.ts index 87ff997..b440ed9 100644 --- a/src/commands/help/help.ts +++ b/src/commands/help/help.ts @@ -1,83 +1,83 @@ -import { Client, Message, MessageEmbed } from 'discord.js' -import WOKCommands from '../..' -import { ICallbackObject, ICommand } from '../../../typings' -import getFirstEmbed from './!get-first-embed' -import ReactionListener, { addReactions } from './!ReactionListener' +import { Client, Message, MessageEmbed } from "discord.js"; +import WOKCommands from "../.."; +import { ICallbackObject, ICommand } from "../../types"; +import getFirstEmbed from "./!get-first-embed"; +import ReactionListener, { addReactions } from "./!ReactionListener"; const sendHelpMenu = (message: Message, instance: WOKCommands) => { - const { embed, reactions } = getFirstEmbed(message, instance) + const { embed, reactions } = getFirstEmbed(message, instance); message.channel .send({ embeds: [embed], }) .then((message) => { - addReactions(message, reactions) - }) -} + addReactions(message, reactions); + }); +}; module.exports = { description: "Displays this bot's commands", - category: 'Help', + category: "Help", - aliases: 'commands', + aliases: "commands", maxArgs: 1, - expectedArgs: '[command]', + expectedArgs: "[command]", init: (client: Client, instance: WOKCommands) => { - client.on('messageReactionAdd', async (reaction, user) => { - new ReactionListener(instance, reaction, user) - }) + client.on("messageReactionAdd", async (reaction, user) => { + new ReactionListener(instance, reaction, user); + }); }, callback: (options: ICallbackObject) => { - const { message, channel, instance, args } = options + const { message, channel, instance, args } = options; - const { guild } = channel + const { guild } = channel; - if (guild && !guild.me?.permissions.has('SEND_MESSAGES')) { + if (guild && !guild.me?.permissions.has("SEND_MESSAGES")) { console.warn( `WOKCommands > Could not send message due to no permissions in channel for ${guild.name}` - ) - return + ); + return; } - if (guild && !guild.me?.permissions.has('ADD_REACTIONS')) { - return instance.messageHandler.get(guild, 'NO_REACT_PERMS') + if (guild && !guild.me?.permissions.has("ADD_REACTIONS")) { + return instance.messageHandler.get(guild, "NO_REACT_PERMS"); } // Typical "!help" syntax for the menu if (args.length === 0) { - sendHelpMenu(message, instance) - return + sendHelpMenu(message, instance); + return; } // If the user is looking for info on a specific command // Ex: "!help prefix" - const arg = args.shift()?.toLowerCase()! + const arg = args.shift()?.toLowerCase()!; - const command = instance.commandHandler.getICommand(arg) + const command = instance.commandHandler.getICommand(arg); if (!command) { - return instance.messageHandler.get(guild, 'UNKNOWN_COMMAND', { + return instance.messageHandler.get(guild, "UNKNOWN_COMMAND", { COMMAND: arg, - }) + }); } - const description = ReactionListener.getHelp(command, instance, guild) + const description = ReactionListener.getHelp(command, instance, guild); const embed = new MessageEmbed() .setTitle( `${instance.displayName} ${instance.messageHandler.getEmbed( guild, - 'HELP_MENU', - 'TITLE' + "HELP_MENU", + "TITLE" )} - ${arg}` ) - .setDescription(description) + .setDescription(description); if (instance.color) { - embed.setColor(instance.color) + embed.setColor(instance.color); } - return embed + return embed; }, -} as ICommand +} as ICommand; diff --git a/src/commands/language.ts b/src/commands/language.ts index aa5e031..76f273f 100644 --- a/src/commands/language.ts +++ b/src/commands/language.ts @@ -1,52 +1,52 @@ -import languageSchema from '../models/languages' -import { ICallbackObject, ICommand } from '../..' -import Events from '../enums/Events' +import Events from "../enums/Events"; +import languageSchema from "../models/languages"; +import { ICallbackObject, ICommand } from "../types"; export = { - description: 'Displays or sets the language for this Discord server', - category: 'Configuration', + description: "Displays or sets the language for this Discord server", + category: "Configuration", - aliases: ['lang'], - permissions: ['ADMINISTRATOR'], + aliases: ["lang"], + permissions: ["ADMINISTRATOR"], maxArgs: 1, - expectedArgs: '[language]', + expectedArgs: "[language]", - cooldown: '2s', + cooldown: "2s", - slash: 'both', + slash: "both", callback: async (options: ICallbackObject) => { - const { channel, text, instance } = options + const { channel, text, instance } = options; - const { guild } = channel + const { guild } = channel; if (!guild) { - return + return; } - const { messageHandler } = instance + const { messageHandler } = instance; if (!instance.isDBConnected()) { - return instance.messageHandler.get(guild, 'NO_DATABASE_FOUND') + return instance.messageHandler.get(guild, "NO_DATABASE_FOUND"); } - const lang = text.toLowerCase() + const lang = text.toLowerCase(); if (!lang) { - return instance.messageHandler.get(guild, 'CURRENT_LANGUAGE', { + return instance.messageHandler.get(guild, "CURRENT_LANGUAGE", { LANGUAGE: instance.messageHandler.getLanguage(guild), - }) + }); } if (!messageHandler.languages().includes(lang)) { - instance.emit(Events.LANGUAGE_NOT_SUPPORTED, guild, lang) + instance.emit(Events.LANGUAGE_NOT_SUPPORTED, guild, lang); - return messageHandler.get(guild, 'LANGUAGE_NOT_SUPPORTED', { + return messageHandler.get(guild, "LANGUAGE_NOT_SUPPORTED", { LANGUAGE: lang, - }) + }); } - instance.messageHandler.setLanguage(guild, lang) + instance.messageHandler.setLanguage(guild, lang); await languageSchema.findOneAndUpdate( { @@ -59,10 +59,10 @@ export = { { upsert: true, } - ) + ); - return instance.messageHandler.get(guild, 'NEW_LANGUAGE', { + return instance.messageHandler.get(guild, "NEW_LANGUAGE", { LANGUAGE: lang, - }) + }); }, -} as ICommand +} as ICommand; diff --git a/src/commands/prefix.ts b/src/commands/prefix.ts index a79076e..8fc55ae 100644 --- a/src/commands/prefix.ts +++ b/src/commands/prefix.ts @@ -1,34 +1,34 @@ -import { ICallbackObject, ICommand } from '../..' -import prefixes from '../models/prefixes' +import prefixes from "../models/prefixes"; +import { ICallbackObject, ICommand } from "../types"; export = { - description: 'Displays or sets the prefix for the current guild', - category: 'Configuration', + description: "Displays or sets the prefix for the current guild", + category: "Configuration", - permissions: ['ADMINISTRATOR'], + permissions: ["ADMINISTRATOR"], maxArgs: 1, - expectedArgs: '[prefix]', + expectedArgs: "[prefix]", - cooldown: '2s', + cooldown: "2s", - slash: 'both', + slash: "both", callback: async (options: ICallbackObject) => { - const { channel, args, text, instance } = options - const { guild } = channel + const { channel, args, text, instance } = options; + const { guild } = channel; if (args.length === 0) { - return instance.messageHandler.get(guild, 'CURRENT_PREFIX', { + return instance.messageHandler.get(guild, "CURRENT_PREFIX", { PREFIX: instance.getPrefix(guild), - }) + }); } if (guild) { - const { id } = guild + const { id } = guild; if (!instance.isDBConnected()) { - return instance.messageHandler.get(guild, 'NO_DATABASE_FOUND') + return instance.messageHandler.get(guild, "NO_DATABASE_FOUND"); } await prefixes.findOneAndUpdate( @@ -42,15 +42,15 @@ export = { { upsert: true, } - ) + ); - instance.setPrefix(guild, text) + instance.setPrefix(guild, text); - return instance.messageHandler.get(guild, 'SET_PREFIX', { + return instance.messageHandler.get(guild, "SET_PREFIX", { PREFIX: text, - }) + }); } - return instance.messageHandler.get(guild, 'CANNOT_SET_PREFIX_IN_DMS') + return instance.messageHandler.get(guild, "CANNOT_SET_PREFIX_IN_DMS"); }, -} as ICommand +} as ICommand; diff --git a/src/commands/requiredrole.ts b/src/commands/requiredrole.ts index 9798d81..dce437f 100644 --- a/src/commands/requiredrole.ts +++ b/src/commands/requiredrole.ts @@ -1,60 +1,60 @@ -import { ICallbackObject, ICommand } from '../..' -import requiredRoleSchema from '../models/required-roles' +import requiredRoleSchema from "../models/required-roles"; +import { ICallbackObject, ICommand } from "../types"; export = { - description: 'Specifies what role each command requires.', - category: 'Configuration', + description: "Specifies what role each command requires.", + category: "Configuration", - permissions: ['ADMINISTRATOR'], - aliases: ['requiredroles', 'requirerole', 'requireroles'], + permissions: ["ADMINISTRATOR"], + aliases: ["requiredroles", "requirerole", "requireroles"], minArgs: 2, maxArgs: 2, - expectedArgs: ' ', + expectedArgs: " ", - cooldown: '2s', + cooldown: "2s", - slash: 'both', + slash: "both", callback: async (options: ICallbackObject) => { - const { channel, args, instance } = options + const { channel, args, instance } = options; - const name = (args.shift() || '').toLowerCase() - const roleId = (args.shift() || '').toLowerCase() + const name = (args.shift() || "").toLowerCase(); + const roleId = (args.shift() || "").toLowerCase(); - const { guild } = channel + const { guild } = channel; if (!guild) { return instance.messageHandler.get( guild, - 'CANNOT_CHANGE_REQUIRED_ROLES_IN_DMS' - ) + "CANNOT_CHANGE_REQUIRED_ROLES_IN_DMS" + ); } if (!instance.isDBConnected()) { - return instance.messageHandler.get(guild, 'NO_DATABASE_FOUND') + return instance.messageHandler.get(guild, "NO_DATABASE_FOUND"); } - const command = instance.commandHandler.getCommand(name) + const command = instance.commandHandler.getCommand(name); if (command) { - if (roleId === 'none') { - command.removeRequiredRole(guild.id, roleId) + if (roleId === "none") { + command.removeRequiredRole(guild.id, roleId); await requiredRoleSchema.deleteOne({ guildId: guild.id, command: command.names[0], - }) + }); return instance.messageHandler.get( guild, - 'REMOVED_ALL_REQUIRED_ROLES', + "REMOVED_ALL_REQUIRED_ROLES", { COMMAND: command.names[0], } - ) + ); } - command.addRequiredRole(guild.id, roleId) + command.addRequiredRole(guild.id, roleId); await requiredRoleSchema.findOneAndUpdate( { @@ -71,16 +71,16 @@ export = { { upsert: true, } - ) + ); - return instance.messageHandler.get(guild, 'ADDED_REQUIRED_ROLE', { + return instance.messageHandler.get(guild, "ADDED_REQUIRED_ROLE", { ROLE: roleId, COMMAND: command.names[0], - }) + }); } - return instance.messageHandler.get(guild, 'UNKNOWN_COMMAND', { + return instance.messageHandler.get(guild, "UNKNOWN_COMMAND", { COMMAND: name, - }) + }); }, -} as ICommand +} as ICommand; diff --git a/src/commands/slash.ts b/src/commands/slash.ts index cf26e25..67f1e25 100644 --- a/src/commands/slash.ts +++ b/src/commands/slash.ts @@ -1,126 +1,126 @@ -import { ApplicationCommand, MessageEmbed } from 'discord.js' -import { ICallbackObject, ICommand } from '../..' +import { ApplicationCommand, MessageEmbed } from "discord.js"; +import { ICallbackObject, ICommand } from "../types"; export = { - description: 'Allows the bot developers to manage existing slash commands', - category: 'Configuration', + description: "Allows the bot developers to manage existing slash commands", + category: "Configuration", - permissions: ['ADMINISTRATOR'], + permissions: ["ADMINISTRATOR"], maxArgs: 1, - expectedArgs: '[command-id]', + expectedArgs: "[command-id]", ownerOnly: true, hidden: true, - slash: 'both', + slash: "both", callback: async (options: ICallbackObject) => { - const { channel, instance, text } = options + const { channel, instance, text } = options; - const { guild } = channel - const { slashCommands } = instance + const { guild } = channel; + const { slashCommands } = instance; - const global = await slashCommands.get() + const global = await slashCommands.get(); if (text) { - let useGuild = true + let useGuild = true; try { global?.forEach((cmd: ApplicationCommand) => { if (cmd.id === text) { - useGuild = false - throw new Error('') + useGuild = false; + throw new Error(""); } - }) + }); } catch (ignored) {} - slashCommands.delete(text, useGuild ? guild.id : undefined) + slashCommands.delete(text, useGuild ? guild.id : undefined); if (useGuild) { - return `Slash command with the ID "${text}" has been deleted from guild "${guild.id}".` + return `Slash command with the ID "${text}" has been deleted from guild "${guild.id}".`; } - return `Slash command with the ID "${text}" has been deleted. This may take up to 1 hour to be seen on all servers using your bot.` + return `Slash command with the ID "${text}" has been deleted. This may take up to 1 hour to be seen on all servers using your bot.`; } - let counter = 0 - let allSlashCommands: string[] = [] + let counter = 0; + let allSlashCommands: string[] = []; if (global.size) { global.forEach((cmd: ApplicationCommand) => { if (cmd && cmd.name) { - const newString = `${cmd.name}: ${cmd.id}\n` + const newString = `${cmd.name}: ${cmd.id}\n`; if ( (allSlashCommands[counter] || []).length + newString.length < 1024 ) { - allSlashCommands[counter] ??= '' - allSlashCommands[counter] += newString + allSlashCommands[counter] ??= ""; + allSlashCommands[counter] += newString; } else { - ++counter - allSlashCommands[counter] ??= '' - allSlashCommands[counter] += newString + ++counter; + allSlashCommands[counter] ??= ""; + allSlashCommands[counter] += newString; } } - }) + }); } else { - allSlashCommands.push('None') + allSlashCommands.push("None"); } const embed = new MessageEmbed().addField( - 'How to delete a slash command:', + "How to delete a slash command:", `${instance.getPrefix(guild)}slash ` - ) + ); for (let a = 0; a < allSlashCommands.length; ++a) { embed.addField( - `Global slash commands:${a === 0 ? '' : ' (Continued)'}`, + `Global slash commands:${a === 0 ? "" : " (Continued)"}`, allSlashCommands[a] - ) + ); } if (guild) { - const guildOnly = await slashCommands.get(guild.id) + const guildOnly = await slashCommands.get(guild.id); - counter = 0 - let guildOnlyCommands: string[] = [] + counter = 0; + let guildOnlyCommands: string[] = []; if (guildOnly.size) { guildOnly.forEach((cmd: ApplicationCommand) => { if (cmd && cmd.name) { - const newString = `${cmd.name}: ${cmd.id}\n` + const newString = `${cmd.name}: ${cmd.id}\n`; if ( (guildOnlyCommands[counter] || []).length + newString.length < 1024 ) { - guildOnlyCommands[counter] ??= '' - guildOnlyCommands[counter] += newString + guildOnlyCommands[counter] ??= ""; + guildOnlyCommands[counter] += newString; } else { - ++counter - guildOnlyCommands[counter] ??= '' - guildOnlyCommands[counter] += newString + ++counter; + guildOnlyCommands[counter] ??= ""; + guildOnlyCommands[counter] += newString; } } - }) + }); } else { - guildOnlyCommands[0] = 'None' + guildOnlyCommands[0] = "None"; } for (let a = 0; a < guildOnlyCommands.length; ++a) { embed.addField( - `Guild slash commands:${a === 0 ? '' : ' (Continued)'}`, + `Guild slash commands:${a === 0 ? "" : " (Continued)"}`, guildOnlyCommands[a] - ) + ); } } if (instance.color) { - embed.setColor(instance.color) + embed.setColor(instance.color); } - return embed + return embed; }, -} as ICommand +} as ICommand; diff --git a/src/enums/CommandErrors.ts b/src/enums/CommandErrors.ts index c4a65a1..f3cb3dd 100644 --- a/src/enums/CommandErrors.ts +++ b/src/enums/CommandErrors.ts @@ -1,10 +1,10 @@ enum CommandErrors { - EXCEPTION = 'EXCEPTION', - COOLDOWN = 'COOLDOWN', - INVALID_ARGUMENTS = 'INVALID ARGUMENTS', - MISSING_PERMISSIONS = 'MISSING PERMISSIONS', - MISSING_ROLES = 'MISSING ROLES', - COMMAND_DISABLED = 'COMMAND DISABLED', + EXCEPTION = "EXCEPTION", + COOLDOWN = "COOLDOWN", + INVALID_ARGUMENTS = "INVALID ARGUMENTS", + MISSING_PERMISSIONS = "MISSING PERMISSIONS", + MISSING_ROLES = "MISSING ROLES", + COMMAND_DISABLED = "COMMAND DISABLED", } -export default CommandErrors +export default CommandErrors; diff --git a/src/enums/Events.ts b/src/enums/Events.ts index 944a08c..1fe5004 100644 --- a/src/enums/Events.ts +++ b/src/enums/Events.ts @@ -1,7 +1,7 @@ enum Events { - DATABASE_CONNECTED = 'databaseConnected', - LANGUAGE_NOT_SUPPORTED = 'languageNotSupported', - COMMAND_EXCEPTION = 'commandException', + DATABASE_CONNECTED = "databaseConnected", + LANGUAGE_NOT_SUPPORTED = "languageNotSupported", + COMMAND_EXCEPTION = "commandException", } -export default Events +export default Events; diff --git a/src/features/message-upsert.ts b/src/features/message-upsert.ts index 0bcfe00..5490fbb 100644 --- a/src/features/message-upsert.ts +++ b/src/features/message-upsert.ts @@ -1,16 +1,16 @@ -import { Client } from 'discord.js' +import { Client } from "discord.js"; export default (client: Client) => { - client.on('messageCreate', (message) => { - client.emit('messageUpsert', message) - }) + client.on("messageCreate", (message) => { + client.emit("messageUpsert", message); + }); - client.on('messageUpdate', (oldMessage, newMessage) => { - client.emit('messageUpsert', newMessage, oldMessage) - }) -} + client.on("messageUpdate", (oldMessage, newMessage) => { + client.emit("messageUpsert", newMessage, oldMessage); + }); +}; export const config = { - displayName: 'Message Upsert', - dbName: 'MESSAGE-UPSERT', -} + displayName: "Message Upsert", + dbName: "MESSAGE-UPSERT", +}; diff --git a/src/get-all-files.ts b/src/get-all-files.ts index 1f3e1f4..d402725 100644 --- a/src/get-all-files.ts +++ b/src/get-all-files.ts @@ -1,27 +1,29 @@ -import fs, { Dirent } from 'fs' +import fs, { Dirent } from "fs"; const getAllFiles = (dir: string, extension?: string) => { const files: Dirent[] = fs.readdirSync(dir, { withFileTypes: true, - }) - let jsFiles: [string, string][] = [] + }); + let jsFiles: [string, string][] = []; for (const file of files) { if (file.isDirectory()) { - jsFiles = [...jsFiles, ...getAllFiles(`${dir}/${file.name}`, extension)] + jsFiles = [...jsFiles, ...getAllFiles(`${dir}/${file.name}`, extension)]; } else if ( - file.name.endsWith(extension || '.js') && - !file.name.startsWith('!') + file.name.endsWith(extension || ".js") && + !file.name.startsWith("!") ) { - let fileName: string | string[] = file.name.replace(/\\/g, '/').split('/') - fileName = fileName[fileName.length - 1] - fileName = fileName.split('.')[0].toLowerCase() + let fileName: string | string[] = file.name + .replace(/\\/g, "/") + .split("/"); + fileName = fileName[fileName.length - 1]; + fileName = fileName.split(".")[0].toLowerCase(); - jsFiles.push([`${dir}/${file.name}`, fileName]) + jsFiles.push([`${dir}/${file.name}`, fileName]); } } - return jsFiles -} + return jsFiles; +}; -export = getAllFiles +export = getAllFiles; diff --git a/src/index.ts b/src/index.ts index ab9fb0e..c23f102 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,64 +1,63 @@ -import { Client, ColorResolvable, Guild, GuildEmoji } from 'discord.js' -import { Connection } from 'mongoose' -import { EventEmitter } from 'events' - -import FeatureHandler from './FeatureHandler' -import mongo, { getMongoConnection } from './mongo' -import prefixes from './models/prefixes' -import MessageHandler from './message-handler' -import SlashCommands from './SlashCommands' -import { ICategorySetting, Options } from '..' -import Events from './enums/Events' -import CommandHandler from './CommandHandler' +import { Client, ColorResolvable, Guild, GuildEmoji } from "discord.js"; +import { EventEmitter } from "events"; +import { Connection } from "mongoose"; +import CommandHandler from "./CommandHandler"; +import Events from "./enums/Events"; +import FeatureHandler from "./FeatureHandler"; +import MessageHandler from "./message-handler"; +import prefixes from "./models/prefixes"; +import mongo, { getMongoConnection } from "./mongo"; +import SlashCommands from "./SlashCommands"; +import { ICategorySetting, Options } from "./types"; export default class WOKCommands extends EventEmitter { - private _client: Client - private _defaultPrefix = '!' - private _commandsDir = 'commands' - private _featuresDir = '' - private _mongoConnection: Connection | null = null - private _displayName = '' - private _prefixes: { [name: string]: string } = {} - private _categories: Map = new Map() // - private _hiddenCategories: string[] = [] - private _color: ColorResolvable | null = null - private _commandHandler: CommandHandler | null = null - private _featureHandler: FeatureHandler | null = null - private _tagPeople = true - private _showWarns = true - private _delErrMsgCooldown = -1 - private _ignoreBots = true - private _botOwner: string[] = [] - private _testServers: string[] = [] - private _defaultLanguage = 'english' - private _ephemeral = true - private _debug = false - private _messageHandler: MessageHandler | null = null - private _slashCommand: SlashCommands | null = null + private _client: Client; + private _defaultPrefix = "!"; + private _commandsDir = "commands"; + private _featuresDir = ""; + private _mongoConnection: Connection | null = null; + private _displayName = ""; + private _prefixes: { [name: string]: string } = {}; + private _categories: Map = new Map(); // + private _hiddenCategories: string[] = []; + private _color: ColorResolvable | null = null; + private _commandHandler: CommandHandler | null = null; + private _featureHandler: FeatureHandler | null = null; + private _tagPeople = true; + private _showWarns = true; + private _delErrMsgCooldown = -1; + private _ignoreBots = true; + private _botOwner: string[] = []; + private _testServers: string[] = []; + private _defaultLanguage = "english"; + private _ephemeral = true; + private _debug = false; + private _messageHandler: MessageHandler | null = null; + private _slashCommand: SlashCommands | null = null; constructor(client: Client, options?: Options) { - super() + super(); - this._client = client + this._client = client; - this.setUp(client, options) + this.setUp(client, options); } private async setUp(client: Client, options?: Options) { if (!client) { - throw new Error('No Discord JS Client provided as first argument!') + throw new Error("No Discord JS Client provided as first argument!"); } let { - commandsDir = '', - commandDir = '', - featuresDir = '', - featureDir = '', + commandsDir = "", + commandDir = "", + featuresDir = "", + featureDir = "", messagesPath, mongoUri, showWarns = true, delErrMsgCooldown = -1, - defaultLanguage = 'english', + defaultLanguage = "english", ignoreBots = true, dbOptions, testServers, @@ -67,74 +66,74 @@ export default class WOKCommands extends EventEmitter { typeScript = false, ephemeral = true, debug = false, - } = options || {} + } = options || {}; if (mongoUri) { - await mongo(mongoUri, this, dbOptions) + await mongo(mongoUri, this, dbOptions); - this._mongoConnection = getMongoConnection() + this._mongoConnection = getMongoConnection(); - const results: any[] = await prefixes.find({}) + const results: any[] = await prefixes.find({}); for (const result of results) { - const { _id, prefix } = result + const { _id, prefix } = result; - this._prefixes[_id] = prefix + this._prefixes[_id] = prefix; } } else { if (showWarns) { console.warn( - 'WOKCommands > No MongoDB connection URI provided. Some features might not work! See this for more details:\nhttps://docs.wornoffkeys.com/databases/mongodb' - ) + "WOKCommands > No MongoDB connection URI provided. Some features might not work! See this for more details:\nhttps://docs.wornoffkeys.com/databases/mongodb" + ); } - this.emit(Events.DATABASE_CONNECTED, null, '') + this.emit(Events.DATABASE_CONNECTED, null, ""); } - this._commandsDir = commandsDir || commandDir || this._commandsDir - this._featuresDir = featuresDir || featureDir || this._featuresDir - this._ephemeral = ephemeral - this._debug = debug + this._commandsDir = commandsDir || commandDir || this._commandsDir; + this._featuresDir = featuresDir || featureDir || this._featuresDir; + this._ephemeral = ephemeral; + this._debug = debug; if ( this._commandsDir && - !(this._commandsDir.includes('/') || this._commandsDir.includes('\\')) + !(this._commandsDir.includes("/") || this._commandsDir.includes("\\")) ) { throw new Error( "WOKCommands > The 'commands' directory must be an absolute path. This can be done by using the 'path' module. More info: https://docs.wornoffkeys.com/setup-and-options-object" - ) + ); } if ( this._featuresDir && - !(this._featuresDir.includes('/') || this._featuresDir.includes('\\')) + !(this._featuresDir.includes("/") || this._featuresDir.includes("\\")) ) { throw new Error( "WOKCommands > The 'features' directory must be an absolute path. This can be done by using the 'path' module. More info: https://docs.wornoffkeys.com/setup-and-options-object" - ) + ); } if (testServers) { - if (typeof testServers === 'string') { - testServers = [testServers] + if (typeof testServers === "string") { + testServers = [testServers]; } - this._testServers = testServers + this._testServers = testServers; } if (botOwners) { - if (typeof botOwners === 'string') { - botOwners = [botOwners] + if (typeof botOwners === "string") { + botOwners = [botOwners]; } - this._botOwner = botOwners + this._botOwner = botOwners; } - this._showWarns = showWarns - this._delErrMsgCooldown = delErrMsgCooldown - this._defaultLanguage = defaultLanguage.toLowerCase() - this._ignoreBots = ignoreBots + this._showWarns = showWarns; + this._delErrMsgCooldown = delErrMsgCooldown; + this._defaultLanguage = defaultLanguage.toLowerCase(); + this._ignoreBots = ignoreBots; - if (typeof disabledDefaultCommands === 'string') { - disabledDefaultCommands = [disabledDefaultCommands] + if (typeof disabledDefaultCommands === "string") { + disabledDefaultCommands = [disabledDefaultCommands]; } this._commandHandler = new CommandHandler( @@ -143,241 +142,245 @@ export default class WOKCommands extends EventEmitter { this._commandsDir, disabledDefaultCommands, typeScript - ) - this._slashCommand = new SlashCommands(this, true, typeScript) - this._messageHandler = new MessageHandler(this, messagesPath || '') + ); + this._slashCommand = new SlashCommands(this, true, typeScript); + this._messageHandler = new MessageHandler(this, messagesPath || ""); this.setCategorySettings([ { - name: 'Configuration', - emoji: '⚙', + name: "Configuration", + emoji: "⚙", }, { - name: 'Help', - emoji: '❓', + name: "Help", + emoji: "❓", }, - ]) + ]); this._featureHandler = new FeatureHandler( client, this, this._featuresDir, typeScript - ) + ); - console.log('WOKCommands > Your bot is now running.') + console.log("WOKCommands > Your bot is now running."); } public setMongoPath(mongoPath: string | undefined): WOKCommands { console.warn( 'WOKCommands > .setMongoPath() no longer works as expected. Please pass in your mongo URI as a "mongoUri" property using the options object. For more information: https://docs.wornoffkeys.com/databases/mongodb' - ) - return this + ); + return this; } public get client(): Client { - return this._client + return this._client; } public get displayName(): string { - return this._displayName + return this._displayName; } public setDisplayName(displayName: string): WOKCommands { - this._displayName = displayName - return this + this._displayName = displayName; + return this; } public get prefixes() { - return this._prefixes + return this._prefixes; } public get defaultPrefix(): string { - return this._defaultPrefix + return this._defaultPrefix; } public setDefaultPrefix(defaultPrefix: string): WOKCommands { - this._defaultPrefix = defaultPrefix - return this + this._defaultPrefix = defaultPrefix; + return this; } public getPrefix(guild: Guild | null): string { - return this._prefixes[guild ? guild.id : ''] || this._defaultPrefix + return this._prefixes[guild ? guild.id : ""] || this._defaultPrefix; } public setPrefix(guild: Guild | null, prefix: string): WOKCommands { if (guild) { - this._prefixes[guild.id] = prefix + this._prefixes[guild.id] = prefix; } - return this + return this; } public get categories(): Map { - return this._categories + return this._categories; } public get hiddenCategories(): string[] { - return this._hiddenCategories + return this._hiddenCategories; } public get color(): ColorResolvable | null { - return this._color + return this._color; } public setColor(color: ColorResolvable | null): WOKCommands { - this._color = color - return this + this._color = color; + return this; } public getEmoji(category: string): string { - const emoji = this._categories.get(category) || '' - if (typeof emoji === 'object') { + const emoji = this._categories.get(category) || ""; + if (typeof emoji === "object") { // @ts-ignore - return `<:${emoji.name}:${emoji.id}>` + return `<:${emoji.name}:${emoji.id}>`; } - return emoji + return emoji; } public getCategory(emoji: string | null): string { - let result = '' + let result = ""; this._categories.forEach((value, key) => { // == is intended here if (emoji == value) { // @ts-ignore - result = key - return false + result = key; + return false; } - }) + }); - return result + return result; } public setCategorySettings(category: ICategorySetting[]): WOKCommands { for (let { emoji, name, hidden, customEmoji } of category) { - if (emoji.startsWith('<:') && emoji.endsWith('>')) { - customEmoji = true - emoji = emoji.split(':')[2] - emoji = emoji.substring(0, emoji.length - 1) + if (emoji.startsWith("<:") && emoji.endsWith(">")) { + customEmoji = true; + emoji = emoji.split(":")[2]; + emoji = emoji.substring(0, emoji.length - 1); } - let targetEmoji: string | GuildEmoji | undefined = emoji + let targetEmoji: string | GuildEmoji | undefined = emoji; if (customEmoji) { - targetEmoji = this._client.emojis.cache.get(emoji) + targetEmoji = this._client.emojis.cache.get(emoji); } if (this.isEmojiUsed(targetEmoji)) { console.warn( `WOKCommands > The emoji "${targetEmoji}" for category "${name}" is already used.` - ) + ); } - this._categories.set(name, targetEmoji || this.categories.get(name) || '') + this._categories.set( + name, + targetEmoji || this.categories.get(name) || "" + ); if (hidden) { - this._hiddenCategories.push(name) + this._hiddenCategories.push(name); } } - return this + return this; } private isEmojiUsed(emoji: string | GuildEmoji | undefined): boolean { if (!emoji) { - return false + return false; } - let isUsed = false + let isUsed = false; this._categories.forEach((value) => { if (value === emoji) { - isUsed = true + isUsed = true; } - }) + }); - return isUsed + return isUsed; } public get commandHandler(): CommandHandler { - return this._commandHandler! + return this._commandHandler!; } public get mongoConnection(): Connection | null { - return this._mongoConnection + return this._mongoConnection; } public isDBConnected(): boolean { - const connection = this.mongoConnection - return !!(connection && connection.readyState === 1) + const connection = this.mongoConnection; + return !!(connection && connection.readyState === 1); } public setTagPeople(tagPeople: boolean): WOKCommands { - this._tagPeople = tagPeople - return this + this._tagPeople = tagPeople; + return this; } public get tagPeople(): boolean { - return this._tagPeople + return this._tagPeople; } public get showWarns(): boolean { - return this._showWarns + return this._showWarns; } public get delErrMsgCooldown(): number { - return this._delErrMsgCooldown + return this._delErrMsgCooldown; } public get ignoreBots(): boolean { - return this._ignoreBots + return this._ignoreBots; } public get botOwner(): string[] { - return this._botOwner + return this._botOwner; } public setBotOwner(botOwner: string | string[]): WOKCommands { console.log( - 'WOKCommands > setBotOwner() is deprecated. Please specify your bot owners in the object constructor instead. See https://docs.wornoffkeys.com/setup-and-options-object' - ) + "WOKCommands > setBotOwner() is deprecated. Please specify your bot owners in the object constructor instead. See https://docs.wornoffkeys.com/setup-and-options-object" + ); - if (typeof botOwner === 'string') { - botOwner = [botOwner] + if (typeof botOwner === "string") { + botOwner = [botOwner]; } - this._botOwner = botOwner - return this + this._botOwner = botOwner; + return this; } public get testServers(): string[] { - return this._testServers + return this._testServers; } public get defaultLanguage(): string { - return this._defaultLanguage + return this._defaultLanguage; } public setDefaultLanguage(defaultLanguage: string): WOKCommands { - this._defaultLanguage = defaultLanguage - return this + this._defaultLanguage = defaultLanguage; + return this; } public get ephemeral(): boolean { - return this._ephemeral + return this._ephemeral; } public get debug(): boolean { - return this._debug + return this._debug; } public get messageHandler(): MessageHandler { - return this._messageHandler! + return this._messageHandler!; } public get slashCommands(): SlashCommands { - return this._slashCommand! + return this._slashCommand!; } } -module.exports = WOKCommands +module.exports = WOKCommands; +module.exports.default = WOKCommands; diff --git a/src/message-handler.ts b/src/message-handler.ts index 7fc7d75..f90aa3b 100644 --- a/src/message-handler.ts +++ b/src/message-handler.ts @@ -1,66 +1,68 @@ -import { Guild } from 'discord.js' +import { Guild } from "discord.js"; -import languageSchema from './models/languages' -import WOKCommands from '.' -import Events from './enums/Events' -const defualtMessages = require('../messages.json') +import languageSchema from "./models/languages"; +import WOKCommands from "."; +import Events from "./enums/Events"; +const defualtMessages = require("../messages.json"); export default class MessageHandler { - private _instance: WOKCommands - private _guildLanguages: Map = new Map() // - private _languages: string[] = [] + private _instance: WOKCommands; + private _guildLanguages: Map = new Map(); // + private _languages: string[] = []; private _messages: { [key: string]: { - [key: string]: any - } - } = {} + [key: string]: any; + }; + } = {}; constructor(instance: WOKCommands, messagePath: string) { - this._instance = instance - ;(async () => { - this._messages = messagePath ? await import(messagePath) : defualtMessages + this._instance = instance; + (async () => { + this._messages = messagePath + ? await import(messagePath) + : defualtMessages; for (const messageId of Object.keys(this._messages)) { for (const language of Object.keys(this._messages[messageId])) { - this._languages.push(language.toLowerCase()) + this._languages.push(language.toLowerCase()); } } if (!this._languages.includes(instance.defaultLanguage)) { throw new Error( `The current default language defined is not supported.` - ) + ); } if (instance.isDBConnected()) { - const results = await languageSchema.find() + const results = await languageSchema.find(); // @ts-ignore for (const { _id: guildId, language } of results) { - this._guildLanguages.set(guildId, language) + this._guildLanguages.set(guildId, language); } } - })() + })(); } public languages(): string[] { - return this._languages + return this._languages; } public async setLanguage(guild: Guild | null, language: string) { if (guild) { - this._guildLanguages.set(guild.id, language) + this._guildLanguages.set(guild.id, language); } } public getLanguage(guild: Guild | null): string { if (guild) { - const result = this._guildLanguages.get(guild.id) + const result = this._guildLanguages.get(guild.id); if (result) { - return result + return result; } } - return this._instance.defaultLanguage + return this._instance.defaultLanguage; } get( @@ -68,24 +70,24 @@ export default class MessageHandler { messageId: string, args: { [key: string]: string } = {} ): string { - const language = this.getLanguage(guild) + const language = this.getLanguage(guild); - const translations = this._messages[messageId] + const translations = this._messages[messageId]; if (!translations) { console.error( `WOKCommands > Could not find the correct message to send for "${messageId}"` - ) - return 'Could not find the correct message to send. Please report this to the bot developer.' + ); + return "Could not find the correct message to send. Please report this to the bot developer."; } - let result = translations[language] + let result = translations[language]; for (const key of Object.keys(args)) { - const expression = new RegExp(`{${key}}`, 'g') - result = result.replace(expression, args[key]) + const expression = new RegExp(`{${key}}`, "g"); + result = result.replace(expression, args[key]); } - return result + return result; } getEmbed( @@ -94,31 +96,31 @@ export default class MessageHandler { itemId: string, args: { [key: string]: string } = {} ): string { - const language = this.getLanguage(guild) + const language = this.getLanguage(guild); - const items = this._messages[embedId] + const items = this._messages[embedId]; if (!items) { console.error( `WOKCommands > Could not find the correct item to send for "${embedId}" -> "${itemId}"` - ) - return 'Could not find the correct message to send. Please report this to the bot developer.' + ); + return "Could not find the correct message to send. Please report this to the bot developer."; } - const translations = items[itemId] + const translations = items[itemId]; if (!translations) { console.error( `WOKCommands > Could not find the correct message to send for "${embedId}"` - ) - return 'Could not find the correct message to send. Please report this to the bot developer.' + ); + return "Could not find the correct message to send. Please report this to the bot developer."; } - let result = translations[language] + let result = translations[language]; for (const key of Object.keys(args)) { - const expression = new RegExp(`{${key}}`, 'g') - result = result.replace(expression, args[key]) + const expression = new RegExp(`{${key}}`, "g"); + result = result.replace(expression, args[key]); } - return result + return result; } } diff --git a/src/models/channel-commands.ts b/src/models/channel-commands.ts index 8882c4d..4656690 100644 --- a/src/models/channel-commands.ts +++ b/src/models/channel-commands.ts @@ -1,9 +1,9 @@ -import mongoose, { Schema } from 'mongoose' +import mongoose, { Schema } from "mongoose"; const reqString = { type: String, required: true, -} +}; const schema = new Schema({ guildId: reqString, @@ -12,8 +12,8 @@ const schema = new Schema({ type: [String], required: true, }, -}) +}); -const name = 'wokcommands-channel-commands' +const name = "wokcommands-channel-commands"; -export = mongoose.models[name] || mongoose.model(name, schema, name) +export = mongoose.models[name] || mongoose.model(name, schema, name); diff --git a/src/models/cooldown.ts b/src/models/cooldown.ts index 6cd6e75..ce793f5 100644 --- a/src/models/cooldown.ts +++ b/src/models/cooldown.ts @@ -1,9 +1,9 @@ -import mongoose, { Schema } from 'mongoose' +import mongoose, { Schema } from "mongoose"; const reqString = { type: String, required: true, -} +}; const schema = new Schema({ // Command-GuildID or Command-GuildID-UserID @@ -14,8 +14,8 @@ const schema = new Schema({ type: Number, required: true, }, -}) +}); -const name = 'wokcommands-cooldowns' +const name = "wokcommands-cooldowns"; -export = mongoose.models[name] || mongoose.model(name, schema, name) +export = mongoose.models[name] || mongoose.model(name, schema, name); diff --git a/src/models/disabled-commands.ts b/src/models/disabled-commands.ts index 3ca3245..2eed6e2 100644 --- a/src/models/disabled-commands.ts +++ b/src/models/disabled-commands.ts @@ -1,15 +1,15 @@ -import mongoose, { Schema } from 'mongoose' +import mongoose, { Schema } from "mongoose"; const reqString = { type: String, required: true, -} +}; const schema = new Schema({ guildId: reqString, command: reqString, -}) +}); -const name = 'wokcommands-disabled-commands' +const name = "wokcommands-disabled-commands"; -export = mongoose.models[name] || mongoose.model(name, schema, name) +export = mongoose.models[name] || mongoose.model(name, schema, name); diff --git a/src/models/languages.ts b/src/models/languages.ts index 1ea0693..8a6891d 100644 --- a/src/models/languages.ts +++ b/src/models/languages.ts @@ -1,16 +1,16 @@ -import mongoose, { Schema } from 'mongoose' +import mongoose, { Schema } from "mongoose"; const reqString = { type: String, required: true, -} +}; const schema = new Schema({ // GuildID _id: reqString, language: reqString, -}) +}); -const name = 'wokcommands-languages' +const name = "wokcommands-languages"; -export = mongoose.models[name] || mongoose.model(name, schema, name) +export = mongoose.models[name] || mongoose.model(name, schema, name); diff --git a/src/models/prefixes.ts b/src/models/prefixes.ts index ec1744d..718875b 100644 --- a/src/models/prefixes.ts +++ b/src/models/prefixes.ts @@ -1,16 +1,16 @@ -import mongoose, { Schema } from 'mongoose' +import mongoose, { Schema } from "mongoose"; const reqString = { type: String, required: true, -} +}; const schema = new Schema({ // Guild ID _id: reqString, prefix: reqString, -}) +}); -const name = 'wokcommands-prefixes' +const name = "wokcommands-prefixes"; -export = mongoose.models[name] || mongoose.model(name, schema, name) +export = mongoose.models[name] || mongoose.model(name, schema, name); diff --git a/src/models/required-roles.ts b/src/models/required-roles.ts index 2ef433e..b37c603 100644 --- a/src/models/required-roles.ts +++ b/src/models/required-roles.ts @@ -1,9 +1,9 @@ -import mongoose, { Schema } from 'mongoose' +import mongoose, { Schema } from "mongoose"; const reqString = { type: String, required: true, -} +}; const schema = new Schema({ guildId: reqString, @@ -12,8 +12,8 @@ const schema = new Schema({ type: [String], required: true, }, -}) +}); -const name = 'wokcommands-required-roles' +const name = "wokcommands-required-roles"; -export = mongoose.models[name] || mongoose.model(name, schema, name) +export = mongoose.models[name] || mongoose.model(name, schema, name); diff --git a/src/mongo.ts b/src/mongo.ts index 16ca8bc..6d02441 100644 --- a/src/mongo.ts +++ b/src/mongo.ts @@ -1,15 +1,15 @@ -import mongoose, { Connection } from 'mongoose' -import WOKCommands from '.' -import Events from './enums/Events' +import mongoose, { Connection } from "mongoose"; +import WOKCommands from "."; +import Events from "./enums/Events"; const results: { - [name: number]: string + [name: number]: string; } = { - 0: 'Disconnected', - 1: 'Connected', - 2: 'Connecting', - 3: 'Disconnecting', -} + 0: "Disconnected", + 1: "Connected", + 2: "Connecting", + 3: "Disconnecting", +}; export default async ( mongoPath: string, @@ -19,14 +19,14 @@ export default async ( const options = { keepAlive: true, ...dbOptions, - } - await mongoose.connect(mongoPath, options) + }; + await mongoose.connect(mongoPath, options); - const { connection } = mongoose - const state = results[connection.readyState] || 'Unknown' - instance.emit(Events.DATABASE_CONNECTED, connection, state) -} + const { connection } = mongoose; + const state = results[connection.readyState] || "Unknown"; + instance.emit(Events.DATABASE_CONNECTED, connection, state); +}; export const getMongoConnection = (): Connection => { - return mongoose.connection -} + return mongoose.connection; +}; diff --git a/src/permissions.ts b/src/permissions.ts index 01cbc3a..17a395a 100644 --- a/src/permissions.ts +++ b/src/permissions.ts @@ -1,38 +1,38 @@ const permissionList = [ - 'CREATE_INSTANT_INVITE', - 'KICK_MEMBERS', - 'BAN_MEMBERS', - 'ADMINISTRATOR', - 'MANAGE_CHANNELS', - 'MANAGE_GUILD', - 'ADD_REACTIONS', - 'VIEW_AUDIT_LOG', - 'PRIORITY_SPEAKER', - 'STREAM', - 'VIEW_CHANNEL', - 'SEND_MESSAGES', - 'SEND_TTS_MESSAGES', - 'MANAGE_MESSAGES', - 'EMBED_LINKS', - 'ATTACH_FILES', - 'READ_MESSAGE_HISTORY', - 'MENTION_EVERYONE', - 'USE_EXTERNAL_EMOJIS', - 'VIEW_GUILD_INSIGHTS', - 'CONNECT', - 'SPEAK', - 'MUTE_MEMBERS', - 'DEAFEN_MEMBERS', - 'MOVE_MEMBERS', - 'USE_VAD', - 'CHANGE_NICKNAME', - 'MANAGE_NICKNAMES', - 'MANAGE_ROLES', - 'MANAGE_WEBHOOKS', - 'MANAGE_EMOJIS', -] + "CREATE_INSTANT_INVITE", + "KICK_MEMBERS", + "BAN_MEMBERS", + "ADMINISTRATOR", + "MANAGE_CHANNELS", + "MANAGE_GUILD", + "ADD_REACTIONS", + "VIEW_AUDIT_LOG", + "PRIORITY_SPEAKER", + "STREAM", + "VIEW_CHANNEL", + "SEND_MESSAGES", + "SEND_TTS_MESSAGES", + "MANAGE_MESSAGES", + "EMBED_LINKS", + "ATTACH_FILES", + "READ_MESSAGE_HISTORY", + "MENTION_EVERYONE", + "USE_EXTERNAL_EMOJIS", + "VIEW_GUILD_INSIGHTS", + "CONNECT", + "SPEAK", + "MUTE_MEMBERS", + "DEAFEN_MEMBERS", + "MOVE_MEMBERS", + "USE_VAD", + "CHANGE_NICKNAME", + "MANAGE_NICKNAMES", + "MANAGE_ROLES", + "MANAGE_WEBHOOKS", + "MANAGE_EMOJIS", +]; -export { permissionList } +export { permissionList }; -type Permissions = typeof permissionList -export default Permissions +type Permissions = typeof permissionList; +export default Permissions; diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..ecec209 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,148 @@ +import type { + ApplicationCommandOptionData, + Client, + CommandInteraction, + Guild, + GuildMember, + Message, + PermissionString, + TextChannel, + User, +} from "discord.js/typings/index.js"; +import type WOKCommands from "."; + +interface OptionsWithS { + commandDir?: never; + featureDir?: never; + + commandsDir: string; + featuresDir?: string; + messagesPath?: string; + mongoUri?: string; + showWarns?: boolean; + delErrMsgCooldown?: number; + defaultLanguage?: string; + ignoreBots?: boolean; + dbOptions?: {}; + testServers?: string | string[]; + botOwners?: string | string[]; + disabledDefaultCommands?: string | string[]; + typeScript?: boolean; + ephemeral?: boolean; + debug?: boolean; +} + +interface OptionsWithoutS { + commandsDir?: never; + featuresDir?: never; + + commandDir: string; + featureDir?: string; + messagesPath?: string; + mongoUri?: string; + showWarns?: boolean; + delErrMsgCooldown?: number; + defaultLanguage?: string; + ignoreBots?: boolean; + dbOptions?: {}; + testServers?: string | string[]; + botOwners?: string | string[]; + disabledDefaultCommands?: string | string[]; + typeScript?: boolean; + ephemeral?: boolean; + debug?: boolean; +} + +export type Options = OptionsWithS | OptionsWithoutS; + +export interface ICallbackObject { + channel: TextChannel; + message: Message; + args: string[]; + text: string; + client: Client; + prefix: string; + instance: WOKCommands; + interaction: CommandInteraction; + options: ApplicationCommandOptionData[]; + user: User; + member: GuildMember; + guild: Guild | null; + cancelCoolDown(): any; +} + +export interface IErrorObject { + error: CommandErrors; + command: string; + message: Message; + info: object; +} + +export type optionTypes = + | "SUB_COMMAND" + | "SUB_COMMAND_GROUP" + | "STRING" + | "INTEGER" + | "BOOLEAN" + | "USER" + | "CHANNEL" + | "ROLE" + | "MENTIONABLE" + | "NUMBER"; + +export interface ICommand { + names?: string[] | string; + aliases?: string[] | string; + category: string; + description: string; + callback?(obj: ICallbackObject): any; + error?(obj: IErrorObject): any; + minArgs?: number; + maxArgs?: number; + syntaxError?: { [key: string]: string }; + expectedArgs?: string; + expectedArgsTypes?: optionTypes[]; + syntax?: string; + requiredPermissions?: PermissionString[]; + permissions?: PermissionString[]; + cooldown?: string; + globalCooldown?: string; + ownerOnly?: boolean; + hidden?: boolean; + guildOnly?: boolean; + testOnly?: boolean; + slash?: boolean | "both"; + options?: ApplicationCommandOptionData[]; + requireRoles?: boolean; +} + +export interface ISlashCommand { + id: string; + application_id: string; + name: string; + description: string; + version: string; + default_permission: boolean; +} + +export interface ICategorySetting { + name: string; + emoji: string; + hidden?: boolean; + customEmoji?: boolean; +} + +export enum CommandErrors { + EXCEPTION = "EXCEPTION", + COOLDOWN = "COOLDOWN", + INVALID_ARGUMENTS = "INVALID ARGUMENTS", + MISSING_PERMISSIONS = "MISSING PERMISSIONS", + MISSING_ROLES = "MISSING ROLES", + COMMAND_DISABLED = "COMMAND DISABLED", +} + +export enum Events { + DATABASE_CONNECTED = "databaseConnected", + LANGUAGE_NOT_SUPPORTED = "languageNotSupported", + COMMAND_EXCEPTION = "commandException", +} diff --git a/tsconfig.json b/tsconfig.json index d9a53d7..c221fd8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,10 +4,12 @@ "target": "esnext", "module": "commonjs", "outDir": "./dist", - "rootDir": "./src", + "declaration": true, "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true - } + }, + "exclude": ["node_modules", "dist"], + "include": ["src/**/*.ts"] } diff --git a/typings.d.ts b/typings.d.ts deleted file mode 100644 index 3bff7e1..0000000 --- a/typings.d.ts +++ /dev/null @@ -1,213 +0,0 @@ -import { - ApplicationCommandOptionData, - Client, - CommandInteraction, - Guild, - GuildMember, - Interaction, - Message, - PermissionString, - TextChannel, - User, -} from 'discord.js' -import { EventEmitter } from 'events' -import WOKCommands from './src' - -export default class WOKCommands extends EventEmitter { - private _client: Client - private _defaultPrefix: string - private _commandsDir: string - private _featuresDir: string - private _mongo: string | undefined - private _mongoConnection: Connection | null - private _displayName: string - private _prefixes: { [name: string]: string } - private _categories: Map - private _hiddenCategories: string[] - private _color: string - private _commandHandler: CommandHandler - private _featureHandler: FeatureHandler | null - private _tagPeople: boolean - private _showWarns: boolean - private _delErrMsgCooldown: number - private _ignoreBots: boolean - private _botOwner: string[] - private _testServers: string[] - private _defaultLanguage: string - private _messageHandler: MessageHandler - private _slashCommand: SlashCommands - - constructor(client: Client, options?: Options) - - public get mongoPath(): string - public setMongoPath(mongoPath: string | undefined): WOKCommands - public get client(): Client - public get displayName(): string - public setDisplayName(displayName: string): WOKCommands - public get prefixes(): { [name: string]: string } - public get defaultPrefix(): string - public setDefaultPrefix(defaultPrefix: string): WOKCommands - public getPrefix(guild: Guild | null): string - public setPrefix(guild: Guild | null, prefix: string): WOKCommands - public get categories(): Map - public get hiddenCategories(): string[] - public get color(): string - public setColor(color: string): WOKCommands - public getEmoji(category: string): string - public getCategory(emoji: string): string - public setCategorySettings( - category: string | Array>, - emoji?: string - ): WOKCommands - public isEmojiUsed(emoji: string): boolean - public get commandHandler(): CommandHandler - public get mongoConnection(): Connection | null - public isDBConnected(): boolean - public setTagPeople(tagPeople: boolean): WOKCommands - public get tagPeople(): boolean - public get showWarns(): boolean - public get delErrMsgCooldown(): number - public get ignoreBots(): boolean - public get botOwner(): string[] - public setBotOwner(botOwner: string | string[]): WOKCommands - public get testServers(): string[] - public get defaultLanguage(): string - public setDefaultLanguage(defaultLanguage: string): WOKCommands - public get messageHandler(): MessageHandler - public get slashCommands(): SlashCommands -} - -interface OptionsWithS { - commandDir?: never - featureDir?: never - - commandsDir: string - featuresDir?: string - messagesPath?: string - mongoUri?: string - showWarns?: boolean - delErrMsgCooldown?: number - defaultLanguage?: string - ignoreBots?: boolean - dbOptions?: {} - testServers?: string | string[] - botOwners?: string | string[] - disabledDefaultCommands?: string | string[] - typeScript?: boolean - ephemeral?: boolean - debug?: boolean -} - -interface OptionsWithoutS { - commandsDir?: never - featuresDir?: never - - commandDir: string - featureDir?: string - messagesPath?: string - mongoUri?: string - showWarns?: boolean - delErrMsgCooldown?: number - defaultLanguage?: string - ignoreBots?: boolean - dbOptions?: {} - testServers?: string | string[] - botOwners?: string | string[] - disabledDefaultCommands?: string | string[] - typeScript?: boolean - ephemeral?: boolean - debug?: boolean -} -export type Options = OptionsWithS | OptionsWithoutS - -export interface ICallbackObject { - channel: TextChannel - message: Message - args: string[] - text: string - client: Client - prefix: string - instance: WOKCommands - interaction: CommandInteraction - options: ApplicationCommandOptionData[] - user: User - member: GuildMember - guild: Guild | null - cancelCoolDown(): any -} - -export interface IErrorObject { - error: CommandErrors - command: string - message: Message - info: object -} - -export type optionTypes = - | 'SUB_COMMAND' - | 'SUB_COMMAND_GROUP' - | 'STRING' - | 'INTEGER' - | 'BOOLEAN' - | 'USER' - | 'CHANNEL' - | 'ROLE' - | 'MENTIONABLE' - | 'NUMBER' - -export interface ICommand { - names?: string[] | string - aliases?: string[] | string - category: string - description: string - callback?(obj: ICallbackObject): any - error?(obj: IErrorObject): any - minArgs?: number - maxArgs?: number - syntaxError?: { [key: string]: string } - expectedArgs?: string - expectedArgsTypes?: optionTypes[] - syntax?: string - requiredPermissions?: PermissionString[] - permissions?: PermissionString[] - cooldown?: string - globalCooldown?: string - ownerOnly?: boolean - hidden?: boolean - guildOnly?: boolean - testOnly?: boolean - slash?: boolean | 'both' - options?: ApplicationCommandOptionData[] - requireRoles?: boolean -} - -export interface ISlashCommand { - id: string - application_id: string - name: string - description: string - version: string - default_permission: boolean -} - -export interface ICategorySetting { - name: string - emoji: string - hidden?: boolean - customEmoji?: boolean -} - -export enum CommandErrors { - EXCEPTION = 'EXCEPTION', - COOLDOWN = 'COOLDOWN', - INVALID_ARGUMENTS = 'INVALID ARGUMENTS', - MISSING_PERMISSIONS = 'MISSING PERMISSIONS', - MISSING_ROLES = 'MISSING ROLES', - COMMAND_DISABLED = 'COMMAND DISABLED', -} - -export enum Events { - DATABASE_CONNECTED = 'databaseConnected', - LANGUAGE_NOT_SUPPORTED = 'languageNotSupported', - COMMAND_EXCEPTION = 'commandException', -}