Back to Posts

從零開始的 Telegram Bot

Posted in Telegram

Telegram 簡介

Telegram 是一款集成眾多優點(e.g., 快速, 自由, 輕量 etc.)的通訊軟體
不管是親友間閒聊,或是社群間討論,用 Telegram 都較 LINE 適合

Telegram API 類型

  • Client API
    • 使用電話號碼登入,等同於一般使用者帳號
    • 無 inline button 等 bot 特色功能
    • 大多應用可由 telegram-cli 達成
  • Bot API(本文重點)
    • 限制較多,如無法主動私訊使用者
    • 每個使用者都可以向 @BotFather 申請至多 20 隻

如何產生 bot

想要一隻 bot 需要先有一個 Telegram 帳號(電話號碼驗證)
私訊 @BotFather 輸入 /newbot 他將會請您依序輸入 bot 顯示的名稱、 bot 的 username(必須為 bot 結尾),且長度需介於 5-32 字元
完成後, BotFather 會顯示您的 Token(格式:12345:AAJqs_w-4),您可利用此 Token 透過 HTTPS 發送請求

發起 API 請求

所有 Bot API 請求必須是 https://api.telegram.org/bot<Token>/<Method Name> 的格式,例如 https://api.telegram.org/bot12345:AAJqs_w-4/getMe

如果有 Android 手機,強烈建議這個 app 測試 Methods,比較不會遇到 URL encode 等奇怪的坑

支援使用 HTTPS GETPOST,可由以下四種方式挑喜歡的用

  • URL query string
    最通用的格式
    e.g., https://api.telegram.org/bot12345:AAJqs_w-4/sendMessage?chat_id=109780439&text=Hello+World
  • application/json
    作者個人最推薦,送出的資料比較好看
  • application/x-www-form-urlencoded
    長得跟 HTML <form> 的資料一樣
  • multipart/form-data
    上傳檔案只能用這種,類似 application/x-www-form-urlencoded

回傳會是 JSON 內容,包含一個 ok 欄位,如果 ok 等於 true 代表請求成功,會包含 result 欄位,裡面是執行結果
反之則會有給人類看的 descript 錯誤描述,以及不一定會出現的 error_coderetry_after

所有 method 都是無視大小寫的,例如 getMeGeTmE 是相同的
所有請求必須使用 UTF-8 編碼

可參考官方文件相同章節

取得訊息

目前 Telegram 支援兩種取得更新的方法,分別為

  • 設定 Webhook
    • 在有人傳送訊息給您的 bot(或加入群組、點擊按鍵等)時, Telegram 將會使用 JSON 格式 POST 到您的伺服器
    • 需使用 setWebhook 預先設定
    • 可用 getWebhookInfo 自行 debug
    • 可參考官方完整教學(英文)
  • 每次主動詢問
    • getUpdates 請求,將會回傳一個 JSON 陣列
    • 如語言支援,也可用 Long polling 取得,詳見 WiKi

接收所有訊息

預設隱私模式(Privacy Mode)是開啟的,開啟時只會收到:

  • / 開頭的指令
  • 對機器人 Reply 的訊息
  • 系統訊息(e.g., 新成員加入)
  • 自己是管理員的頻道

通常會希望關閉,才收得到全部訊息

  1. 私訊 @BotFather
  2. 輸入 /setprivacy 指令
  3. 選擇 Bot
  4. 點擊 Disable

Webook 除錯

官方提供了獨立說明頁

看 Telegram 端有無錯誤

使用 getWebhookInfo 可以看目前狀態,如有錯誤還能從 last_error_message 找到點資訊

對自己的 Webhook 測試

如果上個步驟沒問題的話,這裡有幾個 payload 提供測試,能用 curl 模擬 Telegram 伺服器,測試自己程式有沒有什麼奇怪錯誤

傳送訊息

