Bot API 使用文件
從建立機器人到程式串接
完整介紹 BotMother、訊息介面、驗證碼複製及底部按鈕。範例均使用佔位值。
概覽與功能
#目前公開方法為 getMe、sendMessage、getUpdates。可傳送私聊、群聊文字,接收事件可包含非文字內容。
使用 copy_text 顯示驗證碼複製圖示;使用 reply_markup 下發私聊輸入區下方的文字按鈕。
此網域提供文件;實際 API 仍位於 im.ez7.life 的 /bot-api/ 路徑。收件者可從設定 → 帳號詳情 → ID 複製;收到訊息的 message.chat.id 可直接用於回覆,群聊時是群組 ID。
https://im.ez7.life/bot-api/<BOT_TOKEN>/<METHOD>快速開始
#- 搜尋並加入
@BotMother,開啟對話頂端的機器人管理。 - 建立機器人,複製 Token,存入後端環境變數
EZLIFE_BOT_TOKEN。 - 呼叫
getMe確認身分,再用收件者 ID 呼叫sendMessage。 - 輪詢
getUpdates,處理成功後再儲存下一個 offset。
python3 bot.pyBotMother 管理
#顯示名稱長度 1–64 字元。建立表單的帳號前綴為 3–28 字元,英文字母開頭,只用字母、數字與底線;表單自動補上 _bot,建立前請檢查可用性。
管理頁可搜尋機器人、查看機器人ID、狀態、建立時間與 **** 加尾部六碼,並重新簽發或撤銷 Token。機器人數量上限由管理員設定。
| 指令 | 用途 |
|---|---|
/start | 顯示管理說明 |
/newbot | 開始建立機器人 |
/mybots | 列出自己的機器人 |
/token @username | 重新簽發 Token,舊值失效 |
/revoke @username | 撤銷目前 Token |
/cancel | 取消建立流程 |
/help | 顯示說明 |
Token 與安全
#完整 Token 僅於建立或重新簽發時顯示。請當作機器人密碼,保存在後端,勿放在網站、APK、公開儲存庫或日誌。
重新簽發立即使舊 Token 失效;撤銷後停用外部呼叫。遮罩尾碼不能還原 Token,遺失時請重新簽發並更新程式。
舊 Token 的尾碼會在下次合法 Bot API 呼叫時記錄。帳號詳情中的一般 API Token 用於帳號介面;本 Bot API 使用 BotMother 發出的機器人 Token。
getMe · 機器人身分
#/bot-api/<BOT_TOKEN>/getMe不需要業務參數。回傳機器人 ID、顯示名稱、帳號與群組能力標記,可用來確認 Token。
curl --fail-with-body --request POST \
"https://im.ez7.life/bot-api/${EZLIFE_BOT_TOKEN}/getMe" \
--header 'Content-Type: application/json' --data '{}'{
"ok": true,
"result": {
"id": "1000000000",
"is_bot": true,
"display_name": "Example Bot",
"username": "example_bot",
"can_join_groups": true,
"can_read_all_group_messages": true
}
}sendMessage · 傳送訊息
#/bot-api/<BOT_TOKEN>/sendMessage使用 POST application/json。chat_id 一律為字串,私聊填收件者 ID,群聊填群組 ID 並指定 chat_type: "group"。
文字長度 1–5000 字元,會移除前後空白。請記錄回傳的 message_id;目前沒有冪等鍵,逾時後先確認結果,避免重複傳送。
| 參數 | 類型 | 必填 | 說明 |
|---|---|---|---|
chat_id | string | 是 | 收件者 ID,群聊則為群組 ID;一律字串。 |
text | string | 是 | 訊息文字,1–5000 字元。 |
chat_type | string | 否 | 預設 private;群聊用 group,也接受 supergroup。 |
copy_text | string | 否 | 文字中完整出現的 4–12 位數字字串。 |
reply_markup | object / JSON string | 否 | 可選的回覆鍵盤物件或 JSON 字串。 |
curl --fail-with-body --request POST \
"https://im.ez7.life/bot-api/${EZLIFE_BOT_TOKEN}/sendMessage" \
--header 'Content-Type: application/json' --data-binary @- <<'JSON'
{
"chat_id": "USER_ID",
"text": "你的訂單已處理。"
}
JSON{
"chat_id": "GROUP_ID",
"chat_type": "group",
"text": "你的訂單已處理。"
}{
"ok": true,
"result": {
"message_id": "EXAMPLE_MESSAGE_ID",
"date": 1794297600,
"chat": {
"id": "USER_ID",
"type": "private"
},
"text": "你的訂單已處理。"
}
}傳送成功回傳 ok: true 與 result;驗證碼另含 copy_text,鍵盤另含 reply_markup 與 reply_keyboard_revision。接收訊息回傳 result 陣列,無訊息時 result: []。
驗證碼複製
#文字保留系統名稱、用途與有效期限,另加 copy_text,值必須是文字中完整出現的 4–12 位 ASCII 數字字串,字串可保留開頭的零。
圖示只複製驗證碼。產生、有效期限與驗證由你的系統負責;此欄位只控制顯示與複製。舊用戶端仍可閱讀文字。
{
"chat_id": "USER_ID",
"text": "範例登入驗證碼:003812,5 分鐘內有效。",
"copy_text": "003812"
}底部按鈕鍵盤
#這是多列文字回覆鍵盤。點擊按鈕會傳送其文字,從 getUpdates 的 message.text 處理業務。
1–8 列、每列 1–4 個、總計最多 24 個按鈕。文字長度 1–64 字元,不可空白、換行或含控制字元。按鈕可為字串或只有 text 的物件。
省略 reply_markup 會保留原鍵盤;新鍵盤會取代舊鍵盤。移除請單獨傳入 remove_keyboard: true。
使用者可收合及展開;一次性鍵盤在按鈕文字傳送成功後收合。新版鍵盤會再展開。狀態按機器人與使用者獨立保存,開啟對話時約每五秒檢查。
鍵盤僅支援機器人私聊,群聊帶 reply_markup 會回傳 422。正文 text 仍必填。布林值須為 JSON true/false,不可傳字串;未知鍵盤或按鈕屬性會拒絕。字串形式的 reply_markup 最多 16 KiB。
| 參數 | 類型 | 必填 | 說明 |
|---|---|---|---|
reply_markup | object / JSON string | 否 | 可選的回覆鍵盤物件或 JSON 字串。 |
keyboard | array[] | 是 | 二維陣列,每個內層陣列代表一列。 |
resize_keyboard | boolean | 否 | 預設 true 使用緊湊按鈕;false 使用較高按鈕。 |
one_time_keyboard | boolean | 否 | 預設 false;true 在按鈕傳送成功後收合。 |
remove_keyboard | boolean | 否 | true 清除鍵盤,不可與其他鍵盤欄位並用。 |
{
"chat_id": "USER_ID",
"text": "請選擇服務:",
"reply_markup": {
"keyboard": [
[
{
"text": "語言設定"
},
{
"text": "快遞追蹤"
}
],
[
{
"text": "通知設定"
},
{
"text": "輸入單號"
}
]
],
"resize_keyboard": true,
"one_time_keyboard": false
}
}{
"chat_id": "USER_ID",
"text": "請選擇服務:",
"reply_markup": {
"keyboard": [
[
"語言設定",
"快遞追蹤"
]
],
"one_time_keyboard": true
}
}{
"chat_id": "USER_ID",
"text": "操作已完成。",
"reply_markup": {
"remove_keyboard": true
}
}getUpdates · 接收訊息
#/bot-api/<BOT_TOKEN>/getUpdates短輪詢:沒有訊息立即回傳空陣列。建議每 1–3 秒一次,失敗後延長間隔。尚未提供公開 webhook 或長輪詢。
處理成功後,把下一個 offset 設為最後 update_id + 1;較早事件會確認消費。失敗保留舊 offset,使用 update_id 或業務鍵去重。
同一機器人的多個消費程式須協調,避免彼此推進 offset。非文字事件查看 content_type 與 raw_content。
| 參數 | 類型 | 必填 | 說明 |
|---|---|---|---|
offset | integer | 否 | 下一個事件 ID,非負整數,預設 0。 |
limit | integer | 否 | 每次 1–100 筆,預設 100。 |
curl --fail-with-body --request POST \
"https://im.ez7.life/bot-api/${EZLIFE_BOT_TOKEN}/getUpdates" \
--header 'Content-Type: application/json' \
--data '{"offset": 0, "limit": 100}'{
"ok": true,
"result": [
{
"update_id": 120,
"message": {
"message_id": "EXAMPLE_MESSAGE_ID",
"date": 1794297600,
"chat": {
"id": "1000000001",
"type": "private"
},
"from": {
"id": "1000000001",
"display_name": "Example User"
},
"text": "語言設定",
"content_type": 101,
"raw_content": "{\n \"content\": \"語言設定\"\n}"
}
}
]
}| 參數 | 說明 |
|---|---|
update_id | 遞增事件 ID,用於確認消費。 |
message_id | 平台訊息 ID。 |
date | Unix 時間戳記,單位為秒。 |
chat | 私聊為發送者 ID;群聊為群組 ID,含 private/group 類型。 |
from | 實際發送者 ID 與顯示名稱。 |
text | 文字內容;非文字事件可能為空。 |
content_type | 內容類型;101 為文字。 |
raw_content | 接收圖片、檔案等事件的原始內容。 |
完整 Python 程式
#完整範例僅用 Python 標準函式庫,處理 /start、/ping、按鈕文字並保存 offset。請在私有工作目錄執行。
請將範例按鈕處理替換成實際業務;訂單、付款等操作應可去重,再保存消費進度。
import json
import os
import time
import urllib.error
import urllib.request
from pathlib import Path
TOKEN = os.environ["EZLIFE_BOT_TOKEN"]
BASE = "https://im.ez7.life/bot-api/" + TOKEN
OFFSET_FILE = Path("bot-offset.json")
MENU = [
[
"語言設定",
"快遞追蹤"
],
[
"通知設定",
"輸入單號"
]
]
class ApiFailure(Exception):
pass
class NoRedirect(urllib.request.HTTPRedirectHandler):
def redirect_request(self, *args):
return None
HTTP = urllib.request.build_opener(NoRedirect())
def api(method, payload):
req = urllib.request.Request(
BASE + "/" + method,
data=json.dumps(payload, ensure_ascii=False).encode("utf-8"),
headers={"Content-Type": "application/json"},
method="POST",
)
try:
with HTTP.open(req, timeout=20) as response:
body = json.load(response)
except urllib.error.HTTPError as error:
raise ApiFailure("HTTP " + str(error.code)) from None
except (urllib.error.URLError, TimeoutError, OSError, ValueError):
raise ApiFailure("Network or response failure") from None
if not body.get("ok"):
raise ApiFailure("API error " + str(body.get("error_code", "unknown")))
return body["result"]
def handle(update):
message = update.get("message", {})
chat = message.get("chat", {})
text = message.get("text", "")
if not chat.get("id"):
return
payload = {"chat_id": str(chat["id"]),
"chat_type": chat.get("type", "private")}
if text == "/start" and payload["chat_type"] == "private":
payload.update(text="請選擇服務:", reply_markup={
"keyboard": MENU, "resize_keyboard": True,
"one_time_keyboard": False,
})
elif text == "/ping":
payload["text"] = "pong"
elif text in [label for row in MENU for label in row]:
payload["text"] = "操作已完成。"
else:
return
api("sendMessage", payload)
def save_offset(value):
temp = OFFSET_FILE.with_suffix(".tmp")
fd = os.open(temp, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)
with os.fdopen(fd, "w", encoding="utf-8") as stream:
json.dump(value, stream)
stream.flush()
os.fsync(stream.fileno())
os.replace(temp, OFFSET_FILE)
def main():
offset = json.loads(OFFSET_FILE.read_text()) if OFFSET_FILE.exists() else 0
if isinstance(offset, bool) or not isinstance(offset, int) or offset < 0:
raise ValueError("Invalid offset file")
delay = 1
while True:
try:
updates = api("getUpdates", {"offset": offset, "limit": 100})
for update in updates:
handle(update)
next_offset = int(update["update_id"]) + 1
save_offset(next_offset)
offset = next_offset
delay = 1
time.sleep(2)
except (ApiFailure, OSError, ValueError):
print("Processing failed; offset retained. Check configuration.", flush=True)
time.sleep(delay)
delay = min(delay * 2, 30)
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
pass群組與訊息範圍
#機器人須先加入目標群組。預設需擁有人核准,於機器人對話的更多 → 機器人設定 → 已加入群組檢查邀請。
預設關閉群組隱私模式,啟用接收的群組不必 @ 機器人。自身訊息不進自己的接收佇列;群組生命週期通知不視為一般訊息。
各群接收開關控制事件、自動回覆及轉發。使用者持有的機器人會將啟用群組訊息附群名轉到擁有人私聊;外部存取開關仍控制 API 與事件交付。
機器人設定與自動回覆
#僅擁有人可設定入群核准、外部存取、各群接收及關鍵字自動回覆。關閉外部存取保留 Token,但會拒絕程式呼叫。
最多 50 條規則,關鍵字 1–100 字元、回覆 1–2000 字元。依序比對、不分大小寫的包含關係,第一條啟用且符合的規則回覆。
自動回覆適用私聊與啟用接收的群組,會避免機器人互相觸發。AI API 串接目前屬規劃功能,尚無公開方法。
錯誤處理
#JSON 解析失敗或本文過大等前期錯誤使用 errorCode 與 message;其他 API 錯誤使用 error_code 與 description。先檢查 HTTP 狀態與 ok。
{
"ok": false,
"error_code": 422,
"description": "chat_id 与 1–5000 字的 text 为必填"
}| 狀態 | 處理方式 |
|---|---|
| 400 | JSON 格式無效,請檢查編碼與語法。 |
| 401 | Token 無效、撤銷、重新簽發或機器人停權,請更新憑證。 |
| 403 | 擁有人停用外部存取,請至機器人設定開啟。 |
| 404 | 檢查 /bot-api/ 路徑、Token 格式與方法名稱。 |
| 409 | 同一機器人及使用者的鍵盤正在更新,稍後重試。 |
| 413 | 請求本文超過 1 MiB,請縮小。 |
| 422 | 修正參數、驗證碼格式或鍵盤結構。 |
| 500 | 暫時故障,保留接收 offset 並退避重試;傳送先確認結果。 |
限制與用戶端相容性
#文件以目前公開介面為準。尚未公開傳送媒體、inline callback 按鈕、聯絡人或位置請求按鈕,以及 webhook。
底部鍵盤適用新版 Web/H5;內嵌舊 H5 資源的用戶端需更新才能顯示新控制項。
完整請求本文不能超過 1 MiB。依負載控制傳送及輪詢頻率;本指南不承諾固定吞吐量。群組能力標記不取代實際入群、審核與接收權限。