mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-17 03:53:29 +01:00
Clean up Message#mentions and message updates
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
const Action = require('./Action');
|
const Action = require('./Action');
|
||||||
const Constants = require('../../util/Constants');
|
const Constants = require('../../util/Constants');
|
||||||
const Message = require('../../structures/Message');
|
|
||||||
|
|
||||||
class MessageUpdateAction extends Action {
|
class MessageUpdateAction extends Action {
|
||||||
handle(data) {
|
handle(data) {
|
||||||
@@ -10,14 +9,11 @@ class MessageUpdateAction extends Action {
|
|||||||
if (channel) {
|
if (channel) {
|
||||||
const message = channel.messages.get(data.id);
|
const message = channel.messages.get(data.id);
|
||||||
if (message) {
|
if (message) {
|
||||||
const newMessage = new Message(message.channel, this.patchDataPacket(data, message), client);
|
message.patch(data);
|
||||||
newMessage._edits.push(message, ...message._edits);
|
client.emit(Constants.Events.MESSAGE_UPDATE, message._edits[0], message);
|
||||||
newMessage.reactions = message.reactions;
|
|
||||||
channel.messages.set(data.id, newMessage);
|
|
||||||
client.emit(Constants.Events.MESSAGE_UPDATE, message, newMessage);
|
|
||||||
return {
|
return {
|
||||||
old: message,
|
old: message._edits[0],
|
||||||
updated: newMessage,
|
updated: message,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,29 +28,6 @@ class MessageUpdateAction extends Action {
|
|||||||
updated: null,
|
updated: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
patchDataPacket(data, message) {
|
|
||||||
data.type = 'type' in data ? data.type : Constants.MessageTypes.indexOf(message.type);
|
|
||||||
data.tts = 'tts' in data ? data.tts : message.tts;
|
|
||||||
data.timestamp = 'timestamp' in data ? data.timestamp : message.createdAt.toString();
|
|
||||||
data.pinned = 'pinned' in data ? data.pinned : message.pinned;
|
|
||||||
data.nonce = 'nonce' in data ? data.nonce : message.nonce;
|
|
||||||
data.mentions = 'mentions' in data ? data.mentions : message.mentions.users.keyArray();
|
|
||||||
data.mentions_roles = 'mentions_roles' in data ?
|
|
||||||
data.mentions_roles : message.mentions.roles.keyArray();
|
|
||||||
data.mention_everyone = 'mention_everyone' in data ? data.mention_everyone : message.mentions.everyone;
|
|
||||||
data.embeds = 'embeds' in data ? data.embeds : message.embeds;
|
|
||||||
data.content = 'content' in data ? data.content : message.content;
|
|
||||||
data.author = 'author' in data ? data.author : {
|
|
||||||
username: message.author.username,
|
|
||||||
id: message.author.id,
|
|
||||||
discriminator: message.author.discriminator,
|
|
||||||
avatar: message.author.avatar,
|
|
||||||
};
|
|
||||||
data.attachments = 'attachments' in data ? data.attachments : message.attachments.array();
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
const Mentions = require('./MessageMentions');
|
||||||
const Attachment = require('./MessageAttachment');
|
const Attachment = require('./MessageAttachment');
|
||||||
const Embed = require('./MessageEmbed');
|
const Embed = require('./MessageEmbed');
|
||||||
const MessageReaction = require('./MessageReaction');
|
const MessageReaction = require('./MessageReaction');
|
||||||
@@ -110,69 +111,11 @@ class Message {
|
|||||||
*/
|
*/
|
||||||
this.editedTimestamp = data.edited_timestamp ? new Date(data.edited_timestamp).getTime() : null;
|
this.editedTimestamp = data.edited_timestamp ? new Date(data.edited_timestamp).getTime() : null;
|
||||||
|
|
||||||
/**
|
|
||||||
* An object containing a further users, roles or channels collections
|
|
||||||
* @type {Object}
|
|
||||||
* @property {Collection<Snowflake, User>} mentions.users Mentioned users, maps their ID to the user object.
|
|
||||||
* @property {Collection<Snowflake, GuildMember>} mentions.members Mentioned members, maps their ID
|
|
||||||
* to the member object.
|
|
||||||
* @property {Collection<Snowflake, Role>} mentions.roles Mentioned roles, maps their ID to the role object.
|
|
||||||
* @property {Collection<Snowflake, GuildChannel>} mentions.channels Mentioned channels,
|
|
||||||
* maps their ID to the channel object.
|
|
||||||
* @property {boolean} mentions.everyone Whether or not @everyone was mentioned.
|
|
||||||
*/
|
|
||||||
this.mentions = {
|
|
||||||
users: new Collection(),
|
|
||||||
roles: new Collection(),
|
|
||||||
channels: new Collection(),
|
|
||||||
everyone: data.mention_everyone,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add user mentions
|
|
||||||
for (const mention of data.mentions) {
|
|
||||||
let user = this.client.users.get(mention.id);
|
|
||||||
if (!user) user = this.client.dataManager.newUser(mention);
|
|
||||||
this.mentions.users.set(user.id, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add getter for member mentions
|
|
||||||
Object.defineProperty(this.mentions, 'members', {
|
|
||||||
get: () => {
|
|
||||||
if (this.channel.type !== 'text') return null;
|
|
||||||
const members = new Collection();
|
|
||||||
this.mentions.users.forEach(user => {
|
|
||||||
const member = this.client.resolver.resolveGuildMember(this.channel.guild, user);
|
|
||||||
if (member) members.set(member.id, member);
|
|
||||||
});
|
|
||||||
return members;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add role mentions
|
|
||||||
if (data.mention_roles) {
|
|
||||||
for (const mention of data.mention_roles) {
|
|
||||||
const role = this.channel.guild.roles.get(mention);
|
|
||||||
if (role) this.mentions.roles.set(role.id, role);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add channel mentions
|
|
||||||
if (this.channel.type === 'text') {
|
|
||||||
const channMentionsRaw = data.content.match(/<#([0-9]{14,20})>/g) || [];
|
|
||||||
for (const raw of channMentionsRaw) {
|
|
||||||
const chan = this.channel.guild.channels.get(raw.match(/([0-9]{14,20})/g)[0]);
|
|
||||||
if (chan) this.mentions.channels.set(chan.id, chan);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this._edits = [];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A collection of reactions to this message, mapped by the reaction "id".
|
* A collection of reactions to this message, mapped by the reaction "id".
|
||||||
* @type {Collection<Snowflake, MessageReaction>}
|
* @type {Collection<Snowflake, MessageReaction>}
|
||||||
*/
|
*/
|
||||||
this.reactions = new Collection();
|
this.reactions = new Collection();
|
||||||
|
|
||||||
if (data.reactions && data.reactions.length > 0) {
|
if (data.reactions && data.reactions.length > 0) {
|
||||||
for (const reaction of data.reactions) {
|
for (const reaction of data.reactions) {
|
||||||
const id = reaction.emoji.id ? `${reaction.emoji.name}:${reaction.emoji.id}` : reaction.emoji.name;
|
const id = reaction.emoji.id ? `${reaction.emoji.name}:${reaction.emoji.id}` : reaction.emoji.name;
|
||||||
@@ -180,6 +123,12 @@ class Message {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All valid mentions that the message contains
|
||||||
|
* @type {MessageMentions}
|
||||||
|
*/
|
||||||
|
this.mentions = new Mentions(this, data.mentions, data.mentions_roles, data.mention_everyone);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID of the webhook that sent the message, if applicable
|
* ID of the webhook that sent the message, if applicable
|
||||||
* @type {?Snowflake}
|
* @type {?Snowflake}
|
||||||
@@ -191,6 +140,44 @@ class Message {
|
|||||||
* @type {?boolean}
|
* @type {?boolean}
|
||||||
*/
|
*/
|
||||||
this.hit = typeof data.hit === 'boolean' ? data.hit : null;
|
this.hit = typeof data.hit === 'boolean' ? data.hit : null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The previous versions of the message, sorted with the most recent first
|
||||||
|
* @type {Message[]}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this._edits = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the message
|
||||||
|
* @param {Object} data Raw Discord message update data
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
patch(data) {
|
||||||
|
const clone = Util.cloneObject(this);
|
||||||
|
this._edits.unshift(clone);
|
||||||
|
|
||||||
|
this.editedTimestamp = data.edited_timestamp;
|
||||||
|
if ('content' in data) this.content = data.content;
|
||||||
|
if ('pinned' in data) this.pinned = data.pinned;
|
||||||
|
if ('tts' in data) this.tts = data.tts;
|
||||||
|
if ('embeds' in data) this.embeds = data.embeds.map(e => new Embed(this, e));
|
||||||
|
else this.embeds = new Collection(this.embeds);
|
||||||
|
|
||||||
|
if ('attachments' in data) {
|
||||||
|
this.attachments = new Collection();
|
||||||
|
for (const attachment of data.attachments) this.attachments.set(attachment.id, new Attachment(this, attachment));
|
||||||
|
} else {
|
||||||
|
this.attachments = new Collection(this.attachments);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mentions = new Mentions(
|
||||||
|
this,
|
||||||
|
'mentions' in data ? data.mentions : this.mentions.users,
|
||||||
|
'mentions_roles' in data ? data.mentions_roles : this.mentions.roles,
|
||||||
|
'mention_everyone' in data ? data.mention_everyone : this.mentions.everyone
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
145
src/structures/MessageMentions.js
Normal file
145
src/structures/MessageMentions.js
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
const Collection = require('../util/Collection');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keeps track of mentions in a {@link Message}
|
||||||
|
*/
|
||||||
|
class MessageMentions {
|
||||||
|
/**
|
||||||
|
* @param {Message} message Message to read mentions from
|
||||||
|
* @param {?Array<Object>} users Raw user objects from Discord
|
||||||
|
* @param {?Array<Object>} roles Raw role objects from Discord
|
||||||
|
* @param {?boolean} everyone Whether @everyone or @here were mentioned
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
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<Snowflake, User>}
|
||||||
|
*/
|
||||||
|
this.users = new Collection(users);
|
||||||
|
} else {
|
||||||
|
this.users = new Collection();
|
||||||
|
for (const mention of users) {
|
||||||
|
let user = message.client.users.get(mention.id);
|
||||||
|
if (!user) user = message.client.dataManager.newUser(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<Snowflake, Role>}
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guild the message is in
|
||||||
|
* @type {?Guild}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this._guild = message.channel.guild;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cached members for {@MessageMention#members}
|
||||||
|
* @type {?Collection<Snowflake, GuildMember>}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this._members = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cached channels for {@MessageMention#channels}
|
||||||
|
* @type {?Collection<Snowflake, GuildChannel>}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this._channels = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any members that were mentioned (only in {@link TextChannel}s)
|
||||||
|
* @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.member(user);
|
||||||
|
if (member) this._members.set(member.user.id, member);
|
||||||
|
});
|
||||||
|
return this._members;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any channels that were mentioned (only in {@link TextChannel}s)
|
||||||
|
* @type {?Collection<Snowflake, GuildChannel>}
|
||||||
|
* @readonly
|
||||||
|
*/
|
||||||
|
get channels() {
|
||||||
|
if (this._channels) return this._channels;
|
||||||
|
if (!this.guild) return null;
|
||||||
|
this._channels = new Collection();
|
||||||
|
let matches;
|
||||||
|
while ((matches = this.constructor.CHANNELS_PATTERN.exec(this._content)) !== null) {
|
||||||
|
const chan = this._guild.channels.get(matches[1]);
|
||||||
|
if (chan) this._channels.set(chan.id, chan);
|
||||||
|
}
|
||||||
|
return this._channels;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 = /<@!?[0-9]+>/g;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regular expression that globally matches role mentions like `<@&297577916114403338>`
|
||||||
|
* @type {RegExp}
|
||||||
|
*/
|
||||||
|
MessageMentions.ROLES_PATTERN = /<@&[0-9]+>/g;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regular expression that globally matches channel mentions like `<#222079895583457280>`
|
||||||
|
* @type {RegExp}
|
||||||
|
*/
|
||||||
|
MessageMentions.CHANNELS_PATTERN = /<#([0-9]+)>/g;
|
||||||
|
|
||||||
|
module.exports = MessageMentions;
|
||||||
Reference in New Issue
Block a user