Skip to main content

Reactions

Overview

The Reactions module lets players attach arbitrary reaction types (for example like, dislike, emoji-style ids such as heart, poop, lol, or service marks like view) to supported entities. For each entity the SDK exposes:

  • reactions — an object reaction type → total count across all players (aggregated counters).
  • playerReactions — a list of reaction types the current player has left on this entity.

The server remembers whether the player has set a given reaction on a given entity, so you can build likes, voting, “seen” marks, and custom emoji bars.

Reactions are available for:

tip

reactionType is a free-form string. Agree on a fixed set of keys in your game (like, dislike, heart, view, …) so the UI and analytics stay consistent.

Set reaction

+1 Request

Adds the current player’s reaction to the entity (if it is not already set for this player and this reactionType, depending on server rules).

await gp.reactions.set({
// Entity kind: "CHANNEL" | "CHANNEL_MESSAGE" | "FILE" | "IMAGE"
entityType: 'FILE',
// Entity ID (string; use the same format as elsewhere in the API)
entityId: '12333',
// Any non-empty string identifier you use in the game
reactionType: 'like',
});

Examples: like / dislike on a channel message

const messageId = '884422';

await gp.reactions.set({
entityType: 'CHANNEL_MESSAGE',
entityId: messageId,
reactionType: 'like',
});

await gp.reactions.set({
entityType: 'CHANNEL_MESSAGE',
entityId: messageId,
reactionType: 'dislike',
});

Examples: custom emoji-style keys

// “Heart”, “poop”, “lol” — only names; map them to icons in your UI
await gp.reactions.set({
entityType: 'IMAGE',
entityId: '771209',
reactionType: 'heart',
});

await gp.reactions.set({
entityType: 'IMAGE',
entityId: '771209',
reactionType: 'poop',
});

await gp.reactions.set({
entityType: 'CHANNEL_MESSAGE',
entityId: '112233',
reactionType: 'lol',
});

Remove reaction

+1 Request

Removes the current player’s reaction of the given type from the entity.

await gp.reactions.unset({
entityType: 'FILE',
entityId: '12333',
reactionType: 'like',
});

Events

Subscribe to successful updates and errors.

gp.reactions.on('set', ({ entityType, entityId, reactionType, counter }) => {
// counter — updated total count for this reaction type on the entity
});

gp.reactions.on('unset', ({ entityType, entityId, reactionType, counter }) => {});

gp.reactions.on('set:error', (error) => {});
gp.reactions.on('unset:error', (error) => {});

Real-time notifications

Real-time reaction notifications are also available. They let you see how other players add and remove reactions while you are in the channel.

At the moment, these events work only for the channel message entity.

gp.reactions.on('event:set', ({ entityType, entityId, reactionType, counter }) => {
// counter — updated total count for this reaction type on the entity
});

gp.reactions.on('event:unset', ({ entityType, entityId, reactionType, counter }) => {
// counter — updated total count for this reaction type on the entity
});

Reading counters and player reactions

After you load an entity with the usual methods (fetchChannel, fetchMessages, files.fetch, images.fetch, etc.), read:

  • Totals: entity.reactions[reactionType] (number of reactions of that type from all players).
  • Current player: entity.playerReactions — array of entries; check reactionType to see if the player has reacted.
const channel = await gp.channels.fetchChannel({ channelId: 123 });

const likesCount = channel.reactions.like ?? 0;

const hasLike = channel.playerReactions.some((r) => r.reactionType === 'like');

Channel

const channel = await gp.channels.fetchChannel({ channelId: 123 });

const upvotes = channel.reactions.like ?? 0;
const downvotes = channel.reactions.dislike ?? 0;

const playerLiked = channel.playerReactions.some((r) => r.reactionType === 'like');

Channel message

Use the message id from fetching messages (same id you pass as entityId for CHANNEL_MESSAGE).

const { items: messages } = await gp.channels.fetchMessages({ channelId: 123 });

messages.forEach((message) => {
const heartCount = message.reactions.heart ?? 0;
const playerSentHeart = message.playerReactions.some((r) => r.reactionType === 'heart');
});

File

const { items: files } = await gp.files.fetch();

const file = files.find((f) => String(f.id) === '12333');
if (file) {
const likes = file.reactions.like ?? 0;
const iLiked = file.playerReactions.some((r) => r.reactionType === 'like');
}

Image

const { items: images } = await gp.images.fetch();

const image = images.find((img) => String(img.id) === '771209');
if (image) {
const lolCount = image.reactions.lol ?? 0;
const playerLol = image.playerReactions.some((r) => r.reactionType === 'lol');
}

Example: “viewed” mark on a file

Use a dedicated reaction type (for example view) as a lightweight “player has opened this file” flag: set it when the player views the file, then check playerReactions on later loads.

const fileId = '55501';

// When the player opens the document viewer
await gp.reactions.set({
entityType: 'FILE',
entityId: fileId,
reactionType: 'view',
});

// Later: after fetch, see if this player already “viewed” the file
const { items } = await gp.files.fetch();
const file = items.find((f) => String(f.id) === fileId);

const totalViews = file?.reactions.view ?? 0;
const playerHasViewed = file?.playerReactions.some((r) => r.reactionType === 'view') ?? false;

To clear the mark for the current player (if your design requires it):

await gp.reactions.unset({
entityType: 'FILE',
entityId: fileId,
reactionType: 'view',
});

Types

entityType values

ValueEntity
CHANNELChannel
CHANNEL_MESSAGEChannel message
FILEFile
IMAGEImage

Fields on entities

FieldTypeDescription
reactionsRecord<string, number>Counts per reactionType for all players
playerReactionsArray<{ reactionType: string, ... }>Reactions the current player set on this entity

Exact optional fields on playerReactions items may be extended by the SDK; always rely on reactionType for checks.

Stay in Touch

Other documents of this chapter available Here. To get started, welcome to the Tutorials chapter.

GamePush Community Telegram: @gs_community.

For your suggestions e-mail: official@gamepush.com

We Wish you Success!