reactionId: a unicode emoji for the common case, or a custom emoji id for server-specific emoji. This page covers both sides, adding reactions and listening for them.
Add a reaction
Callmsg.react(reactionId) on a Message to add the bot’s reaction. It returns Promise<void> and requires the reaction_add permission. For a plain emoji, pass the unicode character directly.
if (msg.isDM || !msg.serverId) return; guard does two jobs. It keeps react() away from DM messages, and it narrows msg.serverId from string | null to string so can() accepts it. Without it, TypeScript rejects the can() call and plain JavaScript silently returns false for a null server.
The reactionId is opaque. The SDK does not validate it and passes it straight through to the server. An invalid id is refused by the server, not caught locally.
Remove the bot’s reaction
Callmsg.unreact(reactionId) to remove the bot’s own reaction from a message. It only affects the reaction the bot added, not anyone else’s.
React with a custom emoji
For a server’s custom emoji, pass its id instead of a unicode character. Get ids fromclient.fetchEmojis(), which returns Promise<{ emojis, category }>, the global emoji catalog. Its ids are exactly the custom-emoji ids that react() accepts.
The shape of
emojis and category is defined by the server, so treat them as data to look ids up in rather than a fixed structure.Listen for reaction changes
ThereactionUpdate event fires when a reaction is added or removed on a message your bot can see. It is not scoped to a channel you selected: on a current Cloak server it arrives for every server the bot is in, the same way messageCreate does. Filter on channelId if you care about one place.
string
The message whose reactions changed.
string
The reaction that changed, the same opaque id you pass to
react().number
The new total for that reaction on the message. The event does not say whether the change was an add or a remove, only the new count.
string
The user who added or removed the reaction.
string
The server the message belongs to.
string
The channel the message belongs to.
count is the new total and no add-or-remove flag is included, treat the event as “this reaction now has this many”, not “someone just added one”.
Filter out the bot’s own reactions
reactionUpdate fires for the bot’s own reactions too, including the ones it adds with react(). When that matters, filter on userId.
On an older Cloak server,
serverId and channelId on reactionUpdate can fall back to the bot’s currently selected server and channel. An up-to-date Cloak server always reports the message’s own location.React to being mentioned
A reaction acknowledges something without adding a message to the channel, which makes it a good pairing withmsg.mentionsMe.
mentionsMe does and does not cover.
Handling errors
Three different failures are worth telling apart.Plain Error, before the wire
Plain Error, before the wire
react() and unreact() reject with a plain Error in two cases. On a direct message, unconditionally. And when the message has no createdAt, which the server needs to locate the row. Live messages from messageCreate and messages loaded with fetchMessages both carry createdAt, so in practice only the DM case comes up.CloakActionError, from the server
CloakActionError, from the server
Both methods reject with
CloakActionError when the server refuses. Read .code for the reason and .permission for the missing permission when the code maps to one.A timeout on an older server
A timeout on an older server
Confirming a reaction needs a Cloak server new enough to send the bot a success acknowledgement. Against an older backend the call cannot confirm and times out even though the reaction landed. See What the server must support.
can('reaction_add', serverId) to skip actions the server would only refuse, and still catch the promise for the cases you cannot predict.
Next
Editing, deleting, and pinning
The other four message actions, under the same DM rule.
The Message object
Every field and method a received message carries.
Handling errors
Working with
CloakActionError and friends.Permissions
Why
reaction_add must be granted first.