Skip to content

文档同步

本页由 plugins/adapters/telegram/README.md 自动生成。请修改包内 README 后运行 pnpm sync:adapter-docs。

@zhin.js/adapter-telegram ​

Zhin.js Telegram Bot API 适配器(Plugin Runtime),默认通过 长轮询 getUpdates 收发消息(无需 host)。

功能 ​

  • 长轮询 getUpdates 入站(默认;无需公网 IP / host-http)
  • 解析 text / image / video / audio / voice / document / sticker / location / callback_query
  • 支持私聊与群组
  • 出站 send({ conversation, payload }) → Bot API(Markdown→安全 HTML / media / keyboard)
  • 约定式 defineAdapter / definePlugin(无需 usePlugin)
  • Webhook 模式通过 httpHostToken 注册回调路由,支持 secretToken 校验

更新确认与重投 ​

  • Polling 在 handleUpdate() 的框架接纳 Promise 成功后推进本地 offset;同批次接纳失败会停止处理后续 update,保留失败 update 供下一次重投。Telegram 在下一次携带更高 offset 的 getUpdates 请求时才确认旧 update。
  • Webhook 等待框架接纳后返回 200;请求到达时端点已关闭、尚未进入 Core 的处理被取消或接纳失败返回 503,非法 JSON/update_id 返回 400,secret 不匹配返回 403。仅 native platform.receive 成功不等于消息接纳成功,还需等待 canonical message.receive。已经进入 Core 的业务由 generation lease 完成,随后成功仍返回 200,即使端点期间关闭,避免把完成的副作用错误地触发重投。
  • 每个 Endpoint 最多保存 2,048 个已接纳 update_id,并合并相同 ID 的并发请求;最多允许 256 个不同 ID 的并发接纳,超过容量返回失败供重投。失败不计入已接纳集合。
  • 去重状态和 polling offset 属于当前 Endpoint generation,不是耐久 checkpoint。HMR/进程重启会清空;已接纳但尚未由下一轮 offset 请求确认的尾部 update,或 webhook 200 尚未到达 Telegram 的 update,可能再次投递。当前提供至少一次重投路径,不保证跨重启恰好一次;有外部副作用的插件应使用 update/message ID 做持久幂等。
  • JSON API 和 multipart/form-data 默认 30 秒 deadline;长轮询允许服务端 timeout 外加 15 秒。客户端 callApi / callApiForm 第三个参数可传 AbortSignal,端点停止也会取消当前 API 请求。TelegramApiError.kind 区分 timeout、cancelled、network、http、authentication、rate_limit、api、invalid_response;429 可读取 retryAfterSeconds。发送失败不会自动重试,超时/网络中断的送达结果可能未知。
  • TelegramApiError 同时遵循 EndpointDeliveryError 合同:明确 Bot API 拒绝为 rejected,网络/超时或异常响应为 unknown,发出请求前取消为 not_sent。一个 payload 拆成多个发送动作时,已有动作成功而后续失败会报告 partial_delivery / unknown,并在 cause 保留后续错误;不能把整条消息视为全部拒绝或安全重发。
  • Polling 请求失败时 transport 状态为 reconnecting,成功拉取后恢复 open;Webhook 的 open 代表本地路由与注册成功,不能证明公网代理实时可达。

确认与重试规则依据 Telegram Bot API getUpdates / setWebhook。

安装 ​

bash
pnpm add @zhin.js/adapter-telegram

Plugin Runtime ​

  • @zhin.js/adapter — 约定式 adapters/telegram/index.ts(defineAdapter)
  • @zhin.js/core — Endpoint.emit(...) 入站、outboundMessageToken 出站
  • zhin.js — plugin.ts(definePlugin)
  • 配置经插件 schema.json 落到顶层 <instanceKey>
  • 无需 @zhin.js/host-http(polling 路径)

入站:gateway.receive({ conversation, message, content, sender, metadata })(conversation 为 ConversationRef,由 telegramInboundConversation 归一化)
出站:send({ conversation, payload }) → Telegram Bot API

