From 840b768d9742b450d4002316191a8318aaee372a Mon Sep 17 00:00:00 2001 From: Harold Hunt Date: Wed, 25 Feb 2026 22:06:08 -0500 Subject: [PATCH] Telegram: improve webhook config guidance and startup fallback --- src/config/zod-schema.providers-core.ts | 36 +++++++++++++++++++++---- src/telegram/webhook.test.ts | 9 +++++++ src/telegram/webhook.ts | 3 ++- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/config/zod-schema.providers-core.ts b/src/config/zod-schema.providers-core.ts index 369c338ea0c..971418d8d3d 100644 --- a/src/config/zod-schema.providers-core.ts +++ b/src/config/zod-schema.providers-core.ts @@ -165,11 +165,37 @@ export const TelegramAccountSchemaBase = z .strict() .optional(), proxy: z.string().optional(), - webhookUrl: z.string().optional(), - webhookSecret: z.string().optional().register(sensitive), - webhookPath: z.string().optional(), - webhookHost: z.string().optional(), - webhookPort: z.number().int().positive().optional(), + webhookUrl: z + .string() + .optional() + .describe( + "Public HTTPS webhook URL registered with Telegram for inbound updates. This must be internet-reachable and requires channels.telegram.webhookSecret.", + ), + webhookSecret: z + .string() + .optional() + .describe( + "Secret token sent to Telegram during webhook registration and verified on inbound webhook requests. Telegram returns this value for verification; this is not the gateway auth token and not the bot token.", + ) + .register(sensitive), + webhookPath: z + .string() + .optional() + .describe( + "Local webhook route path served by the gateway listener. Defaults to /telegram-webhook.", + ), + webhookHost: z + .string() + .optional() + .describe( + "Local bind host for the webhook listener. Defaults to 127.0.0.1; keep loopback unless you intentionally expose direct ingress.", + ), + webhookPort: z + .number() + .int() + .positive() + .optional() + .describe("Local bind port for the webhook listener. Defaults to 8787."), actions: z .object({ reactions: z.boolean().optional(), diff --git a/src/telegram/webhook.test.ts b/src/telegram/webhook.test.ts index 0117c55823a..c3de0df5b60 100644 --- a/src/telegram/webhook.test.ts +++ b/src/telegram/webhook.test.ts @@ -207,6 +207,7 @@ describe("startTelegramWebhook", () => { initSpy.mockClear(); createTelegramBotSpy.mockClear(); webhookCallbackSpy.mockClear(); + const runtimeLog = vi.fn(); const abort = new AbortController(); const cfg = { bindings: [] }; const { server } = await startTelegramWebhook({ @@ -216,6 +217,7 @@ describe("startTelegramWebhook", () => { config: cfg, port: 0, // random free port abortSignal: abort.signal, + runtime: { log: runtimeLog, error: vi.fn(), exit: vi.fn() }, }); expect(createTelegramBotSpy).toHaveBeenCalledWith( expect.objectContaining({ @@ -246,6 +248,13 @@ describe("startTelegramWebhook", () => { timeoutMilliseconds: 10_000, }, ); + expect(runtimeLog).toHaveBeenCalledWith( + expect.stringContaining("webhook local listener on http://127.0.0.1:"), + ); + expect(runtimeLog).toHaveBeenCalledWith(expect.stringContaining("/telegram-webhook")); + expect(runtimeLog).toHaveBeenCalledWith( + expect.stringContaining("webhook advertised to telegram on http://"), + ); abort.abort(); }); diff --git a/src/telegram/webhook.ts b/src/telegram/webhook.ts index 0fd887f956c..bb48f6c09eb 100644 --- a/src/telegram/webhook.ts +++ b/src/telegram/webhook.ts @@ -250,7 +250,8 @@ export async function startTelegramWebhook(opts: { throw err; } - runtime.log?.(`webhook listening on ${publicUrl}`); + runtime.log?.(`webhook local listener on http://${host}:${port}${path}`); + runtime.log?.(`webhook advertised to telegram on ${publicUrl}`); let shutDown = false; const shutdown = () => {