使用 Telegram 官方推薦的方式,實作 webhook 和部署機器人到 Heroku。
本文只講部署(deploy)的部分,撰寫程式和申請帳號、操作 Heroku 教學很多了請自行 google。
本文章撰寫給:
1. 想要部署寫好的機器人上 Heroku 但不知道要怎麼做的人
2. 看過各路大神的教學了但還是懵懵懂懂的人
3. 看了半天不懂「一定要用 flask 之類的套件才能實作 webhook 嗎」的人
4. 「我不想看英文」的人
前言
最近總算開始動手實作完一年前想到要做的 Telegram bot 也真的實作完成了(沒想到只花了兩天,可是拖延了一年XD)做出來之後當然就要找一個地方丟上去讓機器人運作囉,雖然說可以自己的電腦跑啦,但本人沒這個打算,所以最後找到了 Heroku 這個雲端平台。
網路上也滿多 python telegram bot 部署到 Heroku 的教學,那聽起來照著做就好啦?原因是這樣的:個人比較傳統,是 Notepad++打開後按照官方的範例和一些大大的教學寫出來的。可是不少人在開發階段就使用了 flask 等套件直接用 webhook;而我還是用 polling 的方式,因此就需要修改 code 搭配 flask 實作 webhook 並部署。(polling 和 webhook 的差別可見
此位大大撰寫的教學文)
一開始爬了幾篇前輩們用中文寫的教學八九不離十都是這招,正當我開始想套用的時候,有位大神提點了我 flask 的作用,讓我開始重新思考並改用英文搜尋,結果就發現了其實可以靠官方和 heroku 提供的方法來解決(而且官方文件其實都有寫0.0)。本文就是為這個方式留下紀錄提供給想用官方提供的方法但不想看英文的人。
先聲明,只要能達成目的的都是方法,沒有優劣之分。另外,也可能此方法是後來才新增支援的,所以前人都沒有紀錄。請大家依照自身的需求決定用何種方式部署最適合自己的專案。
事前準備
1. 不用說,就是你寫好的機器人。沒有的話也可以使用
範例的。
2. Heroku CLI
3. git(使用和部署 Heroku 需要)
4. 已經建立好的一個空白 heroku 專案
開始
為了方便大家有個對照,這邊會在每個步驟最後附上對照目前的狀態對應
範例程式碼的哪個 commit。
建立 Pipfile ★
pipenv 是一套整合套件管理及虛擬環境的的工具,詳細介紹可以去查詢一下,總之是一套個人在做 Python 專案常用的工具。而 Heroku 現在支援在部署的時候使用 Pipfile 來自動安裝所需要的套件(以前要 requirements.txt)。沒安裝過的同學請在命令列下 pip install pipenv 來安裝;已經有安裝的請生出 Pipfile 並產生 Pipfile.lock 吧;如果你這邊已經完成了請直接下一步吧。
建立 Procfile ★★★
Procfile 是 heroku 部署時會用到的檔案,用來讓 Heroku 知道要如何部署並執行你的專案。請注意檔案名稱只要 Procfile 就好不需要有副檔名!內容也請只有接下來說的這行!
檔案內容請寫(注意:Python 2 的話請用 python):
web: python3 {你的機器人}.py
web: python3 bot.py
修改程式碼中關於讀取設定的部分
此部分僅針對有將一些敏感設定採用另外讀取方式的人需要
Heroku 的 dyno 以我自己的理解,就很像 Docker container 一樣,容器關掉東西就通通消失了,所以傳統的一個 env 檔案之類的設定不太適用(如果有上去 repo 的話,大家都知道這種敏感檔案要另外處理)。當然應該另外有方法解決,只是這邊採用「環境變數」的方式:
env = ConfigParser()
env.read('config.ini')
TOKEN = env['bot']['TOKEN']
現在請改成:
# 如果有其他需求的變數也請一併設定
TOKEN = os.environ["TOKEN"]
然後到 heroku 網站下自己的專案→setting→Reveal Config Vars→新增剛剛設定的 Config Vars:(例如剛剛的 TOKEN 請填入 BotFather 給你的機器人 token)
修改機器人和 Telegram API 的溝通方式 ★★
接下來就要從 polling 的方式改成 webhook 的方式啦~
首先請先在程式碼中加上下面這行(我自己是跟剛剛設定環境變數的區塊放一起,總之只要在開始呼叫機器人之前宣告好即可):
PORT = int(os.environ.get('PORT', '8443'))
接著修改 updater.start_polling() 成:(請自行填入自己的 heroku 專案名稱,別傻傻的就複製貼上什麼都沒改啊)
updater.start_webhook(listen="0.0.0.0",
port=PORT,
url_path=TOKEN)
updater.bot.set_webhook("https://{你的 heroku 專案名稱}.herokuapp.com/" + TOKEN)
這樣就完成修改溝通方式以及設定 webhook 了,最後就 commit 並推上 heroku 吧!請開啟命令列:
git commit -am "準備推上 heroku 囉" # 這邊請依照情況自己做 commit
heroku login # 如果之前沒先登入過的話
heroku git:remote -a {你的 heroku 專案名稱}
git push heroku master
完成
如果有成功部署上去,應該會看到 heroku 自動偵測到 Python app 並依照 Pipenv、Pipenv.lock 去安裝需要的相依套件,最後照著 Procfile 去執行你的機器人。
如果是使用範例程式碼的話,在啟動(Start)機器人的時候就會跳出問候訊息;傳送 /hi 的話就會回你「Hello world!」。到這邊一切大功告成~灑花
其他補充
在部署到 heroku 的路上產生的疑問或踩過的坑
一定要在 maser 分支上嗎?
可能大家會在一些教學文上看到大家都是用 master 分支當範例,或是有看到「heroku 只有在分支是 master 的時候才會有作用」之類的句子。這是正確的嗎?一定只能用 master 分支嗎?
教學們並沒有說錯,但講不夠明確,正確的應該是:推上去 heroku 『後』的分支要是 master,heroku 才會運作。也就是說,不管你的分支叫什麼阿貓阿狗奇怪的名稱,只要上到 heroku 這個 remote repo 後東西是在他的 master 就可以!
那具體來說要怎麼做?一言以蔽之的話就是下面這行指令:
git push heroku +HEAD:master
有興趣想知道為什麼的人可以參考文章最後有附上參考來源或
直接點此。
Heroku 免費方案會睡覺,影響很大嗎?
以前是怎樣我不敢說,現在的話以我們部署機器人來說,我看大家比較有感的應該是「三十分鐘沒有活動則會進入休眠」,而其他什麼「每天要睡 8 小時」之類的倒是沒看到。
那這個休眠會差很多嗎?我自己實際部署使用後,測試下來休眠後傳送訊息等機器人起床大約要 10 秒。這樣的影響大還是小請大家自行評估囉。
後記
部署成功,好開心啊!
如果本文有任何錯誤、執行上有碰到問題或是有更好的做法及替代方案都歡迎留言給我。也祝大家順利部署自己的作品(不論用什麼方式和部署到哪裡),成功上線後歡迎留言分享喔。
在 Medium 上的第一篇文就獻給這篇了。
參考資料