fix(telegram): gate native fetch to bun

This commit is contained in:
Peter Steinberger
2026-01-08 08:10:10 +01:00
parent c1e97fab80
commit c241cb25bd
5 changed files with 27 additions and 19 deletions

View File

@@ -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.

View File

@@ -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));

View File

@@ -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");
}

View File

@@ -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,

View File

@@ -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();
}