iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 6
3
Modern Web

使用 Modern Web 技術來打造 Chat App系列 第 6

Day 06:把前幾天的聊天機器人都搬上 Messenger

接下來幾天會介紹怎麼把前幾天在 Console Mode 做的機器人搬上像是 Messenger、LINE 這些台灣人常在使用的管道。

而今天的目標會放在 Messenger 上,首先我們要先修改之前只支援使用 Console Mode 的設定檔:

修改 bottender.config.js 設定檔

bottender.config.js 的設定檔裡面需要新增 messenger 的設定在 channels 裡面:

// bottender.config.js
require('dotenv').config(); // 記得 npm install dotenv

module.exports = {
  //... 其他省略
  
  channels: {
    messenger: {
      enabled: true,
      path: '/',
      pageId: process.env.MESSENGER_PAGE_ID,
      accessToken: process.env.MESSENGER_ACCESS_TOKEN,
      verifyToken: process.env.MESSENGER_VERIFY_TOKEN,
      appId: process.env.MESSENGER_APP_ID,
      appSecret: process.env.MESSENGER_APP_SECRET,
    },
  },
};

這邊我們都是使用 process.env (環境變數) 來避免直接把敏感資訊的字串寫在程式碼裡面,這是一個好習慣,除了可以輕易地在不修改程式的情況下改設定,更可以避免輕易的把 Commit 到 Git 裡面去,或甚至因此上傳到網路、GitHub 上。

最上方的 require('dotenv').config(),是我們打算使用 dotenv 這個套件,來直接讀取 .env 這個檔案的設定注入到 process.env,所以這些敏感的資料我們需要另外建立 .env 檔案來放:

// .env
MESSENGER_PAGE_ID=
MESSENGER_ACCESS_TOKEN=
MESSENGER_VERIFY_TOKEN=
MESSENGER_APP_ID=
MESSENGER_APP_SECRET=

(注意:如果有在用 Git,這個 .env 必須列在 .gitignore 裡面)

從這邊可以看到,我們需要五個環境變數設定:

  • Page Id
  • Access Token
  • Verify Token
  • App Id
  • App Secret

這些東西還不用馬上填,都將在下一個步驟 - 「建立 Facebook 應用程式」之後來填入。

建立 Facebook 應用程式

如果你已經很熟悉怎麼建立 Facebook 應用程式,可以直接跳過這段教學,直接填好 .env 並從下一段「建立 Webhook 開始」。

為了建立 Facebook 應用程式,我們必須到 Facebook Developer 的網頁 - http://developers.facebook.com,然後點擊「我的應用程式」> 「建立應用程式」:

https://ithelp.ithome.com.tw/upload/images/20190921/20103630Y0AgM4yYPO.png

建立一個新的應用程式後,要來新增 Messenger 相關的設定,所以要點擊 Messenger 的「設定」按鈕:

https://ithelp.ithome.com.tw/upload/images/20190921/20103630jJdRUC1OGG.png

跳轉頁面後接著頁面往下滑,可以看到「新增或移除粉絲專頁」,點他新增專頁:

(沒有粉絲專頁則要先建立新的粉絲專頁)

https://ithelp.ithome.com.tw/upload/images/20190921/201036300zcQVqVlMO.png

授權好了之後,會看到這樣的畫面會有「Page Id」,必須填到你的 .env 檔案裡面的 MESSENGER_PAGE_ID 欄位,接著要點「產生權杖」:

https://ithelp.ithome.com.tw/upload/images/20191001/20103630xchmifcXZi.png

產生出來這個複製出來就是「Access Token」,必須填到你的 .env 檔案裡面的 MESSENGER_ACCESS_TOKEN 欄位:

https://ithelp.ithome.com.tw/upload/images/20190921/20103630DJmeEO7mqy.png

Menu「設定」進去「基本資料」那邊則可以拿到「App Id」以及「App Secret」,分別填到你的 .env 檔案裡面的 MESSENGER_APP_ID 以及 MESSENGER_APP_SECRET 欄位:

https://ithelp.ithome.com.tw/upload/images/20190921/20103630MjVilxrCQ5.png

// .env
MESSENGER_PAGE_ID=你的 Page Id
MESSENGER_ACCESS_TOKEN=你的 Access Token
MESSENGER_VERIFY_TOKEN=1Q40y4m1U0t05CL
MESSENGER_APP_ID=你的 App Id
MESSENGER_APP_SECRET=你的 App Secret

