diff --git a/CHANGELOG.md b/CHANGELOG.md index 02912989a..2074cec49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -108,6 +108,7 @@ - Telegram: isolate forum topic transcripts per thread and validate Gemini turn ordering in multi-topic sessions. Thanks @hsrvc for PR #407. - Telegram: render Telegram-safe HTML for outbound formatting and fall back to plain text on parse errors. Thanks @RandyVentures for PR #435. - Telegram: force grammY to use native fetch under Bun for BAN compatibility (avoids TLS chain errors). +- Telegram: keep grammY default fetch on Node; only override under Bun to avoid Node 24 regressions. - iMessage: ignore disconnect errors during shutdown (avoid unhandled promise rejections). Thanks @antons for PR #359. - Messages: stop defaulting ack reactions to 👀 when identity emoji is missing. - Auto-reply: require slash for control commands to avoid false triggers in normal text. diff --git a/src/telegram/bot.ts b/src/telegram/bot.ts index 94f2b35af..89e4b5dd5 100644 --- a/src/telegram/bot.ts +++ b/src/telegram/bot.ts @@ -152,11 +152,11 @@ export function createTelegramBot(opts: TelegramBotOptions) { }, }; const fetchImpl = resolveTelegramFetch(opts.proxyFetch); - const client: ApiClientOptions = { - fetch: fetchImpl as unknown as ApiClientOptions["fetch"], - }; + const client: ApiClientOptions | undefined = fetchImpl + ? { fetch: fetchImpl as unknown as ApiClientOptions["fetch"] } + : undefined; - const bot = new Bot(opts.token, { client }); + const bot = new Bot(opts.token, client ? { client } : undefined); bot.api.config.use(apiThrottler()); bot.use(sequentialize(getTelegramSequentialKey)); diff --git a/src/telegram/fetch.ts b/src/telegram/fetch.ts index 8ff2a659e..dfad44601 100644 --- a/src/telegram/fetch.ts +++ b/src/telegram/fetch.ts @@ -1,6 +1,11 @@ -// BAN compatibility: force native fetch to avoid grammY's node-fetch shim under Bun. -export function resolveTelegramFetch(proxyFetch?: typeof fetch): typeof fetch { - const fetchImpl = proxyFetch ?? globalThis.fetch; +// BAN compatibility: force native fetch under Bun; keep grammY defaults on Node. +export function resolveTelegramFetch( + proxyFetch?: typeof fetch, +): typeof fetch | undefined { + if (proxyFetch) return proxyFetch; + const isBun = "Bun" in globalThis || Boolean(process?.versions?.bun); + if (!isBun) return undefined; + const fetchImpl = globalThis.fetch; if (!fetchImpl) { throw new Error("fetch is not available; set telegram.proxy in config"); } diff --git a/src/telegram/send.ts b/src/telegram/send.ts index c20cf811a..4d4d4b1b3 100644 --- a/src/telegram/send.ts +++ b/src/telegram/send.ts @@ -112,11 +112,10 @@ export async function sendMessageTelegram( const chatId = normalizeChatId(to); // Use provided api or create a new Bot instance. The nullish coalescing // operator ensures api is always defined (Bot.api is always non-null). + const fetchImpl = resolveTelegramFetch(); const api = opts.api ?? - new Bot(token, { - client: { fetch: resolveTelegramFetch() }, - }).api; + new Bot(token, fetchImpl ? { client: { fetch: fetchImpl } } : undefined).api; const mediaUrl = opts.mediaUrl?.trim(); // Build optional params for forum topics and reply threading. @@ -270,11 +269,10 @@ export async function reactMessageTelegram( const token = resolveToken(opts.token, account); const chatId = normalizeChatId(String(chatIdInput)); const messageId = normalizeMessageId(messageIdInput); + const fetchImpl = resolveTelegramFetch(); const api = opts.api ?? - new Bot(token, { - client: { fetch: resolveTelegramFetch() }, - }).api; + new Bot(token, fetchImpl ? { client: { fetch: fetchImpl } } : undefined).api; const request = createTelegramRetryRunner({ retry: opts.retry, configRetry: account.config.retry, diff --git a/src/telegram/webhook-set.ts b/src/telegram/webhook-set.ts index 002f70b37..fc81c1106 100644 --- a/src/telegram/webhook-set.ts +++ b/src/telegram/webhook-set.ts @@ -7,9 +7,11 @@ export async function setTelegramWebhook(opts: { secret?: string; dropPendingUpdates?: boolean; }) { - const bot = new Bot(opts.token, { - client: { fetch: resolveTelegramFetch() }, - }); + const fetchImpl = resolveTelegramFetch(); + const bot = new Bot( + opts.token, + fetchImpl ? { client: { fetch: fetchImpl } } : undefined, + ); await bot.api.setWebhook(opts.url, { secret_token: opts.secret, drop_pending_updates: opts.dropPendingUpdates ?? false, @@ -17,8 +19,10 @@ export async function setTelegramWebhook(opts: { } export async function deleteTelegramWebhook(opts: { token: string }) { - const bot = new Bot(opts.token, { - client: { fetch: resolveTelegramFetch() }, - }); + const fetchImpl = resolveTelegramFetch(); + const bot = new Bot( + opts.token, + fetchImpl ? { client: { fetch: fetchImpl } } : undefined, + ); await bot.api.deleteWebhook(); }