const { Structures } = require('discord.js'); const { Emojis } = require('../../util/'); const { stripIndents } = require('common-tags'); const Message = Structures.extend('Message', (Message) => { class ExtendedMessage extends Message { constructor(...args) { super(...args); this.command = null; //Will set to command if the message induces a command. this.arguments = null; this.parameters = null; this._pending = null; } format(index, parameters = { }, code = false) { let language = 'en_us'; if(this.guild && this.guild._settings.locale) language = this.guild._settings.locale; parameters.prefix = this.guild?.prefix; return this.client.format(language, index, parameters, code); } async resolve() { if(this.guild && this.guild.debug) { this.guild._debugLog(`Command [${this.command.moduleResolveable}] execution by ${this.author.tag}. Parameters: ${this.parameters.join(', ')} || Arguments: ${Object.values(this.arguments).map((arg) => `${arg.name}:${arg.value}`)}`); } if (this.command.showUsage && !this.parameters.length && !Object.values(this.arguments).length) { return this.embed(this.command.usageEmbed(this)); } this.client.emit('commandExecute', this); try { const resolved = this.command.execute(this, { params: this.parameters, args: this.arguments }); this.command._invokes.success++; if(resolved instanceof Promise) await resolved; return { error: false }; } catch (error) { this.command._invokes.fail++; return { error: true, message: error }; } } async embed(embed, opts = {}) { if (!embed.color) embed.color = 619452; const send = { content: opts.reply ? `<@${this.author.id}>` : '', embed }; this._pending = await this.channel.send(send); return this._pending; } async formattedRespond(index, opts = { }) { if (!opts.params) opts.params = {}; return this.respond(this.format(index, opts.params), opts); } async respond(str, opts = { files: [], embed: null, dm: false, disableMentions: 'none' }) { if(typeof str === 'string') { if(opts.emoji) { const emoji = Emojis[opts.emoji]; if(!emoji) this.command.client.logger.warn(`Invalid emoji provided to command ${this.command.resolveable}: "${opts.emoji}".`); str = `${emoji} ${str}`; } if(opts.reply) str = `<@!${this.author.id}> ${str}`; } this._pending = await this[opts.dm ? 'author' : 'channel'].send(str, { files: opts.files, embed: opts.embed, disableMentions: opts.disableMentions }); return this._pending; } async limitedRespond(str, opts = { attachments: [] }) { if(typeof str === 'string') { if(opts.emoji) { const emoji = Emojis[opts.emoji]; if(!emoji) this.client.logger.warn(`Invalid emoji provided to command ${this.command.resolveable}: "${opts.emoji}".`); str = `${emoji} ${str}`; } if(opts.reply) str = `<@!${this.author.id}> ${str}`; } return this.client.rateLimiter.limitSend(this.channel, str, opts.limit, opts.utility); } async edit(str, opts = {}) { if(!this.editable) return null; if(typeof str === 'string') { if(opts.emoji) str = `${Emojis[opts.emoji]} ${str}`; if(opts.reply) str = `<@!${this.author.id}> ${str}`; } return super.edit(str); } async prompt(str, opts = {}) { if(typeof str === 'string') { if(opts.emoji) str = `${Emojis[opts.emoji]} ${str}`; if(opts.reply) str = `<@!${this.author.id}> ${str}`; } await this.channel.send(str); return this.channel.awaitMessages((m) => m.author.id === this.author.id, { max: 1, time: opts.time || 30000, errors: ['time'] }) .then((collected) => { return collected.first(); }) .catch((error) => { //eslint-disable-line no-unused-vars, handle-callback-err return null; }); } async _showUsage(comp = null) { const component = comp ? comp : this.command; const prefix = this.guild?.prefix; const fields = []; if(component.examples.length > 0) { fields.push({ name: `》 ${this.format('GENERAL_EXAMPLES')}`, value: component.examples.map((e) => component.rawExamples ? `\`${prefix}${e}\`` : `\`${prefix}${component.name} ${e}\``).join('\n') }); } if(component.aliases.length > 0) { fields.push({ name: `》 ${this.format('GENERAL_ALIASES')}`, value: component.aliases.join(', ') }); } if(component.arguments.length > 0) { fields.push({ name: `》 ${this.format('GENERAL_ARGUMENTS')}`, value: component.arguments.map((a) => `\`${a.types.length === 1 && a.types.includes('FLAG') ? '--' : ''}${a.name}${a.usage ? ` ${a.usage}` : ''}\`: ${this.format(`A_${a.name.toUpperCase()}_${component.name.toUpperCase()}_DESCRIPTION`)}`) }); } const embed = { author: { name: `${component.name}${component.module ? ` (${component.module.resolveable})` : ''}`, // eslint-disable-next-line camelcase icon_url: this.client.user.displayAvatarURL() }, description: stripIndents`\`${prefix}${component.name}${component.usage ? ` ${component.usage}` : ''}\`${component.guildOnly ? ' *(guild-only)*' : ''} ${this.format(component.description)}`, fields }; return this.embed(embed); } get prefix() { return this.guild ? this.guild.prefix : this.author.prefix; } get _clean() { if (!this.command) return this.cleanContent; let str = this.content.replace(new RegExp(`^(${this.prefix}|<@!?${this.client.id}>)`, 'iu'), '').replace(this._caller, ''); if (this._settingCaller) str = str.replace(this._settingCaller, ''); return str.trim(); } get link() { return `https://discord.com/channels/${this.guild.id}/${this.channel.id}/${this.id}`; } } return ExtendedMessage; }); module.exports = Message;