@spectrum-ts/telegram 9.0.0 → 9.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +57 -38
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,45 +1,9 @@
|
|
|
1
1
|
import { UnsupportedError, definePlatform, fusor, toVCard } from "@spectrum-ts/core";
|
|
2
|
-
import z from "zod";
|
|
3
|
-
import { asAttachment, asCustom, asGroup, asMarkdown, asReaction, asText, asVoice, renderInlineTokens, tracedFetch } from "@spectrum-ts/core/authoring";
|
|
4
2
|
import { createTelegramClient, editMessageText, getFile, getWebhookInfo, sendChatAction, sendMessageDraft, setMessageReaction, setWebhook } from "@photon-ai/telegram-ts";
|
|
3
|
+
import { asAttachment, asCustom, asGroup, asMarkdown, asReaction, asText, asVoice, renderInlineTokens, tracedFetch } from "@spectrum-ts/core/authoring";
|
|
4
|
+
import z from "zod";
|
|
5
5
|
import { Marked } from "marked";
|
|
6
6
|
import { timingSafeEqual } from "node:crypto";
|
|
7
|
-
//#region src/config.ts
|
|
8
|
-
/**
|
|
9
|
-
* The platform identifier — used for ALL THREE of:
|
|
10
|
-
*
|
|
11
|
-
* - the `definePlatform` name (so `message.platform` / `__platform` and
|
|
12
|
-
* the `platformStates` key are this value),
|
|
13
|
-
* - the `fusor(...)` routing key the handler is registered under, and
|
|
14
|
-
* - the value Fusor tags inbound Telegram events with (`event.platform`).
|
|
15
|
-
*
|
|
16
|
-
* Spectrum's webhook delivery looks the runtime up by `event.platform` against
|
|
17
|
-
* the platform name (`platformStates.get(event.platform)`), while routing is by
|
|
18
|
-
* the fusor key — so these MUST be the same string. It must also match Fusor's
|
|
19
|
-
* configured platform identifier for Telegram (the `<platform>` path segment
|
|
20
|
-
* the webhook is delivered under).
|
|
21
|
-
*/
|
|
22
|
-
const TELEGRAM_PLATFORM = "telegram";
|
|
23
|
-
const configSchema = z.object({
|
|
24
|
-
/** Bot token from @BotFather (outbound API calls + media downloads). */
|
|
25
|
-
botToken: z.string().regex(/^\d+:[A-Za-z0-9_-]+$/, "botToken must be in the form '<id>:<token>'"),
|
|
26
|
-
/**
|
|
27
|
-
* The `secret_token` passed to `setWebhook`. When present, inbound webhooks
|
|
28
|
-
* are verified against the `X-Telegram-Bot-Api-Secret-Token` header; when
|
|
29
|
-
* omitted, the check is skipped. Telegram does not HMAC-sign the body, so
|
|
30
|
-
* this shared token is the only inbound authentication.
|
|
31
|
-
*/
|
|
32
|
-
webhookSecret: z.string().regex(/^[A-Za-z0-9_-]{1,256}$/).optional(),
|
|
33
|
-
/** Override the Bot API base URL. Defaults to `https://api.telegram.org`. */
|
|
34
|
-
baseUrl: z.url().default("https://api.telegram.org")
|
|
35
|
-
});
|
|
36
|
-
/**
|
|
37
|
-
* The bot's own numeric id is the prefix of the token (`<id>:<hash>`). Used to
|
|
38
|
-
* drop inbound updates the bot itself produced, so a bot never echoes its own
|
|
39
|
-
* sends.
|
|
40
|
-
*/
|
|
41
|
-
const botIdFromToken = (botToken) => botToken.split(":")[0] ?? "";
|
|
42
|
-
//#endregion
|
|
43
7
|
//#region src/client.ts
|
|
44
8
|
const REQUEST_TIMEOUT_MS = 3e4;
|
|
45
9
|
const TRAILING_SLASHES = /\/+$/;
|
|
@@ -117,6 +81,60 @@ const downloadFile = async (config, fileId) => {
|
|
|
117
81
|
if (!res.ok) throw new Error(`Telegram media download failed: ${res.status} ${res.statusText}`);
|
|
118
82
|
return Buffer.from(await res.arrayBuffer());
|
|
119
83
|
};
|
|
84
|
+
/**
|
|
85
|
+
* A chat's `title` via `getChat`. Only groups/supergroups/channels have one;
|
|
86
|
+
* private chats return a name instead, so those resolve `undefined`.
|
|
87
|
+
*/
|
|
88
|
+
const getChatDisplayName = async (config, chatId) => {
|
|
89
|
+
return (await telegramClient(config).post({
|
|
90
|
+
body: { chat_id: chatId },
|
|
91
|
+
throwOnError: true,
|
|
92
|
+
url: "/getChat"
|
|
93
|
+
})).data.result?.title ?? void 0;
|
|
94
|
+
};
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/config.ts
|
|
97
|
+
/**
|
|
98
|
+
* The platform identifier — used for ALL THREE of:
|
|
99
|
+
*
|
|
100
|
+
* - the `definePlatform` name (so `message.platform` / `__platform` and
|
|
101
|
+
* the `platformStates` key are this value),
|
|
102
|
+
* - the `fusor(...)` routing key the handler is registered under, and
|
|
103
|
+
* - the value Fusor tags inbound Telegram events with (`event.platform`).
|
|
104
|
+
*
|
|
105
|
+
* Spectrum's webhook delivery looks the runtime up by `event.platform` against
|
|
106
|
+
* the platform name (`platformStates.get(event.platform)`), while routing is by
|
|
107
|
+
* the fusor key — so these MUST be the same string. It must also match Fusor's
|
|
108
|
+
* configured platform identifier for Telegram (the `<platform>` path segment
|
|
109
|
+
* the webhook is delivered under).
|
|
110
|
+
*/
|
|
111
|
+
const TELEGRAM_PLATFORM = "telegram";
|
|
112
|
+
const configSchema = z.object({
|
|
113
|
+
/**
|
|
114
|
+
* Bot token from @BotFather (outbound API calls + media downloads). Falls back
|
|
115
|
+
* to `SPECTRUM_TELEGRAM_BOT_TOKEN` when omitted (explicit config wins).
|
|
116
|
+
*/
|
|
117
|
+
botToken: z.string().regex(/^\d+:[A-Za-z0-9_-]+$/, "botToken must be in the form '<id>:<token>'"),
|
|
118
|
+
/**
|
|
119
|
+
* The `secret_token` passed to `setWebhook`. When present, inbound webhooks
|
|
120
|
+
* are verified against the `X-Telegram-Bot-Api-Secret-Token` header; when
|
|
121
|
+
* omitted, the check is skipped. Telegram does not HMAC-sign the body, so
|
|
122
|
+
* this shared token is the only inbound authentication. Falls back to
|
|
123
|
+
* `SPECTRUM_TELEGRAM_WEBHOOK_SECRET` when omitted.
|
|
124
|
+
*/
|
|
125
|
+
webhookSecret: z.string().regex(/^[A-Za-z0-9_-]{1,256}$/).optional(),
|
|
126
|
+
/**
|
|
127
|
+
* Override the Bot API base URL. Precedence is explicit config >
|
|
128
|
+
* `SPECTRUM_TELEGRAM_BASE_URL` > the `https://api.telegram.org` default.
|
|
129
|
+
*/
|
|
130
|
+
baseUrl: z.url().default("https://api.telegram.org")
|
|
131
|
+
});
|
|
132
|
+
/**
|
|
133
|
+
* The bot's own numeric id is the prefix of the token (`<id>:<hash>`). Used to
|
|
134
|
+
* drop inbound updates the bot itself produced, so a bot never echoes its own
|
|
135
|
+
* sends.
|
|
136
|
+
*/
|
|
137
|
+
const botIdFromToken = (botToken) => botToken.split(":")[0] ?? "";
|
|
120
138
|
//#endregion
|
|
121
139
|
//#region src/inbound/media.ts
|
|
122
140
|
const DEFAULT_VIDEO_MIME = "video/mp4";
|
|
@@ -908,6 +926,7 @@ const telegram = definePlatform(TELEGRAM_PLATFORM, {
|
|
|
908
926
|
} },
|
|
909
927
|
user: { resolve: resolveUser },
|
|
910
928
|
space: { create: createSpace },
|
|
929
|
+
actions: { getDisplayName: async ({ config }, space) => await getChatDisplayName(config, space.id) },
|
|
911
930
|
messages: handleMessages,
|
|
912
931
|
send
|
|
913
932
|
});
|