const Collection = require('../util/Collection'); const GuildMember = require('./GuildMember'); /** * Keeps track of mentions in a {@link Message}. */ class MessageMentions { constructor(message, users, roles, everyone) { /** * Whether `@everyone` or `@here` were mentioned * @type {boolean} */ this.everyone = Boolean(everyone); if (users) { if (users instanceof Collection) { /** * Any users that were mentioned * @type {Collection} */ this.users = new Collection(users); } else { this.users = new Collection(); for (const mention of users) { let user = message.client.users.create(mention); this.users.set(user.id, user); } } } else { this.users = new Collection(); } if (roles) { if (roles instanceof Collection) { /** * Any roles that were mentioned * @type {Collection} */ this.roles = new Collection(roles); } else { this.roles = new Collection(); for (const mention of roles) { const role = message.channel.guild.roles.get(mention); if (role) this.roles.set(role.id, role); } } } else { this.roles = new Collection(); } /** * Content of the message * @type {Message} * @private */ this._content = message.content; /** * The client the message is from * @type {Client} * @private */ this._client = message.client; /** * The guild the message is in * @type {?Guild} * @private */ this._guild = message.channel.guild; /** * Cached members for {@MessageMention#members} * @type {?Collection} * @private */ this._members = null; /** * Cached channels for {@MessageMention#channels} * @type {?Collection} * @private */ this._channels = null; } /** * Any members that were mentioned (only in {@link TextChannel}s) * @type {?Collection} * @readonly */ get members() { if (this._members) return this._members; if (!this._guild) return null; this._members = new Collection(); this.users.forEach(user => { const member = this._guild.member(user); if (member) this._members.set(member.user.id, member); }); return this._members; } /** * Any channels that were mentioned * @type {Collection} * @readonly */ get channels() { if (this._channels) return this._channels; this._channels = new Collection(); let matches; while ((matches = this.constructor.CHANNELS_PATTERN.exec(this._content)) !== null) { const chan = this._client.channels.get(matches[1]); if (chan) this._channels.set(chan.id, chan); } return this._channels; } /** * Check if a user is mentioned. * Takes into account user mentions, role mentions, and @everyone/@here mentions. * @param {UserResolvable|GuildMember|Role|GuildChannel} data User/GuildMember/Role/Channel to check * @param {boolean} [strict=true] If role mentions and everyone/here mentions should be included * @returns {boolean} */ has(data, strict = true) { if (strict && this.everyone) return true; if (strict && data instanceof GuildMember) { for (const role of this.roles) if (data.roles.has(role.id)) return true; } const id = data.id || data; return this.users.has(id) || this.channels.has(id) || this.roles.has(id); } } /** * Regular expression that globally matches `@everyone` and `@here` * @type {RegExp} */ MessageMentions.EVERYONE_PATTERN = /@(everyone|here)/g; /** * Regular expression that globally matches user mentions like `<@81440962496172032>` * @type {RegExp} */ MessageMentions.USERS_PATTERN = /<@!?(1|\d{17,19})>/g; /** * Regular expression that globally matches role mentions like `<@&297577916114403338>` * @type {RegExp} */ MessageMentions.ROLES_PATTERN = /<@&(\d{17,19})>/g; /** * Regular expression that globally matches channel mentions like `<#222079895583457280>` * @type {RegExp} */ MessageMentions.CHANNELS_PATTERN = /<#(\d{17,19})>/g; module.exports = MessageMentions;