# How to Handle Message Reactions and Read Receipts in LINEJS

> Learn to handle message reactions and read receipts in LINEJS using Message react and read methods or direct service access. Boost your LINE bot development.

- Repository: [Evex  Developers/linejs](https://github.com/evex-dev/linejs)
- Tags: how-to-guide
- Published: 2026-03-01

---

**To handle message reactions and read receipts in LINEJS, use the `Message.react()` and `Message.read()` methods for high-level operations, or call `client.base.talk.react()` and `client.base.talk.sendChatChecked()` for direct service access.**

LINEJS is a TypeScript client library that abstracts the LINE Messaging API into an intuitive service layer. When you handle message reactions and read receipts in LINEJS, you interact with a three-tier architecture: high-level `Message` wrappers, underlying service implementations, and Thrift RPC builders. This guide covers both the convenient instance methods and the low-level service calls used by the evex-dev/linejs codebase.

## Understanding the LINEJS Architecture

LINEJS organizes messaging operations into distinct layers that ultimately generate Thrift RPCs. At the highest level, the `Message` class in [`packages/linejs/client/features/message/talk.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/client/features/message/talk.ts) provides user-friendly methods. These wrap the **TalkService** in [`packages/linejs/base/service/talk/mod.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/service/talk/mod.ts), which constructs payloads using builders defined in [`packages/linejs/base/thrift/readwrite/struct.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/thrift/readwrite/struct.ts). All communication flows through protocol 4 (the "Talk" protocol) to the `/S4` endpoint.

The two primary operations follow this flow:

- **React to a message**: `Message.react()` → `TalkService.react()` → `LINEStruct.react_args` → `/S4`
- **Send read receipt**: `Message.read()` → `TalkService.sendChatChecked()` → `LINEStruct.sendChatChecked_args` → `/S4`

## How to React to Messages in LINEJS

You can add emoji reactions using either the high-level Message API or direct service calls. Both approaches generate the same `react` RPC defined in the LINE protocol.

### Using the High-Level Message API

The simplest approach uses the `react()` method available on `Message` instances. When you receive a message through the event system, call `react()` with a `MessageReactionType` enum value.

```typescript
import { MessageReactionType } from "@evex/linejs-types";
import { LineClient } from "@evex/linejs";

async function addReaction(client: LineClient, msgId: string) {
  const msg = await client.base.talk.getMessage({ id: msgId });
  
  // React with the predefined 👍 (LIKE) reaction
  await msg.react(MessageReactionType.LIKE);
}

```

According to the evex-dev/linejs source code, this method (lines 101-110 in [`packages/linejs/client/features/message/talk.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/client/features/message/talk.ts)) forwards to `client.base.talk.react()` after converting the message ID to a BigInt.

### Direct Talk Service Implementation

