2017-08-22

用 Node.js 製作 Facebook Messenger 聊天機器人

之前心血來潮玩了一下 Facebook Messenger 聊天機器人,照著 jw84/messenger-bot-tutorial: Facebook Messenger bot 15 minute tutorial 的教學, 很快就上手了。了解運作原理以及接收/傳送訊息的方式,便可舉一反三, 比較麻煩的是必需有 https 加密連線的伺服器,還好 Heroku 有免費提供,可以在上面佈署 Node.js 來達成目標。

右圖取自 Open Clip Art - Callout chat



接下來入門步驟主要參考自 jw84/messenger-bot-tutorial: Facebook Messenger bot 15 minute tutorial , 只是用我覺得比較清楚的方式整理一下以及加上自己的經驗,作為未來參考的筆記。

  1. 安裝 npm 和 git 。

    sudo apt-get install npm
    sudo apt-get install git
    

    安裝 Heroku ,我是按照 這段的方法

    # Where REPLACE_ME_OS is one of “linux”, “darwin”, “windows” and 
    # REPLACE_ME_ARCH is one of “x64” or “x86” 
    # You also must replace “6.x.x” with the actual version.
    
    wget https://cli-assets.heroku.com/heroku-cli/channels/stable/heroku-cli-REPLACEME_OS-REPLACE_ME_ARCH.tar.gz -O heroku.tar.gz
    tar -xvzf heroku.tar.gz
    mkdir -p /usr/local/lib /usr/local/bin
    mv heroku-cli-v6.x.x-darwin-64 /usr/local/lib/heroku
    ln -s /usr/local/lib/heroku/bin/heroku /usr/local/bin/heroku
    
    
  2. Heroku 網站 註冊帳號。

  3. 下指令登入 Heroku ,輸入註冊的 e-mail 及密碼,登入後好像就會一直維持登入的狀態,要換帳號就再下一次指令。

    heroku login
    
  4. 建立新的 Heroku 專案,然後他會產生一個名字,兩個英文字和一個數字,像是 qwerty-asdf-12345 。 如果需要管理很多專案,建議另外用記事本記下來。

    heroku create
    
  5. cd 到電腦上選一個空資料夾來放作品,開始建立 Node.js 專案。

    npm init
    npm install express request body-parser --save
    

    建立一個檔案名為 index.js ,複製貼上以下內容:

    'use strict'
    
    const express = require('express')
    const bodyParser = require('body-parser')
    const request = require('request')
    const app = express()
    
    app.set('port', (process.env.PORT || 5000))
    
    // Process application/x-www-form-urlencoded
    app.use(bodyParser.urlencoded({extended: false}))
    
    // Process application/json
    app.use(bodyParser.json())
    
    // Index route
    app.get('/', function (req, res) {
     res.send('Hello world, I am a chat bot')
    })
    
    // for Facebook verification
    app.get('/webhook/', function (req, res) {
     if (req.query['hub.verify_token'] === 'my_voice_is_my_password_verify_me') {
      res.send(req.query['hub.challenge'])
     }
     res.send('Error, wrong token')
    })
    
    // Spin up the server
    app.listen(app.get('port'), function() {
     console.log('running on port', app.get('port'))
    })
    
    

    再建立一個檔案名為 Procfile ,複製貼上這句,是用來告訴 Heroku 執行哪一個程式。

    web: node index.js
    

    上傳到 heroku。

    git init
    git add .
    git commit --message "hello world"
    git push heroku master
    

    如果是第一次用 git 好像要先下這兩句:

    git config --global user.email "you@example.com"
    git config --global user.name "Your Name"
    

    注意!如果有不只一個專案,上傳前記得先切換專案:(qwerty-asdf-12345 是專案名稱)

    heroku git:remote -a qwerty-asdf-12345
    
  6. 到 Facebook 建立粉絲專頁 , 然後也 建立 App

    建立 App 時, Add Product 選擇 Messenger,進入後到 Webhooks 區塊點 Setup Webhooks, Callback URL 填入 https://qwerty-asdf-12345.herokuapp.com/webhook/ , 其中 qwerty-asdf-12345 是專案名稱,這裡填入的必需是 https 開頭的網址。 Verify Token 填入 my_voice_is_my_password_verify_me , 這句可以自己設定但沒必要,在之前已經上傳的 index.js 裡面有,拿來認證用的。 然後 Subscription Fields 全部打勾。

    到 Token Generation 區塊選擇粉絲專頁,賦予 app 權限並記錄下產生的 Page Access Token。 下以下指令,把 <PAGE_ACCESS_TOKEN> 換成自己的 Page Access Token ,出現 {"success":true} 就成功了。 或是直接在 Webhooks 下面選擇要連結的粉絲專頁點 Subscribe。

    curl -X POST "https://graph.facebook.com/v2.6/me/subscribed_apps?access_token=<PAGE_ACCESS_TOKEN>"
    

    到 Heroku Personal apps 頁面選擇專案名稱,進入後到 Settings 分頁裡的 Config Variables 新增一組新的, KEY 為 FB_PAGE_ACCESS_TOKEN 、 VALUE 為剛才產生的 Page Access Token ;或者也可以下指令來設定。 這樣做的好處是以後在程式碼裡面做事,寫 FB_PAGE_ACCESS_TOKEN 就能代替那串真正的 Access Token, 不會因為和別人分享程式碼而不小心將 Access Token 外流。

    heroku config:set FB_PAGE_ACCESS_TOKEN=<PAGE_ACCESS_TOKEN>
    
  7. 開始測試收發訊息,把以下內容複製貼上加到 index.js 後面。

    app.post('/webhook/', function (req, res) {
        let messaging_events = req.body.entry[0].messaging
        for (let i = 0; i < messaging_events.length; i++) {
         let event = req.body.entry[0].messaging[i]
         let sender = event.sender.id
         if (event.message && event.message.text) {
          let text = event.message.text
          sendTextMessage(sender, "Text received, echo: " + text.substring(0, 200))
         }
        }
        res.sendStatus(200)
    })
    
    const token = process.env.FB_PAGE_ACCESS_TOKEN
    
    
    function sendTextMessage(sender, text) {
        let messageData = { text:text }
        request({
         url: 'https://graph.facebook.com/v2.6/me/messages',
         qs: {access_token:token},
         method: 'POST',
      json: {
          recipient: {id:sender},
       message: messageData,
      }
     }, function(error, response, body) {
      if (error) {
          console.log('Error sending messages: ', error)
      } else if (response.body.error) {
          console.log('Error: ', response.body.error)
         }
        })
    }
    
    
  8. 上傳作品,以後上傳作品也是下這三句。

    git add .
    git commit -m 'updated the bot to speak'
    git push heroku master
    
    

    到 Facebook 粉絲專頁隨便傳個訊息 (123) ,他會自動回傳 (Text received, echo: 123) 。


