/Line, Line Bot, Python

Line Bot | 使用 Python 為 Line Bot 建立獨一無二的圖文選單( Rich menus)

基本圖文選單創建

為 Line Bot 建立基本的圖文選單其實不難,在 Line 為每個開發者提供的管理介面( Line Developers )就有這個功能:

可在 Line developers 中自行新增圖文選單

建立選單的介面也很簡易:

Step1. 選擇圖文選單的版型,目前官方提供了七種樣式可供選擇:


Step2. 上傳圖文選單的圖片及點擊固定區域時所執行的事情,例如:發送訊息、跳轉連結等等:

上傳圖文選單的圖片及設定點擊時的事件

上方兩個步驟完成後,便能得到一個標準的圖文選單:

使用版型一創建的簡易圖文選單

儘管官方提供了簡易的後台操作、七種選單的版型,讓許多人都可以在短時間內建立一個符合自己需求的圖文選單,但是這終究無法滿足所有人。

建立 Rich menus

如上方所說,為了讓客戶在 Line Bot 上簡化操作,因此將功能置於圖文選單,透過點擊來完成事情是很重要的。

像是在事件數量大於 6 個(官方提供的最多可設定事件數)的情況:

此圖文選單的按鈕區塊多達九個

或是需要不規則的特殊排列(官方提供的版型都是固定切割的),官方範例:

不規則的按鈕擺放方式

以上兩種圖文選單的類型( Rich menus ),都無法以官方提供的介面實現,必須另外使用 API 處理。

下方的範例會使用 Python 和他的線上編輯器 Jupyter ,再搭配 Line 提供的 API 套件 line-bot-sdk-python 實作。

新增 Rich menus

透過發送一個 request 請求到 https://api.line.me/v2/bot/richmenu 創建 Rich menus ,該次請求需要在 headers 中的 Authorization 屬性內帶上該 Line Bot 的 Token 值, body 內則是關於選單的設置,下方會再詳細說明 Token 該在哪取得及 body 的設定內容,整個請求的樣貌會像這樣:

import requests
import json

headers = {"Authorization":"Bearer 3Ma92PMIfy790Z...","Content-Type":"application/json"}

body = {
    "size": {"width": 2500, "height": 1686},
    "selected": "true",
    "name": "Controller",
    "chatBarText": "Controller",
    "areas":[
        {
          "bounds": {"x": 551, "y": 325, "width": 321, "height": 321},
          "action": {"type": "message", "text": "up"}
        },
        {
          "bounds": {"x": 876, "y": 651, "width": 321, "height": 321},
          "action": {"type": "message", "text": "right"}
        },
        {
          "bounds": {"x": 551, "y": 972, "width": 321, "height": 321},
          "action": {"type": "message", "text": "down"}
        },
        {
          "bounds": {"x": 225, "y": 651, "width": 321, "height": 321},
          "action": {"type": "message", "text": "left"}
        },
        {
          "bounds": {"x": 1433, "y": 657, "width": 367, "height": 367},
          "action": {"type": "message", "text": "btn b"}
        },
        {
          "bounds": {"x": 1907, "y": 657, "width": 367, "height": 367},
          "action": {"type": "message", "text": "btn a"}
        }
    ]
  }

req = requests.request('POST', 'https://api.line.me/v2/bot/richmenu', 
                       headers=headers,data=json.dumps(body).encode('utf-8'))

print(req.text)

每個 Line Bot 的 Token 都可以在開發人員介面中找到:

如果這裡還沒有 Token 可以點選 Issue 產生

body 是有關 Rich menus 的設置內容,他有以下幾個屬性:

  1. size :目前寬度僅能設置 2500 ,高度有 843 或 1686 兩種選擇。
  2. selected :控制 Rich menus 是否預設開啟, truefalse 請使用字串格式。
  3. name :為該 Rich menus 的名稱。
  4. chatBarText :圖文選單下方的文字內容,點擊可開關選單,可以設置為「點我收合選單」。
  5. areas :為一個陣列,內部的每個物件都是一個按鈕及點擊執行的事件的描述。物件內的第一個屬性 bounds 可以設置按鈕的位置座標及大小, action 屬性則是能夠控制點擊後發生的事件內容,目前設置的所有事件都是發送訊息。

更多事件可以參考官方文件,之後會再整理成另一篇文章說明。

設定好 body 後還需要使用 json.dumps 將它轉換為字串,並依照 utf-8 編碼送出請求,請求成功後,會在 response 中顯示 Rich menus 的 id:

建立成功會回傳該 Rich menus 的 id

注意!每個 Line Bot 都只能有 1000 個圖文選單,如果超過的話會回傳狀態 400 失敗。

設定 Rich menus 的圖片

此時便需要透過 line-bot-sdk-python 來將圖片掛上該圖文選單,記得在此步驟之前先在 pip 上下載該套件:

from linebot import (
    LineBotApi, WebhookHandler
)

line_bot_api = LineBotApi('3Ma92PMIfy790Z...')

with open("control.jpg", 'rb') as f:
    line_bot_api.set_rich_menu_image("richmenu-762...", "image/jpeg", f)

LineBotApi 需傳入 Token 啟用, setrichmenu_image 的第一個參數為剛剛創建的 Rich menus 的 id ,執行成功後什麼都不會回傳,但錯誤時會出現訊息,例如已設置圖片的 Rich menus 無法重複設置。

另外需要注意,圖片的大小需和該 Rich menus 的 size 一模一樣,如果一直上傳失敗可以試著調整圖片尺寸,這裡提供一個線上調整尺寸的工具

啟用 Rich menus

啟用 Rich menus 只要透過發送 request 就能完成:

import requests

headers = {"Authorization":"Bearer 3Ma92PMIfy790Z...","Content-Type":"application/json"}

req = requests.request('POST', 'https://api.line.me/v2/bot/user/all/richmenu/richmenu-7621...', 
                       headers=headers)

print(req.text)

headersAuthorization 屬性帶上 Line Bot 的 Token 值, requesturlhttps://api.line.me/v2/bot/user/all/richmenu/ 再加上 Rich menus 的 id ,請求成功會回傳一個空物件:

請求成功時回傳空物件

這時候再打開 Line Bot 的介面,就可以看到圖文選單的內容已經改變。

查看所有 Rich menus

只要透過 line-bot-sdk-python 提供的 getrichmenu_list 便能取得所有的 Rich menu 選單 id。

from linebot import (
    LineBotApi, WebhookHandler
)

line_bot_api = LineBotApi('3Ma92PMIfy790Z...')

rich_menu_list = line_bot_api.get_rich_menu_list()

for rich_menu in rich_menu_list:
    print(rich_menu.rich_menu_id)

列出結果:

取得該 Line Bot 內所有 Rich menus

刪除 Rich menus

要刪除某個 Rich menus 也很容易,只需要把該 Rich menus 的 id 傳進 deleterichmenu 中就行了:

from linebot import (
    LineBotApi, WebhookHandler
)

line_bot_api = LineBotApi('3Ma92PMIfy790Z...')

line_bot_api.delete_rich_menu('richmenu-1b67...')

執行後不會回傳任何值,可以再透過 getrichmenu_list 查看 Rich menus 是否已經刪除。


本文是以官方文件上的說明為主,將它以 Python 實作,如果以上內容有任何問題,或是不理解的地方,都歡迎留言告訴我,謝謝大家!

參考文章

  1. https://developers.line.biz/en/docs/messaging-api/using-rich-menus/