至於 MESSENGER_VERIFY_TOKEN 可以隨便填一段字或是學我在 Strong Password Generator 上面產生一段比較安全的。

這樣就收集完 Facebook 這邊需要的資料囉!

建立 Webhook

開啟 Server

當我們按照前面的教學,把 bottender.config.js 加上 channels.messenger 的設定時,這時候執行 bottender dev 將會自動地開啟 Server,並使用 ngrok 產生一個對外的 HTTPS 網址。

npx bottender dev

(注意:這次就不要加 --console 了)

https://ithelp.ithome.com.tw/upload/images/20190921/20103630ud6ghVnf48.png

為什麼需要 ngrok 呢?

因為當我們開發時在自己電腦上開啟 Server 時,我們能透過 http://localhost:port 去連到,但這樣子 Facebook 是無法連到我們的 Server 的,所以需要開 Tunnel,而且他們還能提供 Secure 的 HTTPS 連線。

這樣子的服務、工具,最有名的就是以下幾個:

在打開 ngrok 的情況下,前往 http://localhost:4040 應該能看到它的 Inspector:

https://ithelp.ithome.com.tw/upload/images/20190921/201036301RzrFTntoh.png

這可以用來檢查 Facebook 是否有送東西過來我們的 Server。

用 CLI 設定 Webhook

開好了 Server 跟 ngrok 後要另外用另一個 Terminal 分頁來執行以下指令:

npx bottender messenger webhook set

https://ithelp.ithome.com.tw/upload/images/20190921/20103630pSFbto0EPM.png

這邊會從你的 bottender.config.js 把一些資訊拉出來,並把網址從 ngrok 找到,送去給 Facebook 訂閱相關事件送到 Webhook。

最後在 Messenger 上測試一下 Bot:

https://ithelp.ithome.com.tw/upload/images/20190921/20103630eEbUapDZk5.jpg

是不是很熟悉?這就是我們前兩天做的笑話機器人跟比特幣機器人喔。

結語

不管是接什麼平台,這開應用程式跟設定的步驟總是最煩瑣而且又容易出錯,不過馬上就要苦盡甘來了,最難的就是這個了。


上一篇
Day 05:串接 API,讓 Chatbot 不是只能講幹話
下一篇
Day 07:Messenger 的事件處理基礎
系列文
使用 Modern Web 技術來打造 Chat App30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
Ho.Chun
iT邦新手 5 級 ‧ 2019-10-21 15:33:48

請問一下,當我想開啟 ngrok 時遇到這個 error
https://ithelp.ithome.com.tw/upload/images/20191021/20106955gvBz8CwJTw.png

PS. 目前步驟已填完 .env 那些KEY

C. T. Lin iT邦新手 5 級 ‧ 2019-10-21 15:39:55 檢舉

目前還沒遇過這個狀況,這樣資訊還不太夠
不好意思有沒有可能提供一下更詳細的重現步驟或 Repo,讓我們有辦法 Debug 這個部分呢?

Ho.Chun iT邦新手 5 級 ‧ 2019-10-21 15:53:02 檢舉

https://github.com/hochun836/chatbot
PS. 這邊我就沒上傳 .env

目前我的資料結構
https://ithelp.ithome.com.tw/upload/images/20191021/20106955I3ahQBbFnr.png

補上 Node / NPX 版本
https://ithelp.ithome.com.tw/upload/images/20191021/20106955NNI58sL69Q.png

Ho.Chun iT邦新手 5 級 ‧ 2019-10-21 16:40:14 檢舉

我直接下載 ngrok 測試,發現應該是我本機連不到 ngrok server 造成 timeout 所導致 /images/emoticon/emoticon16.gif

0
Ho.Chun
iT邦新手 5 級 ‧ 2019-10-25 00:35:03

不好意思! 又來打擾
目前

  1. ngrok 開啟成功
  2. webhook 設定完成

