
用 Python 開發 Facebook Bot

原文刊登於 DualCores Studio,Inside 獲授權轉載。
作者為大白,Co-founder & Developer @DualCores Studio,歡迎對於 Bot 開發、人工智慧、語意分析、機器學習有興趣的朋友一起交流學習,接下來會更專注分享相關的題目。
最近聊天機器人 Bot 這股趨勢才慢慢要崛起,之前做了一點觀察紀錄,這次進入實作階段,首先就直接使用 Facebook Message Platform 做為開始。
其實 Facebook 官方文件寫的也蠻清楚的,只是有一些技巧要注意。
前置作業
- 先有一個粉絲團 :粉絲團就是用來當作 Bot 的身份,只支援粉絲團對一般使用者聊天而已,先確定你有一個粉絲團是用來讓 Bot 綁定的,這邊可以選擇你既有的粉絲團或是新建立一個,如果是新建立的,粉絲團新建立完後可以先不發佈,但是如果要開始測試 Bot 的話,就要發佈了。
- 準備開發環境和專案 :新建立一個 Python 專案,並且將我們會用到的套件:Flask、Requests 安裝好。
- 申請一個 FB 應用程式 :去 facebook for developer 建立或選擇一個應用程式,如果是新建立的話,應用程式類型選擇「網站」即可,建立完之後在主控台左側功能表找到「Messager」點下。
▲點選左邊功能表的「Message」,再按下「開始使用」。 ▲選擇一個粉絲專頁後(可能需要登入),右邊的存取權杖 (Access Token) 會自動產生,這等等會用到。 - 為自己的網域名稱申請 SSL:Facebook 要求所有 Messager 呼叫的 API 都是要走 https,所以這步驟是必要的(我也覺得比較麻煩的地方),這邊我用的是 Let's Encrypt 來申請,依照「Installing Client Software」的步驟來進行,先用 git clone 把專案複製下來,然後在終端機使用 certbot-auto 工具來產生憑證,我是用 Apache HTTP Server,所以執行
sudo ./certbot-auto --apache -d YOUR_DOMAIN_NAME.COM
YOUR_DOMAIN_NAME.COM 要換成你自己的網域名稱,不用加 http:// 開頭,接著依照它的指示做即可。
憑證產生好後,我們需要將憑證複製到我們的 API 專案內,我這邊是在專案內建立一個 ssl 的資料夾,並且使用終端機切換目錄到 /etc/letsencrypt/live/YOUR_DOMAIN_NAME.COM/(這邊 YOUR_DOMAIN_NAME.COM 記得代換成自己的網域名稱)裡面,將 fullchain.pem 和 privkey.pem 複製到剛剛建立的 ssl 資料夾,這等等會用到,千萬別複製錯檔案,我一開始就是複製到 cert.pem / privkey.pem,然後後面就出錯了(看下圖)。
OK,到目前為止,前置步驟算完成,我們可以開始寫程式了。
程式撰寫
程式的部分主要分成三個主要步驟:
- 設定 Webhook 做驗證。
- 從 Facebook 接收使用者的訊息。
- 傳遞訊息到 Facebook。
1. 設定 Webhook
新增一個可以接收驗證碼的 HTTP GET 方法,裡面的 I_AM_VERIFICATION_CODE 要換成自己的,其他 hub. 開頭的都是 Facebook 既定好的,要照著寫。
@app.route(API_ROOT + FB_WEBHOOK, methods=["GET"]) def fb_webhook(): verification_code = 'I_AM_VERIFICIATION_CODE' verify_token = request.args.get('hub.verify_token') if verification_code == verify_token: return request.args.get('hub.challenge')
再回到 Facebook 應用程式主控台,按下 Setup Webhooks 會出現下圖的視窗,要將你的 API 網址 (API_ROOT + FB_WEBHOOK) 和上面的 I_AM_VERIFICATION_CODE 分別輸入進去,然後勾選你要的訊息功能:
勾選訂閱項目如下:
- message_deliveries: 訊息傳遞的相關報表。
- messages: 最基本的訊息接收和傳遞。(最基本一定要勾選的)
- messaging_optins: 允許使用者使用在你網站上的 Send-to-Messager 按鈕,並且可以授權傳遞訊息到這。
- messaging_postbacks: 允許你傳遞除了文字之外的訊息種類,例如:按鈕和按鈕按下後的事件。
2. 接收訊息。
從 Facebook 傳遞過來的文字訊息 JSON 格式(如果你是傳圖片或其他非文字的類型,會有點不同)如下:
{ "object": "page", "entry": [ { "id": 1719080561637302, "time": 1463187309603, "messaging": [ { "sender": { "id": 1176454272400076 }, "recipient": { "id": 1719080561637302 }, "timestamp": 1463187309521, "message": { "mid": "mid.1463187309223:ae45fc642d87298297", "seq": 23, "text": "嗨,你好。" } } ] } ] }
可以從 entry → messaging 取得每一則訊息傳送者和內容,取得訊息程式如下,使用 HTTP POST,然後去解 JSON 即可:
@app.route(API_ROOT + FB_WEBHOOK, methods=['POST']) def fb_handle_message(): message_entries = json.loads(request.data.decode('utf8'))['entry'] for entry in message_entries: messagings = entry['messaging'] for message in messagings: sender = message['sender']['id'] if message.get('message'): text = message['message']['text'] print("{} says {}".format(sender, text)) return "Hi"
3. 傳遞訊息。
傳遞訊息也很簡單,只需要呼叫 Graph Message API 即可,程式碼如下:
def send_fb_message(to, message): post_message_url = 'https://graph.facebook.com/v2.6/me/messages?access_token={token}'.format(token=config.FB_TOKEN) response_message = json.dumps({"recipient":{"id": to}, "message":{"text":message}}) req = requests.post(post_message_url, headers={"Content-Type": "application/json"}, data=response_message) print("[{}] Reply to {}: {}", req.status_code, to, message)
裡面的 config.FB_TOKEN 是我們在前置作業新增的 FB 應用程式所產生的,要去應用程式的主控台去找。
FB_TOKEN 就是從這頁面的粉絲專頁存取權杖複製而得。
再來要綁定這個 FB 應用程式和你 Bot 的粉絲團,開啟終端機執行
curl -ik -X POST "https://graph.facebook.com/v2.6/me/subscribed_apps?access_token=ACCESS_TOKEN"
上面的 ACCESS_TOKEN 要用剛剛的粉絲專頁存取權杖複製代換,執行完成功後會出現 {“success”: true} →
最後一步,我們要啟動我們的 API,加入執行 API 的程式:
if __name__ == '__main__': context = ('ssl/fullchain.pem', 'ssl/privkey.pem') app.run(host='0.0.0.0', debug=True, ssl_context=context)
這邊的 context 所用到是我們前置作業所複製出來的兩個憑證,為了是讓我們的 API 是用 https 存取,這也是 Facebook Message Platform 所要求的。
最後執行 API 來讓我們跟 Bot 聊天吧。
完成程式碼如 GitHub 連結:請給星星吧,我需要你們的支持~
常見問題可能的解法
- Callback 網址有問題?先用工具測試你的 Webhook GET API 是否正常運作,可以呼叫 Webhook API 然後給 hub.verify_token 和 hub.challege 這兩個參數,照我們寫的程式正確會回傳 hub.challege 的值。
▲使用 Postman 測試 Webhook API - 訊息沒有收到或傳遞失敗?別忘了要綁定 Facebook 應用程式和粉絲團(執行 curl 那一段)
歡迎加入「Inside」Line 官方帳號,關注最新創業、科技、網路、工作訊息
