



























@@ -0,0 +1,70 @@
1+type JsonObject = Record<string, unknown>;
2+3+type TelegramBotApiOptions = {
4+baseUrl?: string;
5+fetchImpl?: (url: string, init: RequestInit) => Promise<Response>;
6+timeoutMs?: number;
7+};
8+9+const DEFAULT_BASE_URL =
10+process.env.OPENCLAW_TELEGRAM_USER_BOT_API_BASE_URL ?? "https://api.telegram.org";
11+const DEFAULT_TIMEOUT_MS = readPositiveInt(
12+process.env.OPENCLAW_TELEGRAM_USER_BOT_API_TIMEOUT_MS,
13+30000,
14+);
15+16+function readPositiveInt(raw: string | undefined, fallback: number) {
17+const parsed = Number.parseInt(raw ?? "", 10);
18+return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
19+}
20+21+function optionalString(source: JsonObject, key: string) {
22+const value = source[key];
23+return typeof value === "string" && value.trim() ? value.trim() : undefined;
24+}
25+26+export async function telegramBotApi(
27+token: string,
28+method: string,
29+body: JsonObject = {},
30+options: TelegramBotApiOptions = {},
31+) {
32+const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
33+const timeoutMs = Math.max(1, options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
34+const timeoutError = Object.assign(
35+new Error(`Telegram Bot API ${method} timed out after ${timeoutMs}ms`),
36+{ code: "ETIMEDOUT" },
37+);
38+const controller = new AbortController();
39+let timeout: NodeJS.Timeout | undefined;
40+const timeoutPromise = new Promise<never>((_, reject) => {
41+timeout = setTimeout(() => {
42+controller.abort(timeoutError);
43+reject(timeoutError);
44+}, timeoutMs);
45+timeout.unref?.();
46+});
47+48+try {
49+const response = await Promise.race([
50+(options.fetchImpl ?? fetch)(`${baseUrl}/bot${token}/${method}`, {
51+method: "POST",
52+headers: { "content-type": "application/json" },
53+body: JSON.stringify(body),
54+signal: controller.signal,
55+}),
56+timeoutPromise,
57+]);
58+const payload = (await Promise.race([response.json(), timeoutPromise])) as JsonObject;
59+if (!response.ok || payload.ok !== true) {
60+throw new Error(
61+optionalString(payload, "description") ?? `${method} failed with HTTP ${response.status}`,
62+);
63+}
64+return payload.result;
65+} finally {
66+if (timeout) {
67+clearTimeout(timeout);
68+}
69+}
70+}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。