mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-10 00:23:30 +01:00
feat: super reactions (#9336)
* feat: super reactions * docs: Touch-up * feat: count super reactions in events * feat: document me_burst property Co-authored-by: Danial Raza <danialrazafb@gmail.com> * feat: document type query for fetching reaction users * fix: cover case when burstColors can be undefined at init of a reaction * Update packages/discord.js/src/structures/MessageReaction.js Co-authored-by: Vlad Frangu <me@vladfrangu.dev> * chore: futureproof so use an object --------- Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com> Co-authored-by: Danial Raza <danialrazafb@gmail.com> Co-authored-by: Vlad Frangu <me@vladfrangu.dev> Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
This commit is contained in:
@@ -9,6 +9,7 @@ const Partials = require('../../util/Partials');
|
||||
message_id: 'id',
|
||||
emoji: { name: '<27>', id: null },
|
||||
channel_id: 'id',
|
||||
burst: boolean
|
||||
// If originating from a guild
|
||||
guild_id: 'id',
|
||||
member: { ..., user: { ... } } }
|
||||
@@ -36,17 +37,24 @@ 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 };
|
||||
/**
|
||||
* 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 {MessageReactionEventDetails} details Details of adding the reaction
|
||||
*/
|
||||
this.client.emit(Events.MessageReactionAdd, reaction, user);
|
||||
this.client.emit(Events.MessageReactionAdd, reaction, user, { burst: data.burst });
|
||||
|
||||
return { message, reaction, user };
|
||||
}
|
||||
|
||||
@@ -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 {MessageReactionEventDetails} details Details of removing the reaction
|
||||
*/
|
||||
this.client.emit(Events.MessageReactionRemove, reaction, user);
|
||||
this.client.emit(Events.MessageReactionRemove, reaction, user, { burst: data.burst });
|
||||
|
||||
return { message, reaction, user };
|
||||
}
|
||||
|
||||
@@ -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<Collection<Snowflake, User>>}
|
||||
*/
|
||||
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 },
|
||||
|
||||
@@ -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}
|
||||
@@ -39,10 +45,20 @@ class MessageReaction {
|
||||
|
||||
this._emoji = new ReactionEmoji(this, data.emoji);
|
||||
|
||||
this.burstColors = null;
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
if ('burst_colors' in data) {
|
||||
/**
|
||||
* Hexadecimal colors used for this 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 +66,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 reactions
|
||||
* @property {number} normal Count of normal reactions
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,18 +155,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++;
|
||||
this.me ||= user.id === this.message.client.user.id;
|
||||
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 (user.id === this.message.client.user.id) {
|
||||
if (burst) this.meBurst = true;
|
||||
else this.me = true;
|
||||
}
|
||||
}
|
||||
|
||||
_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 (user.id === this.message.client.user.id) this.me = false;
|
||||
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) {
|
||||
if (burst) this.meBurst = false;
|
||||
else this.me = false;
|
||||
}
|
||||
if (this.count <= 0 && this.users.cache.size === 0) {
|
||||
this.message.reactions.cache.delete(this.emoji.id ?? this.emoji.name);
|
||||
}
|
||||
|
||||
26
packages/discord.js/typings/index.d.ts
vendored
26
packages/discord.js/typings/index.d.ts
vendored
@@ -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';
|
||||
@@ -2414,10 +2415,13 @@ export class MessageReaction {
|
||||
private constructor(client: Client<true>, data: RawMessageReactionData, message: Message);
|
||||
private _emoji: GuildEmoji | ReactionEmoji;
|
||||
|
||||
public burstColors: string[] | null;
|
||||
public readonly client: Client<true>;
|
||||
public count: number;
|
||||
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;
|
||||
@@ -2428,6 +2432,10 @@ export class MessageReaction {
|
||||
public valueOf(): Snowflake | string;
|
||||
}
|
||||
|
||||
export interface MessageReactionEventDetails {
|
||||
burst: boolean;
|
||||
}
|
||||
|
||||
export interface ModalComponentData {
|
||||
customId: string;
|
||||
title: string;
|
||||
@@ -5294,8 +5302,16 @@ export interface ClientEvents {
|
||||
messages: ReadonlyCollection<Snowflake, Message | PartialMessage>,
|
||||
channel: GuildTextBasedChannel,
|
||||
];
|
||||
messageReactionAdd: [reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser];
|
||||
messageReactionRemove: [reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser];
|
||||
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<true>];
|
||||
@@ -5740,6 +5756,7 @@ export interface FetchMessagesOptions {
|
||||
}
|
||||
|
||||
export interface FetchReactionUsersOptions {
|
||||
type?: ReactionType;
|
||||
limit?: number;
|
||||
after?: Snowflake;
|
||||
}
|
||||
@@ -6475,6 +6492,11 @@ export interface MessageSelectOption {
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface ReactionCountDetailsData {
|
||||
burst: number;
|
||||
normal: number;
|
||||
}
|
||||
|
||||
export interface SelectMenuComponentOptionData {
|
||||
default?: boolean;
|
||||
description?: string;
|
||||
|
||||
Reference in New Issue
Block a user