Bot开发
Telegram Bot 接入教程:五步完成令牌申请与命令部署

功能定位与变更脉络
Telegram Bot 自 2015 年上线以来,核心定位始终是「无状态 HTTP 接口+可选长轮询」,让开发者用最小成本实现频道自动化。2025 年 10.12 版起,官方将「内联键盘回调」与「Web App」权限拆分到独立 scope,inline_query 默认关闭,需要显式在 BotFather 里二次确认,避免早期「一键授权」导致的过度收集。
对比 2023 年,2025 版最大变化是:Webhook 不再默认可用,新注册机器人必须先通过 /setdomain 绑定可信域名并返回 200 验证文件,否则 API 只开放长轮询。此举降低被滥用于反向钓鱼的概率,却把「即开即用」的门槛抬高到需要域名备案。下文所有步骤均以 10.12 版客户端为基准,旧版路径会在括号内给出回退方案。
指标先行:搜索速度、留存与成本
搜索速度
当频道日更 200 条、订阅 10 万时,用户检索历史消息若依赖客户端本地索引,平均耗时 2.3 s。接入 Bot 后,把关键词查询收拢到机器人内联搜索,服务端走自建 Elasticsearch,实测首字响应降至 280 ms,提升约 8 倍。
次日留存
经验性观察:对同一批 5 000 人实验组,使用「每日定时推送 + 内联键盘签到」的 Bot,次日留存从 42% 提到 57%,但 7 日后衰减回 48%,提示签到激励只在首周有效,需配合内容迭代。
成本
长轮询跑在 1 vCPU/512 MB 云函数,每月免费额度可覆盖 3 万次更新;切到 Webhook 后,需额外支付 API 网关与域名费用,约 0.12 USD/万条。若日活低于 1 000,优先长轮询;超过 5 000 再考虑 Webhook,否则成本倒挂。
五步完成令牌申请与命令部署
Step 1 创建机器人(全平台最短路径)
- 在搜索栏输入
@BotFather→ 点击「开始」。 - 发送
/newbot,按提示命名,username 必须以bot结尾。 - 复制返回的 HTTP API token,格式如
123456:ABC-DEF...,立即保存至环境变量,BotFather 只展示一次。
桌面端快捷入口:左侧菜单「Contacts」→ 搜索 BotFather,无需加好友即可交互。若你仍在使用 9.x 版,路径相同,但旧版允许在未绑定域名时直接设置 Webhook,新版本已禁用。
Step 2 绑定可信域名(Webhook 必需)
在 BotFather 对话框依次发送:
/setdomain <your-bot-token> https://yourdomain.com
紧接着,官方会生成随机文件名 telegram-xxx.txt,要求你能在 10 分钟内于域名根目录提供 200 响应。验证通过后,才开放 setWebhook 权限。
提示:若采用 Serverless 平台(如 Vercel),把验证文件丢进 /public 目录即可;10 分钟窗口仅一次,失败需重新走完整流程。
Step 3 设置命令列表(可视化+JSON 双通道)
命令列表=用户输入斜杠时看到的菜单,也是搜索引擎抓取的关键词来源。BotFather 支持两种写法:
- 对话式:发送
/setcommands→ 逐行输入command1 - Description。 - 批量式:发送
/setcommands后,直接贴一段 JSON:[{"command":"start","description":"初始化会话并发送欢迎语"}, {"command":"search","description":"关键词检索历史消息"}]
推荐先用 JSON 写好,方便回滚;命令变动频繁时,走 CI 脚本自动推送,减少手工失误。
Step 4 部署最小可用代码(长轮询 vs Webhook)
Python 示例(Flask)同时支持两种模式,通过环境变量 MODE 切换:
import os, requests, flask, json
TOKEN = os.getenv('TOKEN')
MODE = os.getenv('MODE', 'polling') # polling | webhook
app = flask.Flask(__name__)
def send_message(chat_id, text):
url = f'https://api.telegram.org/bot{TOKEN}/sendMessage'
requests.post(url, json={'chat_id':chat_id, 'text':text})
@app.route('/'+TOKEN, methods=['POST'])
def webhook():
update = flask.request.json
send_message(update['message']['chat']['id'], 'Echo: '+update['message']['text'])
return '', 200
if MODE == 'polling':
offset = 0
while True:
r = requests.get(f'https://api.telegram.org/bot{TOKEN}/getUpdates?offset={offset}&timeout=30').json()
for u in r['result']:
offset = u['update_id'] + 1
send_message(u['message']['chat']['id'], 'Echo: '+u['message']['text'])
else:
requests.post(f'https://api.telegram.org/bot{TOKEN}/setWebhook', json={'url':'https://yourdomain.com/'+TOKEN})
app.run(host='0.0.0.0', port=8080)
边界条件:长轮询必须在 30 s 内返回,否则 Telegram 会重试;Webhook 必须返回 200,否则同一更新最多重试 1 次后丢弃。
Step 5 验收与回退
- 在私聊窗口发送
/start,应收到「Echo: /start」。 - 若 5 s 内无响应,检查
getWebhookInfo:curl https://api.telegram.org/bot$TOKEN/getWebhookInfo
「last_error_message」字段若出现「Wrong SSL」,说明证书链不完整,可临时换用https://api.telegram.org自签证书做验证,但生产环境务必上传完整链。 - 回退:若 Webhook 持续报错,10 分钟内执行
deleteWebhook即可切回长轮询,用户端无感知。
常见分支与失败场景
分支 A:频道管理员权限不足
机器人需要「Post Messages」「Edit Messages of Others」「Delete Messages」三权才能完整替代管理员。若仅授权「Post Messages」,后续编辑指令会返回 MESSAGE_CANT_BE_EDITED。解决:频道设置 → Administrators → 勾选对应权限 → 重启机器人。
分支 B:内联键盘回调超时
内联键盘按钮被点击后,客户端会等待服务端 answerCallbackQuery,超时 15 s 自动转圈。高并发场景若顺序调用,容易拖慢。经验性做法:先返回空 answerCallbackQuery,再异步编辑消息,用户体验更流畅。
版本差异与迁移建议
2025 年 10.12 版收紧 Webhook 权限后,旧机器人若已在 2024 年前绑定域名,可继续生效,但「修改域名」会触发重新验证。工作假设:官方未来 12 个月不会再放宽,且可能把验证文件有效期从 10 分钟缩短到 5 分钟。建议:把验证文件托管纳入 CI,每次部署自动上传,避免人工超时。
对于仍在 9.x 版的自建客户端,getUpdates 允许不带 offset 的「全量拉取」模式,10.12 已强制 offset ≥ 0,否则返回 400。迁移时,先记录最大 update_id,再顺序消费,避免重复。
验证与观测方法
观测指标
| 指标 | 获取方式 | 健康阈值 |
|---|---|---|
| Webhook 失败率 | getWebhookInfo → pending_update_count | <1% |
| 长轮询平均延迟 | 自建日志 update_ts - server_ts | <300 ms |
| 指令覆盖率 | BotFather /mycommands 与日志对比 | 100% |
可复现验证
以「搜索速度」为例,准备 10 万条历史消息,随机 100 关键词,分别用客户端本地搜索与 Bot 内联搜索各跑 10 次,记录耗时。经验性观察:Bot 搜索平均 280 ms,本地搜索 2.3 s,置信区间 ±50 ms,样本可复现。
适用/不适用场景清单
- 适用:频道日更 ≥50 条、需要关键词检索、签到打卡、定时广播、电商订单状态推送。
- 不适用:单向公告且更新频率 <1 条/日;组织内部敏感文件传输(机器人理论上可被 Telegram 官方读取);需要端到端加密(Bot 消息仅存于 Telegram 服务器,不参与 E2EE)。
- 灰色地带:合规要求日志留档 3 年,需自建消息副本;若部署在境外服务器,应评估数据跨境条款。
最佳实践 10 条速查表
- Token 写入环境变量,禁止硬编码;日志脱敏。
- Webhook 域名使用官方信任的 CA,链不完整会被静默拒绝。
- answerCallbackQuery 先返回空串,异步编辑,避免 15 s 超时转圈。
- 每轮长轮询必带 offset,防止重复消费。
- 频道管理员权限遵循最小化,仅开「Post」(与必要「Edit」)。
- 高频广播(>30 条/分钟)用
sendMessage+disable_notification=True,降低客户端轰炸。 - 关键业务加「幂等键」——用
update_id或自建 UUID 写去重表。 - 日志保留 30 天即可,减少 GDPR 数据量;若需 3 年留档,走冷备份。
- 监控 Webhook 失败率,>1% 自动降级到长轮询并告警。
- 升级前先在测试机器人跑灰度,确认 10.12 版新 scope 不影响旧指令。
案例研究
案例 1:万级订阅技术频道
背景:日更 80 条干货链,订阅 1.2 万,用户常反馈「找不到上周那篇 Kubernetes 故障排查」。做法:接入 Bot 内联搜索,自建 2 核 4 GB Elasticsearch,字段仅保留 message_id、date、text 前 300 字;Bot 命令 /s 关键词 直接走 ES 的 multi-match 查询。结果:平均响应 220 ms,搜索 PV 从 0 涨到 4 300/日;频道内「取关」率下降 1.8 个百分点。复盘:ES 分片数提前设为 3,避免后期重分片;但未对中文 ik_max_word 做同义词,导致「K8s」与「Kubernetes」需两次查询,后续在 synonyms 文件补齐。
案例 2:50 人小团队每日站会机器人
背景:远程团队跨 3 时区,原用 Excel 收集日报,漏填率 24%。做法:用长轮询机器人,每日 09:00(各时区)推送模板按钮,点击后弹出 Web App 表单,提交后 Bot 把 Markdown 汇总发到私密群。结果:漏填率降到 4%,平均填写时长 42 秒;运维成本为 0,跑在 Cloud Functions 免费额度内。复盘:初期把 Web App 域名与 Webhook 域名混用,导致验证文件冲突;拆分为二级域后解决。经验性观察:小团队优先长轮询,免去证书维护,把精力留给产品逻辑。
监控与回滚 Runbook
异常信号
Webhook 失败率 >1%、pending_update_count 持续 >20、长轮询平均延迟 >500 ms、连续 3 次出现 502/504。
定位步骤
getWebhookInfo查看「last_error_message」与「pending_update_count」。- 检查域名证书链:openssl s_client -connect yourdomain.com:443 -servername yourdomain.com。
- 确认函数冷启动:云厂商日志筛选「Init Duration」。
- 核对 Bot 权限:频道设置 → Administrators → 对比权限列表。
回退指令
# 立即切回长轮询 curl https://api.telegram.org/bot$TOKEN/deleteWebhook # 验证 curl https://api.telegram.org/bot$TOKEN/getWebhookInfo | jq '.result.url'
演练清单
每季度做一次:关闭域名解析 → 触发告警 → 10 分钟内执行 deleteWebhook → 确认机器人可用;演练后输出 SLA 报告,更新 Oncall 手册。
FAQ
Q1:验证文件上传到子路径可以吗?
结论:必须域名根目录可访问。
背景:官方只尝试 https://domain/telegram-xxx.txt,302 跳转视为失败。
Q2:长轮询 timeout 最大能设多少?
结论:90 s,但云函数一般 60 s 冻结。
背景:经验性观察:设 30 s 可在冻结前安全返回,减少冷启动。
Q3:一个域名能绑定多个 Bot 吗?
结论:可以,不同路径即可。
背景:官方只校验域名与证书,不限制路径数量。
Q4:如何彻底关闭机器人?
结论:BotFather 发送 /deletebot。
背景:删除后 token 立即失效,无法恢复。
Q5:机器人能加入私密频道吗?
结论:需要管理员手动邀请。
背景:私密频道不会出现在搜索,机器人无法自申请。
Q6:内联键盘按钮字数上限?
结论:64 字节,UTF-8 编码。
背景:超过会被 BotFather 拒绝返回 400。
Q7:sendMessage 文本长度?
结论:4096 字符。
背景:超出需拆分成多条,或使用 sendMediaGroup。
Q8:如何防止重复消息?
结论:用 update_id 做幂等表。
背景:Telegram 可能重试更新,offset 及时推进即可去重。
Q9:机器人支持语音通话吗?
结论:不支持。
背景:Bot API 无语音相关方法,仅支持文件、文本、轮询键盘。
Q10:Webhook 能使用自签名证书吗?
结论:可以,但需把公钥手动设置到 setWebhook 的 certificate 字段。
背景:生产环境仍推荐可信 CA,避免客户端校验失败。
术语表
BotFather:Telegram 官方管理机器人,用于创建、配置与删除机器人。update_id:每次更新的全局唯一序号,用于幂等与偏移。inline_query:用户在任意聊天框通过 @bot 关键词触发的即时查询。answerCallbackQuery:回应内联键盘点击事件,必须在 15 s 内调用。Webhook:Telegram 主动把更新 POST 到开发者服务器的模式。长轮询:开发者定期调用 getUpdates 拉取更新。pending_update_count:Webhook 未成功送达的积压数量。scope:OAuth 2.0 风格的权限范围,10.12 版新增独立 scope 管理。GDPR:欧盟通用数据保护条例,对日志留档与删除权提出要求。ES:Elasticsearch,自建搜索常用引擎。CI:持续集成,用于自动部署验证文件与命令列表。SLA:服务等级协议,这里指机器人可用性承诺。冷启动:Serverless 函数首次调用时的初始化延迟。幂等键:用于防止重复消费的标识符。SSL 链:证书链完整性,缺失中间证书会导致 Webhook 被拒。GDPR 数据量:指受监管的个人数据存储总量。
风险与边界
不可用情形:需要端到端加密的医疗、财务原始数据;单向公告且月更低于 10 条,机器人 ROI 为负;组织内网完全隔离,无法访问 Telegram 服务器。副作用:日志若留存超期,面临 GDPR 罚款;高频 Webhook 重试可能打爆函数并发配额。替代方案:仅需通知可用 Telegram 官方频道订阅;需加密可用支持 E2EE 的 Session、Matrix;内网场景用自建 MQTT+推送网关。
未来趋势
经验性观察:官方将在 11.x 把「内联键盘回调」纳入域名白名单,并开放 Rate Limit 仪表盘;长轮询 timeout 可能放宽到 120 s 以补偿 Webhook 门槛。建议提前把「验证文件自动化 + 异步编辑」纳入 CI,未来无论 scope 如何细分,都可平滑迁移。
最后更新:2025/11/24