From 6c1338558f57ef4c38fdc5bfb2948e838faaa38c Mon Sep 17 00:00:00 2001 From: nolan Date: Mon, 27 Jul 2020 20:00:24 -0700 Subject: [PATCH] enable/disable commands --- .../en_us/commands/en_us_administration.lang | 53 ++++++- language/languages/en_us/en_us_general.lang | 12 +- structure/client/DiscordClient.js | 1 + structure/client/Resolver.js | 12 ++ .../commands/administration/Disable.js | 131 ++++++++++++++++++ .../commands/administration/Enable.js | 107 ++++++++++++++ .../{utility => administration}/Settings.js | 2 +- .../components/commands/developer/Evaluate.js | 3 +- .../client/components/inhibitors/Disabled.js | 6 +- .../components/observers/MessageCache.js | 31 ++--- .../administration/DisabledCommands.js | 62 +++++++++ .../PermissionType.js | 2 +- .../settings/moderation/Protection.js | 2 +- .../settings/utility/IgnoreChannels.js | 22 +-- structure/extensions/Guild.js | 19 ++- structure/extensions/Message.js | 4 +- structure/interfaces/Argument.js | 1 + structure/interfaces/Command.js | 5 - util/emojis.json | 2 +- 19 files changed, 426 insertions(+), 51 deletions(-) create mode 100644 structure/client/components/commands/administration/Disable.js create mode 100644 structure/client/components/commands/administration/Enable.js rename structure/client/components/commands/{utility => administration}/Settings.js (99%) create mode 100644 structure/client/components/settings/administration/DisabledCommands.js rename structure/client/components/settings/{utility => administration}/PermissionType.js (97%) diff --git a/language/languages/en_us/commands/en_us_administration.lang b/language/languages/en_us/commands/en_us_administration.lang index 4668517..f0e05c3 100644 --- a/language/languages/en_us/commands/en_us_administration.lang +++ b/language/languages/en_us/commands/en_us_administration.lang @@ -23,7 +23,7 @@ in channel{plural} {channels} [C_REVOKE_DESCRIPTION] Revoke permissions granted to roles or users. -NOTE: If a user left the guild, you must use the ID to revoke the permissions. +NOTE: If a user left the server, you must use the ID to revoke the permissions. [C_REVOKE_MISSINGRESOLVEABLES] Unable to find any roles or users, view `{prefix}cmd revoke` for more information. @@ -56,7 +56,7 @@ switch({user}) { } [C_PERMISSIONS_SHOWDESCRIPTION] -An overview of all {resolve}'s permissions in the guild. If you would like to see an in-depth view of the role or user's permissions, use `{prefix}perms [user|role]`. +An overview of all {resolve}'s permissions in the server. If you would like to see an in-depth view of the role or user's permissions, use `{prefix}perms [user|role]`. [C_PERMISSIONS_MAXFIELDS] :warning: **You have met the max amount of fields and you will need to use `{prefix}perms --json` to view them.** :warning: @@ -81,3 +81,52 @@ Channel-specific permissions are listed below. [C_PERMISSIONS_PERMISSIONSNOTFOUND] Found {type} **{resolveable}** but {they}had no permissions. + +//Disable Command +[C_DISABLE_DESCRIPTION] +Disable commands in your server to prevent usage. + +[C_DISABLE_LIST] +The command{plural} currently disabled in your server are: {commands} + +[C_DISABLE_LISTFAIL] +There are no disabled commands in your server. + +[C_DISABLE_MISSINGCOMMANDS] +You must provide commands to disable. + +[C_DISABLE_SUCCESS] +Successfully **disabled** command{plural} {commands} in your server. + +[C_DISABLE_FAIL] +Failed to disable command{plural} {commands}. You are unable to disable the **command:enable** and **command:disable** commands. + +[C_DISABLE_WARNING] +You disabled a command inside of the **Administration** module. It is dangerous to do so, as it may disable configurability of your server. Note you are unable to disable the `command:enable` and `command:disable` commands. + +[C_DISABLE_SUCCESSGLOBAL] +Successfully **disabled** command{plural} {commands} globally. **`[{amount}/{total}]`** +These changes will be reverted if a shard restarts; edit the file{plural} for sustainability. + +[C_DISABLE_FAILGLOBAL] +Failed to globally disable command{plural} {commands}. **`[0/{total}]`** + +//Enable Command +[C_ENABLE_DESCRIPTION] +Enable commands in your server. + +[C_ENABLE_MISSINGCOMMANDS] +You must provide commands to enable. + +[C_ENABLE_SUCCESS] +Successfully **enabled** command{plural} {commands} in your server. + +[C_ENABLE_FAIL] +Failed to enable command{plural} {commands}, they likely were not disabled. + +[C_ENABLE_SUCCESSGLOBAL] +Successfully **enabled** command{plural} {commands} globally. **`[{amount}/{total}]`** +These changes will be reverted if a shard restarts; edit the file{plural} for sustainability. + +[C_ENABLE_FAILGLOBAL] +Failed to globally enable command{plural} {commands}. **`[0/{total}]`** \ No newline at end of file diff --git a/language/languages/en_us/en_us_general.lang b/language/languages/en_us/en_us_general.lang index 6400d56..e738cab 100644 --- a/language/languages/en_us/en_us_general.lang +++ b/language/languages/en_us/en_us_general.lang @@ -151,7 +151,17 @@ The command **{command}** requires the bot to have permissions to use. *Missing: {missing}.* [I_DISABLED_ERROR] -The command **{command}** is currently {globally}disabled. +The command **{command}** is disabled {modifier}. + +[I_DISABLED_ERRORMODIFIER] +switch("{globally}") { + case true: + 'globally'; + break; + case false: + 'in this server'; + break; +} [I_GUILDONLY_ERROR] The command **{command}** can only be run in servers. diff --git a/structure/client/DiscordClient.js b/structure/client/DiscordClient.js index 4d842c6..0bf8aa6 100644 --- a/structure/client/DiscordClient.js +++ b/structure/client/DiscordClient.js @@ -85,6 +85,7 @@ class DiscordClient extends Client { } this._defaultConfig = def; return def; + } } diff --git a/structure/client/Resolver.js b/structure/client/Resolver.js index b21f778..ecc1891 100644 --- a/structure/client/Resolver.js +++ b/structure/client/Resolver.js @@ -15,6 +15,18 @@ class Resolver { * @returns * @memberof Resolver */ + resolveComponent(arg, strict = true, type) { + + const string = arg.toLowerCase(); + + const components = this.client.registry.components + .filter((c) => c.type === type) + .filter(strict ? filterExact(string) : filterInexact(string)); //eslint-disable-line no-use-before-define + + return components.first(); + + } + components(str = '', type, exact = true) { const string = str.toLowerCase(); diff --git a/structure/client/components/commands/administration/Disable.js b/structure/client/components/commands/administration/Disable.js new file mode 100644 index 0000000..d98b038 --- /dev/null +++ b/structure/client/components/commands/administration/Disable.js @@ -0,0 +1,131 @@ +const { Command } = require('../../../../interfaces/'); +const { Emojis } = require('../../../../../util/'); + +class DisableCommand extends Command { + + constructor(client) { + + super(client, { + name: 'disable', + module: 'administration', + usage: "", + examples: [ + "snipe", + "command:snipe command:note" + ], + memberPermissions: ['ADMINISTRATOR', 'MANAGE_GUILD'], + showUsage: true, + guildOnly: true, + arguments: [ + { + name: 'global', + type: 'BOOLEAN', + types: [ + 'FLAG' + ], + default: true, + archivable: false + } + ] + }); + + } + + async execute(message, { params, args }) { + + if(params.join(' ').toLowerCase() === 'list') { + const disabled = message.guild._settings.disabledCommands; + if(disabled.length > 0) { + message.respond(message.format('C_DISABLE_LIST', { + plural: disabled.length === 1 ? '' : 's', + commands: disabled.map((d) => `\`${d}\``).join(', ') + }), { emoji: 'success' }); + } else { + message.respond(message.format('C_DISABLE_LISTFAIL'), { emoji: 'success' }); + } + return undefined; + } + + const { parsed } = await this.client.resolver.infinite(params, [ + this.client.resolver.resolveComponent.bind(this.client.resolver) + ], true, 'command'); + + if(parsed.length === 0) { + return message.respond(message.format('C_DISABLE_MISSINGCOMMANDS'), { + emoji: 'failure' + }); + } + + if(args.global) { + if(!message.author.developer) return message.respond(message.format('C_DISABLE_PERMISSIONSREQUIRED'), { + emoji: 'failure' + }); + + const results = await this.client.shard.broadcastEval(`this.registry.components + .filter((c) => [${parsed.map((p) => `"${p.resolveable}"`).join(', ')}].includes(c.resolveable)) + .map((c) => c.disable())`); + + const succeeded = results.filter((r) => r.some((r) => !r.error)); + if(succeeded.length > 0) { + return message.respond(message.format('C_DISABLE_SUCCESSGLOBAL', { + plural: parsed.length === 1 ? '' : 's', + commands: parsed.map((p) => `\`${p.resolveable}\``).join(', '), + amount: succeeded.length, + total: results.length + }), { emoji: 'success' }); + } + + return message.respond(message.format('C_DISABLE_FAILGLOBAL', { + plural: parsed.length === 1 ? '' : 's', + commands: parsed.map((p) => `\`${p.resolveable}\``).join(', '), + total: results.length + }), { emoji: 'failure' }); + + } + + const { disabledCommands } = message.guild._settings; + + let warning = false, + commands = []; //eslint-disable-line prefer-const + for(const command of parsed) { + if(command.module.id === 'administration') { + if(['command:enable', 'command:disable'].includes(command.resolveable)) continue; + warning = true; + } + commands.push(command.resolveable); + if(disabledCommands.includes(command.resolveable)) continue; + else disabledCommands.push(command.resolveable); + } + + await message.guild._updateSettings({ + disabledCommands + }); + + if(commands.length === 0) { + message.respond(message.format('C_DISABLE_FAIL', { + plural: parsed.length === 1 ? '' : 's', + commands: parsed.map((p) => `\`${p.resolveable}\``).join(', ') + }), { emoji: 'failure' }); + } else { + message.respond(message.format('C_DISABLE_SUCCESS', { + plural: parsed.length === 1 ? '' : 's', + commands: parsed.map((p) => `\`${p.resolveable}\``).join(', ') + }), { + emoji: 'success', + embed: warning ? { + author: { + name: `${Emojis.warning} Warning` + }, + description: message.format('C_DISABLE_WARNING'), + color: 0xffe15c + } : null + }); + } + + return undefined; + + } + +} + +module.exports = DisableCommand; \ No newline at end of file diff --git a/structure/client/components/commands/administration/Enable.js b/structure/client/components/commands/administration/Enable.js new file mode 100644 index 0000000..b58389a --- /dev/null +++ b/structure/client/components/commands/administration/Enable.js @@ -0,0 +1,107 @@ +const { Command } = require('../../../../interfaces/'); + +class DisableCommand extends Command { + + constructor(client) { + + super(client, { + name: 'enable', + module: 'administration', + usage: "", + examples: [ + "strike", + "command:strike command:note" + ], + memberPermissions: ['ADMINISTRATOR', 'MANAGE_GUILD'], + showUsage: true, + guildOnly: true, + arguments: [ + { + name: 'global', + type: 'BOOLEAN', + types: [ + 'FLAG' + ], + default: true, + archivable: false + } + ] + }); + + } + + async execute(message, { params, args }) { + + const { parsed } = await this.client.resolver.infinite(params, [ + this.client.resolver.resolveComponent.bind(this.client.resolver) + ], true, 'command'); + + if(parsed.length === 0) { + return message.respond(message.format('C_ENABLE_MISSINGCOMMANDS'), { + emoji: 'failure' + }); + } + + if(args.global) { + if(!message.author.developer) return message.respond(message.format('C_ENABLE_PERMISSIONSREQUIRED'), { + emoji: 'failure' + }); + + const results = await this.client.shard.broadcastEval(`this.registry.components + .filter((c) => [${parsed.map((p) => `"${p.resolveable}"`).join(', ')}].includes(c.resolveable)) + .map((c) => c.enable())`); + + const succeeded = results.filter((r) => r.some((r) => !r.error)); + if(succeeded.length > 0) { + return message.respond(message.format('C_ENABLE_SUCCESSGLOBAL', { + plural: parsed.length === 1 ? '' : 's', + commands: parsed.map((p) => `\`${p.resolveable}\``).join(', '), + amount: succeeded.length, + total: results.length + }), { emoji: 'success' }); + } + + return message.respond(message.format('C_ENABLE_FAILGLOBAL', { + plural: parsed.length === 1 ? '' : 's', + commands: parsed.map((p) => `\`${p.resolveable}\``).join(', '), + total: results.length + }), { emoji: 'failure' }); + + } + + const { disabledCommands } = message.guild._settings; + + const removed = []; + for(const command of parsed) { + if(disabledCommands.includes(command.resolveable)) { + const index = disabledCommands.indexOf(command.resolveable); + if(index > -1) { + removed.push(command.resolveable); + disabledCommands.splice(index, 1); + } + } + } + + await message.guild._updateSettings({ + disabledCommands + }); + + if(removed.length === 0) { + message.respond(message.format('C_ENABLE_FAIL', { + plural: parsed.length === 1 ? '' : 's', + commands: parsed.map((p) => `\`${p.resolveable}\``).join(', ') + }), { emoji: 'failure' }); + } else { + message.respond(message.format('C_ENABLE_SUCCESS', { + plural: parsed.length === 1 ? '' : 's', + commands: parsed.map((p) => `\`${p.resolveable}\``).join(', ') + }), { emoji: 'success' }); + } + + return undefined; + + } + +} + +module.exports = DisableCommand; \ No newline at end of file diff --git a/structure/client/components/commands/utility/Settings.js b/structure/client/components/commands/administration/Settings.js similarity index 99% rename from structure/client/components/commands/utility/Settings.js rename to structure/client/components/commands/administration/Settings.js index 6adddd4..630d4b2 100644 --- a/structure/client/components/commands/utility/Settings.js +++ b/structure/client/components/commands/administration/Settings.js @@ -9,7 +9,7 @@ class SettingsCommand extends Command { super(client, { name: 'settings', - module: 'utility', + module: 'administration', aliases: [ 'setting', 'set' diff --git a/structure/client/components/commands/developer/Evaluate.js b/structure/client/components/commands/developer/Evaluate.js index 89cc2f4..54853f2 100644 --- a/structure/client/components/commands/developer/Evaluate.js +++ b/structure/client/components/commands/developer/Evaluate.js @@ -33,7 +33,8 @@ class Evaluate extends Command { } ], showUsage: true, - keepQuotes: true + keepQuotes: true, + guarded: true }); } diff --git a/structure/client/components/inhibitors/Disabled.js b/structure/client/components/inhibitors/Disabled.js index 5a5b177..0b876b7 100644 --- a/structure/client/components/inhibitors/Disabled.js +++ b/structure/client/components/inhibitors/Disabled.js @@ -16,7 +16,11 @@ class Disabled extends Inhibitor { execute(message, command) { - if(command.disabled) return super._fail({ globally: '' }); + if(command.disabled) return super._fail({ modifier: message.format('I_DISABLED_ERRORMODIFIER', { globally: true }, true) }); + if(message.guild._settings.disabledCommands.includes(command.resolveable)) { + return super._fail({ modifier: message.format('I_DISABLED_ERRORMODIFIER', { globally: false }, true) }); + } + return super._succeed(); } diff --git a/structure/client/components/observers/MessageCache.js b/structure/client/components/observers/MessageCache.js index c511950..710b45d 100644 --- a/structure/client/components/observers/MessageCache.js +++ b/structure/client/components/observers/MessageCache.js @@ -77,8 +77,6 @@ class MessageCache extends Observer { async _grabMessageData(message) { - const beforeTime = Date.now(); - const metadata = { guild: message.guild.id, message: message.id, @@ -122,18 +120,18 @@ class MessageCache extends Observer { }; const fsize = data.size/CONSTANTS.IMAGES.MB_DIVIDER; // File size in MB - if(fsize > CONSTANTS.IMAGES.UPLOAD_LIMIT[message.guild.premium]) { + if(fsize > CONSTANTS.IMAGES.UPLOAD_LIMIT[message.guild.premiumTier]) { metadata.attachments.push(data); - continue; //Cannot upload images larger than the guild's upload limit (Users w/ nitro can upload more than that) + continue; //Cannot upload images larger than the guild's upload limit (Users w/ nitro can upload more than that, but the bot will be unable to post them.) } const buffer = await Util.downloadAsBuffer(attachment.proxyURL || attachment.url).catch((err) => { - this.client.logger.error(`Failed to save buffer with image data: ${data}\n${err.stack || err}`); + this.client.logger.error(`Failed to download buffer for "${chalk.bold(data.name)}".\n${err.stack || err}`); return null; }); - if(buffer && fsize < 15) { //Mongodb will not save images larger than 16mb, but I'm checking for 15 just incase. - try { + if(buffer) { + if(fsize < 15) { const result = await this.client.transactionHandler.send({ provider: 'mongodb', request: { @@ -146,9 +144,9 @@ class MessageCache extends Observer { } }); data.index = result?.insertedId; - // this.client.logger.debug(`Saved file ${data.name} (${fsize.toFixed(2)}mb), took ${Date.now()-beforeTime}ms.`); - } catch (err) { - this.client.logger.error('Something went wrong with storing image to database: \n' + err.stack || err); + } else { + //Upload using GridFS, not a priority right now. + this.client.logger.error(`Temporary logging; attachment "${chalk.bold(data.name)}" exceeds 15mb.`); } } @@ -157,9 +155,7 @@ class MessageCache extends Observer { } - const afterTime = Date.now(); - - this.client.logger.debug(`${chalk.bold('[IMAGE]')} User ${message.author.tag} in guild ${message.guild.name} (#${message.channel.name}) uploaded ${message.attachments.size} attachment${message.attachments.size === 1 ? '' : 's'} (${size.toFixed(2)}mb); took ${afterTime-beforeTime}ms to save ${message.attachments.size} attachment${message.attachments.size === 1 ? '' : 's'}.`); + this.client.logger.debug(`${chalk.bold('[IMAGE]')} User ${message.author.tag} in guild ${message.guild.name} (#${message.channel.name}) uploaded ${message.attachments.size} attachment${message.attachments.size === 1 ? '' : 's'} (${size.toFixed(2)}mb).`); await this.client.transactionHandler.send({ provider: 'mongodb', request: { @@ -203,8 +199,6 @@ class MessageCache extends Observer { } }); - this.client.logger.log(`${chalk.bold('[IMAGE]')} Trashed ${deleteAttachments.length} items from the attachment database.`); - const msgIds = messages.map((m) => m._id); const deleteMessages = await this.client.transactionHandler.send({ provider: 'mongodb', @@ -216,8 +210,11 @@ class MessageCache extends Observer { } } }); - - this.client.emit(`${chalk.bold('[IMAGE]')} Trashed ${deleteMessages.length} items from the attachment database.`); + + const messageCount = deleteMessages.deletedCount; + const attachmentCount = deleteAttachments.deletedCount; + this.client.logger.info(`${chalk.bold('[IMAGE]')} Trashed ${messageCount} messages${messageCount === 1 ? '' : 's'} and ${attachmentCount} attachment${attachmentCount === 1 ? '' : 's'}.`); + } } diff --git a/structure/client/components/settings/administration/DisabledCommands.js b/structure/client/components/settings/administration/DisabledCommands.js new file mode 100644 index 0000000..06d1269 --- /dev/null +++ b/structure/client/components/settings/administration/DisabledCommands.js @@ -0,0 +1,62 @@ +const { Setting } = require('../../../../interfaces/'); + +class DisabledCommandsSetting extends Setting { + + constructor(client) { + + super(client, { + name: 'disabledCommands', + module: 'administration', + aliases: ['disabled', 'disableCommands', 'disableCommand', 'disableCmd', 'disableCmds', 'disabledCmds', 'disable'], + usage: "<+|-|list> [command..]", + resolve: 'GUILD', + default: { + disabledCommands: [ + 'command:strike' + ] + }, + examples: [ + 'list', + 'add command:strike', + 'remove command:strike' + ] + }); + + } + + async handle(message, params) { + + const parameters = params.join(' ').toLowerCase(); + + let type = null; + for(const [ key, value ] of Object.entries(Constants.Types)) { + if(value.includes(parameters)) type = key; + } + + if(!type) return { + msg: message.format('S_PERMISSIONTYPE_INVALIDTYPE'), + error: true + }; + + await message.guild._updateSettings({ [this.index]: type }); + + const description = message.format('S_PERMISSIONTYPE_DESCRIPTIONS', { type }, true); + return { + msg: `${message.format('S_PERMISSIONTYPE_SUCCESS', { type, description })}`, + error: false + }; + + } + + fields(guild) { + return [ + { + name: '》Disabled Commands', + value: `\`${guild._settings.permissionType}\`` + } + ]; + } + +} + +module.exports = DisabledCommandsSetting; \ No newline at end of file diff --git a/structure/client/components/settings/utility/PermissionType.js b/structure/client/components/settings/administration/PermissionType.js similarity index 97% rename from structure/client/components/settings/utility/PermissionType.js rename to structure/client/components/settings/administration/PermissionType.js index 7c3349d..d136fd6 100644 --- a/structure/client/components/settings/utility/PermissionType.js +++ b/structure/client/components/settings/administration/PermissionType.js @@ -14,7 +14,7 @@ class PermissionTypeSetting extends Setting { super(client, { name: 'permissionType', - module: 'utility', + module: 'administration', aliases: ['permissionTypes', 'permTypes', 'permType'], usage: "[permission-type]", resolve: 'GUILD', diff --git a/structure/client/components/settings/moderation/Protection.js b/structure/client/components/settings/moderation/Protection.js index aa52cd1..15725c4 100644 --- a/structure/client/components/settings/moderation/Protection.js +++ b/structure/client/components/settings/moderation/Protection.js @@ -111,7 +111,7 @@ class ProtectionSetting extends Setting { inline: true }, { name: '》Roles', - value: roles?.map(r => r.name).join(', ') || 'N/A', + value: roles?.map((r) => r.name).join(', ') || 'N/A', inline: false } ]; diff --git a/structure/client/components/settings/utility/IgnoreChannels.js b/structure/client/components/settings/utility/IgnoreChannels.js index 2fa91c4..78eefea 100644 --- a/structure/client/components/settings/utility/IgnoreChannels.js +++ b/structure/client/components/settings/utility/IgnoreChannels.js @@ -53,7 +53,7 @@ class IgnoreSetting extends Setting { setting.enabled = true; index = 'S_IGNORE_ADD'; - const changed = channels.filter(c => response.changed.includes(c.id)).map(c => c.name).join('`, `'); + const changed = channels.filter((c) => response.changed.includes(c.id)).map((c) => c.name).join('`, `'); langParams.changes = changed.length ? changed : 'N/A'; } else if (method === 'remove') { @@ -63,7 +63,7 @@ class IgnoreSetting extends Setting { setting.enabled = setting.channels.length && true; index = 'S_IGNORE_REMOVE'; - const changed = channels.filter(c => response.changed.includes(c.id)).map(c => c.name).join('`, `'); + const changed = channels.filter((c) => response.changed.includes(c.id)).map((c) => c.name).join('`, `'); langParams.changes = changed.length ? changed : 'N/A'; } else if (method === 'list') { @@ -71,19 +71,19 @@ class IgnoreSetting extends Setting { const roles = await resolver.resolveRoles(setting.roleBypass, false, guild); index = 'S_IGNORE_LIST'; - const ch = response.resolved ? response.resolved?.map(c => c.name).join('`, `') : ''; - const r = roles.length ? roles.map(r => r.name).join('`, `') : ''; + const ch = response.resolved ? response.resolved?.map((c) => c.name).join('`, `') : ''; + const r = roles.length ? roles.map((r) => r.name).join('`, `') : ''; langParams.channels = ch.length ? ch : 'N/A'; langParams.roles = r.length ? r : 'N/A'; } else if (method === 'set') { const channels = response.resolved; - setting.channels = channels.map(c => c.id); + setting.channels = channels.map((c) => c.id); setting.enabled = channels.length && true; index = 'S_IGNORE_SET'; - const ch = channels.map(c => c.name).join('`, `'); + const ch = channels.map((c) => c.name).join('`, `'); langParams.changes = ch.length ? ch : 'N/A'; } else if (method === 'bypass') { @@ -96,7 +96,7 @@ class IgnoreSetting extends Setting { setting.roleBypass = response.result; index = 'S_IGNORE_BYPASS_ADD'; - const changed = roles.filter(r => response.changed.includes(r.id)).map(r => r.name).join('`, `'); + const changed = roles.filter((r) => response.changed.includes(r.id)).map((r) => r.name).join('`, `'); langParams.changes = changed.length ? changed : 'N/A'; } else if (response.method === 'remove') { @@ -105,10 +105,10 @@ class IgnoreSetting extends Setting { setting.roleBypass = response.result; index = 'S_IGNORE_BYPASS_REMOVE'; - const changed = roles.filter(r => response.changed.includes(r.id)).map(r => r.name).join('`, `'); + const changed = roles.filter((r) => response.changed.includes(r.id)).map((r) => r.name).join('`, `'); langParams.changes = changed.length ? changed : 'N/A'; - } else return { error: true, msg: message.format('ERR_INVALID_SUBMETHOD', { submethod: params[0] }) } + } else return { error: true, msg: message.format('ERR_INVALID_SUBMETHOD', { submethod: params[0] }) }; } else return { error: true, msg: message.format('ERR_INVALID_METHOD', { method }) }; @@ -128,10 +128,10 @@ class IgnoreSetting extends Setting { value: setting?.enabled || 'false' }, { name: '》Channels', - value: channels?.map(c => c.name).join(', ') || 'N/A' + value: channels?.map((c) => c.name).join(', ') || 'N/A' }, { name: '》Roles', - value: roles?.map(r => r.name).join(', ') || 'N/A' + value: roles?.map((r) => r.name).join(', ') || 'N/A' } ]; diff --git a/structure/extensions/Guild.js b/structure/extensions/Guild.js index 497c47e..6c84685 100644 --- a/structure/extensions/Guild.js +++ b/structure/extensions/Guild.js @@ -22,8 +22,9 @@ const Guild = Structures.extend('Guild', (Guild) => { async settings() { if(!this._settings) this._settings = this.client.transactionHandler.send({ provider: 'mongodb', request: { collection: 'guilds', type: 'findOne', query: { guildId: this.id } } }); if(this._settings instanceof Promise) this._settings = await this._settings || null; - if(!this._settings) this._settings = { guildId: this.id, ...this.client.defaultConfig }; - else this._settings = { ...this.client.defaultConfig, ...this._settings }; + if(!this._settings) this._settings = { guildId: this.id, ...this.defaultConfig }; + // else this._settings = Object.assign({}, { ...this.defaultConfig, ...this._settings }); //eslint-disable-line prefer-object-spread + else this._settings = { ...this.defaultConfig, ...this._settings }; //eslint-disable-line prefer-object-spread return this._settings; } @@ -54,7 +55,7 @@ const Guild = Structures.extend('Guild', (Guild) => { } } }); - this._settings = { ...{}, ...this.client.defaultConfig }; //Create a new object so settings that change the _settings value won't replicate it towards the defaultConfig. + this._settings = { ...{}, ...this.defaultConfig }; //Create a new object so settings that change the _settings value won't replicate it towards the defaultConfig. this._storageLog(`Database Delete (guild:${this.id}).`); } catch(error) { this._storageError(error); @@ -81,8 +82,8 @@ const Guild = Structures.extend('Guild', (Guild) => { } }); this._settings = { - ...this.client.defaultConfig, - caseId: this._settings.caseId + ...this.defaultConfig, + ...{ caseId: this._settings.caseId } }; this._storageLog(`Database Reset (guild:${this.id}).`); } catch(error) { @@ -117,8 +118,8 @@ const Guild = Structures.extend('Guild', (Guild) => { async _removeSettings(value) { //Remove property if(!this._settings) await this.settings(); - if(this.client.defaultConfig[value]) { - await this._updateSettings({ [value]: this.client.defaultConfig[value] }); + if(this.defaultConfig[value]) { + await this._updateSettings({ [value]: this.defaultConfig[value] }); return undefined; } try { @@ -232,6 +233,10 @@ const Guild = Structures.extend('Guild', (Guild) => { /* Lazy Developer Getters */ + get defaultConfig() { + return JSON.parse(JSON.stringify(this.client.defaultConfig)); + } + get prefix() { return this._settings.prefix || this.client._options.bot.prefix; diff --git a/structure/extensions/Message.js b/structure/extensions/Message.js index 7780e71..af1620b 100644 --- a/structure/extensions/Message.js +++ b/structure/extensions/Message.js @@ -94,7 +94,7 @@ const Message = Structures.extend('Message', (Message) => { } - async respond(str, opts = { attachments: [] }) { + async respond(str, opts = { attachments: [], embed: null }) { if(typeof str === 'string') { if(opts.emoji) { @@ -106,7 +106,7 @@ const Message = Structures.extend('Message', (Message) => { } //console.log(str) - this._pending = await this.channel.send(str, { files: opts.attachments }); + this._pending = await this.channel.send(str, { files: opts.attachments, embed: opts.embed }); return this._pending; } diff --git a/structure/interfaces/Argument.js b/structure/interfaces/Argument.js index 33d393b..a2964ac 100644 --- a/structure/interfaces/Argument.js +++ b/structure/interfaces/Argument.js @@ -34,6 +34,7 @@ class Argument { this.type = options.type && Constants.Types.includes(options.type) ? options.type : 'BOOLEAN'; //What type the argument is ['STRING', 'INTEGER', 'FLOAT', 'BOOLEAN']. this.types = options.types || ['FLAG', 'VERBAL']; //['FLAG'], ['VERBAL'], or ['FLAG', 'VERBAL']. Declares if argument can be used verbally-only, flag-only, or both. + this.archivable = options.archivable === undefined ? true : Boolean(options.archivable); //Displays argument in showUsage or not. //NOTE: Instead of telling the person the argument is missing and is required, ask them and continue the command execution afterwards. More work to do. diff --git a/structure/interfaces/Command.js b/structure/interfaces/Command.js index 95c877c..93eef83 100644 --- a/structure/interfaces/Command.js +++ b/structure/interfaces/Command.js @@ -33,11 +33,6 @@ class Command extends Component { this.arguments = opts.arguments || []; this.keepQuotes = Boolean(opts.keepQuotes); - //Moderation - this.infractionType = opts.infractionType; - this.customArguments = opts.customArguments || []; //Arguments that will be attempted to be parsed in the command. - this.forcedArguments = opts.forcedArguments || {}; //Arguments that will be forcefully added (with defaults) if an "alias" exists. - this.clientPermissions = opts.clientPermissions || []; this.memberPermissions = opts.memberPermissions || []; diff --git a/util/emojis.json b/util/emojis.json index 9e058c0..6c465c3 100644 --- a/util/emojis.json +++ b/util/emojis.json @@ -2,7 +2,7 @@ "success": "<:success:723595130808041512>", "failure": "<:failure:723595130912637018>", "loading": "", - "warning": "⚠", + "warning": "⚠️", "enabled": "<:enabled:723589993733423215>", "disabled": "<:disabled:723589993506799618>", "text-channel": "<:textchannel:716414423094525952>",