到此為止機器人終於運作了,好的開始是成功的一半! 接下來就是研究如何收發訊息,依自己的需要來改程式碼,替聊天機器人增加功能。


Response Assistant

進入粉絲專頁的 Settings/Messaging ,底下選項有 Send Instant Replies to anyone who messages your Page 、 Stay responsive when you can't get to your computer or phone、 Show a Messenger Greeting ,身為聊天機器人,前兩項看起來沒有意義,實際上測試就只會傳回機器人的訊息; 但 Messenger Greeting 就很值得設定,這是使用者第一次聊天會看到的文字, 可以設為 Hi {{Person's first name}}! 歡迎使用......!

Get Started 按鈕

Get Started 按鈕 只會對第一次使用的人顯示,可以設定按按鈕後讓使用者收到什麼訊息。 要啟用 Get Started 按鈕,需要下 curl 指令:

curl -X POST -H "Content-Type: application/json" -d '{
  "setting_type":"call_to_actions",
  "thread_state":"new_thread",
  "call_to_actions":[
    {
      "payload":"get_started"
    }
  ]
}' "https://graph.facebook.com/v2.6/me/thread_settings?access_token=<PAGE_ACCESS_TOKEN>"

然後,要怎麼回應使用者呢?要先知道收到了什麼,觀察上面 app.post('/webhook/', function (req, res) {... 那段程式,自己加一句 sendTextMessage(sender,JSON.stringify(req.body)) , 在 if 外面,讓他回傳收到的東西,如果只填 req 的話不知道為什麼不會回覆。 自己去按一下 Get Started 按鈕來看結果,如果已經不是第一次傳訊息而沒有按鈕的話,把訊息刪除就能重頭開始。

結果還沒按到按鈕就跳出了一堆這種東西:
{"object":"page","entry":[{"id":"113804092590975","time":1503163405641,"messaging":[{"sender":{"id":"1698642063542925"},"recipient":{"id":"113804092590975"},"timestamp":1503163405638,"read":{"watermark":1503163405400,"seq":0}}]}]}

看來只要使用者已讀訊息就會讓伺服器知道,所以一收到訊息剛好立即已讀就會再收到一次,而造成機器人不停的傳訊息。 我們知道已讀的訊息長怎樣了,就是用 "read" 和代表時間的 "watermark":1503163405400 , 若日後有需要用到,就能判斷 "read" 來決定如何處理這筆資料。 另外還有個用 "delivery" 代表已送達的訊息也會傳送不停。 因此把程式碼加個 if 來過濾掉這些訊息,並且簡化取得的資料為原本的 event = req.body.entry[0].messaging[i] 。 去按一下 Get Started 按鈕,回傳:
{"recipient":{"id":"113804092590975"},"timestamp":1503165243350,"sender":{"id":"1424115491013073"},"postback":{"payload":"get_started","title":"Get Started"}}

中文版的是:
{"recipient":{"id":"113804092590975"},"timestamp":1503165193113,"sender":{"id":"1698642063542925"},"postback":{"payload":"get_started","title":"開始使用"}}

如果直接用文字輸入 Get Started 送出,得到的會不一樣:
{"sender":{"id":"1424115491013073"},"recipient":{"id":"113804092590975"},"timestamp":1503165292699,"message":{"mid":"mid.$cAAA9dYwjCPlkLOdom1d-6If_DNao","seq":111142,"text":"Get Started"}}

事實上我猜 Facebook 的說明文件裡應該有這東西,不過自己觀察比較好玩。 所以現在知道怎麼處理 Get Started 按鈕了,例如可以用程式裡已有的 sendTextMessage() 這個 function 傳訊息回應他。 整段程式碼如下:

app.post('/webhook/', function (req, res) {
    let messaging_events = req.body.entry[0].messaging
    for (let i = 0; i < messaging_events.length; i++) {
     let event = req.body.entry[0].messaging[i]
     let sender = event.sender.id
     
     // 查看接收到的訊息
     if (!event.read && !event.delivery) {
      // sendTextMessage(sender,JSON.stringify(event))
     }
     
     if (event.postback && event.postback.payload) {
   if (event.postback.payload == "get_started") {
    sendTextMessage(sender, "歡迎使用......! 使用說明.......")
   }
     }
     
     if (event.message && event.message.text) {
      let text = event.message.text
      sendTextMessage(sender, "Text received, echo: " + text.substring(0, 200))
     }
    }
    res.sendStatus(200)
})

Persistent Menu

Persistent Menu 是訊息輸入框左邊的選單,可以設定選單項目讓使用者按。 項目可以是回傳訊息(postback) 或開啟網頁(web_url)。 要啟用選單,需要下 curl 指令,其中 type 為 postback 或 web_url (現在有新的 nested), title 為顯示的文字,payload 為回傳的訊息,url 就是開啟的網址。

curl -X POST -H "Content-Type: application/json" -d '{
  "setting_type" : "call_to_actions",
  "thread_state" : "existing_thread",
  "call_to_actions":[
    {
      "type":"postback",
      "title":"使用說明",
      "payload":"使用說明"
    },
 {
      "type":"web_url",
      "title":"開啟網頁1",
      "url":"https://....."
    },
    {
      "type":"web_url",
      "title":"開啟網頁2",
      "url":"https://......"
    }
  ]
}' "https://graph.facebook.com/v2.6/me/thread_settings?access_token=<PAGE_ACCESS_TOKEN>"

接著處理回傳的訊息:
{"recipient":{"id":"113804092590975"},"timestamp":1503168321183,"sender":{"id":"1698642063542925"},"postback":{"payload":"使用說明","title":"使用說明"}}

收到使用者點選"使用說明"的訊息後,送出使用方式,可以在 app.post('/webhook/',... 那段程式裡加上:

if (event.postback.payload == "使用說明") {
    sendTextMessage(sender, "使用方式......")
}

接收文字及改良傳送文字

前面有提到使用者傳送文字後,伺服器會收到像這樣的資料:
{"sender":{"id":"1424115491013073"},"recipient":{"id":"113804092590975"},"timestamp":1503165292699,"message":{"mid":"mid.$cAAA9dYwjCPlkLOdom1d-6If_DNao","seq":111142,"text":"Get Started"}}

因此就是以 event.message.text 來讀取內容。

至於傳送文字,Facebook 說明文件 說傳送文字上限是 640 個字元,我測試過若超過會無法傳送。 雖然看起來好像夠用了,但畢竟用途這麼廣泛,哪天會不會不小心超過字數很難說, 於是我改寫程式讓他分次傳送,每次最多 640 個字元, 要注意的是要確定訊息送達了才傳下一則,否則下一則有可能提早送達, 因此我用遞迴方式來改寫:

function sendTextMessage(sender, text) {
    let messageData = { text:text.substring(0, 640) }
    request({
     url: 'https://graph.facebook.com/v2.6/me/messages',
     qs: {access_token:token},
     method: 'POST',
  json: {
      recipient: {id:sender},
   message: messageData,
  }
 }, function(error, response, body) {
  if (error) {
      console.log('Error sending messages: ', error)
  } else if (response.body.error) {
      console.log('Error: ', response.body.error)
     }
     
     if (text.substring(640).length > 0) sendTextMessage(sender, text.substring(640))
    })
}

接收及傳送圖片、影片、聲音和檔案

使用者傳送 圖片(image) ,伺服器會收到:
{"sender":{"id":"1452521714829182"},"recipient":{"id":"552307314960024"},"timestamp":1503303984065,"message":{"mid":"mid.$cAAGspu-D-WhkNSurwVeA-ZaRvKdo","seq":10461,"attachments":[{"type":"image","payload":{"url":"https://scontent-lht6-1.xx.fbcdn.net/v/t35.0-12/21014579_2030492610570512_1936831906_o.png?_nc_ad=z-m&oh=b4866e862d59886ce57160fd135a66a8&oe=599D2FFB"}}]}}

至於影片(video)、 聲音(audio) 和檔案(file) 只是將 "type":"image" 改掉而已,而 "url" 就是附件網址。 如果使用者一次傳很多項附件,會在 "attachments" 裡個別列出; 如果使用者同時傳送附件和文字,"message" 裡則會多一項 "text" 。

傳送圖片:

function sendAttachment(sender) {
 messageData = { 
  "attachment":{
   "type":"image",
   "payload":{
    "url":"www......jpg"
   }
  }
 }
    request({
     url: 'https://graph.facebook.com/v2.6/me/messages',
     qs: {access_token:token},
     method: 'POST',
  json: {
      recipient: {id:sender},
   message: messageData,
  }
 }, function(error, response, body) {
  if (error) {
      console.log('Error sending messages: ', error)
  } else if (response.body.error) {
      console.log('Error: ', response.body.error)
     }
     
    })
}

至於傳送影片(video)、 聲音(audio) 和檔案(file),就是將 "type":"image" 改掉。 然後若是傳送多個附件或加上文字,我猜應該就是加在 "attachments" 裡或在 "message" 裡加上 "text", messageData 陣列的內容應該就跟收到的訊息內容一樣吧? 可惜實驗後發現錯了,messageData 裡不但不能有 mid、 seq、 attachments(只能是attachment,沒有s), 一次傳送多檔或加入 text 都會失敗。

表情符號、按讚、貼圖、gif、網址、座標

使用者傳送這幾種東西,分別會收到的 "message" 內容如下:
表情符號:
{"mid":"mid.$cAAGspu-D-WhkNbv7H1eBHayp4TNQ","seq":10515,"text":"😂"}

按讚(小):
{"mid":"mid.$cAAGspu-D-WhkNYGDq1eBDw6bJqNa","seq":10473,"sticker_id":369239263222822,"attachments":[{"type":"image","payload":{"url":"https://scontent-lht6-1.xx.fbcdn.net/v/t39.1997-6/851557_369239266556155_759568595_n.png?_nc_ad=z-m&oh=f41542005a7945be79a6181951f7a37b&oe=5A2703DC","sticker_id":369239263222822}}]}

按讚(中):
{"mid":"mid.$cAAGspu-D-WhkNYQa-VeBD7SCWQ3n","seq":10483,"sticker_id":369239343222814,"attachments":[{"type":"image","payload":{"url":"https://scontent-lht6-1.xx.fbcdn.net/v/t39.1997-6/p100x100/851587_369239346556147_162929011_n.png?_nc_ad=z-m&oh=6c4deff5f1cf8c2f7940dab6f54862a2&oe=5A2DF5B0","sticker_id":369239343222814}}]}

按讚(大):
{"mid":"mid.$cAAGspu-D-WhkNYQNyleBD7E2pwdi","seq":10478,"sticker_id":369239383222810,"attachments":[{"type":"image","payload":{"url":"https://scontent-lht6-1.xx.fbcdn.net/v/t39.1997-6/p100x100/851582_369239386556143_1497813874_n.png?_nc_ad=z-m&oh=87fdbca9b865b3a42be4eb10cf46cd24&oe=5A38C44D","sticker_id":369239383222810}}]}

輸贏狐貼圖:
{"mid":"mid.$cAAGspu-D-WhkNYtpCVeBEYgjSbYH","seq":10491,"sticker_id":209575325899636,"attachments":[{"type":"image","payload":{"url":"https://scontent-lht6-1.xx.fbcdn.net/v/t39.1997-6/p100x100/851582_209575329232969_976565560_n.png?_nc_ad=z-m&oh=699f06661162192b1810ff58139521ec&oe=5A23AD85","sticker_id":209575325899636}}]}

gif:
{"mid":"mid.$cAAGspu-D-WhkNbXw9VeBHCnQM4NB","seq":10496,"attachments":[{"type":"image","payload":{"url":"https://scontent-lht6-1.xx.fbcdn.net/v/t34.0-12/19858758_10154486779901104_1435725398_n.gif?fallback=1&_nc_ad=z-m&oh=41b56c041e149e56749431fd2263b9b9&oe=599D2AE0"}}]}

網址:
{"mid":"mid.$cAAGspu-D-WhkNbeqyleBHJhGauLJ","seq":10509,"text":"https://doofenshmirtzevilincorporated.blogspot.tw/","attachments":[{"title":"總共一百零四天的暑假又到來","url":"https://l.facebook.com/l.php?u=https%3A%2F%2Fdoofenshmirtzevilincorporated.blogspot.tw%2F&h=ATOLt1ATZF83pTgwm7WqfS3HNXHNfOrqtYd-7LJDFpIbkF2fwGyBu2a0PYEJ2GCGhrilC9ambi_0ZWL5aRGJwddrWQP06wUbvvHBZYFxNq1rfFh1Sg&s=1&enc=AZO3mv_JAr7irHbc56Dhy15jFPewXz852K6DDIWmW07DHKnb6_bMs8XkB4kO-nlRGVAKR-e5XvoyJOs1Ji0F1QnP","type":"fallback","payload":null}]}

座標:
{"mid":"mid.$cAAGspu-D-WhkNELmMVeAv2cdwp22","seq":10319,"attachments":[{"title":"Pinned Location","url":"https://l.facebook.com/l.php?u=https%3A%2F%2Fwww.bing.com%2Fmaps%2Fdefault.aspx%3Fv%3D2%26pc%3DFACEBK%26mid%3D8100%26where1%3D-31.957707%252C%2B139.752693%26FORM%3DFBKPL1%26mkt%3Den-US&h=ATOoTxg6RrfNPRfCkEcWonOqogMEqE_4XXq6xtgy_CLtYSOV7-Y_jCKNg-X7gKufIsgZqpY4KVQXItLFBbtsQC0hTkwp-tUlPEdp4xO-zKRy8_rW-A&s=1&enc=AZObNvASpWzDli1ESoHq3h5z83p23ZKfKvYG8gavsKoZx_wzSjE9i4ihWR13hD0qFpo278VOEsB9YCAOLXkimqJc","type":"location","payload":{"coordinates":{"lat":-31.957707,"long":139.752693}}}]}

看來表情符號只是 emoji 文字而已;按讚似乎是貼圖的一種,包含 sticker_id 和 image; 座標可以從 payload/coordinates 找到緯度經度。

把 "attachments" 裡的資料當成 "attachment" 送出,只有表情符號和gif可以文字和圖片送出, 其他都失敗了,看來聊天機器人大概真的 不能送出貼圖 吧。

Button Template

Button Template 用來傳送 1~3 個按鈕給使用者選擇,有點像 Persistent Menu,但 buttons/type 有 web_url、 postback 和 更多選擇 。 messageData 範例如下:

"attachment":{
 "type":"template",
 "payload":{
  "template_type":"button",
  "text":"What do you want to do next?",
  "buttons":[
   {
    "type":"web_url",
    "url":"https://www.messenger.com",
    "title":"Visit Messenger"
   },
   {
    "type":"postback",
    "title":"Bookmark Item",
    "payload":"DEVELOPER_DEFINED_PAYLOAD"
   }
  ]
 }
}

使用者點選 postback 按鈕後,伺服器收到的回應:
{"recipient":{"id":"552307314960024"},"timestamp":1503327519700,"sender":{"id":"1452521714829182"},"postback":{"payload":"DEVELOPER_DEFINED_PAYLOAD","title":"Bookmark Item"}}

Generic Template

Generic Template 是把好幾個選單(elements,最多 10 個) 一次傳給使用者,選單可以有圖片文字跟最多 3 個按鈕。 messageData 範例:

"attachment":{
  "type":"template",
  "payload":{
    "template_type":"generic",
    "elements":[
       {
        "title":"Welcome to Peter\'s Hats",
        "image_url":"https://petersfancybrownhats.com/company_image.png",
        "subtitle":"We\'ve got the right hat for everyone.",
        "default_action": {
          "type": "web_url",
          "url": "https://peterssendreceiveapp.ngrok.io/view?item=103",
          "messenger_extensions": true,
          "webview_height_ratio": "tall",
          "fallback_url": "https://peterssendreceiveapp.ngrok.io/"
        },
        "buttons":[
          {
            "type":"web_url",
            "url":"https://petersfancybrownhats.com",
            "title":"View Website"
          },{
            "type":"postback",
            "title":"Start Chatting",
            "payload":"DEVELOPER_DEFINED_PAYLOAD"
          }              
        ]      
      }
    ]
  }
}

使用者點選 postback 按鈕後,伺服器收到的回應:
{"recipient":{"id":"552307314960024"},"timestamp":1503329043696,"sender":{"id":"1452521714829182"},"postback":{"payload":"DEVELOPER_DEFINED_PAYLOAD","title":"Start Chatting"}}

Quick Replies

Quick Replies 是在傳送 text 和 attachment(image or template) 給使用者之後,順便傳送最多 11 個按鈕, 按鈕可以是文字/圖片加文字/座標。messageData 範例:

"text":"123",
"quick_replies":[
  {
    "content_type":"text",
    "title":"Search",
    "payload":"qwer",
    "image_url":"https://openclipart.org/image/2400px/svg_to_png/257587/Geese-Bus.png"
  },
  {
    "content_type":"location"
  },
  {
    "content_type":"text",
    "title":"Something Else",
    "payload":"1234"
  }
]

使用者點選文字/圖片加文字按鈕後,伺服器收到的回應:
{"sender":{"id":"1452521714829182"},"recipient":{"id":"552307314960024"},"timestamp":1503326464107,"message":{"quick_reply":{"payload":"qwer"},"mid":"mid.$cAAGspu-D-WhkNoKwa1eBT1nu73MQ","seq":10570,"text":"Search"}}

看來是同時有 payload 和 text,這點和前面的不太一樣。

其他

寫到這裡,功能應該也差不多夠用了,還有個小功能是可以讓使用者看到機器人正在打字中的 Sender Actions 就不另外寫了。 有些後來推出的新功能有點複雜,我還在研究中,像是 List Template Webview ,以後有機會再補充。

事實上 messenger 聊天機器人的原理很簡單,接收時從 webwook 接收資料, 發送時利用 post request 加上 access token 發送資料,至於資料的格式和限制則要看說明書。 因此若是改寫成 php 應該不會太難。而在測試傳訊息給使用者的時候,當然也可以像說明文件寫的用 curl 指令如下:

curl -X POST -H "Content-Type: application/json" -d '{
  "recipient":{
    "id":"1452521714829182"
  }, 
  "message":{
    "text":"😂"
  }
}' "https://graph.facebook.com/me/messages?access_token=<PAGE_ACCESS_TOKEN>"

了解 Facebook Messenger 聊天機器人接收與傳送的資料後,設計起來就簡單多了, 但實際設計時可能常常又受限於他的限制,像是字數或按鈕數量不夠用和無法送出貼圖, 就要發揮創意想辦法解決了,或是定期看看推出了什麼新功能; 而不確定有沒有這個功能和限制時,最好看一下說明文件以及自己試用看看。 最後,更多有關 Facebook Messenger 聊天機器人的設計建議,可以去看 Design Guidelines

公開發佈

作品完成後,並不是所有人都能馬上使用,必須 提交給 Facebook 審核 。 在審核通過之前,聊天機器人只會對 App admins, developers 和 testers 這些人有反應 (可在 App 的 roles 頁面設定)。 提交給 Facebook 審核的方式為,到 App 的 Messenger 頁面底下 App Review for Messenger 區塊, 選擇 pages_messaging 右邊的 Add to Submission。 然後如果下面出現的 Submit For Review 按鈕不能按,表示還沒達成左邊列出的要求, 像是要上傳 1024 x 1024 的 App Icon、 填寫 Privacy Policy URL 和 Category, 還要點 Edit Notes 填寫給審察者看的內容,我記得第一個做的聊天機器人還要上傳使用時的螢幕錄影, 都完成就可以送出,慢慢等他審核通過。

用了這麼久的 Facebook Messenger,第一次看到他可以自動回覆想必很讓人興奮, 何況是動手寫程式做出來。 Botlist 這網站搜集了很多聊天機器人, 包括 Messenger 和其他平台。 用 Messenger 聊天機器人最大的好處,就是手機上不需要再安裝一樣功能的 app, 也可以一邊和人聊天一邊用聊天機器人做事。 要是覺得 Messenger 限制太多或平常沒在用 Messenger 的話, 也有其他平台的機器人可以玩,有機會我也來玩玩看好了。


2017/9/26 補充

我想要將別人傳來的訊息的回覆,也傳一份給自己,也就是說 recipient 的 id 不再是收到的 sender,而是固定的我的 id, 直接寫成 recipient: {id:1424115491013073}, 發生了很可怕的事,就是訊息傳送不停!

怪了,為什麼傳給特定的人會出錯啊?打開把接收到的訊息回傳的功能,還是看不到問題。 後來才發現機器人傳訊息給我的時候,會回傳 Message Echo , 而這串訊息 sender id 是機器人的,message.text 是傳給我的文字, 因此原本機器人要把這文字處理後傳給自己的,卻被指定傳給我了,才會傳個不停; 而且那個"把接收到的訊息回傳的功能"是傳給 sender 我才會看不到,要是也改成自己的 id 就有趣了...

總之要把 Message Echo 關掉或過濾掉,到 Page Subscription 那裡把 message_echoes 取消打勾就好了, 或是過濾 message.is_echo。 其實 Page Subscription 那裡有些東西像是 message_reads 或 message_deliveries,根本就可以不用勾的啊@@ 就不用再麻煩的處理這種訊息了。

3 comments :

  1. That is the suitable blog for anyone who desires to search out out about this topic. You realize so much it's almost hard to argue with you (not that I actually would want). You undoubtedly put a brand new spin on a topic that's been written about for years. Great stuff, just great! you can also check my post on Facebook Marketplace not Working t know more on that.

    ReplyDelete
  2. Visit the historical city of India and also see the beauty of Taj Mahal in the reflection of Sun in our Sunrise Tour of Taj Mahal.

    ReplyDelete
  3. Amazing post I Read your blog, it`s so informative awesome thanks for sharing
    any one can explore INDIA visit us we are PACIFIC TOUR INDIA join us
    Some Packages:-
    Golden Triangle Tour 5 Days

    Golden Triangle Tour 6 Days

    Golden Triangle Tour 4 Days

    Golden Triangle & Varanasi

    Golden Triangle & Ranthambore

    for more information contact us
    CONTACT INFO
    Shop No.16, First Floor, Prerna Plaza, Fatehabad Road, Agra- 282001
    Mob : +91 - 9759747417, 9568617417
    Email: info@pacifictourindia.com,
    Web-side: www.pacifictourindia.com

    ReplyDelete