From ba6f44c89f6d57fb6d0732f0d0228f6ee5482a16 Mon Sep 17 00:00:00 2001 From: Jaw0r3k Date: Fri, 7 Apr 2023 13:20:03 +0200 Subject: [PATCH 1/8] feat: super reactions --- .../src/structures/MessageReaction.js | 26 +++++++++++++++++++ packages/discord.js/typings/index.d.ts | 7 +++++ 2 files changed, 33 insertions(+) diff --git a/packages/discord.js/src/structures/MessageReaction.js b/packages/discord.js/src/structures/MessageReaction.js index 43f05e32b417..8bf4a5a52c8c 100644 --- a/packages/discord.js/src/structures/MessageReaction.js +++ b/packages/discord.js/src/structures/MessageReaction.js @@ -43,6 +43,14 @@ class MessageReaction { } _patch(data) { + if ('burst_colors' in data) { + /** + * HEX colors used for super reaction + * @type {string[]} + */ + this.burstColors = data.burst_colors; + } + if ('count' in data) { /** * The number of people that have given the same reaction @@ -50,6 +58,24 @@ class MessageReaction { */ this.count ??= data.count; } + + if ('count_details' in data) { + /** + * The reaction count details object contains information about super and normal reaction counts. + * @typedef {Object} ReactionCountDetailsData + * @property {number} burst Count of super reaction + * @property {number} normal Count of normal reaction + */ + + /** + * The reaction count details object contains information about super and normal reaction counts. + * @type {?ReactionCountDetailsData} + */ + this.countDetails = { + burst: data.count_details.burst, + normal: data.count_details.normal, + }; + } } /** diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index fb06027cefd3..22ba612dbab0 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -2180,8 +2180,10 @@ export class MessageReaction { private constructor(client: Client, data: RawMessageReactionData, message: Message); private _emoji: GuildEmoji | ReactionEmoji; + public burstColors: string[]; public readonly client: Client; public count: number; + public countDetails: ReactionCountDetailsData; public get emoji(): GuildEmoji | ReactionEmoji; public me: boolean; public message: Message | PartialMessage; @@ -5906,6 +5908,11 @@ export interface MessageSelectOption { value: string; } +export interface ReactionCountDetailsData { + burst: number; + normal: number; +} + export interface SelectMenuComponentOptionData { default?: boolean; description?: string; From 1f93666e6a8b0b69102f1dfde3b137ff948ff18f Mon Sep 17 00:00:00 2001 From: Jiralite <33201955+Jiralite@users.noreply.github.com> Date: Wed, 21 Feb 2024 08:30:34 +0000 Subject: [PATCH 2/8] docs: Touch-up --- packages/discord.js/src/structures/MessageReaction.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/discord.js/src/structures/MessageReaction.js b/packages/discord.js/src/structures/MessageReaction.js index 8bf4a5a52c8c..45828fd426b8 100644 --- a/packages/discord.js/src/structures/MessageReaction.js +++ b/packages/discord.js/src/structures/MessageReaction.js @@ -45,7 +45,7 @@ class MessageReaction { _patch(data) { if ('burst_colors' in data) { /** - * HEX colors used for super reaction + * Hexadecimal colors used for this super reaction * @type {string[]} */ this.burstColors = data.burst_colors; @@ -63,13 +63,13 @@ class MessageReaction { /** * The reaction count details object contains information about super and normal reaction counts. * @typedef {Object} ReactionCountDetailsData - * @property {number} burst Count of super reaction - * @property {number} normal Count of normal reaction + * @property {number} burst Count of super reactions + * @property {number} normal Count of normal reactions */ /** * The reaction count details object contains information about super and normal reaction counts. - * @type {?ReactionCountDetailsData} + * @type {ReactionCountDetailsData} */ this.countDetails = { burst: data.count_details.burst, From fe90335fb33f67f41f4a540f143111885a6d5080 Mon Sep 17 00:00:00 2001 From: Jaw0r3k Date: Sat, 16 Mar 2024 14:06:31 +0100 Subject: [PATCH 3/8] feat: count super reactions in events --- .../src/client/actions/MessageReactionAdd.js | 6 +++-- .../client/actions/MessageReactionRemove.js | 5 +++-- .../src/structures/MessageReaction.js | 22 +++++++++++++++---- packages/discord.js/typings/index.d.ts | 4 ++-- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/packages/discord.js/src/client/actions/MessageReactionAdd.js b/packages/discord.js/src/client/actions/MessageReactionAdd.js index ea97bd60d56f..2c6a3a4a2247 100644 --- a/packages/discord.js/src/client/actions/MessageReactionAdd.js +++ b/packages/discord.js/src/client/actions/MessageReactionAdd.js @@ -36,17 +36,19 @@ class MessageReactionAdd extends Action { emoji: data.emoji, count: message.partial ? null : 0, me: user.id === this.client.user.id, + burst_colors: data.burst_colors, }); if (!reaction) return false; - reaction._add(user); + reaction._add(user, data.burst); if (fromStructure) return { message, reaction, user }; /** * Emitted whenever a reaction is added to a cached message. * @event Client#messageReactionAdd * @param {MessageReaction} messageReaction The reaction object * @param {User} user The user that applied the guild or reaction emoji + * @param {boolean} burst Determines when a super reaction is added */ - this.client.emit(Events.MessageReactionAdd, reaction, user); + this.client.emit(Events.MessageReactionAdd, reaction, user, data.burst); return { message, reaction, user }; } diff --git a/packages/discord.js/src/client/actions/MessageReactionRemove.js b/packages/discord.js/src/client/actions/MessageReactionRemove.js index 9ca3a8e5e951..14d44add658d 100644 --- a/packages/discord.js/src/client/actions/MessageReactionRemove.js +++ b/packages/discord.js/src/client/actions/MessageReactionRemove.js @@ -29,14 +29,15 @@ class MessageReactionRemove extends Action { // Verify reaction const reaction = this.getReaction(data, message, user); if (!reaction) return false; - reaction._remove(user); + reaction._remove(user, data.burst); /** * Emitted whenever a reaction is removed from a cached message. * @event Client#messageReactionRemove * @param {MessageReaction} messageReaction The reaction object * @param {User} user The user whose emoji or reaction emoji was removed + * @param {boolean} burst Determines when a super reaction was removed */ - this.client.emit(Events.MessageReactionRemove, reaction, user); + this.client.emit(Events.MessageReactionRemove, reaction, user, data.burst); return { message, reaction, user }; } diff --git a/packages/discord.js/src/structures/MessageReaction.js b/packages/discord.js/src/structures/MessageReaction.js index 45828fd426b8..e4e2236fe99c 100644 --- a/packages/discord.js/src/structures/MessageReaction.js +++ b/packages/discord.js/src/structures/MessageReaction.js @@ -147,17 +147,31 @@ class MessageReaction { return this._emoji.id ?? this._emoji.name; } - _add(user) { + _add(user, burst) { if (this.partial) return; this.users.cache.set(user.id, user); - if (!this.me || user.id !== this.message.client.user.id || this.count === 0) this.count++; + if (!this.me || user.id !== this.message.client.user.id || this.count === 0) { + this.count++; + if (burst) { + this.countDetails.burst++; + } else { + this.countDetails.normal++; + } + } this.me ||= user.id === this.message.client.user.id; } - _remove(user) { + _remove(user, burst) { if (this.partial) return; this.users.cache.delete(user.id); - if (!this.me || user.id !== this.message.client.user.id) this.count--; + if (!this.me || user.id !== this.message.client.user.id) { + this.count--; + if (burst) { + this.countDetails.burst--; + } else { + this.countDetails.normal--; + } + } if (user.id === this.message.client.user.id) this.me = false; if (this.count <= 0 && this.users.cache.size === 0) { this.message.reactions.cache.delete(this.emoji.id ?? this.emoji.name); diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 2ad71f026a86..62a576a00d81 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -5120,8 +5120,8 @@ export interface ClientEvents { ]; messageReactionRemoveEmoji: [reaction: MessageReaction | PartialMessageReaction]; messageDeleteBulk: [messages: Collection, channel: GuildTextBasedChannel]; - messageReactionAdd: [reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser]; - messageReactionRemove: [reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser]; + messageReactionAdd: [reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser, burst: boolean]; + messageReactionRemove: [reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser, burst: boolean]; messageUpdate: [oldMessage: Message | PartialMessage, newMessage: Message | PartialMessage]; presenceUpdate: [oldPresence: Presence | null, newPresence: Presence]; ready: [client: Client]; From 3ff64bbe1e015a2bd371f3d25445dc314f250b91 Mon Sep 17 00:00:00 2001 From: Jaw0r3k Date: Fri, 9 Aug 2024 00:54:14 +0200 Subject: [PATCH 4/8] feat: document me_burst property Co-authored-by: Danial Raza --- .../src/client/actions/MessageReactionAdd.js | 1 + .../src/structures/MessageReaction.js | 31 +++++++++++-------- packages/discord.js/typings/index.d.ts | 1 + 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/packages/discord.js/src/client/actions/MessageReactionAdd.js b/packages/discord.js/src/client/actions/MessageReactionAdd.js index 2c6a3a4a2247..01234d24b080 100644 --- a/packages/discord.js/src/client/actions/MessageReactionAdd.js +++ b/packages/discord.js/src/client/actions/MessageReactionAdd.js @@ -9,6 +9,7 @@ const Partials = require('../../util/Partials'); message_id: 'id', emoji: { name: '�', id: null }, channel_id: 'id', + burst: boolean // If originating from a guild guild_id: 'id', member: { ..., user: { ... } } } diff --git a/packages/discord.js/src/structures/MessageReaction.js b/packages/discord.js/src/structures/MessageReaction.js index e4e2236fe99c..6299b7297683 100644 --- a/packages/discord.js/src/structures/MessageReaction.js +++ b/packages/discord.js/src/structures/MessageReaction.js @@ -31,6 +31,12 @@ class MessageReaction { */ this.me = data.me; + /** + * Whether the client has super-reacted using this emoji + * @type {boolean} + */ + this.meBurst = data.me_burst; + /** * A manager of the users that have given this reaction * @type {ReactionUserManager} @@ -152,27 +158,26 @@ class MessageReaction { this.users.cache.set(user.id, user); if (!this.me || user.id !== this.message.client.user.id || this.count === 0) { this.count++; - if (burst) { - this.countDetails.burst++; - } else { - this.countDetails.normal++; - } + if (burst) this.countDetails.burst++; + else this.countDetails.normal++; + } + if (user.id === this.message.client.user.id) { + if (burst) this.meBurst = true; + else this.me = true; } - this.me ||= user.id === this.message.client.user.id; } - _remove(user, burst) { if (this.partial) return; this.users.cache.delete(user.id); if (!this.me || user.id !== this.message.client.user.id) { this.count--; - if (burst) { - this.countDetails.burst--; - } else { - this.countDetails.normal--; - } + if (burst) this.countDetails.burst--; + else this.countDetails.normal--; + } + if (user.id === this.message.client.user.id) { + if (burst) this.meBurst = false; + else this.me = false; } - if (user.id === this.message.client.user.id) this.me = false; if (this.count <= 0 && this.users.cache.size === 0) { this.message.reactions.cache.delete(this.emoji.id ?? this.emoji.name); } diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 62a576a00d81..4f31a13fe08e 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -2343,6 +2343,7 @@ export class MessageReaction { public countDetails: ReactionCountDetailsData; public get emoji(): GuildEmoji | ReactionEmoji; public me: boolean; + public meBurst: boolean; public message: Message | PartialMessage; public get partial(): false; public users: ReactionUserManager; From 3d92aa997bd9b8a84531043c859e2b05374c34a4 Mon Sep 17 00:00:00 2001 From: Jaw0r3k Date: Fri, 9 Aug 2024 22:03:09 +0200 Subject: [PATCH 5/8] feat: document type query for fetching reaction users --- packages/discord.js/src/managers/ReactionUserManager.js | 7 ++++--- packages/discord.js/typings/index.d.ts | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/discord.js/src/managers/ReactionUserManager.js b/packages/discord.js/src/managers/ReactionUserManager.js index 014cea8a3eae..c9a88be617be 100644 --- a/packages/discord.js/src/managers/ReactionUserManager.js +++ b/packages/discord.js/src/managers/ReactionUserManager.js @@ -2,7 +2,7 @@ const { Collection } = require('@discordjs/collection'); const { makeURLSearchParams } = require('@discordjs/rest'); -const { Routes } = require('discord-api-types/v10'); +const { ReactionType, Routes } = require('discord-api-types/v10'); const CachedManager = require('./CachedManager'); const { DiscordjsError, ErrorCodes } = require('../errors'); const User = require('../structures/User'); @@ -31,6 +31,7 @@ class ReactionUserManager extends CachedManager { /** * Options used to fetch users who gave a reaction. * @typedef {Object} FetchReactionUsersOptions + * @property {ReactionType} [type=ReactionType.Normal] The reaction type to fetch * @property {number} [limit=100] The maximum amount of users to fetch, defaults to `100` * @property {Snowflake} [after] Limit fetching users to those with an id greater than the supplied id */ @@ -40,9 +41,9 @@ class ReactionUserManager extends CachedManager { * @param {FetchReactionUsersOptions} [options] Options for fetching the users * @returns {Promise>} */ - async fetch({ limit = 100, after } = {}) { + async fetch({ type = ReactionType.Normal, limit = 100, after } = {}) { const message = this.reaction.message; - const query = makeURLSearchParams({ limit, after }); + const query = makeURLSearchParams({ limit, after, type }); const data = await this.client.rest.get( Routes.channelMessageReaction(message.channelId, message.id, this.reaction.emoji.identifier), { query }, diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index f9505b41e9a6..fe31f5b05271 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -181,6 +181,7 @@ import { APISelectMenuDefaultValue, SelectMenuDefaultValueType, InviteType, + ReactionType, } from 'discord-api-types/v10'; import { ChildProcess } from 'node:child_process'; import { EventEmitter } from 'node:events'; @@ -5693,6 +5694,7 @@ export interface FetchMessagesOptions { } export interface FetchReactionUsersOptions { + type?: ReactionType; limit?: number; after?: Snowflake; } From 782735e1c2072aacc6b4a373eaadd5cfcddf07a3 Mon Sep 17 00:00:00 2001 From: Jaw0r3k Date: Wed, 21 Aug 2024 00:46:32 +0200 Subject: [PATCH 6/8] fix: cover case when burstColors can be undefined at init of a reaction --- packages/discord.js/src/structures/MessageReaction.js | 4 +++- packages/discord.js/typings/index.d.ts | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/discord.js/src/structures/MessageReaction.js b/packages/discord.js/src/structures/MessageReaction.js index 6299b7297683..6a7114fe1d82 100644 --- a/packages/discord.js/src/structures/MessageReaction.js +++ b/packages/discord.js/src/structures/MessageReaction.js @@ -45,6 +45,8 @@ class MessageReaction { this._emoji = new ReactionEmoji(this, data.emoji); + this.burstColors = null; + this._patch(data); } @@ -52,7 +54,7 @@ class MessageReaction { if ('burst_colors' in data) { /** * Hexadecimal colors used for this super reaction - * @type {string[]} + * @type {?(string[])} */ this.burstColors = data.burst_colors; } diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index fe31f5b05271..a26c00db4671 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -2374,7 +2374,7 @@ export class MessageReaction { private constructor(client: Client, data: RawMessageReactionData, message: Message); private _emoji: GuildEmoji | ReactionEmoji; - public burstColors: string[]; + public burstColors: string[] | null; public readonly client: Client; public count: number; public countDetails: ReactionCountDetailsData; From d97935459c549b1d1595c7afdfcb8376cd006508 Mon Sep 17 00:00:00 2001 From: Jaw0r3k Date: Thu, 22 Aug 2024 14:41:41 +0200 Subject: [PATCH 7/8] Update packages/discord.js/src/structures/MessageReaction.js Co-authored-by: Vlad Frangu --- packages/discord.js/src/structures/MessageReaction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/discord.js/src/structures/MessageReaction.js b/packages/discord.js/src/structures/MessageReaction.js index 6a7114fe1d82..b6230bacb2ec 100644 --- a/packages/discord.js/src/structures/MessageReaction.js +++ b/packages/discord.js/src/structures/MessageReaction.js @@ -54,7 +54,7 @@ class MessageReaction { if ('burst_colors' in data) { /** * Hexadecimal colors used for this super reaction - * @type {?(string[])} + * @type {?string[]} */ this.burstColors = data.burst_colors; } From 46ce15a9c7251b3fd929d642f8bb2130a226ff12 Mon Sep 17 00:00:00 2001 From: Jaw0r3k Date: Tue, 27 Aug 2024 23:55:15 +0200 Subject: [PATCH 8/8] chore: futureproof so use an object --- .../src/client/actions/MessageReactionAdd.js | 9 +++++++-- .../src/client/actions/MessageReactionRemove.js | 4 ++-- packages/discord.js/typings/index.d.ts | 16 ++++++++++++++-- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/packages/discord.js/src/client/actions/MessageReactionAdd.js b/packages/discord.js/src/client/actions/MessageReactionAdd.js index 01234d24b080..e1da76e42171 100644 --- a/packages/discord.js/src/client/actions/MessageReactionAdd.js +++ b/packages/discord.js/src/client/actions/MessageReactionAdd.js @@ -42,14 +42,19 @@ class MessageReactionAdd extends Action { if (!reaction) return false; reaction._add(user, data.burst); if (fromStructure) return { message, reaction, user }; + /** + * Provides additional information about altered reaction + * @typedef {Object} MessageReactionEventDetails + * @property {boolean} burst Determines whether a super reaction was used + */ /** * Emitted whenever a reaction is added to a cached message. * @event Client#messageReactionAdd * @param {MessageReaction} messageReaction The reaction object * @param {User} user The user that applied the guild or reaction emoji - * @param {boolean} burst Determines when a super reaction is added + * @param {MessageReactionEventDetails} details Details of adding the reaction */ - this.client.emit(Events.MessageReactionAdd, reaction, user, data.burst); + this.client.emit(Events.MessageReactionAdd, reaction, user, { burst: data.burst }); return { message, reaction, user }; } diff --git a/packages/discord.js/src/client/actions/MessageReactionRemove.js b/packages/discord.js/src/client/actions/MessageReactionRemove.js index 14d44add658d..7dc9777b9d68 100644 --- a/packages/discord.js/src/client/actions/MessageReactionRemove.js +++ b/packages/discord.js/src/client/actions/MessageReactionRemove.js @@ -35,9 +35,9 @@ class MessageReactionRemove extends Action { * @event Client#messageReactionRemove * @param {MessageReaction} messageReaction The reaction object * @param {User} user The user whose emoji or reaction emoji was removed - * @param {boolean} burst Determines when a super reaction was removed + * @param {MessageReactionEventDetails} details Details of removing the reaction */ - this.client.emit(Events.MessageReactionRemove, reaction, user, data.burst); + this.client.emit(Events.MessageReactionRemove, reaction, user, { burst: data.burst }); return { message, reaction, user }; } diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index a26c00db4671..59ee9154ccfe 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -2391,6 +2391,10 @@ export class MessageReaction { public valueOf(): Snowflake | string; } +export interface MessageReactionEventDetails { + burst: boolean; +} + export interface ModalComponentData { customId: string; title: string; @@ -5249,8 +5253,16 @@ export interface ClientEvents { messages: ReadonlyCollection, channel: GuildTextBasedChannel, ]; - messageReactionAdd: [reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser, burst: boolean]; - messageReactionRemove: [reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser, burst: boolean]; + messageReactionAdd: [ + reaction: MessageReaction | PartialMessageReaction, + user: User | PartialUser, + details: MessageReactionEventDetails, + ]; + messageReactionRemove: [ + reaction: MessageReaction | PartialMessageReaction, + user: User | PartialUser, + details: MessageReactionEventDetails, + ]; messageUpdate: [oldMessage: Message | PartialMessage, newMessage: Message | PartialMessage]; presenceUpdate: [oldPresence: Presence | null, newPresence: Presence]; ready: [client: Client];