平台权限(platform permit) ​

  • sender role 已恢复:群消息入站时经 getChatMember(60s 缓存)解析,写入 metadata.senderRole / metadata.senderPermissions。
  • plugin.ts 在 generation setup 注册 checker,并在 dispose 注销;Plugin Runtime CapabilityIngress 与 ToolSystem 统一经 Core canAccessTool() 消费 permissions。

前置条件 ​

要求说明
Bot Token通过 @BotFather 创建并获取 Token
Polling(默认)本地/生产均可;主动拉取更新,无需公网 HTTPS
网络出站可访问 api.telegram.org
host-httpPolling 不需要;Webhook 需要 CLI HTTP Host

必填字段(endpoints[i]):id、token。

最小配置 ​

yaml
configVersion: 2
# zhin.config.yml(Plugin Runtime)
plugins:
  telegram: "@zhin.js/adapter-telegram"
telegram:
  # polling: true   # 默认
  endpoints:
    - id: my-telegram-bot
      token: ${TELEGRAM_TOKEN}

主配置 plugins 映射需引用 @zhin.js/adapter-telegram(instanceKey: telegram)。

环境变量 ​

变量说明
TELEGRAM_TOKEN示例中由 YAML ${TELEGRAM_TOKEN} 引用的 Bot Token;变量名可自行定义
TELEGRAM_WEBHOOK_SECRET示例中由 YAML ${TELEGRAM_WEBHOOK_SECRET} 引用的 webhook secret;变量名可自行定义

Webhook ​

配置 polling: false,启用 CLI HTTP Host,并提供公网 HTTPS 回调地址。 webhook.path 必须与反向代理转发路径一致,多账号使用不同路径。

yaml
configVersion: 2
http:
  host: 127.0.0.1
  port: 8086
plugins:
  telegram: "@zhin.js/adapter-telegram"
telegram:
  polling: false
  endpoints:
    - id: my-telegram-bot
      token: ${TELEGRAM_TOKEN}
  webhook:
    domain: https://bot.example.com
    path: /telegram/webhook
    secretToken: ${TELEGRAM_WEBHOOK_SECRET}

启动时注册 Host 路由并调用 setWebhook;停止时释放路由。 配置 secretToken 后,回调须携带匹配的 X-Telegram-Bot-Api-Secret-Token,否则返回 403。

稳定化范围 ​

当前为 Advanced / 首批升档候选,完整适配器测试已纳入 pnpm check:stable。 长轮询停止会中止请求与退避;即使传输层在中止后返回更新,也不会派发或推进 offset。 轮询 offset 仅保存在当前 Endpoint 内存中,不承诺跨重启去重或业务处理恰好一次。 Webhook 接收确认不等于业务处理完成;需要幂等性的业务应自行持久化去重。 详见平台稳定验收。

消息类型映射 ​

Telegram入站 content(文本摘要)出站 wire
text原文sendMessage
markdown原文sendMessage(parse_mode: HTML)
photo[image] / captionsendPhoto(file_id / url)
video[video]sendVideo
audio / voice[audio] / [voice]sendAudio / sendVoice
document[file: name]sendDocument
sticker[sticker: …]sendSticker
location[location: lat,lon]sendLocation
callback_query[action: data]—

AI tools ​

KindPath
Platform tools (10)tools/(invite / pin / admins / sticker / poll 等)
Skill docagents/telegram/skills/telegram-chat-admin/SKILL.md, agents/telegram/skills/telegram-messages/SKILL.md

故障排查 ​

现象排查
收不到消息Token 是否正确;进程已 open();同一 Token 勿多进程同时 polling
Polling 报错检查能否访问 api.telegram.org;查看日志 op: poll
Webhook 配置报错检查 HTTP Host、公网 HTTPS、反向代理路径与 secretToken
发送失败Token 是否被撤销;查看 Bot API 错误描述

Documentation ​

License ​

MIT

禁用按钮 ​

canonical keyboard 的 disabled: true 按钮映射为 Telegram Bot API 10.3 的 disabled: {},不携带 callback_data;启用按钮仍使用原回调数据,并保留 1–64 UTF-8 字节校验。自建 Bot API Server 需支持该版本,见 DisabledButton。