正在載入索引…

Day 27:群組事件與檔案訊息接收

2.9k 字,約 3 分鐘

2025 iThome 鐵人賽:Line Bot × NestJS:30 天開發日記。 原文發表於 iThome,也可以在下方留言。

文章目錄
  1. 前言
    1. 事前準備
    2. 群組 Webhook 事件
    3. 後端伺服器新增群組對應 Webhook 事件
    4. 驗證 Webhook 事件觸發結果
      1. Join 事件
      2. Leave 事件
      3. MemberJoined 事件
      4. MemberLeft 事件
    5. MessageEvent - 檔案類型
    6. 本週結語

前言

今天主要補充 LINE Bot 在群組中的專屬特性,包括群組限定的 Webhook 事件,以及前面提到但尚未說明的第 7 種訊息類型 file 檔案訊息。

本日程式碼的範例連結

事前準備

預設情況下,LINE Bot 無法加入群組,即使加入也會立即自動退出。因此需要先在 LINE Developers Console 中開啟 Bot 可加入群組功能。

此外,每個群組只能存在一個 LINE Bot。如果群組中已有 Bot,嘗試加入第二個 Bot 時會被自動退出。

群組 Webhook 事件

前面提到的加入事件(Follow)及封鎖事件(Unfollow)都是針對一對一聊天的情境。但在群組環境中,會有額外的事件類型需要處理:

1. Bot 本身的事件

  • Join 事件:當 Bot 被邀請加入群組時觸發
  • Leave 事件:當 Bot 被踢出群組時觸發

2. 群組成員相關事件

  • Member Joined 事件:Bot 所在的群組有新成員加入時觸發
  • Member Left 事件:Bot 所在的群組有成員離開時觸發

後端伺服器新增群組對應 Webhook 事件

Webhook 事件中的 source 欄位用於標識訊息來源,主要分為以下類型:

  • user:一對一聊天(單聊)
  • group:群組聊天
  • room:多人聊天室

本質上可以區分為「單聊」與「群聊」兩大類型。接下來要實作的四個群組相關事件,都屬於群聊類型。

line-webhook/line-webhook.service.ts

ts
// 略
const webhookEventHandlerMap = {
  message: (event) => this.handleMessageEvent(event),
  follow: (event) => this.handleFollowEvent(event),
  unfollow: (event) => this.handleUnfollowEvent(event),
  join: (event) => this.handleJoinEvent(event),
  leave: (event) => this.handleLeaveEvent(event),
  memberJoined: (event) => this.handleMemberJoinedEvent(event),
  memberLeft: (event) => this.handleMemberLeftEvent(event),
} satisfies Partial<WebhookEventHandlerMap>;

private async handleJoinEvent(event: JoinEvent): Promise<void> {
  const replyMessage = this.lineMessageService.createTextMessage({
    text: '機器人已加入群組或聊天室,請多指教!',
  });

  await this.lineClient.replyMessage({
    replyToken: event.replyToken,
    messages: [replyMessage],
  });
}

private async handleLeaveEvent(event: LeaveEvent): Promise<void> {
  const { source } = event;
  console.log(`機器人已離開群組或聊天室 ${JSON.stringify(source)}`);
}

private async handleMemberJoinedEvent(event: MemberJoinEvent): Promise<void> {
  const replyMessage = this.lineMessageService.createTextMessage({
    text: '歡迎新成員加入!',
  });

  await this.lineClient.replyMessage({
    replyToken: event.replyToken,
    messages: [replyMessage],
  });
}

private async handleMemberLeftEvent(event: MemberLeaveEvent): Promise<void> {
  const { left } = event;
  console.log(`成員已離開:${JSON.stringify(left)}`);
}

驗證 Webhook 事件觸發結果

Join 事件

當機器人加入群組時,會收到相應的 Webhook 事件通知:

Leave 事件

當機器人離開群組時,同樣會收到事件通知。可以從事件中知道是從哪個群組離開的:

json
{
  // 略
  "source": {
    "type": "group",
    "groupId": "C00da164ef4a4b88e3e6419af6b4b981c"
  }
}

MemberJoined 事件

當群組內有新成員被邀請加入時觸發此事件。

透過此事件可以取得(這個部分在 MemberLeft 也可取得):

  • 成員編號:該成員在此群組中的唯一識別碼
  • 群組編號:發生事件的群組識別碼

MemberLeft 事件

當群組內有成員主動退出或被踢除時觸發此事件。

MessageEvent - 檔案類型

在前面提及的 MessageEvent 中,LINE Bot 檔案類型訊息有以下特性需要注意:

  • 接收限制:檔案類型訊息只能在群組中傳送,一對一聊天無法傳送檔案
  • 回覆限制:雖然 LINE Bot 可以接收檔案類型訊息,但無法主動傳送檔案類型的訊息給使用者

line-webhook.service/line-webhook.service.ts

ts
  private async handleMessageEvent(event: MessageEvent): Promise<void> {
    const messageEventHandlerMap = {
      file: () =>
        this.lineMessageService.createTextMessage({
          text: '收到檔案囉,但目前還不支援喔~',
      }),
    } satisfies MessageEventHandlerMap;

成果展示

當收到檔案類型訊息時,可以從事件物件中取得傳入檔案的基本資訊。若需要取得檔案的實體內容,則可透過訊息編號進行下載:

取得檔案內容的方式可以參考 Day 8 的說明。

json
{
  "event": {
    "type": "message",
    "message": {
      "type": "file",
      "id": "582616131509420205",
      "fileName": "2025 鐵人賽.pdf",
      "fileSize": 2106585,
      "contentProvider": {
        "type": "line"
      }
    }
    // 略
  }
}

本週結語

今天補充了 LINE Bot 在群組環境中的額外觸發事件,以及檔案類型訊息的處理方式。透過這些功能,Bot 可以監聽特定關鍵字、收集使用者上傳的檔案、在新成員加入時發送歡迎訊息,或追蹤成員異動進行記錄。這讓 LINE Bot 不只能處理一對一對話,更能在群組協作場景中發揮實用價值。

LINE 平台非常注重隱私保護,因此無論在單聊或群聊的情況下,LINE Bot 都無法直接透過 API 取得用戶的詳細資訊。正因如此,開發者需要透過 Webhook 事件來記錄和管理用戶資訊,建立自己的用戶資料庫,才能在後續有推播需求時,準確地將訊息發送給目標用戶。

留言

留言使用 GitHub 帳號登入(Giscus),留言會存在 GitHub Discussions。