但最後一步,從 Messager 傳訊息給 BOT
BOT 卻沒收到 request
請問還有哪些地方要設定呢 (?

附上過程圖
[ngrok 開啟成功]
https://ithelp.ithome.com.tw/upload/images/20191025/201069551zG34WRVms.png

[webhook 設定成功]
https://ithelp.ithome.com.tw/upload/images/20191025/20106955yZT1gnpBEb.png

https://ithelp.ithome.com.tw/upload/images/20191025/20106955gvzFfWun4k.png

看更多先前的回應...收起先前的回應...
C. T. Lin iT邦新手 5 級 ‧ 2019-10-25 00:42:30 檢舉

最常見的狀況可能是沒聽到對應的 event,可以檢查一下這裡

https://ithelp.ithome.com.tw/upload/images/20191025/201036304cjeAtjG8V.png

MESSENGER_PAGE_ID 有填到理論上應該要自動設定,這個部分有填嗎?(另外想問一下 bottender 的版號)

Ho.Chun iT邦新手 5 級 ‧ 2019-10-25 00:54:00 檢舉

這邊有
https://ithelp.ithome.com.tw/upload/images/20191025/20106955g9CjRS8yKX.png

bottender 版本
https://ithelp.ithome.com.tw/upload/images/20191025/20106955IhXYCaI2H9.png

C. T. Lin iT邦新手 5 級 ‧ 2019-10-25 01:35:35 檢舉

這樣看起來很正常,收不到蠻奇怪的
另外一個我懷疑的是 Primary Receiver 的設定有沒有異常,有時候如果這個粉絲頁曾經綁過其他 App 會出一點問題

可以參考這篇檢查一下這個設定:

https://ithelp.ithome.com.tw/articles/10220717#response-312610

Ho.Chun iT邦新手 5 級 ‧ 2019-10-25 09:44:10 檢舉

感謝 !! 我晚上回去試試 /images/emoticon/emoticon41.gif

Ho.Chun iT邦新手 5 級 ‧ 2019-10-25 21:36:05 檢舉

設定完後,可以在 ngrok 那邊看到 POST 200 成功
但訊息依舊直接進入 inbox /images/emoticon/emoticon17.gif

Ho.Chun iT邦新手 5 級 ‧ 2019-10-25 22:04:27 檢舉

不好意思! 提個問題,想要看到 BOT 回應訊息
一定要用粉絲專頁的"管理員"
自己傳訊息到自己的紛絲專頁嗎 (?

我用兩個帳號測試
傳訊息 from 管理員的帳號 => 看的到 BOT 回應
傳訊息 from 一般的帳號 => 看不到 BOT 回應,訊息會直接進入 inbox

C. T. Lin iT邦新手 5 級 ‧ 2019-10-26 17:40:28 檢舉

如果你的 App 尚未調成 Public 並送審權限,那就會只有管理員或是任何被你加到測試人員的人可以測試(應該可以在 App 設定某處加測試人員)

Ho.Chun iT邦新手 5 級 ‧ 2019-10-28 00:21:53 檢舉

好的感謝 !! /images/emoticon/emoticon41.gif

0
ddr820525
iT邦新手 5 級 ‧ 2020-03-18 10:18:38

請問一下
要把講笑話和btc放在一起是怎麼弄的
為什麼我的指顯示講話的內容

看更多先前的回應...收起先前的回應...
C. T. Lin iT邦新手 5 級 ‧ 2020-03-19 11:49:42 檢舉

可以貼一下你的程式碼嗎?

ddr820525 iT邦新手 5 級 ‧ 2020-03-19 12:50:17 檢舉
const random = require('random-item');
const coinranking = require('../coinranking'); 

module.exports = async function App(context) {
  if (context.event.text === '講笑話') {
    await context.sendText(
      random([
        '加油站最怕什麼樣的員工?油腔滑調的員工',
        '有一天,西瓜、榴槤、奇異果一起出去玩,結果榴槤不見了。因為榴槤忘返',
        '海記憶體知己,天涯若比鄰',
      ])
    );
  } else {
    await context.sendText(random(['你講什麼鬼話?', '乖,聊聊別的']));
  }
};
const coins = [
  {
    id: 1,
    symbol: 'BTC',
    name: 'Bitcoin',
  },
  {
    id: 2,
    symbol: 'ETH',
    name: 'Ethereum',
  },
  {
    id: 3,
    symbol: 'XRP',
    name: 'XRP',
  },
];

module.exports = async function App(context) {
  const { text } = context.event;
  for (let c of coins) {
    if (new RegExp(`(${c.symbol})|(${c.name})`, 'i').test(text)) {
      const {
        data: { coin },
      } = await coinranking.getCoin(c.id);
      await context.sendText(`${c.symbol} 現在價格是 ${coin.price} TWD`);
      return;
    }
  }
};

ddr820525 iT邦新手 5 級 ‧ 2020-03-19 12:50:30 檢舉

我是不是寫錯地方

ddr820525 iT邦新手 5 級 ‧ 2020-03-19 12:57:57 檢舉

我搞定了哈哈抱歉,就把方法一樣寫在裡面就好了!
不好意思剛剛使用這個框架有點不習慣QQ

我要留言

立即登入留言