用Python開發Facebook Bot

讓我們來進入實作階段,首先就直接使用Facebook Message Platform做為開始。

最近聊天機器人Bot這股趨勢才慢慢要崛起,之前做了一點 觀察紀錄,這次進入實作階段,首先就直接使用 Facebook Message Platform 做為開始。

pymessager-graphic

其實Facebook官方文件寫的也蠻清楚的,只是有一些技巧要注意。

前置作業

  1. 先有一個粉絲團:粉絲團就是用來當作Bot的身份,只支援粉絲團對一般使用者聊天而已,先確定你有一個粉絲團是用來讓Bot綁定的,這邊可以選擇你既有的粉絲團或是新建立一個,如果是新建立的,粉絲團新建立完後可以先不發佈,但是如果要開始測試Bot的話,就要發佈了。
  2. 準備開發環境和專案:新建立一個Python專案,並且將我們會用到的套件:FlaskRequests 安裝好。
  3. 申請一個FB應用程式:去 facebook for developer 建立或選擇一個應用程式,如果是新建立的話,應用程式類型選擇「網站」即可,建立完之後在主控台左側功能表找到「Messager」點下。
螢幕快照 2016-05-13 下午3.49.55
點選左邊功能表的「Message」,再按下「開始使用」。
螢幕快照 2016-05-13 下午3.50.37
選擇一個粉絲專頁後(可能需要登入),右邊的存取權杖 (Access Token)會自動產生,這等等會用到。
4. 為自己的網域名稱申請SSLFacebook要求所有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://開頭,接著依照它的指示做即可。

certbot1
我是選擇Easy,讓http和https都可以使用,如果選擇Secure,則所有API呼叫都要走https。
certbot_done
成功完成的畫面

憑證產生好後,我們需要將憑證複製到我們的API專案內,我這邊是在專案內建立一個 ssl 的資料夾,並且使用終端機切換目錄到 /etc/letsencrypt/live/YOUR_DOMAIN_NAME.COM/ (這邊YOUR_DOMAIN_NAME.COM 記得代換成自己的網域名稱)裡面,將 fullchain.pemprivkey.pem 複製到剛剛建立的 ssl 資料夾,這等等會用到,千萬別複製錯檔案,我一開始就是複製到 cert.pem / privkey.pem,然後後面就出錯了(看下圖)。

螢幕快照 2016-05-12 下午6.57.53
複製錯憑證檔案,在設定Callback Webhook就出錯了。

OK,到目前為止,前置步驟算完成,我們可以開始寫程式了。


程式撰寫

程式的部分主要分成三個主要步驟:

  1. 設定Webhook做驗證。
  2. 從Facebook接收使用者的訊息。
  3. 傳遞訊息到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')
view raw fb_webhook.py hosted with ❤ by GitHub

再回到Facebook應用程式主控台,按下Setup Webhooks會出現下圖的視窗,要將你的API網址 (API_ROOT + FB_WEBHOOK) 和上面的I_AM_VERIFICATION_CODE分別輸入進去,然後勾選你要的訊息功能:

勾選訂閱項目如下:

  1. message_deliveries: 訊息傳遞的相關報表。
  2. messages: 最基本的訊息接收和傳遞。(最基本一定要勾選的)
  3. messaging_optins: 允許使用者使用在你網站上的Send-to-Messager按鈕,並且可以授權傳遞訊息到這。
  4. 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_receive_message():
message_entries = json.loads(request.data.decode('utf8'))['entry']
for entry in message_entries:
for message in entry['messaging']:
if message.get('message'):
print("{sender[id]} says {message[text]}".format(**message))
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)
view raw send_fb_message.py hosted with ❤ by GitHub

裡面的 config.FB_TOKEN 是我們在前置作業新增的FB應用程式所產生的,要去應用程式的主控台去找。

螢幕快照 2016-05-13 下午3.50.37
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}

螢幕快照 2016-05-14 上午9.12.42

最後一步,我們要啟動我們的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聊天吧。

pymessager-usage

完成程式碼如 GitHub 連結:請給星星吧,我需要你們的支持~

常見問題 && 可能的解法

  1. Callback網址有問題?先用工具測試你的Webhook GET API是否正常運作,可以呼叫Webhook API然後給 hub.verify_tokenhub.challege 這兩個參數,照我們寫的程式正確會回傳 hub.challege 的值。
螢幕快照 2018-05-20 上午10.32.51
FB_TOKEN就是從這頁面的粉絲專頁存取權杖複製而得。
  • 訊息沒有收到或傳遞失敗? 別忘了要綁定Facebook應用程式和粉絲團(執行 curl 那一段)
  • 如果你還有其他疑問,歡迎留言來詢問。

    7 thoughts on “用Python開發Facebook Bot

    Add yours

    1. I have deployed the bot you’ve shared here(I am very grateful for it).But now I want to connect it to my machine learning model.I cannot figure out to do that so can you please point at any article that you have written or can you help me yourself.

      Like

      1. Your machine learning model should have some “APIs” that be public accessed, your bot can call those APIs to progress the model, leave message if you have more questions. 🙂

        Like

      1. 回應對話當然可以自訂,現在有很多第三方服務還有 NLP 就是在處理對話解析和回覆,但能不能通過圖靈測試,這就要看演算法功力了。

        Like

    2. 請問CallBack URL出現The URL couldn’t be validated. Callback verification failed with the following errors: HTTP Status Code = 403; HTTP Message = Forbidden這個訊息是缺什麼嗎? 網址也申請使用ssl了

      Like

      1. 你的Callback網址本身可以直接用瀏覽器GET嗎?可以先用瀏覽器測試Callback網址是否可以正常存取後再去FB應用程式設定。

        Like

    3. I have been browsing on-line more than 3 hours today, yet I never found any fascinating article like yours. It’s lovely price enough for me. In my opinion, if all web owners and bloggers made excellent content as you probably did, the internet will likely be much more helpful than ever before.

      Like

    Leave a Reply to Beata Luncsford Cancel reply

    Fill in your details below or click an icon to log in:

    WordPress.com Logo

    You are commenting using your WordPress.com account. Log Out /  Change )

    Google photo

    You are commenting using your Google account. Log Out /  Change )

    Twitter picture

    You are commenting using your Twitter account. Log Out /  Change )

    Facebook photo

    You are commenting using your Facebook account. Log Out /  Change )

    Connecting to %s

    Blog at WordPress.com.

    Up ↑