Skip to content

Commit

Permalink
feat(Reactions): Support super reactions (#1470)
Browse files Browse the repository at this point in the history
Co-authored-by: bsian03 <[email protected]>
  • Loading branch information
conorwastakenwastaken and bsian03 authored Jul 11, 2024
1 parent 0d81657 commit 793e858
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 9 deletions.
24 changes: 21 additions & 3 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ declare namespace Eris {
type MessageContent = string | AdvancedMessageContent;
type MessageContentEdit = string | AdvancedMessageContentEdit;
type PossiblyUncachedMessage = Message | { channel: TextableChannel | { id: string; guild?: Uncached }; guildID?: string; id: string };
type ReactionTypes = Constants["ReactionTypes"][keyof Constants["ReactionTypes"]];

// Permission
type PermissionType = Constants["PermissionOverwriteTypes"][keyof Constants["PermissionOverwriteTypes"]];
Expand Down Expand Up @@ -948,8 +949,8 @@ declare namespace Eris {
messageCreate: [message: Message<PossiblyUncachedTextableChannel>];
messageDelete: [message: PossiblyUncachedMessage];
messageDeleteBulk: [messages: PossiblyUncachedMessage[]];
messageReactionAdd: [message: PossiblyUncachedMessage, emoji: PartialEmoji, reactor: Member | Uncached];
messageReactionRemove: [message: PossiblyUncachedMessage, emoji: PartialEmoji, userID: string];
messageReactionAdd: [message: PossiblyUncachedMessage, emoji: PartialEmoji, reactor: Member | Uncached, burst: boolean];
messageReactionRemove: [message: PossiblyUncachedMessage, emoji: PartialEmoji, userID: string, burst: boolean];
messageReactionRemoveAll: [message: PossiblyUncachedMessage];
messageReactionRemoveEmoji: [message: PossiblyUncachedMessage, emoji: PartialEmoji];
messageUpdate: [message: Message<PossiblyUncachedTextableChannel>, oldMessage: OldMessage | null];
Expand Down Expand Up @@ -1542,6 +1543,7 @@ declare namespace Eris {
/** @deprecated */
before?: string;
limit?: number;
type?: ReactionTypes;
}
interface InteractionButton extends ButtonBase {
custom_id: string;
Expand Down Expand Up @@ -1582,6 +1584,18 @@ declare namespace Eris {
filename?: string;
id: string | number;
}
interface Reaction {
burst_colors: string[];
count: number;
count_details: ReactionCountDetails;
me: boolean;
me_burst: boolean;
type: ReactionTypes;
}
interface ReactionCountDetails {
burst: number;
normal: number;
}
interface SelectMenu {
custom_id: string;
disabled?: boolean;
Expand Down Expand Up @@ -2456,6 +2470,10 @@ declare namespace Eris {
RoleFlags: {
IN_PROMPT: 1;
};
ReactionTypes: {
NORMAL: 0;
BURST: 1;
};
StageInstancePrivacyLevel: {
PUBLIC: 1;
GUILD_ONLY: 2;
Expand Down Expand Up @@ -3816,7 +3834,7 @@ declare namespace Eris {
messageReference: MessageReference | null;
pinned: boolean;
prefix?: string;
reactions: { [s: string]: { count: number; me: boolean } };
reactions: { [s: string]: Reaction };
referencedMessage?: Message | null;
roleMentions: string[];
roleSubscriptionData?: RoleSubscriptionData;
Expand Down
1 change: 1 addition & 0 deletions lib/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -3091,6 +3091,7 @@ class Client extends EventEmitter {
* @arg {Object} [options] Options for the request. If this is a number ([DEPRECATED] behavior), it is treated as `options.limit`
* @arg {String} [options.after] Get users after this user ID
* @arg {Number} [options.limit=100] The maximum number of users to get
* @arg {Number} [options.type=0] The type of reaction (`0` for normal, `1` for burst)
* @arg {String} [before] [DEPRECATED] Get users before this user ID. Discord no longer supports this parameter
* @arg {String} [after] [DEPRECATED] Get users after this user ID
* @returns {Promise<Array<User>>}
Expand Down
5 changes: 5 additions & 0 deletions lib/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,11 @@ module.exports.PremiumTypes = {
NITRO: 2
};

module.exports.ReactionTypes = {
NORMAL: 0,
BURST: 1
};

module.exports.RoleConnectionMetadataTypes = {
INTEGER_LESS_THAN_OR_EQUAL: 1,
INTEGER_GREATER_THAN_OR_EQUAL: 2,
Expand Down
26 changes: 22 additions & 4 deletions lib/gateway/Shard.js
Original file line number Diff line number Diff line change
Expand Up @@ -1117,13 +1117,25 @@ class Shard extends EventEmitter {
const reaction = packet.d.emoji.id ? `${packet.d.emoji.name}:${packet.d.emoji.id}` : packet.d.emoji.name;
if(message.reactions[reaction]) {
++message.reactions[reaction].count;
++message.reactions[reaction].count_details[packet.d.burst ? "burst" : "normal"];
if(packet.d.user_id === this.client.user.id) {
message.reactions[reaction].me = true;
if(packet.d.burst) {
message.reactions[reaction].me_burst = true;
}
}
message.reactions[reaction].burst_colors = packet.d.burst_colors;
} else {
message.reactions[reaction] = {
burst_colors: packet.d.burst_colors,
count: 1,
me: packet.d.user_id === this.client.user.id
count_details: {
burst: +packet.d.burst,
normal: +!packet.d.burst
},
me: packet.d.user_id === this.client.user.id && !packet.d.burst,
me_burst: packet.d.user_id === this.client.user.id && packet.d.burst,
type: packet.d.type
};
}
} else {
Expand All @@ -1148,8 +1160,9 @@ class Shard extends EventEmitter {
* @prop {String?} emoji.id The emoji ID (null for non-custom emojis)
* @prop {String} emoji.name The emoji name
* @prop {Member | Object} reactor The member, if the reaction is in a guild. If the reaction is not in a guild, this will be an object with an `id` key. No other property is guaranteed
* @prop {Boolean} burst Whether the reaction is a super reaction
*/
this.emit("messageReactionAdd", message, packet.d.emoji, member || {id: packet.d.user_id});
this.emit("messageReactionAdd", message, packet.d.emoji, member || {id: packet.d.user_id}, packet.d.burst);
break;
}
case "MESSAGE_REACTION_REMOVE": {
Expand All @@ -1163,10 +1176,14 @@ class Shard extends EventEmitter {
const reactionObj = message.reactions[reaction];
if(reactionObj) {
--reactionObj.count;
--reactionObj.count_details[packet.d.burst ? "burst" : "normal"];
if(reactionObj.count === 0) {
delete message.reactions[reaction];
} else if(packet.d.user_id === this.client.user.id) {
reactionObj.me = false;
message.reactions[reaction].me = false;
if(packet.d.burst) {
message.reactions[reaction].me_burst = false;
}
}
}
} else {
Expand All @@ -1191,8 +1208,9 @@ class Shard extends EventEmitter {
* @prop {String?} emoji.id The ID of the emoji (null for non-custom emojis)
* @prop {String} emoji.name The emoji name
* @prop {String} userID The ID of the user that removed the reaction
* @prop {Boolean} burst Whether the reaction is a super reaction
*/
this.emit("messageReactionRemove", message, packet.d.emoji, packet.d.user_id);
this.emit("messageReactionRemove", message, packet.d.emoji, packet.d.user_id, packet.d.burst);
break;
}
case "MESSAGE_REACTION_REMOVE_ALL": {
Expand Down
1 change: 1 addition & 0 deletions lib/structures/DMChannel.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ class DMChannel extends Channel {
* @arg {Object} [options] Options for the request. If this is a number, it is treated as `options.limit` ([DEPRECATED] behavior)
* @arg {String} [options.after] Get users after this user ID
* @arg {Number} [options.limit=100] The maximum number of users to get
* @arg {Number} [options.type=0] The type of reaction (`0` for normal, `1` for burst)
* @arg {String} [before] [DEPRECATED] Get users before this user ID. Discord no longer supports this parameter
* @arg {String} [after] [DEPRECATED] Get users after this user ID
* @returns {Promise<Array<User>>}
Expand Down
1 change: 1 addition & 0 deletions lib/structures/GuildTextableChannel.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ class GuildTextableChannel extends GuildChannel {
* @arg {Object} [options] Options for the request. If this is a number, it is treated as `options.limit` ([DEPRECATED] behavior)
* @arg {String} [options.after] Get users after this user ID
* @arg {Number} [options.limit=100] The maximum number of users to get
* @arg {Number} [options.type=0] The type of reaction (`0` for normal, `1` for burst)
* @arg {String} [before] [DEPRECATED] Get users before this user ID. Discord no longer supports this parameter
* @arg {String} [after] [DEPRECATED] Get users after this user ID
* @returns {Promise<Array<User>>}
Expand Down
8 changes: 6 additions & 2 deletions lib/structures/Message.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const User = require("./User");
* @prop {String?} messageReference.messageID The ID of the original message this message was crossposted from
* @prop {Boolean} pinned Whether the message is pinned or not
* @prop {String?} prefix The prefix used in the Message, if any (CommandClient only)
* @prop {Object} reactions An object containing the reactions on the message. Each key is a reaction emoji and each value is an object with properties `me` (Boolean) and `count` (Number) for that specific reaction emoji.
* @prop {Object} reactions An object containing the reactions on the message. Each key is a reaction emoji and each value is an object with properties `burst_colors` (Array<String>), `count` (Number), `count_details` (an object with `burst` and `normal` keys corresponding to the amount of reactions), `me` (Boolean) and `me_burst` for that specific reaction emoji.
* @prop {Message?} referencedMessage The message that was replied to. If undefined, message data was not received. If null, the message was deleted.
* @prop {Array<String>} roleMentions Array of mentioned roles' ids
* @prop {Object?} roleSubscriptionData An object containing the data of the role subscription purchase or renewal that prompted this `ROLE_SUBSCRIPTION_PURCHASE` message. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#role-subscription-data-object) for object structure
Expand Down Expand Up @@ -209,8 +209,11 @@ class Message extends Base {
if(data.reactions) {
data.reactions.forEach((reaction) => {
this.reactions[reaction.emoji.id ? `${reaction.emoji.name}:${reaction.emoji.id}` : reaction.emoji.name] = {
burst_colors: reaction.burst_colors,
count: reaction.count,
me: reaction.me
count_details: reaction.count_details,
me: reaction.me,
me_burst: reaction.me_burst
};
});
}
Expand Down Expand Up @@ -447,6 +450,7 @@ class Message extends Base {
* @arg {Object} [options] Options for the request. If this is a number, it is treated as `options.limit` ([DEPRECATED] behavior)
* @arg {String} [options.after] Get users after this user ID
* @arg {Number} [options.limit=100] The maximum number of users to get
* @arg {Number} [options.type=0] The type of reaction (`0` for normal, `1` for burst)
* @arg {String} [before] [DEPRECATED] Get users before this user ID. Discord no longer supports this parameter
* @arg {String} [after] [DEPRECATED] Get users after this user ID
* @returns {Promise<Array<User>>}
Expand Down

0 comments on commit 793e858

Please sign in to comment.