(一)一步步打造 Telegram Bot

最近因為一些契機學了 Python 3,用它做了一個 Telegram BotGitHub 連結),裡面用到 NLP Service,用三篇文章記錄一下實作過程還有眉角。第一篇先講要做一個最簡單的回聲 Chatbot 要怎麼做。

使用的工具及服務:

  1. Python 3(for develop)
  2. pipenv(for dependency management)
  3. ngrok(for testing)

Step 1. Creating new bot

Telegram 很有趣的地方在於,與其他通訊軟體(Line、Messenger)相比,開發者管理 Bot 的方式也是透過官方提供的一位 Bot 在處理的,它叫做 BotFather(眾 Bot 之父 XD)。如果已經有 Telegram 帳號,只要加 BotFather 為好友,就可以開始管理你的 Bot。

加入 BotFather 好友後,它會親切地問候,並告訴你他能為你提供什麼服務。

I can help you create and manage Telegram bots. If you're new to the Bot API, please see the manual (https://core.telegram.org/bots).
You can control me by sending these commands:
/newbot - create a new bot
/mybots - edit your bots [beta]
/mygames - edit your games (https://core.telegram.org/bots/games) [beta]
Edit Bots
/setname - change a bot's name
/setdescription - change bot description
/setabouttext - change bot about info
/setuserpic - change bot profile photo
/setcommands - change the list of commands
/deletebot - delete a bot
Bot Settings
/token - generate authorization token
/revoke - revoke bot access token
/setinline - toggle inline mode (https://core.telegram.org/bots/inline)
/setinlinegeo - toggle inline location requests (https://core.telegram.org/bots/inline#location-based-results)
/setinlinefeedback - change inline feedback (https://core.telegram.org/bots/inline#collecting-feedback) settings
/setjoingroups - can your bot be added to groups?
/setprivacy - toggle privacy mode (https://core.telegram.org/bots#privacy-mode) in groups
Games
/newgame - create a new game (https://core.telegram.org/bots/games)
/listgames - get a list of your games
/editgame - edit a game
/deletegame - delete an existing game

使用 /new bot 指令,接著輸入 Chatbot name 及 username,最後就會得到

Done! Congratulations on your new bot. You will find it at t.me/chatbot_workshop_bot. You can now add a description, about section and profile picture for your bot, see /help for a list of commands. By the way, when you've finished creating your cool bot, ping our Bot Support if you want a better username for it. Just make sure the bot is fully operational before you do this.
Use this token to access the HTTP API:
606248605:AAGv_TOJdNNMc_v3toHK_X6M-dev_1tG-JA
For a description of the Bot API, see this page: https://core.telegram.org/bots/api

第二行有一段網址 t.me/chatbot_workshop_bot,它是之後 Chatbot 發佈後要提供給使用者加好友的連結,比如 https://t.me/innovation_chatbot

606248605:AAGv_TOJdNNMc_v3toHK_X6M-dev_1tG-JA 則是 token,用來 access Telegram Bot API。請勿外洩,否則他人就可以擷取使用者傳給 Bot 的訊息,然後幫你回覆。

Step 2. Understanding chatbot’s architecture

/new bot結束後,得到自己的 Bot 與 token。就可以開始和 Bot 對話(雖然它還不會回答)。講幾句話以後,透過瀏覽器進入以下連結

https://api.telegram.org/bot{$token}/getUpdates

$token 換成在 Step 1 拿到的 token,例如:https://api.telegram.org/bot606248605:AAGv_TOJdNNMc_v3toHK_X6M-dev_1tG-JA/getUpdates

就會在瀏覽器上看到自己和 Chatbot 的對話紀錄

{
ok: true,
result: [
{
update_id: 140863081,
message: {
message_id: 2,
from: {
id: 338083968,
is_bot: false,
first_name: "zaoldyeck",
username: "zaoldyeck9970",
language_code: "zh-Hant-TW"
},
chat: {
id: 338083968,
first_name: "zaoldyeck",
username: "zaoldyeck9970",
type: "private"
},
date: 1527754411,
text: "Hello"
}
}
]
}

https://api.telegram.org/bot{$token}/getUpdates 是 Telegram 提供的 API,讓我們可以用 token 取得使用者傳給 Bot 的訊息,Telegram Bot API 使用方式紀錄在官方文件

取得使用者訊息的兩種方法-Long Polling vs Webhook

  1. Long Polling 是指程式間隔一定時間透過 getUpdates(上面所使用的方法)取得訊息,缺點是浪費資源、不夠即時,所以適合在程式還沒有 deploy,在 develop 和 test 階段時使用。
  2. Webhook 是指向 Telegram 設定一組 callback url,只要當使用者傳送訊息給 Chatbot,Telegram 就會把用息連同 metada 透過 url 傳給 web server。適合在程式已經 deploy,有固定 url 的 production 環境使用。

完整 Chatbot 運作流程如下,NLP 與 Third party API integration 的環節會在後面兩篇文章實作。

Step 3. Prepare development environment

先建立一個專案目錄

$ mkdir $project_name

進入專案目錄

$ cd $project_name

install 開發 Chatbot 需要的 Module

$ pipenv install --three python-telegram-bot flask gunicorn requests
參數及 module 說明
--three 用 Python 3 建立虛擬環境
python-telegram-bot Telegram Bot API wrapper.
flask Web framework. Using for building webhook API.
gunicorn Python WSGI HTTP server for UNIX. Using for deploying web server.
requests HTTP client library.

安裝完後,專案目錄中會增加兩個檔案

Project Directory
├── Pipfile.lock
└── Pipfile

Take a look at Pipfile

接著,在專案目錄中新增一個 config file,把 Chatbot 所用到 Service 的 key 及 secret 都寫在 config file 中。這麼做的優點如下:

  1. service key 及 secret 不應該寫在程式碼裡,避免因為有做版本控制,在 git commit & push 後將機密資訊暴露在 public repository
  2. 集中管理,日後若需要更改 key,直接編輯 config file 即可,不用更動程式碼,也能確保程式中有用到 key 及 secret 的模組都會同步更新
  3. 部署專案時,比起在 server 設定環境變數,loading config file 的方式會更加方便容易

Python 有預設的 Configuration file parser module

在專案目錄中新增 config.ini 檔案

$ touch config.ini

編輯成以下格式

使用時,把各 service 申請到的 token / key / secret放在 = 後面即可,例如:

[TELEGRAM]
ACCESS_TOKEN = 606248605:AAGv_TOJdNNMc_v3toHK_X6M-dev_1tG-JA

至此開發環境準備完成,專案目錄中共有三個檔案

Project Directory
├── config.ini
├── Pipfile.lock
└── Pipfile

Step 4. Develop first echo chatbot

這一步會先完成一個鸚鵡回話 Chatbot,講解 python-telegram-bot 提供哪些模組幫助我們做 Telegram Bot 開發。

在專案目錄中,新增 main.py 檔案

$ touch main.py

程式碼如下

完成後,就可以用 pipenv running。在專案目錄中執行以下命令

$ pipenv run python3 main.py

Flask server 就會開始運行

* Serving Flask app "main" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: on
2018-06-15 16:38:07,843 - werkzeug - INFO - * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
2018-06-15 16:38:07,845 - werkzeug - INFO - * Restarting with stat
2018-06-15 16:38:08,279 - werkzeug - WARNING - * Debugger is active!
2018-06-15 16:38:08,324 - werkzeug - INFO - * Debugger PIN: 244-087-163

但是程式是在本機運行,要怎麼讓使用者傳送給 Telegram Bot 的訊息可以透過 webhook 傳送給本機 web server 呢?

此時就可以用 ngrok 服務,它會幫我們在 cloud 建立 public domain 對 local 端的 poxy。執行以下命令

$ ngrok http 5000
5000 剛好對應 Flask App listening 的 port
Session Status                online
Session Expires 7 hours, 58 minutes
Version 2.2.8
Region United States (us)
Web Interface http://127.0.0.1:4040
Forwarding http://76f2a29d.ngrok.io -> localhost:5000
Forwarding https://76f2a29d.ngrok.io -> localhost:5000
Connections                   ttl     opn     rt1     rt5     p50     p90
2 0 0.03 0.01 1.21 1.89

接下來就可以把 https://76f2a29d.ngrok.io/hook 設定為 Telegram Bot 的 webhook。

請注意,ngrok 只有在 development 使用,production 環境還是會將程式部署到正式的 service

設定 Telegram Bot webhook 的方法可參考文件,透過瀏覽器進入以下連結

https://api.telegram.org/bot{$token}/setWebhook?url={$webhook_url}

$token$webhook_url 請換成在 Step 1 申請到的,例如:

https://api.telegram.org/bot606248605:AAGv_TOJdNNMc_v3toHK_X6M-dev_1tG-JA/setWebhook?url=https://bcf4cd97.ngrok.io/hook

看到瀏覽器出現以下訊息,就表示 webhook 設定成功了

{
ok: true,
result: true,
description: "Webhook was set"
}

開始和 Chatbot 對話,它就會向鸚鵡一樣回覆你傳給它的訊息。

下一篇文章會講如何用 OLAMI Open API 為 Chatbot 增加 NLP 功能,讓 Chatbot 可以根據使用者訊息判斷須回覆的內容,例如詢問股市、天氣。

範例完整程式碼
如果想要把現階段的 Chatbot 部署上 production 環境,步驟可以參考最後一篇文章的 Step 9. Deployment