再戰 Line Bot SDK -接收訊息與回應

初次嘗試 Line Bot sdk — 爬蟲與推送訊息

在上一篇文章中,嘗試了使用 Line Bot SDK 進行主動推送訊息,這次要嘗試另一種關鍵的用法—接收與回應訊息


接受訊息

一支程式要接受其他使用者傳來的 Line 訊息,應該要怎麼做呢?

接收訊息可以拆解成兩個步驟:

  1. 使用者傳送訊息到 Line 的伺服器
  2. Line 將這則訊息的資訊傳送到你指定的網址 (Callback URL)

這個 Callback URL 可以在 Message API 的管理介面進行設定,但要注意的一點是「Callback URL 必需要是 https,否則 line 不會送訊息過來」。

如果是在自架的 server 需要自己解決這個問題,不過如果把服務放在 Heroku 上的話,他本身提供的網址就是 https 的了。


準備程式

由於這次需要啟動一個服務來接收 Line 傳來的訊息,因此我採用了非常輕量化的 Python Web Framework Flask,並且將服務部署在 Heroku 上。

為了部署在 Heroku 上,需要準備幾個檔案

my_bot/
- requirements.txt
- runtime.txt
- Procfile
- app.py

runtime.txt

這檔案是宣告要用什麼語言環境,在這邊只要填入一個你喜歡的 python 版本就好 XD

# runtime.txt
python-3.6.2

requirements.txt

這檔案是宣告需要安裝哪些 python package,在 build 時會自動使用 pip 安裝這些 package,這次則是填入我們所需要的 line-bot-sdkflask

# requirements.txt
line-bot-sdk
flask

Procfile

這檔案用於告訴 Heroku 如何啟動你的服務,由於啟動 flask 的服務只要直接用 python 執行即可,因此內容也只要這樣一行就好。

# Procfile
web: python app.py

app.py

這檔案是最主要的 flask 程式內容,要注意的是中間需要填入你自己的 Channel access tokenChannel secret ,否則程式無法執行。

# encoding: utf-8
from flask import Flask, abort, request
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage, TextSendMessage

app = Flask(__name__)

# 填入你的 message api 資訊
line_bot_api = LineBotApi('YOUR CHANNEL ACCESS TOKEN')
handler = WebhookHandler('YOUR CHANNEL SECRET')

# 設定你接收訊息的網址,如 https://YOURAPP.herokuapp.com/callback
@app.route("/callback", methods=['POST'])
def callback():
    # get X-Line-Signature header value
    signature = request.headers['X-Line-Signature']

    # get request body as text
    body = request.get_data(as_text=True)
    print("Request body: " + body, "Signature: " + signature)

    # handle webhook body
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)

    return 'OK'

@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    print("Handle: reply_token: " + event.reply_token + ", message: " + event.message.text)
    content = "{}: {}".format(event.source.user_id, event.message.text)
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=content))

import os
if __name__ == "__main__":
    app.run(host='0.0.0.0',port=os.environ['PORT'])

這支程式只是很簡單的照樣回傳使用者說的話(#42, #43),而程式中的 print 則是用在紀錄 log 用,之後就可以透過 heroku logs 來查看。


部屬到 Heroku

當準備好了以上程式以後,就可以透過 git 與 heroku toolbelt 來部屬程式了。

# 移動到資料夾
cd my_bot/

# 初始 git repo
git init

# 初始 commit
git add .
git commit -a "initial commit"

當執行完以上步驟以後,應該就已經建立好了一個 git repo,再到 Heroku 的管理介面建立一個屬於你自己的專案。安裝好 heroku toolbelt 後就能按以下步驟將程式部屬上去

# 在 my_bot/ 下

# 先登入 heroku
heroku login

# 將 heroku server 加入 git repo remote 中
heroku git:remote -a YOUR_APP_NAME

# 將程式上傳
git push heroku master

等待一下以後應該就能看到部屬成功的訊息 remote: Verifying deploy... done. ,接下來回到 Heroku 管理介面該專案的 Setting 底下看到這專案的網址

取得這網址以後再到 Line Message API 的管理介面將其加入 Callback URL 中

如果你編輯完成後順手按了一下Verify,卻發現出現一條紅字說伺服器回應了500 INTERNAL SERVER ERROR時不用緊張,只是因為測試用的資料並沒有真的可用的reply_token,才會出現這錯誤。


測試結果

這時候你傳訊息給你的機器人後,應該就會看到他回了一樣的內容回來了。至於前面被我碼掉的是該使用者的 user_id(不是 Line ID),則是主動推送訊息時很重要的東西,有機會的話下一篇會講到(但是不知道是多久以後w)


總結

這次的簡單範例已經可以達到了接收訊息與回應,如果過程中再加上一點字串比對的方法,就有辦法針對預設的關鍵字做出回應了。

前一陣子火熱的 “ChatBot” 風潮看來最近消退許多了,畢竟如果沒有真的處理好自然語言的語意分析,終究沒辦法達成與使用者 Chat 的目的,最多只能算是 ResponseBot 而已吧。

照慣例附上程式碼的 GitHub 連結

Posts in this series