diff --git a/src/client.js b/src/client.js index f2e46c9e8..7e0b45502 100644 --- a/src/client.js +++ b/src/client.js @@ -16,6 +16,7 @@ class CommandoClient extends discord.Client { * @property {boolean} [nonCommandEditable=true] - Whether messages without commands can be edited to a command * @property {string|string[]|Set} [owner] - ID of the bot owner's Discord user, or multiple IDs * @property {string} [invite] - Invite URL to the bot's support server + * @property {boolean} [mentionPrefix=true] Enable whether the bot mention, should also be a command prefix. */ /** @@ -26,6 +27,7 @@ class CommandoClient extends discord.Client { if(options.commandPrefix === null) options.commandPrefix = ''; if(typeof options.commandEditableDuration === 'undefined') options.commandEditableDuration = 30; if(typeof options.nonCommandEditable === 'undefined') options.nonCommandEditable = true; + if(options.mentionPrefix === null) options.mentionPrefix = true; super(options); /** @@ -166,6 +168,14 @@ class CommandoClient extends discord.Client { return undefined; } + get mentionPrefix() { + return this.options.mentionPrefix; + } + + set mentionPrefix(value) { + this.options.mentionPrefix = value; + } + async destroy() { await super.destroy(); if(this.provider) await this.provider.destroy(); diff --git a/src/commands/base.js b/src/commands/base.js index 9b7a9637d..ffafcfd45 100644 --- a/src/commands/base.js +++ b/src/commands/base.js @@ -476,9 +476,10 @@ class Command { * @param {string} command - A command + arg string * @param {string} [prefix] - Prefix to use for the prefixed command format * @param {User} [user] - User to use for the mention command format + * @param {boolean} [mentionPrefix] - Value, wether or not mention as prefix is enabled. * @return {string} */ - static usage(command, prefix = null, user = null) { + static usage(command, prefix = null, user = null, mentionPrefix = null) { const nbcmd = command.replace(/ /g, '\xa0'); if(!prefix && !user) return `\`${nbcmd}\``; @@ -490,9 +491,11 @@ class Command { } let mentionPart; - if(user) mentionPart = `\`@${user.username.replace(/ /g, '\xa0')}#${user.discriminator}\xa0${nbcmd}\``; + if(user && mentionPrefix) { + mentionPart = `\`@${user.username.replace(/ /g, '\xa0')}#${user.discriminator}\xa0${nbcmd}\``; + } - return `${prefixPart || ''}${prefix && user ? ' or ' : ''}${mentionPart || ''}`; + return `${prefixPart || ''}${prefix && user && mentionPrefix ? ' or ' : ''}${mentionPart || ''}`; } /** diff --git a/src/dispatcher.js b/src/dispatcher.js index 53d60f405..442c341aa 100644 --- a/src/dispatcher.js +++ b/src/dispatcher.js @@ -253,9 +253,12 @@ class CommandDispatcher { } } + // Find the command to run with default command handling const prefix = message.guild ? message.guild.commandPrefix : this.client.commandPrefix; - if(!this._commandPatterns[prefix]) this.buildCommandPattern(prefix); + const mentionAsPrefix = this.client.mentionPrefix; + + if(!this._commandPatterns[prefix]) this.buildCommandPattern(prefix, mentionAsPrefix); let cmdMsg = this.matchDefault(message, this._commandPatterns[prefix], 2); if(!cmdMsg && !message.guild) cmdMsg = this.matchDefault(message, /^([^\s]+)/i, 1, true); return cmdMsg; @@ -284,18 +287,25 @@ class CommandDispatcher { /** * Creates a regular expression to match the command prefix and name in a message * @param {?string} prefix - Prefix to build the pattern for + * @param {boolean} mentionPrefix - Boolean value, for mention as a prefix. * @return {RegExp} * @private */ - buildCommandPattern(prefix) { + buildCommandPattern(prefix, mentionPrefix) { let pattern; - if(prefix) { + if(prefix && mentionPrefix) { const escapedPrefix = escapeRegex(prefix); pattern = new RegExp( `^(<@!?${this.client.user.id}>\\s+(?:${escapedPrefix}\\s*)?|${escapedPrefix}\\s*)([^\\s]+)`, 'i' ); - } else { + } else if(!prefix && mentionPrefix) { pattern = new RegExp(`(^<@!?${this.client.user.id}>\\s+)([^\\s]+)`, 'i'); + } else if(prefix && !mentionPrefix) { + const escapedPrefix = escapeRegex(prefix); + pattern = new RegExp(`((?:${escapedPrefix}\\s*)?|${escapedPrefix}\\s*)([^\\s]+)`, 'i'); + } else { + const escapedDefaultPrefix = escapeRegex('!'); + pattern = new RegExp(`((?:${escapedDefaultPrefix}\\s*)?|${escapedDefaultPrefix}\\s*)([^\\s]+)`, 'i'); } this._commandPatterns[prefix] = pattern; this.client.emit('debug', `Built command pattern for prefix "${prefix}": ${pattern}`); diff --git a/src/extensions/message.js b/src/extensions/message.js index a43a4b4ff..0e958273d 100644 --- a/src/extensions/message.js +++ b/src/extensions/message.js @@ -95,7 +95,7 @@ module.exports = Structures.extend('Message', Message => { if(this.guild) prefix = this.guild.commandPrefix; else prefix = this.client.commandPrefix; } - return Command.usage(command, prefix, user); + return Command.usage(command, prefix, user, this.client.mentionPrefix); } /** diff --git a/typings/index.d.ts b/typings/index.d.ts index ff1dfeaf5..79b06ec11 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -109,7 +109,7 @@ declare module 'discord.js-commando' { public unload(): void; public usage(argString?: string, prefix?: string, user?: User): string; - public static usage(command: string, prefix?: string, user?: User): string; + public static usage(command: string, prefix?: string, user?: User, mentionPrefix?: boolean): string; } export class CommandDispatcher { @@ -119,7 +119,7 @@ declare module 'discord.js-commando' { private _commandPatterns: object; private _results: Map; - private buildCommandPattern(prefix: string): RegExp; + private buildCommandPattern(prefix: string, mentionPrefix: boolean): RegExp; private cacheCommandoMessage(message: Message, oldMessage: Message, cmdMsg: CommandoMessage, responses: Message | Message[]): void; private handleMessage(message: Message, oldMessage?: Message): Promise; private inhibit(cmdMsg: CommandoMessage): Inhibition; @@ -202,6 +202,7 @@ declare module 'discord.js-commando' { public provider: SettingProvider; public registry: CommandoRegistry; public settings: GuildSettingsHelper; + public mentionPrefix: boolean; public isOwner(user: UserResolvable): boolean; public setProvider(provider: SettingProvider | Promise): Promise;