For batch operations or when working with raw IDs, use `TalkService.react()` directly. This method builds a Thrift request using `LINEStruct.react_args` (defined at lines 706-712 in [`packages/linejs/base/thrift/readwrite/struct.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/thrift/readwrite/struct.ts)).

```typescript
import { MessageReactionType } from "@evex/linejs-types";

async function lowLevelReact(client: LineClient) {
  // React to a message without a Message wrapper
  await client.base.talk.react({
    id: 1234567890n,               // message ID as bigint
    reaction: MessageReactionType.HEART,
  });
}

```

The implementation in [`packages/linejs/base/service/talk/mod.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/service/talk/mod.ts) (lines 701-719) constructs the payload with `reqSeq: 0`, the target `messageId`, and the `predefinedReactionType` enum before dispatching via `client.request.request()`.

## How to Send Read Receipts in LINEJS

Read receipts (chat checked notifications) inform senders that you've viewed their messages. LINEJS provides both automated and manual methods for sending these receipts.

### Marking Messages as Read via Message Instance

The `Message.read()` method automatically handles MID resolution and request sequencing. It determines the correct chat MID based on whether the message is incoming or outgoing (using `this.isMyMessage` to choose between `this.to.id` and `this.from.id`).

```typescript
async function markAsRead(client: LineClient, msgId: string) {
  const msg = await client.base.talk.getMessage({ id: msgId });
  
  // Sends the read receipt (chat checked) to LINE
  await msg.read();
}

```

This wrapper calls `client.base.talk.sendChatChecked()` with the chat MID, last message ID, and a fresh sequence number from `client.base.getReqseq()` (lines 115-122 in [`packages/linejs/client/features/message/talk.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/client/features/message/talk.ts)).

### Manual Read Receipt Delivery

Use `sendChatChecked()` directly when you need precise control over the chat MID and message ID, or when processing messages outside the standard `Message` instance context.

```typescript
async function manualReadReceipt(client: LineClient) {
  await client.base.talk.sendChatChecked({
    chatMid: "c1234567890",        // chat MID
    lastMessageId: "1234567890",   // message ID as string
    seq: await client.base.getReqseq(),
  });
}

```

The service implementation in [`packages/linejs/base/service/talk/mod.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/service/talk/mod.ts) (lines 989-1012) uses `LINEStruct.sendChatChecked_args` (defined at lines 8438-8442 in [`packages/linejs/base/thrift/readwrite/struct.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/thrift/readwrite/struct.ts)) to build the Thrift payload for the `sendChatChecked` RPC.

## Handling Square (Group/Room) Chats

For Square chats (groups and rooms), LINEJS provides analogous methods in the SquareService with similar signatures but different underlying RPCs.

### Reactions and Read Receipts in Square Chats

Use `client.base.square.reactToMessage()` and `client.base.square.markAsRead()` for Square-specific operations. These are implemented in [`packages/linejs/base/service/square/mod.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/service/square/mod.ts) at lines 73-80 and 61-66 respectively.

```typescript
import { MessageReactionType } from "@evex/linejs-types";

async function squareDemo(client: LineClient, messageId: string, roomMid: string) {
  // React to a Square message
  await client.base.square.reactToMessage({
    messageId,
    reaction: MessageReactionType.LIKE,
  });

  // Mark the Square chat as read up to the latest message
  await client.base.square.markAsRead({
    chatMid: roomMid,
    lastReadMessageId: messageId,
    seq: await client.base.getReqseq(),
  });
}

```

Both Square methods follow the same fire-and-forget pattern as their Talk counterparts, with the server pushing downstream events like `MessageReactionsUpdated` or `ReadReceiptUpdated` to other clients.

## Summary

- **Message.react()** provides a high-level interface for adding reactions, automatically converting string IDs to BigInt and handling the `MessageReactionType` enum mapping.
- **Message.read()** simplifies read receipts by resolving chat MIDs based on message direction and managing request sequences via `getReqseq()`.
- **Direct service calls** (`client.base.talk.react()` and `client.base.talk.sendChatChecked()`) offer flexibility for batch operations or custom workflows requiring raw ID access.
- **Square chats** use separate service methods (`reactToMessage` and `markAsRead`) implemented in [`packages/linejs/base/service/square/mod.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/service/square/mod.ts).
- All operations generate Thrift RPCs via `LINEStruct` builders and transmit over protocol 4 to the `/S4` endpoint according to the LINE protocol specification.

## Frequently Asked Questions

### What is the difference between `Message.react()` and `client.base.talk.react()`?

`Message.react()` is a convenience wrapper that accepts a `MessageReactionType` enum and handles BigInt conversion for the message ID before calling `client.base.talk.react()`. The direct service method requires you to pass the message ID as a BigInt and the reaction type explicitly. Both ultimately generate the same `react_args` Thrift payload sent to the `/S4` endpoint.

### How does LINEJS handle request sequencing for read receipts?

LINEJS manages request sequences through `client.base.getReqseq()`, which generates a monotonic sequence number for each operation. When you call `Message.read()` or `client.base.talk.sendChatChecked()`, the library includes this `seq` value in the Thrift payload. The LINE servers use this sequence to track operation ordering and prevent duplicate receipts across reconnections.

### Can I use custom emoji reactions with LINEJS?

The current implementation in [`packages/linejs/base/service/talk/mod.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/service/talk/mod.ts) uses `predefinedReactionType`, which maps to the `MessageReactionType` enum (LIKE, LOVE, HAHA, etc.). Custom emoji reactions are not supported through the `react()` method; you must use the predefined enum values provided by the LINE protocol as defined in [`packages/types/line_types.ts`](https://github.com/evex-dev/linejs/blob/main/packages/types/line_types.ts).

### What protocol endpoint does LINEJS use for reaction RPCs?

LINEJS sends reaction and read receipt RPCs to the `/S4` endpoint using protocol type 4 (the Talk protocol). This is consistent across both `TalkService.react()` (lines 701-719) and `TalkService.sendChatChecked()` (lines 989-1012) in [`packages/linejs/base/service/talk/mod.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/service/talk/mod.ts).