iT邦幫忙

2026 iThome 鐵人賽

DAY 16
0
AI 自動化

用 LINE Bot 和 Agent Skill 自動化整理筆記與 IG 發文系列 第 16 篇

Day 16|體驗細節:輸入中動畫、Quick Reply、圖文選單、只服務自己

  • 分享至 

  • xImage
  •  

昨天講完搜尋、刪除、註記、標待辦這些指令都是純規則,最後留了一個問題:指令格式要靠我自己記,打錯字就不會觸發。今天看四個讓這個 Bot 比較好用的小地方,分別是輸入中動畫、Quick Reply、圖文選單,還有只服務我一個人的白名單。

先從動畫講起。傳一個網址給 Bot,它要抓內文、叫 AI 分類、寫進 Notion,跑完常常要十幾秒。這段時間 LINE 上只會顯示「已讀」,我沒辦法分辨它是在跑,還是根本沒收到。所以 handleTextMessage 一開始就先呼叫 showLoadingAnimation:

async function showLoadingAnimation(env, userId, seconds = 30) {
  if (!userId) return;
  try {
    await fetch('https://api.line.me/v2/bot/chat/loading/start', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${env.LINE_CHANNEL_ACCESS_TOKEN}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ chatId: userId, loadingSeconds: seconds }),
    });
  } catch {
    // 動畫只是體驗優化,失敗不影響主流程,靜默略過即可
  }
}

這支函式有三個地方我是刻意這樣寫的。第一,chatId 用的是 userId,所以群組或多人聊天室沒有 userId 的時候,直接 return 略過,不會報錯。第二,整段包在 try/catch 裡,而且 catch 是空的。動畫只是讓畫面好看一點,它壞了不該連累存筆記,所以失敗就當沒發生。看到空的 catch 不要當成偷懶,這是設計。第三,秒數預設給 30,動畫只是「最多顯示這麼久」,Bot 送出回覆的時候它會自己消失,不需要我去關。

還有一個限制要先講:這個動畫只有手機版 LINE 看得到,電腦版不會顯示。這是 LINE 平台的限制,不是程式哪裡寫錯,我一開始在電腦上測還以為壞了。

https://ithelp.ithome.com.tw/upload/images/20260930/20112956FNb8TTTxSN.png

接著是 Quick Reply。它出現在「依分類搜尋」這個功能:我傳「依分類搜尋」,Bot 回一句「請選擇想查的分類」,訊息下面跳出七顆按鈕,點一下就查。要做到這件事,reply 這個函式多留了一個可選的第四參數:

async function reply(env, replyToken, text, quickReplyLabels) {
  const message = { type: 'text', text: text.slice(0, 4900) };

  if (quickReplyLabels?.length) {
    message.quickReply = {
      items: quickReplyLabels.slice(0, 13).map((label) => ({
        type: 'action',
        action: { type: 'message', label: label.slice(0, 20), text: label },
      })),
    };
  }
  ...
}

呼叫的地方只有一行,把 CATEGORIES 整個丟進去:reply(env, replyToken, '📂 請選擇想查的分類:', CATEGORIES)。按鈕上限 13 個、label 最多 20 個字,這兩個數字是 LINE API 的規定,我在程式裡先用 slice 截好,免得哪天分類多加幾個就被 LINE 拒收。

這裡有個小巧思:按鈕的 action 是 type: 'message',點下去的效果等於我自己打了那個分類名稱送出。也就是說,點「投資理財」之後進來的是一則普通的文字訊息「投資理財」,沒有網址,就掉到 handleSearch,最後走 searchNotion。Quick Reply 沒有另外開一條處理路徑,只是幫我打字,後面全部沿用昨天那套。因為這樣,分類清單只要改 CATEGORIES 一個地方,按鈕就跟著變,搜尋邏輯也不用動。

https://ithelp.ithome.com.tw/upload/images/20260930/20112956JPPBGLHD4g.png

圖文選單是最偷懶、也最有用的一個。畫面下方固定有六格:說明、待辦清單、最近存的、依分類搜尋、開啟 Notion,還有一格純裝飾,因為想不到還要放什麼功能。前四格的動作類型都是「文字」,點下去就是替我送出對應的字,跟 Quick Reply 是同一個概念,都是把「我得記住要打什麼」這件事換成點一下。「開啟 Notion」那格是連結類型,直接開資料庫網址。

https://ithelp.ithome.com.tw/upload/images/20260930/201129566u2koKKQkL.png

有一件事要老實講:圖文選單的設定不在這個 repo 裡。它是我在 LINE Official Account Manager 後台手動設定的,沒有進版控。這代表如果我改了 handleSearch 認得的關鍵字,或是新增指令,選單那邊不會跟著變,要自己再進後台確認。我在 README 裡把六格的設定寫成表格當作備忘,但那終究只是文件,不是程式會自動檢查的東西。另外「開啟 Notion」在 LINE 內建瀏覽器裡開,不會直接跳去 Notion App,得自己點選單改用系統瀏覽器開,這也是內建瀏覽器的通病,沒辦法從 Bot 這邊解。

最後是白名單。這個官方帳號誰都可以加好友,但背後吃的是我的 AI 額度、寫的是我的 Notion。如果連結外流,別人傳一則訊息就能花我的額度、往我的資料庫塞東西。所以 handleEvents 最前面有這一段:

console.log('userId:', event.source?.userId);

// 只服務你自己,避免任何加到好友的人都能用你的額度寫入你的 Notion
if (env.OWNER_USER_ID && event.source?.userId !== env.OWNER_USER_ID) {
  continue;
}

不是我本人的訊息直接 continue,Bot 什麼都不回。我選擇不回,是因為回一句「你沒有權限」等於告訴對方這裡有東西,靜默忽略比較乾脆。取得自己 userId 的那個雞生蛋問題,Day 7 已經講過了,這裡就不重複。

要留意的是 env.OWNER_USER_ID && 這個寫法:沒設定這個 secret 的時候,整個條件是 false,誰都攔不住。它是選填的,所以部署完如果忘了補,Bot 其實是對所有人開放的。另外動畫是在白名單檢查之後才呼叫,陌生人的訊息不會觸發任何 LINE API,連動畫都不會吃到。

四個東西放在一起看,其實都在做同一件事:不讓功能本身之外的麻煩打擾我。等待時有動畫,指令有按鈕,不想記格式就點選單,陌生人進來就當沒看到。功能今天沒有變多,用起來卻順很多。

明天是第二部的最後一篇,回頭看整個 line-notion-bot:哪些地方用了 AI,哪些地方我刻意不用。


上一篇
Day 15|指令用規則、內容用 AI:用 LINE 搜尋、刪除、註記、標待辦
下一篇
Day 17|中場回顧:這個 Bot 哪裡用了 AI、哪裡刻意不用
系列文
用 LINE Bot 和 Agent Skill 自動化整理筆記與 IG 發文 共 17 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言