Telegram 是藉由 sendMessage 傳送訊息給使用者,下面列出幾個主要參數

  • chat_id(必要選項)
    • 私訊(Private)為正數(例如 109780439
    • 頻道(Channel)為負數(例如 -1001068773197),也可以用 @頻道名(例如 @HiNetNotify
    • 群組(Group)為負數(例如 -248855446
    • 超級群組(Supergroup)跟 Channel 完全相同(聽說是從 channel 改來的功能)
  • text(必要選項)
    送訊息內容
  • parse_mode
    未設定則為純文字,皆支援複合使用(像是 <b><i>重要</i></b>
    • Markdown
      可以用 [連結](url)*粗體*_斜體_`等寬字````程式碼(等寬區塊)```
      在有使用者輸入資料得環境不建議使用,如果解析錯誤 Telegram Server 會出現錯誤,無法發送訊息
    • HTML
      同一般 HTML 用法,支援 bstrongiemacodepre
      非標籤的 <>&" 需要 HTML entity encode(&amp;)後使用

標記使用者

直接於訊息文字內使用 @username 的格式就能 tag 到使用者
如果不想打擾到對方,可用 [@username](https://t.me/username){:target="_blank"} 方式,讓連結可點擊,但不會出現通知
對於沒有 @username 的使用者,能使用 User ID 以 [Name](tg://user?id=109780439) 的格式標注

Inline Keyboard

在大部分 method 都可以使用
@music 的 callback 按鈕

Inline Button 可以用 text 搭配下列其一

  • url
  • callback_data
    最長限 64 位元組
  • switch_inline_query_current_chat
    在該聊天室打開 inline query 介面
  • switch_inline_query
    同上,但會打開聊天室列表,供選擇要發在哪群

需特別注意 inline_keyboard 是放在 reply_markup 底下,且為兩層 Array 包按鈕 Object,如下所示

sendMessage {
    "text": "Hello",
    "chat_id": 109780439
    "reply_markup": {
        "inline_keyboard": [   // 第一層(row)
            [   // 第二層(col)
                {   // 第三層(button 本體)
                    "text": "OwO",
                    "callback_data": "test_data"
                }
            ],
        ],
        [
            [
                {   // 第二排 第一個
                    "text": "Open",
                    "url": "https://blog.sean.taipei/2017/05/telegram-bot"
                }
            ]
        ]
    },
}

如果點了 callback_data 的按鈕,會觸發 callback_query 事件,需用 answerCallbackQuery 回應

此請求需含

  • callback_query_id(必要參數)
    update.callback_query.id
  • text
    要顯示的文字,為空則不顯示通知
  • show_alert
    如為 true 則跳出對話匡,反之只會在聊天視窗上出現橫條
  • url
    限用 Telegram 內部連結

就算沒有東西要通知使用者,也該在處理完後發一個僅有 callback_query_id 的空請求,否則使用者會持續看到處理中的標示

可參考官方的介紹

Inline Bot

除了使用 /command 外,使用者亦可經由 inline query 與 bot 互動
如果啟用了 inline query ,使用者可以經由在對話框輸入 bot username 呼叫此功能
此功能可以在任何群組、私訊、頻道使用
使用者能直接在任意聊天室輸入 bot 的 username,輸入任何 query

如果要啟用此功能,須於 @BotFather 使用 /setinline 指令設定

收到 inline_query 後,需用 answerInlineQuery 回應

請求的 result 欄位必須為 Array of InlineQueryResult,格式如下所示

answerInlineQuery {
    "inline_query_id": 471503396014238996,
    "results": [
        {
            "type": "article",
            "id": "unique",
            "title": "Hello World",
            "description": "Testing",
            "input_message_content": {
                "parse_mode": "Markdown",
                "message_text": "*Hello World*!"
            }
        }
    ]
}

請參見 API 文件Inline Bot 介紹

Inline Feedback

通常會提供不只一筆結果提供選擇,且預設對同關鍵字會快取五分鐘,不是每次輸入都會收到

預設當然是 Disable ,想分析用戶都點了什麼的話可以用 /setinlinefeedback 設為 Enable
如果您的 bot 很多人使用,怕被回傳訊息塞滿,可以調整成折衷的 1/10, 1/100, 甚至是 1/1000,如此就只會收到特定比例的通知

HTML5 Games

機器人可以利用 HTML5 網頁讓使用者在群組、私訊發起挑戰,透過內建排行榜一較高下
分享

如要申請,需向 @BotFather 使用 /newgame ,同意使用條款後依序設定標題、描述、預覽圖、GIF、ID

如果使用者用 https://t.me/Sean_Bot?game=starPusher 格式開啟,會直接發送預設內容與 Play <Name> 按鈕
也可以在回覆 inline query 時使用 InlineQueryResultGame 或用 sendGame

每個使用者點 Play 後,都會發送含有 game_short_namecallback_query,需要用 answerCallbackQuery ,並將遊戲網址置於 url 參數
客戶端收到後會利用 In-App Browser 開啟遊戲網頁

排行榜需要由伺服器呼叫 setGameScore ,並須自行防堵作弊

Example: Foxmosa 推星星

可參考介紹API 文件

調整 Bot 的五官

幾乎所有設定都要讓 @BotFather 處理,這裡也不例外,下面列出建議設定的資訊,讓 Bot 看起來完整點

  • /setname 改名字,應該不需多加解釋
  • /setdescription 位於私訊 Bot,還沒開始對話時,顯示於空白聊天室的文字
  • /setabouttext 顯示於 Profile 頁面,會出現在 username 上方
  • /setuserpic 上傳新頭貼,要是方形的,否則被裁切會顯得奇怪
  • /setcommands 更改在聊天室輸入 / 時出現的列表,要注意指令只能由小寫字母、數字和底線([a-z0-9_])組成,例如 show_info - 說明文字(可以空白) 格式

下載檔案

bot 收到的每個檔案都只會看到 file_id ,需經由 getFile 取得檔案路徑後,
https://api.telegram.org/file/bot<token>/<file_path> 下載

目前限制 bot 透過官方 API 不能下載大於 20MB 的檔案

PWRTelegram

非官方 API Proxy ,具有許多特色功能,但須自行承擔風險

支援用普通 user 帳號及 bot Token 登入

可參考專案網站上的 API Document 或 Awesome Telegram Bot app

聽起來很棒 但我該用什麼語言起手

通常會直接用熟悉的語言,各大語言皆有 Telegram Bot 的 Library

可參考 Bot Code Examples,其中收錄十餘種語言的 lib repo

後記

Telegram Bot 功能繁多,無法一一列舉、介紹,僅就主要功能介紹,payload 範例也只附加於較複雜的 method

如有任何疑問歡迎隨時到 群組 討論

相關連結

官方 API 文件
FAQ(for bots)
Android 版 Bot 發送器 可用來體驗 Methods 用法
Telegram 傳奇
Stack Overflow 英文程度可以的話,可以直接上去發問

Telegram 群組

Telegram 機器人應用交流 測試、討論 Bot 相關問題
Telegram 推廣特區 中文化、各式應用交流

Telegram 頻道

Bot News 官方 Bot 新聞
Bots Channel
Telegram Geeks Telegram 新功能搶鮮報

Telegram 機器人

Bot Father 管理員
Bot Support Bot 專用客服中心
Telegram Bot Raw 可以藉此簡單查看 Bot API 收到的訊息長什麼樣子
Telegram Store Bot 列表及評分

本名韋詠祥,習慣用英文 Sean 暱稱。
自國中開始接觸程式,至今善於組合各種技巧,用來解決生活周遭的問題。
以資安競賽、網路治理、個人專案為興趣。

Read Next

Google Play 判斷失靈 - 因假冒自己被下架

Read Previous

新北市校務行政系統學生個資外洩