跳轉至

建立 2026-09-21 更新 2026-09-21

處理事件與回覆訊息

回聲機器人只會複誦。這頁讓它「聽得懂」:認識 LINE 傳來的事件種類、搞清楚 Reply 與 Push 的差別、寫一個指令路由,並學會送出貼圖、快速回覆按鈕與 Flex 訊息。程式接續 上一頁callLinereplypushreplyText

事件(event)長什麼樣

doPost 收到的 JSON 大致是:

{
  "destination": "機器人的 userId",
  "events": [
    {
      "type": "message",
      "replyToken": "一次性回覆憑證",
      "source": { "type": "user", "userId": "使用者的 userId" },
      "webhookEventId": "事件唯一編號",
      "message": { "type": "text", "id": "訊息編號", "text": "你好" }
    }
  ]
}

events 是陣列,因為 LINE 可能一次送多個事件,一定要逐一處理。常見的事件類型:

event.type 何時發生 replyToken 常見處理
message 使用者傳訊息(文字、圖片、貼圖、位置…,看 event.message.type 依內容回覆
follow 加機器人好友或解除封鎖 送歡迎詞、說明指令
unfollow 使用者封鎖機器人 沒有 標記使用者已離開(無法回覆)
postback 使用者按了帶資料的按鈕 event.postback.data 執行動作
joinleave 機器人被加入或移出群組 join 群組機器人初始化

event.source.userId 是使用者在你這個機器人底下的識別碼,不是 LINE ID,也不是暱稱。要主動推播給某人,就要先把它存起來。群組事件的 source 會多帶 groupId

Reply 與 Push 的差別

Reply(回覆) Push(推播)
用途 回應使用者剛傳來的事件 主動發訊息(提醒、通知)
需要什麼 replyToken 對方的 userId
時效 replyToken 只能用一次,收到後約 1 分鐘內要用 隨時
費用 免費,不計入每月訊息則數 計入每月則數
一次最多 5 則訊息 5 則訊息

原則:能 Reply 就 Reply。Push 有每月免費則數限制(見 上線注意),留給定時提醒這類「使用者沒開口」的情境。

指令路由

把使用者輸入切成「指令 + 參數」,用 switch 分派,是最簡單也最好維護的寫法。把 handleEvent 改成:

const HELP_TEXT = "可用指令:\n說明\n時間\n算 12 + 30";

function handleEvent(event) {
  if (event.type === "follow") {
    return replyText(event.replyToken, "歡迎!輸入「說明」看看我會做什麼。");
  }
  if (event.type !== "message" || event.message.type !== "text") return;
  handleText(event);
}

function handleText(event) {
  const text = event.message.text.trim();
  const [cmd, ...args] = text.split(/\s+/);

  switch (cmd) {
    case "說明":
      return replyText(event.replyToken, HELP_TEXT);
    case "時間":
      return replyText(
        event.replyToken,
        Utilities.formatDate(new Date(), "Asia/Taipei", "yyyy-MM-dd HH:mm")
      );
    case "算":
      return replyText(event.replyToken, calc(args));
    default:
      return replyText(event.replyToken, "看不懂「" + text + "」,輸入「說明」查看指令。");
  }
}

function calc(args) {
  const [a, op, b] = [Number(args[0]), args[1], Number(args[2])];
  if (Number.isNaN(a) || Number.isNaN(b)) return "格式:算 12 + 30";
  const ops = { "+": a + b, "-": a - b, "*": a * b, "/": b === 0 ? "不能除以 0" : a / b };
  return op in ops ? String(ops[op]) : "只支援 + - * /";
}

設計重點:一定要有 default 分支,回一句「看不懂」加上提示,不要讓使用者傳了沒反應。使用者的輸入不可預期,格式錯誤時要回「正確格式長怎樣」,比回錯誤訊息有用。

其他訊息型態

replypushmessages 是陣列,一次最多 5 則,可以混搭型態。

貼圖

reply(event.replyToken, [
  { type: "text", text: "收到!" },
  { type: "sticker", packageId: "446", stickerId: "1988" },
]);

貼圖要用 LINE 官方開放給機器人使用的 packageIdstickerId 組合,可查 官方貼圖清單

快速回覆(Quick Reply)

在輸入框上方出現幾顆按鈕,點下去等於代替使用者「傳出一則文字」。適合讓不想打字的人選擇。

reply(event.replyToken, [{
  type: "text",
  text: "要查哪一段?",
  quickReply: {
    items: [
      { type: "action", action: { type: "message", label: "今天", text: "今天" } },
      { type: "action", action: { type: "message", label: "本月", text: "本月" } },
    ],
  },
}]);

按鈕送出的文字會回到你的 handleText,所以「按鈕」和「打字」走同一套指令路由,不用另外寫。

Flex Message(自訂版面)

需要卡片、表格式版面、圖文並排時使用。結構是 JSON,用官方的 Flex Message Simulator 拖拉設計,再把 JSON 貼進程式。

reply(event.replyToken, [{
  type: "flex",
  altText: "今日摘要", // 通知與不支援 Flex 的畫面會顯示這段
  contents: {
    type: "bubble",
    body: {
      type: "box",
      layout: "vertical",
      contents: [
        { type: "text", text: "今日摘要", weight: "bold", size: "xl" },
        { type: "text", text: "共 3 筆,合計 420 元", margin: "md" },
      ],
    },
  },
}]);

圖片、影片、檔案

使用者傳來的檔案,事件裡只有 event.message.id,要另外用 GET https://api-data.line.me/v2/bot/message/{messageId}/content 下載,再存進 Drive。這超過入門範圍,需要時看 官方參考

主動推播與取得使用者資料

Push 用在使用者沒開口、你想主動通知的時候,push 的第一個參數是 userId

function notifyMe() {
  const myUserId = PropertiesService.getScriptProperties().getProperty("MY_USER_ID");
  push(myUserId, [{ type: "text", text: "提醒:今天要交報告" }]);
}

自己的 userId 怎麼取得:在 handleEvent 裡暫時加一行 console.log(event.source.userId),用手機傳訊息給機器人,再到 GAS 的 執行 頁看紀錄,複製後存進 Script Properties。

想在回覆裡用對方的暱稱,可以呼叫 GET https://api.line.me/v2/bot/profile/{userId} 取得 displayName。這是 GET,要另外用 UrlFetchApp.fetchAuthorization 標頭。

notifyMe 掛上 時間驅動觸發,就成了每天定時提醒。

下一步:把使用者輸入存下來,做一個真的有用的機器人,見 試算表記帳機器人