summaryrefslogtreecommitdiff
path: root/node_modules/discord.js/src/structures/MessageMentions.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/discord.js/src/structures/MessageMentions.js')
-rw-r--r--node_modules/discord.js/src/structures/MessageMentions.js297
1 files changed, 297 insertions, 0 deletions
diff --git a/node_modules/discord.js/src/structures/MessageMentions.js b/node_modules/discord.js/src/structures/MessageMentions.js
new file mode 100644
index 0000000..a07e77f
--- /dev/null
+++ b/node_modules/discord.js/src/structures/MessageMentions.js
@@ -0,0 +1,297 @@
+'use strict';
+
+const { Collection } = require('@discordjs/collection');
+const { FormattingPatterns } = require('discord-api-types/v10');
+const { flatten } = require('../util/Util');
+
+/**
+ * Keeps track of mentions in a {@link Message}.
+ */
+class MessageMentions {
+ /**
+ * A regular expression that matches `@everyone` and `@here`.
+ * The `mention` group property is present on the `exec` result of this expression.
+ * @type {RegExp}
+ * @memberof MessageMentions
+ */
+ static EveryonePattern = /@(?<mention>everyone|here)/;
+
+ /**
+ * A regular expression that matches user mentions like `<@81440962496172032>`.
+ * The `id` group property is present on the `exec` result of this expression.
+ * @type {RegExp}
+ * @memberof MessageMentions
+ */
+ static UsersPattern = FormattingPatterns.UserWithOptionalNickname;
+
+ /**
+ * A regular expression that matches role mentions like `<@&297577916114403338>`.
+ * The `id` group property is present on the `exec` result of this expression.
+ * @type {RegExp}
+ * @memberof MessageMentions
+ */
+ static RolesPattern = FormattingPatterns.Role;
+
+ /**
+ * A regular expression that matches channel mentions like `<#222079895583457280>`.
+ * The `id` group property is present on the `exec` result of this expression.
+ * @type {RegExp}
+ * @memberof MessageMentions
+ */
+ static ChannelsPattern = FormattingPatterns.Channel;
+
+ /**
+ * A global regular expression variant of {@link MessageMentions.ChannelsPattern}.
+ * @type {RegExp}
+ * @memberof MessageMentions
+ * @private
+ */
+ static GlobalChannelsPattern = new RegExp(this.ChannelsPattern.source, 'g');
+
+ /**
+ * A global regular expression variant of {@link MessageMentions.UsersPattern}.
+ * @type {RegExp}
+ * @memberof MessageMentions
+ * @private
+ */
+ static GlobalUsersPattern = new RegExp(this.UsersPattern.source, 'g');
+
+ constructor(message, users, roles, everyone, crosspostedChannels, repliedUser) {
+ /**
+ * The client the message is from
+ * @type {Client}
+ * @readonly
+ */
+ Object.defineProperty(this, 'client', { value: message.client });
+
+ /**
+ * The guild the message is in
+ * @type {?Guild}
+ * @readonly
+ */
+ Object.defineProperty(this, 'guild', { value: message.guild });
+
+ /**
+ * The initial message content
+ * @type {string}
+ * @readonly
+ * @private
+ */
+ Object.defineProperty(this, '_content', { value: message.content });
+
+ /**
+ * Whether `@everyone` or `@here` were mentioned
+ * @type {boolean}
+ */
+ this.everyone = Boolean(everyone);
+
+ if (users) {
+ if (users instanceof Collection) {
+ /**
+ * Any users that were mentioned
+ * <info>Order as received from the API, not as they appear in the message content</info>
+ * @type {Collection<Snowflake, User>}
+ */
+ this.users = new Collection(users);
+ } else {
+ this.users = new Collection();
+ for (const mention of users) {
+ if (mention.member && message.guild) {
+ message.guild.members._add(Object.assign(mention.member, { user: mention }));
+ }
+ const user = message.client.users._add(mention);
+ this.users.set(user.id, user);
+ }
+ }
+ } else {
+ this.users = new Collection();
+ }
+
+ if (roles instanceof Collection) {
+ /**
+ * Any roles that were mentioned
+ * <info>Order as received from the API, not as they appear in the message content</info>
+ * @type {Collection<Snowflake, Role>}
+ */
+ this.roles = new Collection(roles);
+ } else if (roles) {
+ this.roles = new Collection();
+ const guild = message.guild;
+ if (guild) {
+ for (const mention of roles) {
+ const role = guild.roles.cache.get(mention);
+ if (role) this.roles.set(role.id, role);
+ }
+ }
+ } else {
+ this.roles = new Collection();
+ }
+
+ /**
+ * Cached members for {@link MessageMentions#members}
+ * @type {?Collection<Snowflake, GuildMember>}
+ * @private
+ */
+ this._members = null;
+
+ /**
+ * Cached channels for {@link MessageMentions#channels}
+ * @type {?Collection<Snowflake, BaseChannel>}
+ * @private
+ */
+ this._channels = null;
+
+ /**
+ * Cached users for {@link MessageMentions#parsedUsers}
+ * @type {?Collection<Snowflake, User>}
+ * @private
+ */
+ this._parsedUsers = null;
+
+ /**
+ * Crossposted channel data.
+ * @typedef {Object} CrosspostedChannel
+ * @property {Snowflake} channelId The mentioned channel's id
+ * @property {Snowflake} guildId The id of the guild that has the channel
+ * @property {ChannelType} type The channel's type
+ * @property {string} name The channel's name
+ */
+
+ if (crosspostedChannels) {
+ if (crosspostedChannels instanceof Collection) {
+ /**
+ * A collection of crossposted channels
+ * <info>Order as received from the API, not as they appear in the message content</info>
+ * @type {Collection<Snowflake, CrosspostedChannel>}
+ */
+ this.crosspostedChannels = new Collection(crosspostedChannels);
+ } else {
+ this.crosspostedChannels = new Collection();
+ for (const d of crosspostedChannels) {
+ this.crosspostedChannels.set(d.id, {
+ channelId: d.id,
+ guildId: d.guild_id,
+ type: d.type,
+ name: d.name,
+ });
+ }
+ }
+ } else {
+ this.crosspostedChannels = new Collection();
+ }
+
+ /**
+ * The author of the message that this message is a reply to
+ * @type {?User}
+ */
+ this.repliedUser = repliedUser ? this.client.users._add(repliedUser) : null;
+ }
+
+ /**
+ * Any members that were mentioned (only in {@link Guild}s)
+ * <info>Order as received from the API, not as they appear in the message content</info>
+ * @type {?Collection<Snowflake, GuildMember>}
+ * @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.members.resolve(user);
+ if (member) this._members.set(member.user.id, member);
+ });
+ return this._members;
+ }
+
+ /**
+ * Any channels that were mentioned
+ * <info>Order as they appear first in the message content</info>
+ * @type {Collection<Snowflake, BaseChannel>}
+ * @readonly
+ */
+ get channels() {
+ if (this._channels) return this._channels;
+ this._channels = new Collection();
+ let matches;
+
+ while ((matches = this.constructor.GlobalChannelsPattern.exec(this._content)) !== null) {
+ const channel = this.client.channels.cache.get(matches.groups.id);
+ if (channel) this._channels.set(channel.id, channel);
+ }
+
+ return this._channels;
+ }
+
+ /**
+ * Any user mentions that were included in the message content
+ * <info>Order as they appear first in the message content</info>
+ * @type {Collection<Snowflake, User>}
+ * @readonly
+ */
+ get parsedUsers() {
+ if (this._parsedUsers) return this._parsedUsers;
+ this._parsedUsers = new Collection();
+ let matches;
+ while ((matches = this.constructor.GlobalUsersPattern.exec(this._content)) !== null) {
+ const user = this.client.users.cache.get(matches[1]);
+ if (user) this._parsedUsers.set(user.id, user);
+ }
+ return this._parsedUsers;
+ }
+
+ /**
+ * Options used to check for a mention.
+ * @typedef {Object} MessageMentionsHasOptions
+ * @property {boolean} [ignoreDirect=false] Whether to ignore direct mentions to the item
+ * @property {boolean} [ignoreRoles=false] Whether to ignore role mentions to a guild member
+ * @property {boolean} [ignoreRepliedUser=false] Whether to ignore replied user mention to an user
+ * @property {boolean} [ignoreEveryone=false] Whether to ignore `@everyone`/`@here` mentions
+ */
+
+ /**
+ * Checks if a user, guild member, thread member, role, or channel is mentioned.
+ * Takes into account user mentions, role mentions, channel mentions,
+ * replied user mention, and `@everyone`/`@here` mentions.
+ * @param {UserResolvable|RoleResolvable|ChannelResolvable} data The User/Role/Channel to check for
+ * @param {MessageMentionsHasOptions} [options] The options for the check
+ * @returns {boolean}
+ */
+ has(data, { ignoreDirect = false, ignoreRoles = false, ignoreRepliedUser = false, ignoreEveryone = false } = {}) {
+ const user = this.client.users.resolve(data);
+
+ if (!ignoreEveryone && user && this.everyone) return true;
+
+ const userWasRepliedTo = user && this.repliedUser?.id === user.id;
+
+ if (!ignoreRepliedUser && userWasRepliedTo && this.users.has(user.id)) return true;
+
+ if (!ignoreDirect) {
+ if (user && (!ignoreRepliedUser || this.parsedUsers.has(user.id)) && this.users.has(user.id)) return true;
+
+ const role = this.guild?.roles.resolve(data);
+ if (role && this.roles.has(role.id)) return true;
+
+ const channel = this.client.channels.resolve(data);
+ if (channel && this.channels.has(channel.id)) return true;
+ }
+
+ if (!ignoreRoles) {
+ const member = this.guild?.members.resolve(data);
+ if (member) {
+ for (const mentionedRole of this.roles.values()) if (member.roles.cache.has(mentionedRole.id)) return true;
+ }
+ }
+
+ return false;
+ }
+
+ toJSON() {
+ return flatten(this, {
+ members: true,
+ channels: true,
+ });
+ }
+}
+
+module.exports = MessageMentions;