feat(telegram): expose apiRoot config for custom Bot API server#46755
feat(telegram): expose apiRoot config for custom Bot API server#46755dzianisv wants to merge 2 commits intoopenclaw:mainfrom
Conversation
Add channels.telegram.apiRoot (string, optional) that passes through to grammY's ApiClientOptions.apiRoot. When unset, behavior is unchanged (defaults to https://api.telegram.org). Also supports TELEGRAM_API_ROOT env var as fallback. This enables: - Self-hosted Telegram Bot API servers (tdlib/telegram-bot-api) for higher upload limits and faster file access - Centralized gateway proxies that inject bot tokens (security: multi-tenant deployments where the real token should not leave the proxy host) - Testing with mock Bot API servers grammY already supports apiRoot as a first-class option — this change just reads the config value and passes it through. Closes openclaw#28535
Greptile SummaryThis PR adds a new optional
Confidence Score: 5/5
Last reviewed commit: 885cbd7 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 885cbd73d9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const apiRoot = | ||
| telegramCfg?.apiRoot?.trim() || process.env.TELEGRAM_API_ROOT?.trim() || undefined; |
There was a problem hiding this comment.
Route all Telegram send clients through configured apiRoot
This change only applies apiRoot to the bot client created in createTelegramBot, but other outbound paths still construct separate clients in extensions/telegram/src/send.ts (resolveTelegramClientOptions and resolveTelegramApiContext) without reading account.config.apiRoot. That means flows using sendMessageTelegram/reaction/delete helpers (for example channel outbound and pairing notifications) still call the default Telegram endpoint, so deployments that depend on channels.telegram.apiRoot (proxy/self-hosted Bot API) will see partial failures or endpoint bypass despite setting this config.
Useful? React with 👍 / 👎.
| "channels.telegram.apiRoot": | ||
| "Custom base URL for all outbound Telegram Bot API calls. Defaults to https://api.telegram.org. Point this at a self-hosted Bot API server or a centralized gateway proxy.", |
There was a problem hiding this comment.
Add schema label for new Telegram apiRoot help key
A new FIELD_HELP entry is introduced for channels.telegram.apiRoot, but there is no matching key in src/config/schema.labels.ts, which breaks the help/label parity contract enforced by src/config/schema.help.quality.test.ts and leaves label-driven config UIs without a display label for this field. When adding a help key, the corresponding label should be added in the same change.
Useful? React with 👍 / 👎.
Address review feedback: - extensions/telegram/src/send.ts: add apiRoot to resolveTelegramClientOptions so outbound send helpers (pairing, reactions, etc.) also route through the configured API root - src/config/schema.labels.ts: add label for channels.telegram.apiRoot to maintain help/label parity
|
Thanks for adding Media download (
|
| File | Line | Usage |
|---|---|---|
audit-membership-runtime.ts |
11 | TELEGRAM_API_BASE used for membership audit API calls |
api-fetch.ts |
6 | getChat API call |
probe.ts |
7 | TELEGRAM_API_BASE used for health check probes |
These should also respect apiRoot config (or TELEGRAM_API_ROOT env) to be consistent.
We have a working patch for the media download path (including local file read support) in a dedicated branch: tata-meow/openclaw@fix/telegram-apiroot-media.
|
@tata-meow Great analysis — these are exactly the gaps I ran into as well. I've addressed all of these in #48842:
The |
Summary
Add
channels.telegram.apiRoot(string, optional) that passes through to grammY'sApiClientOptions.apiRoot. When unset, behavior is unchanged (defaults tohttps://api.telegram.org).Also supports
TELEGRAM_API_ROOTenv var as fallback.Motivation
I'm building @OpenClawBoxBot (openclaw.vibebrowser.com) — a managed OpenClaw hosting platform via Telegram. Each customer gets an isolated OpenClaw gateway instance running in Kubernetes.
The architecture uses a centralized Telegram gateway proxy: the bot pod receives Telegram updates via long-polling and forwards them to the tenant gateway's webhook. The gateway's Telegram channel processes everything natively (all media types, threading, reactions, streaming). For outbound API calls (
sendMessage,sendPhoto,getFile), the gateway needs to route through a proxy in the bot pod that injects the real bot token.Without
apiRoot, the gateway always callsapi.telegram.orgdirectly, which means the real bot token must be in every tenant gateway — a security problem for multi-tenant deployments where customers could extract the token.With
apiRoot, I can point outbound calls athttp://bot-proxy:8081and keep the real token centralized.Use cases
Changes
src/config/types.telegram.ts: addapiRoot?: stringtoTelegramAccountConfigsrc/config/zod-schema.providers-core.ts: addapiRootto the Zod validation schemaextensions/telegram/src/bot.ts: readapiRootfrom config (withTELEGRAM_API_ROOTenv fallback) and pass to grammY'sApiClientOptionssrc/config/schema.help.ts: add help text for the new keygrammY already supports
apiRootas a first-class option — this change just reads the config value and passes it through.Config example
Closes #28535