@wirecat/tg-cli 0.0.0 → 0.43.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.
Files changed (181) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +527 -0
  3. package/THIRD_PARTY_NOTICES +55 -0
  4. package/dist/app.d.ts +11 -0
  5. package/dist/app.d.ts.map +1 -0
  6. package/dist/app.js +16 -0
  7. package/dist/app.js.map +1 -0
  8. package/dist/bin/tg.d.ts +3 -0
  9. package/dist/bin/tg.d.ts.map +1 -0
  10. package/dist/bin/tg.js +18 -0
  11. package/dist/bin/tg.js.map +1 -0
  12. package/dist/bot/adapter.d.ts +9 -0
  13. package/dist/bot/adapter.d.ts.map +1 -0
  14. package/dist/bot/adapter.js +171 -0
  15. package/dist/bot/adapter.js.map +1 -0
  16. package/dist/bot/generated/definitions.d.ts +3 -0
  17. package/dist/bot/generated/definitions.d.ts.map +1 -0
  18. package/dist/bot/generated/definitions.js +19104 -0
  19. package/dist/bot/generated/definitions.js.map +1 -0
  20. package/dist/bot/generated/manifest.d.ts +3 -0
  21. package/dist/bot/generated/manifest.d.ts.map +1 -0
  22. package/dist/bot/generated/manifest.js +15354 -0
  23. package/dist/bot/generated/manifest.js.map +1 -0
  24. package/dist/bot/generated/schemas.d.ts +1407 -0
  25. package/dist/bot/generated/schemas.d.ts.map +1 -0
  26. package/dist/bot/generated/schemas.js +5118 -0
  27. package/dist/bot/generated/schemas.js.map +1 -0
  28. package/dist/bot/generated/types.d.ts +6884 -0
  29. package/dist/bot/generated/types.d.ts.map +1 -0
  30. package/dist/bot/generated/types.js +5 -0
  31. package/dist/bot/generated/types.js.map +1 -0
  32. package/dist/bot/map.d.ts +122 -0
  33. package/dist/bot/map.d.ts.map +1 -0
  34. package/dist/bot/map.js +193 -0
  35. package/dist/bot/map.js.map +1 -0
  36. package/dist/bot/proxy.d.ts +15 -0
  37. package/dist/bot/proxy.d.ts.map +1 -0
  38. package/dist/bot/proxy.js +64 -0
  39. package/dist/bot/proxy.js.map +1 -0
  40. package/dist/bot/transport.d.ts +42 -0
  41. package/dist/bot/transport.d.ts.map +1 -0
  42. package/dist/bot/transport.js +158 -0
  43. package/dist/bot/transport.js.map +1 -0
  44. package/dist/browser.d.ts +6 -0
  45. package/dist/browser.d.ts.map +1 -0
  46. package/dist/browser.js +18 -0
  47. package/dist/browser.js.map +1 -0
  48. package/dist/commands/bot-api.d.ts +3 -0
  49. package/dist/commands/bot-api.d.ts.map +1 -0
  50. package/dist/commands/bot-api.js +112 -0
  51. package/dist/commands/bot-api.js.map +1 -0
  52. package/dist/commands/bot.d.ts +7 -0
  53. package/dist/commands/bot.d.ts.map +1 -0
  54. package/dist/commands/bot.js +99 -0
  55. package/dist/commands/bot.js.map +1 -0
  56. package/dist/commands/context.d.ts +59 -0
  57. package/dist/commands/context.d.ts.map +1 -0
  58. package/dist/commands/context.js +176 -0
  59. package/dist/commands/context.js.map +1 -0
  60. package/dist/commands/proxy-config.d.ts +9 -0
  61. package/dist/commands/proxy-config.d.ts.map +1 -0
  62. package/dist/commands/proxy-config.js +63 -0
  63. package/dist/commands/proxy-config.js.map +1 -0
  64. package/dist/commands/session.d.ts +22 -0
  65. package/dist/commands/session.d.ts.map +1 -0
  66. package/dist/commands/session.js +191 -0
  67. package/dist/commands/session.js.map +1 -0
  68. package/dist/commands/setup.d.ts +3 -0
  69. package/dist/commands/setup.d.ts.map +1 -0
  70. package/dist/commands/setup.js +203 -0
  71. package/dist/commands/setup.js.map +1 -0
  72. package/dist/commands/update.d.ts +2 -0
  73. package/dist/commands/update.d.ts.map +1 -0
  74. package/dist/commands/update.js +35 -0
  75. package/dist/commands/update.js.map +1 -0
  76. package/dist/install/postinstall.d.ts +8 -0
  77. package/dist/install/postinstall.d.ts.map +1 -0
  78. package/dist/install/postinstall.js +62 -0
  79. package/dist/install/postinstall.js.map +1 -0
  80. package/dist/paths.d.ts +9 -0
  81. package/dist/paths.d.ts.map +1 -0
  82. package/dist/paths.js +11 -0
  83. package/dist/paths.js.map +1 -0
  84. package/dist/program.d.ts +8 -0
  85. package/dist/program.d.ts.map +1 -0
  86. package/dist/program.js +138 -0
  87. package/dist/program.js.map +1 -0
  88. package/dist/proxy.d.ts +31 -0
  89. package/dist/proxy.d.ts.map +1 -0
  90. package/dist/proxy.js +99 -0
  91. package/dist/proxy.js.map +1 -0
  92. package/dist/telegram/adapter.d.ts +432 -0
  93. package/dist/telegram/adapter.d.ts.map +1 -0
  94. package/dist/telegram/adapter.js +1898 -0
  95. package/dist/telegram/adapter.js.map +1 -0
  96. package/dist/telegram/bot-history.d.ts +18 -0
  97. package/dist/telegram/bot-history.d.ts.map +1 -0
  98. package/dist/telegram/bot-history.js +145 -0
  99. package/dist/telegram/bot-history.js.map +1 -0
  100. package/dist/telegram/comments.d.ts +18 -0
  101. package/dist/telegram/comments.d.ts.map +1 -0
  102. package/dist/telegram/comments.js +48 -0
  103. package/dist/telegram/comments.js.map +1 -0
  104. package/dist/telegram/credentials.d.ts +22 -0
  105. package/dist/telegram/credentials.d.ts.map +1 -0
  106. package/dist/telegram/credentials.js +49 -0
  107. package/dist/telegram/credentials.js.map +1 -0
  108. package/dist/telegram/errors.d.ts +6 -0
  109. package/dist/telegram/errors.d.ts.map +1 -0
  110. package/dist/telegram/errors.js +186 -0
  111. package/dist/telegram/errors.js.map +1 -0
  112. package/dist/telegram/folder-rules.d.ts +14 -0
  113. package/dist/telegram/folder-rules.d.ts.map +1 -0
  114. package/dist/telegram/folder-rules.js +23 -0
  115. package/dist/telegram/folder-rules.js.map +1 -0
  116. package/dist/telegram/format-html.d.ts +4 -0
  117. package/dist/telegram/format-html.d.ts.map +1 -0
  118. package/dist/telegram/format-html.js +29 -0
  119. package/dist/telegram/format-html.js.map +1 -0
  120. package/dist/telegram/format-markdown.d.ts +3 -0
  121. package/dist/telegram/format-markdown.d.ts.map +1 -0
  122. package/dist/telegram/format-markdown.js +160 -0
  123. package/dist/telegram/format-markdown.js.map +1 -0
  124. package/dist/telegram/join-requests.d.ts +15 -0
  125. package/dist/telegram/join-requests.d.ts.map +1 -0
  126. package/dist/telegram/join-requests.js +35 -0
  127. package/dist/telegram/join-requests.js.map +1 -0
  128. package/dist/telegram/map.d.ts +92 -0
  129. package/dist/telegram/map.d.ts.map +1 -0
  130. package/dist/telegram/map.js +471 -0
  131. package/dist/telegram/map.js.map +1 -0
  132. package/dist/telegram/poll-voters.d.ts +15 -0
  133. package/dist/telegram/poll-voters.d.ts.map +1 -0
  134. package/dist/telegram/poll-voters.js +31 -0
  135. package/dist/telegram/poll-voters.js.map +1 -0
  136. package/dist/telegram/polls.d.ts +5 -0
  137. package/dist/telegram/polls.d.ts.map +1 -0
  138. package/dist/telegram/polls.js +20 -0
  139. package/dist/telegram/polls.js.map +1 -0
  140. package/dist/telegram/profile.d.ts +9 -0
  141. package/dist/telegram/profile.d.ts.map +1 -0
  142. package/dist/telegram/profile.js +175 -0
  143. package/dist/telegram/profile.js.map +1 -0
  144. package/dist/telegram/proxy.d.ts +48 -0
  145. package/dist/telegram/proxy.d.ts.map +1 -0
  146. package/dist/telegram/proxy.js +108 -0
  147. package/dist/telegram/proxy.js.map +1 -0
  148. package/dist/telegram/registration.d.ts +31 -0
  149. package/dist/telegram/registration.d.ts.map +1 -0
  150. package/dist/telegram/registration.js +95 -0
  151. package/dist/telegram/registration.js.map +1 -0
  152. package/dist/telegram/send-as.d.ts +17 -0
  153. package/dist/telegram/send-as.d.ts.map +1 -0
  154. package/dist/telegram/send-as.js +67 -0
  155. package/dist/telegram/send-as.js.map +1 -0
  156. package/dist/telegram/stats.d.ts +13 -0
  157. package/dist/telegram/stats.d.ts.map +1 -0
  158. package/dist/telegram/stats.js +135 -0
  159. package/dist/telegram/stats.js.map +1 -0
  160. package/dist/telegram/storage.d.ts +4 -0
  161. package/dist/telegram/storage.d.ts.map +1 -0
  162. package/dist/telegram/storage.js +68 -0
  163. package/dist/telegram/storage.js.map +1 -0
  164. package/dist/telegram/upload.d.ts +9 -0
  165. package/dist/telegram/upload.d.ts.map +1 -0
  166. package/dist/telegram/upload.js +29 -0
  167. package/dist/telegram/upload.js.map +1 -0
  168. package/dist/update.d.ts +28 -0
  169. package/dist/update.d.ts.map +1 -0
  170. package/dist/update.js +56 -0
  171. package/dist/update.js.map +1 -0
  172. package/dist/version.d.ts +2 -0
  173. package/dist/version.d.ts.map +1 -0
  174. package/dist/version.js +2 -0
  175. package/dist/version.js.map +1 -0
  176. package/install/postinstall.mjs +3 -0
  177. package/install/windows.ps1 +161 -0
  178. package/package.json +71 -2
  179. package/skills/tg-cli/SKILL.md +489 -0
  180. package/spec/bot/LICENSE +21 -0
  181. package/spec/bot/README.md +16 -0
@@ -0,0 +1,193 @@
1
+ import { CliError } from "@wirecat/cli-core";
2
+ const KINDS = {
3
+ private: "dialog",
4
+ group: "group",
5
+ supergroup: "group",
6
+ channel: "channel",
7
+ };
8
+ const ENTITY = { bold: "bold", italic: "italic", strike: "strikethrough", code: "code" };
9
+ const nameOf = (person) => person ? [person.first_name, person.last_name].filter(Boolean).join(" ") || null : null;
10
+ const iso = (seconds) => new Date(seconds * 1000).toISOString();
11
+ /**
12
+ * A file by Telegram's `file_id` only. ⚠ Never a download address: Telegram's has the bot token in
13
+ * it, and an `Attachment.url` would put the token into the store and into command output.
14
+ */
15
+ const attachmentsOf = (message) => {
16
+ const files = [
17
+ ["photo", message.photo?.at(-1)],
18
+ ["file", message.document],
19
+ ["voice", message.voice],
20
+ ["video", message.video],
21
+ ["audio", message.audio],
22
+ ];
23
+ return files.flatMap(([kind, file]) => {
24
+ if (!file)
25
+ return [];
26
+ const attachment = { kind, providerRef: { fileId: file.file_id } };
27
+ if (file.file_name)
28
+ attachment.name = file.file_name;
29
+ if (file.file_size !== undefined)
30
+ attachment.size = file.file_size;
31
+ if (file.duration !== undefined)
32
+ attachment.duration = file.duration;
33
+ return [attachment];
34
+ });
35
+ };
36
+ const quoted = (message, selfId) => ({
37
+ id: String(message.message_id),
38
+ senderId: message.from ? String(message.from.id) : null,
39
+ senderName: nameOf(message.from),
40
+ timestamp: iso(message.date),
41
+ text: message.text ?? message.caption ?? "",
42
+ attachments: attachmentsOf(message),
43
+ outgoing: selfId === undefined || !message.from ? null : String(message.from.id) === selfId,
44
+ });
45
+ /** `selfId` is the bot's own id, when known, so `outgoing` says whether the bot wrote it. */
46
+ export const toMessage = (message, selfId) => {
47
+ const mapped = {
48
+ id: String(message.message_id),
49
+ chatId: String(message.chat.id),
50
+ senderId: message.from ? String(message.from.id) : null,
51
+ senderName: nameOf(message.from),
52
+ timestamp: iso(message.date),
53
+ editedAt: message.edit_date === undefined ? null : iso(message.edit_date),
54
+ text: message.text ?? message.caption ?? "",
55
+ outgoing: selfId === undefined || !message.from ? null : String(message.from.id) === selfId,
56
+ attachments: attachmentsOf(message),
57
+ replyTo: message.reply_to_message ? quoted(message.reply_to_message, selfId) : null,
58
+ forwardedFrom: null,
59
+ reactions: null,
60
+ };
61
+ if (message.reply_to_message)
62
+ mapped.replyToId = String(message.reply_to_message.message_id);
63
+ return mapped;
64
+ };
65
+ export const toChat = (chat) => ({
66
+ id: String(chat.id),
67
+ title: chat.title ?? nameOf(chat),
68
+ kind: KINDS[chat.type] ?? "unknown",
69
+ unreadCount: null,
70
+ lastMessageAt: null,
71
+ participantsCount: null,
72
+ providerMetadata: { type: chat.type, ...(chat.username ? { username: chat.username } : {}) },
73
+ });
74
+ /** Markup is in UTF-16 positions, which is what Telegram's [entities](https://core.telegram.org/bots/api#messageentity) count. */
75
+ export const entitiesOf = (markup) => markup.map((span) => {
76
+ const base = { offset: span.from, length: span.length };
77
+ switch (span.type) {
78
+ case "bold":
79
+ case "italic":
80
+ case "strike":
81
+ case "code":
82
+ return { type: ENTITY[span.type], ...base };
83
+ case "underline":
84
+ case "spoiler":
85
+ case "blockquote":
86
+ return { type: span.type, ...base };
87
+ case "pre":
88
+ return { type: "pre", ...base, language: span.language ?? "" };
89
+ case "link":
90
+ return { type: "text_link", ...base, url: span.url };
91
+ default:
92
+ throw new CliError("validation_error", "Telegram does not support this formatting span");
93
+ }
94
+ });
95
+ /**
96
+ * The shared admin rights in [promoteChatMember](https://core.telegram.org/bots/api#promotechatmember)'s
97
+ * words, as tg's personal account maps them. Telegram has no right to read: an admin always reads.
98
+ */
99
+ export const ADMIN_RIGHT_FIELDS = {
100
+ members: "can_restrict_members",
101
+ admins: "can_promote_members",
102
+ info: "can_change_info",
103
+ pin: "can_pin_messages",
104
+ link: "can_invite_users",
105
+ post: "can_post_messages",
106
+ edit: "can_edit_messages",
107
+ delete: "can_delete_messages",
108
+ };
109
+ export const BOT_ADMIN_RIGHTS = Object.keys(ADMIN_RIGHT_FIELDS);
110
+ /** Every right promoteChatMember takes; all of them false demotes. */
111
+ export const PROMOTE_FIELDS = [
112
+ "is_anonymous",
113
+ "can_manage_chat",
114
+ "can_delete_messages",
115
+ "can_manage_video_chats",
116
+ "can_restrict_members",
117
+ "can_promote_members",
118
+ "can_change_info",
119
+ "can_invite_users",
120
+ "can_post_stories",
121
+ "can_edit_stories",
122
+ "can_delete_stories",
123
+ "can_post_messages",
124
+ "can_edit_messages",
125
+ "can_pin_messages",
126
+ "can_manage_topics",
127
+ "can_send_welcome_messages",
128
+ ];
129
+ export const toAdmin = ({ status, user, custom_title, ...rights }) => ({
130
+ id: String(user.id),
131
+ name: nameOf(user),
132
+ username: user.username ?? null,
133
+ role: status === "creator" ? "owner" : "admin",
134
+ rights: BOT_ADMIN_RIGHTS.filter((right) => status === "creator" || rights[ADMIN_RIGHT_FIELDS[right]] === true),
135
+ title: custom_title ?? null,
136
+ });
137
+ /**
138
+ * Asked for every time, because Telegram keeps the last list it was given (RISK-95): without
139
+ * `chat_member`, nobody joining or leaving would ever arrive.
140
+ */
141
+ export const UPDATE_TYPES = [
142
+ "message",
143
+ "edited_message",
144
+ "channel_post",
145
+ "edited_channel_post",
146
+ "callback_query",
147
+ "my_chat_member",
148
+ "chat_member",
149
+ ];
150
+ const inChat = ({ status, is_member }) => status === "creator" ||
151
+ status === "administrator" ||
152
+ status === "member" ||
153
+ (status === "restricted" && is_member === true);
154
+ const personOf = (user) => ({ id: String(user.id), name: nameOf(user), username: user.username ?? null });
155
+ /** One update in the shared words; a kind not decoded here is `other`, under Telegram's own name. */
156
+ export const toEvent = (update, selfId) => {
157
+ const created = update.message ?? update.channel_post;
158
+ if (created)
159
+ return { event: "message", message: { ...toMessage(created, selfId), chatTitle: null } };
160
+ const edited = update.edited_message ?? update.edited_channel_post;
161
+ if (edited)
162
+ return { event: "edit", message: { ...toMessage(edited, selfId), chatTitle: null } };
163
+ const press = update.callback_query;
164
+ if (press) {
165
+ return {
166
+ event: "callback",
167
+ callbackId: press.id,
168
+ chatId: press.message ? String(press.message.chat.id) : null,
169
+ messageId: press.message ? String(press.message.message_id) : null,
170
+ from: personOf(press.from),
171
+ data: press.data ?? "",
172
+ };
173
+ }
174
+ const change = update.chat_member;
175
+ if (change) {
176
+ const was = inChat(change.old_chat_member);
177
+ const is = inChat(change.new_chat_member);
178
+ const person = change.new_chat_member.user;
179
+ const self = change.from.id === person.id;
180
+ if (was !== is) {
181
+ return {
182
+ event: is ? (self ? "joined" : "added") : self ? "left" : "removed",
183
+ chatId: String(change.chat.id),
184
+ person: personOf(person),
185
+ at: iso(change.date),
186
+ };
187
+ }
188
+ }
189
+ const kind = Object.keys(update).find((key) => key !== "update_id") ?? "unknown";
190
+ const chat = update[kind]?.chat;
191
+ return { event: "other", type: kind, chatId: chat ? String(chat.id) : null };
192
+ };
193
+ //# sourceMappingURL=map.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"map.js","sourceRoot":"","sources":["../../src/bot/map.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { Dispatcher } from "undici";
2
+ import { type ProxyServer } from "../proxy.js";
3
+ import type { FetchLike } from "./transport.js";
4
+ /**
5
+ * The Bot API is HTTPS, so it can go through a SOCKS5 or an HTTP proxy — never an MTProxy, which
6
+ * carries only Telegram's own protocol. Credentials go as options, never in the URL, so no error
7
+ * undici builds from the URL can carry them.
8
+ */
9
+ export declare const botDispatcher: (proxy: ProxyServer) => Promise<Dispatcher | undefined>;
10
+ /**
11
+ * undici's own `fetch` with its agent, not the global one: an agent from one copy of undici is not
12
+ * promised to work with another's fetch.
13
+ */
14
+ export declare const proxiedFetch: (proxy: ProxyServer) => FetchLike | undefined;
15
+ //# sourceMappingURL=proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/bot/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACxC,OAAO,EAAE,KAAK,WAAW,EAA4B,MAAM,aAAa,CAAA;AACxE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE/C;;;;GAIG;AACH,eAAO,MAAM,aAAa,UAAiB,WAAW,KAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAiBtF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,UAAW,WAAW,KAAG,SAAS,GAAG,SAY7D,CAAA"}
@@ -0,0 +1,64 @@
1
+ import { proxyAddress, proxyError } from "../proxy.js";
2
+ /**
3
+ * The Bot API is HTTPS, so it can go through a SOCKS5 or an HTTP proxy — never an MTProxy, which
4
+ * carries only Telegram's own protocol. Credentials go as options, never in the URL, so no error
5
+ * undici builds from the URL can carry them.
6
+ */
7
+ export const botDispatcher = async (proxy) => {
8
+ if (proxy.kind === "mtproxy")
9
+ return undefined;
10
+ // Loaded on use: Bun answers `import "undici"` with its own module, which has no SOCKS agent.
11
+ const { ProxyAgent, Socks5ProxyAgent } = await import("undici");
12
+ const uri = proxyAddress(proxy);
13
+ if (typeof ProxyAgent !== "function" || typeof Socks5ProxyAgent !== "function")
14
+ throw proxyError(proxy, "cannot carry the Bot API under this runtime — run tg with Node");
15
+ if (proxy.kind === "socks5")
16
+ return new Socks5ProxyAgent(uri, {
17
+ ...(proxy.user === undefined ? {} : { username: proxy.user }),
18
+ ...(proxy.secret === undefined ? {} : { password: proxy.secret }),
19
+ });
20
+ const basic = proxy.user === undefined
21
+ ? undefined
22
+ : `Basic ${Buffer.from(`${proxy.user}:${proxy.secret ?? ""}`).toString("base64")}`;
23
+ return new ProxyAgent({ uri, ...(basic ? { token: basic } : {}) });
24
+ };
25
+ /**
26
+ * undici's own `fetch` with its agent, not the global one: an agent from one copy of undici is not
27
+ * promised to work with another's fetch.
28
+ */
29
+ export const proxiedFetch = (proxy) => {
30
+ if (proxy.kind === "mtproxy")
31
+ return undefined;
32
+ let dispatcher;
33
+ return async (url, init) => {
34
+ dispatcher ??= botDispatcher(proxy);
35
+ const [{ fetch }, agent] = await Promise.all([import("undici"), dispatcher]);
36
+ try {
37
+ return (await fetch(url, { ...init, ...(agent ? { dispatcher: agent } : {}) }));
38
+ }
39
+ catch (error) {
40
+ throw proxyRefusal(proxy, error) ?? error;
41
+ }
42
+ };
43
+ };
44
+ /**
45
+ * With a proxy, tg opens no connection but the one to the proxy, so a refused or unknown address is
46
+ * the proxy's; a tunnel the proxy would not open is too. Either way the request never left.
47
+ */
48
+ const proxyRefusal = (proxy, error) => {
49
+ for (let cause = error; cause instanceof Error; cause = cause.cause) {
50
+ const code = cause.code;
51
+ const status = /Proxy response \((\d+)\)/.exec(cause.message)?.[1];
52
+ const reason = status !== undefined
53
+ ? `refused the tunnel (HTTP ${status})`
54
+ : typeof code === "string" && code.startsWith("UND_ERR_SOCKS5")
55
+ ? `refused (${code})`
56
+ : typeof code === "string" && /^(ECONN|ENOTFOUND|EAI_AGAIN|ETIMEDOUT|ENETUNREACH|EHOSTUNREACH)/.test(code)
57
+ ? `cannot be reached (${code})`
58
+ : undefined;
59
+ if (reason)
60
+ return proxyError(proxy, reason);
61
+ }
62
+ return undefined;
63
+ };
64
+ //# sourceMappingURL=proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/bot/proxy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import type { EventSink } from "@wirecat/cli-messaging/cli";
2
+ export type FetchLike = (url: string, init: RequestInit) => Promise<Response>;
3
+ export interface BotTransportOptions {
4
+ token: string;
5
+ baseUrl?: string;
6
+ fetch?: FetchLike;
7
+ timeoutMs?: number;
8
+ /** Ends the command's request in flight: the deadline, or Ctrl-C on a command that runs until told to. */
9
+ signal?: AbortSignal;
10
+ events?: EventSink;
11
+ }
12
+ /**
13
+ * Telegram's Bot API, method by method.
14
+ *
15
+ * ⚠ **The token is part of every address** — `/bot<token>/<method>` — so the address never leaves
16
+ * this class: not in an error, not in a trace line, and never by passing on a failed request's own
17
+ * error, whose text may hold it. A failure keeps the method, Telegram's code and Telegram's words.
18
+ */
19
+ export declare class TelegramBotTransport {
20
+ #private;
21
+ constructor(options: BotTransportOptions);
22
+ /**
23
+ * `reads: false` for a write, so a write that got no answer is `outcome_unknown`, never retried by
24
+ * anyone. `file` goes up in the same request, as multipart: Telegram has no upload step of its own.
25
+ * `timeoutMs` replaces the transport's for one call — a long poll waits longer than any other request.
26
+ */
27
+ call(method: string, params?: Record<string, unknown>, { reads, file, files, body, secrets, timeoutMs, }?: {
28
+ reads?: boolean;
29
+ file?: OutgoingFile;
30
+ files?: readonly OutgoingFile[];
31
+ body?: string;
32
+ secrets?: readonly string[];
33
+ timeoutMs?: number;
34
+ }): Promise<unknown>;
35
+ }
36
+ /** A file sent with a method — `photo` for sendPhoto, `document`, `voice`. */
37
+ export interface OutgoingFile {
38
+ field: string;
39
+ name: string;
40
+ bytes: Uint8Array;
41
+ }
42
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/bot/transport.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAM3D,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAE7E,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,0GAA0G;IAC1G,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,MAAM,CAAC,EAAE,SAAS,CAAA;CACnB;AAWD;;;;;;GAMG;AACH,qBAAa,oBAAoB;;IAQ/B,YAAY,OAAO,EAAE,mBAAmB,EAOvC;IAED;;;;OAIG;IACG,IAAI,CACR,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACpC,EACE,KAAY,EACZ,IAAI,EACJ,KAAU,EACV,IAAI,EACJ,OAAY,EACZ,SAA2B,GAC5B,GAAE;QACD,KAAK,CAAC,EAAE,OAAO,CAAA;QACf,IAAI,CAAC,EAAE,YAAY,CAAA;QACnB,KAAK,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;QAC/B,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;QAC3B,SAAS,CAAC,EAAE,MAAM,CAAA;KACd,GACL,OAAO,CAAC,OAAO,CAAC,CAkElB;CAsBF;AAED,8EAA8E;AAC9E,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,UAAU,CAAA;CAClB"}
@@ -0,0 +1,158 @@
1
+ import { CliError, isCliError } from "@wirecat/cli-core";
2
+ import { apiJson, apiPlainJson, parseApiJson } from "@wirecat/cli-messaging/cli";
3
+ const API = "https://api.telegram.org";
4
+ const DEFAULT_TIMEOUT_MS = 30_000;
5
+ /**
6
+ * Telegram's Bot API, method by method.
7
+ *
8
+ * ⚠ **The token is part of every address** — `/bot<token>/<method>` — so the address never leaves
9
+ * this class: not in an error, not in a trace line, and never by passing on a failed request's own
10
+ * error, whose text may hold it. A failure keeps the method, Telegram's code and Telegram's words.
11
+ */
12
+ export class TelegramBotTransport {
13
+ #token;
14
+ #baseUrl;
15
+ #fetch;
16
+ #timeoutMs;
17
+ #signal;
18
+ #events;
19
+ constructor(options) {
20
+ this.#token = options.token;
21
+ this.#baseUrl = options.baseUrl ?? API;
22
+ this.#fetch = options.fetch ?? fetch;
23
+ this.#timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
24
+ this.#signal = options.signal;
25
+ this.#events = options.events;
26
+ }
27
+ /**
28
+ * `reads: false` for a write, so a write that got no answer is `outcome_unknown`, never retried by
29
+ * anyone. `file` goes up in the same request, as multipart: Telegram has no upload step of its own.
30
+ * `timeoutMs` replaces the transport's for one call — a long poll waits longer than any other request.
31
+ */
32
+ async call(method, params = {}, { reads = true, file, files = [], body, secrets = [], timeoutMs = this.#timeoutMs, } = {}) {
33
+ this.#events?.({ event: "request", operation: method });
34
+ const started = performance.now();
35
+ const signals = [AbortSignal.timeout(timeoutMs), ...(this.#signal ? [this.#signal] : [])];
36
+ let response;
37
+ try {
38
+ response = await this.#fetch(`${this.#baseUrl}/bot${this.#token}/${method}`, {
39
+ method: "POST",
40
+ ...(file || files.length
41
+ ? {
42
+ headers: { Accept: "application/json" },
43
+ body: multipart(body === undefined ? params : parseApiJson(body), file ? [file, ...files] : files),
44
+ }
45
+ : {
46
+ headers: { "Content-Type": "application/json", Accept: "application/json" },
47
+ body: body ?? apiJson(params),
48
+ }),
49
+ signal: AbortSignal.any(signals),
50
+ });
51
+ }
52
+ catch (error) {
53
+ const failure = this.#unanswered(method, error, reads, timeoutMs);
54
+ this.#events?.({ event: "response", operation: method, outcome: "error", errorCode: failure.code });
55
+ throw failure;
56
+ }
57
+ let text;
58
+ try {
59
+ text = await response.text();
60
+ }
61
+ catch (error) {
62
+ const failure = this.#unanswered(method, error, reads, timeoutMs);
63
+ this.#events?.({ event: "response", operation: method, outcome: "error", errorCode: failure.code });
64
+ throw failure;
65
+ }
66
+ const answered = {
67
+ event: "response",
68
+ operation: method,
69
+ status: response.status,
70
+ bytes: Buffer.byteLength(text),
71
+ durationMs: Math.round(performance.now() - started),
72
+ };
73
+ let answer;
74
+ try {
75
+ answer = apiPlainJson(parseApiJson(text));
76
+ }
77
+ catch {
78
+ this.#events?.({ ...answered, outcome: "error", errorCode: "invalid_response" });
79
+ throw new CliError("invalid_response", `Telegram answered ${method} with something that is not JSON`, {
80
+ operation: method,
81
+ status: response.status,
82
+ });
83
+ }
84
+ if (answer.ok === true) {
85
+ this.#events?.({ ...answered, outcome: "ok" });
86
+ return answer.result;
87
+ }
88
+ const secretValues = [this.#token, ...secrets];
89
+ if (answer.description) {
90
+ for (const secret of secretValues)
91
+ if (secret)
92
+ answer.description = answer.description.split(secret).join("[redacted]");
93
+ answer.description = answer.description.replace(/\b\d+:[A-Za-z0-9_-]{20,}\b/g, "[redacted]");
94
+ }
95
+ const refusal = refusalOf(method, answer, response.status);
96
+ this.#events?.({ ...answered, outcome: "error", errorCode: refusal.code });
97
+ throw refusal;
98
+ }
99
+ #unanswered(method, error, reads, timeoutMs) {
100
+ // A proxy that refused, or was not there, never passed the request on — not an unknown outcome.
101
+ if (isCliError(error) && error.details.proxy !== undefined)
102
+ return error;
103
+ const timedOut = error?.name === "TimeoutError";
104
+ if (this.#signal?.aborted && this.#signal.reason?.name !== "TimeoutError") {
105
+ return new CliError("cancelled", `${method} was cancelled`, { operation: method });
106
+ }
107
+ if (!reads) {
108
+ return new CliError("outcome_unknown", `${method} got no answer; Telegram may or may not have carried it out — check before repeating it`, { operation: method, retryable: false });
109
+ }
110
+ return new CliError(timedOut ? "timeout" : "network_error", timedOut ? `${method} got no answer within ${timeoutMs} ms` : `${method} could not reach Telegram`, { operation: method, retryable: true });
111
+ }
112
+ }
113
+ /** A field that is not a string goes as JSON, as Telegram reads `reply_parameters` and `caption_entities` from a form. */
114
+ const multipart = (params, files) => {
115
+ const form = new FormData();
116
+ for (const [name, value] of Object.entries(params)) {
117
+ if (value !== undefined)
118
+ form.append(name, typeof value === "string" ? value : apiJson(value));
119
+ }
120
+ for (const file of files)
121
+ form.append(file.field, new Blob([file.bytes]), file.name);
122
+ return form;
123
+ };
124
+ /**
125
+ * Telegram's own words go into the message: they name the problem ("chat not found") and never the
126
+ * token. Its `error_code` is "subject to change", so the code here follows the HTTP status.
127
+ */
128
+ const refusalOf = (method, answer, status) => {
129
+ const said = answer.description ?? `HTTP ${status}`;
130
+ const details = { operation: method, status };
131
+ const retryAfter = answer.parameters?.retry_after;
132
+ if (retryAfter !== undefined) {
133
+ return new CliError("rate_limited", `Telegram asks to wait ${retryAfter} s before ${method}: ${said}`, {
134
+ ...details,
135
+ retryAfterMs: retryAfter * 1000,
136
+ retryable: true,
137
+ });
138
+ }
139
+ const migrated = answer.parameters?.migrate_to_chat_id;
140
+ if (migrated !== undefined) {
141
+ return new CliError("not_found", `this group became a supergroup with id ${migrated} — use that id from now on (${said})`, { ...details, migratedTo: String(migrated) });
142
+ }
143
+ // A token Telegram cannot parse answers 404, a revoked one 401; the methods called are this code's own.
144
+ const code = status === 401 || status === 404
145
+ ? "authentication_error"
146
+ : status === 403
147
+ ? "permission_error"
148
+ : status >= 500
149
+ ? "provider_unavailable"
150
+ : /not found/i.test(said)
151
+ ? "not_found"
152
+ : status === 400
153
+ ? "validation_error"
154
+ : "provider_error";
155
+ const message = code === "authentication_error" ? `Telegram did not accept this bot token (${said})` : `${method}: ${said}`;
156
+ return new CliError(code, message, details);
157
+ };
158
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/bot/transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAwC,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9F,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAEhF,MAAM,GAAG,GAAG,0BAA0B,CAAA;AACtC,MAAM,kBAAkB,GAAG,MAAM,CAAA;AAuBjC;;;;;;GAMG;AACH,MAAM,OAAO,oBAAoB;IACtB,MAAM,CAAQ;IACd,QAAQ,CAAQ;IAChB,MAAM,CAAW;IACjB,UAAU,CAAQ;IAClB,OAAO,CAAyB;IAChC,OAAO,CAAuB;IAEvC,YAAY,OAA4B;QACtC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,CAAA;QAC3B,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,IAAI,GAAG,CAAA;QACtC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAA;QACpC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAA;QACzD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAA;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAA;IAC/B,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,IAAI,CACR,MAAc,EACd,MAAM,GAA4B,EAAE,EACpC,EACE,KAAK,GAAG,IAAI,EACZ,IAAI,EACJ,KAAK,GAAG,EAAE,EACV,IAAI,EACJ,OAAO,GAAG,EAAE,EACZ,SAAS,GAAG,IAAI,CAAC,UAAU,GAC5B,GAOG,EAAE;QAEN,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAA;QACvD,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;QACjC,MAAM,OAAO,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QACzF,IAAI,QAAkB,CAAA;QACtB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,OAAO,IAAI,CAAC,MAAM,IAAI,MAAM,EAAE,EAAE;gBAC3E,MAAM,EAAE,MAAM;gBACd,GAAG,CAAC,IAAI,IAAI,KAAK,CAAC,MAAM;oBACtB,CAAC,CAAC;wBACE,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;wBACvC,IAAI,EAAE,SAAS,CACb,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAE,YAAY,CAAC,IAAI,CAA6B,EAC7E,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAChC;qBACF;oBACH,CAAC,CAAC;wBACE,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,EAAE,kBAAkB,EAAE;wBAC3E,IAAI,EAAE,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;qBAC9B,CAAC;gBACN,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC;aACjC,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,CAAA;YACjE,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;YACnG,MAAM,OAAO,CAAA;QACf,CAAC;QAED,IAAI,IAAY,CAAA;QAChB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;QAC9B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,CAAA;YACjE,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;YACnG,MAAM,OAAO,CAAA;QACf,CAAC;QACD,MAAM,QAAQ,GAAG;YACf,KAAK,EAAE,UAAmB;YAC1B,SAAS,EAAE,MAAM;YACjB,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC;YAC9B,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC;SACpD,CAAA;QACD,IAAI,MAAc,CAAA;QAClB,IAAI,CAAC;YACH,MAAM,GAAG,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC,CAAW,CAAA;QACrD,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,CAAA;YAChF,MAAM,IAAI,QAAQ,CAAC,kBAAkB,EAAE,qBAAqB,MAAM,kCAAkC,EAAE;gBACpG,SAAS,EAAE,MAAM;gBACjB,MAAM,EAAE,QAAQ,CAAC,MAAM;aACxB,CAAC,CAAA;QACJ,CAAC;QACD,IAAI,MAAM,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;YACvB,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;YAC9C,OAAO,MAAM,CAAC,MAAM,CAAA;QACtB,CAAC;QACD,MAAM,YAAY,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,CAAA;QAC9C,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YACvB,KAAK,MAAM,MAAM,IAAI,YAAY;gBAC/B,IAAI,MAAM;oBAAE,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;YACtF,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,6BAA6B,EAAE,YAAY,CAAC,CAAA;QAC9F,CAAC;QACD,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;QAC1D,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;QAC1E,MAAM,OAAO,CAAA;IACf,CAAC;IAED,WAAW,CAAC,MAAc,EAAE,KAAc,EAAE,KAAc,EAAE,SAAiB;QAC3E,gGAAgG;QAChG,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS;YAAE,OAAO,KAAK,CAAA;QACxE,MAAM,QAAQ,GAAI,KAA2B,EAAE,IAAI,KAAK,cAAc,CAAA;QACtE,IAAI,IAAI,CAAC,OAAO,EAAE,OAAO,IAAK,IAAI,CAAC,OAAO,CAAC,MAA4B,EAAE,IAAI,KAAK,cAAc,EAAE,CAAC;YACjG,OAAO,IAAI,QAAQ,CAAC,WAAW,EAAE,GAAG,MAAM,gBAAgB,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAA;QACpF,CAAC;QACD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,IAAI,QAAQ,CACjB,iBAAiB,EACjB,GAAG,MAAM,yFAAyF,EAClG,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,CACxC,CAAA;QACH,CAAC;QACD,OAAO,IAAI,QAAQ,CACjB,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,eAAe,EACtC,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM,yBAAyB,SAAS,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,2BAA2B,EAClG,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CACvC,CAAA;IACH,CAAC;CACF;AASD,0HAA0H;AAC1H,MAAM,SAAS,GAAG,CAAC,MAA+B,EAAE,KAA8B,EAAY,EAAE;IAC9F,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAA;IAC3B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,IAAI,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;IAChG,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,KAAK;QAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;IACpF,OAAO,IAAI,CAAA;AACb,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,SAAS,GAAG,CAAC,MAAc,EAAE,MAAc,EAAE,MAAc,EAAY,EAAE;IAC7E,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,IAAI,QAAQ,MAAM,EAAE,CAAA;IACnD,MAAM,OAAO,GAAoB,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,CAAA;IAC9D,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,EAAE,WAAW,CAAA;IACjD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,IAAI,QAAQ,CAAC,cAAc,EAAE,yBAAyB,UAAU,aAAa,MAAM,KAAK,IAAI,EAAE,EAAE;YACrG,GAAG,OAAO;YACV,YAAY,EAAE,UAAU,GAAG,IAAI;YAC/B,SAAS,EAAE,IAAI;SAChB,CAAC,CAAA;IACJ,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,EAAE,kBAAkB,CAAA;IACtD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,IAAI,QAAQ,CACjB,WAAW,EACX,0CAA0C,QAAQ,+BAA+B,IAAI,GAAG,EACxF,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,CAC7C,CAAA;IACH,CAAC;IACD,wGAAwG;IACxG,MAAM,IAAI,GACR,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG;QAC9B,CAAC,CAAC,sBAAsB;QACxB,CAAC,CAAC,MAAM,KAAK,GAAG;YACd,CAAC,CAAC,kBAAkB;YACpB,CAAC,CAAC,MAAM,IAAI,GAAG;gBACb,CAAC,CAAC,sBAAsB;gBACxB,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;oBACvB,CAAC,CAAC,WAAW;oBACb,CAAC,CAAC,MAAM,KAAK,GAAG;wBACd,CAAC,CAAC,kBAAkB;wBACpB,CAAC,CAAC,gBAAgB,CAAA;IAC9B,MAAM,OAAO,GACX,IAAI,KAAK,sBAAsB,CAAC,CAAC,CAAC,2CAA2C,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,KAAK,IAAI,EAAE,CAAA;IAC7G,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;AAC7C,CAAC,CAAA"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Hands a link to the system's own opener. Best effort: a server has no browser, so the caller
3
+ * prints the link as well and never depends on this.
4
+ */
5
+ export declare const openInBrowser: (url: string, platform?: NodeJS.Platform) => boolean;
6
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,aAAa,QAAS,MAAM,aAAY,MAAM,CAAC,QAAQ,KAAsB,OAWzF,CAAA"}
@@ -0,0 +1,18 @@
1
+ import { spawn } from "node:child_process";
2
+ /**
3
+ * Hands a link to the system's own opener. Best effort: a server has no browser, so the caller
4
+ * prints the link as well and never depends on this.
5
+ */
6
+ export const openInBrowser = (url, platform = process.platform) => {
7
+ const [command, ...args] = platform === "darwin" ? ["open", url] : platform === "win32" ? ["cmd", "/c", "start", "", url] : ["xdg-open", url];
8
+ try {
9
+ const child = spawn(command ?? "xdg-open", args, { detached: true, stdio: "ignore" });
10
+ child.on("error", () => { });
11
+ child.unref();
12
+ return true;
13
+ }
14
+ catch {
15
+ return false;
16
+ }
17
+ };
18
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAE1C;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAW,EAAE,QAAQ,GAAoB,OAAO,CAAC,QAAQ,EAAW,EAAE;IAClG,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GACtB,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,GAAG,CAAC,CAAA;IACpH,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,IAAI,UAAU,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAA;QACrF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAC3B,KAAK,CAAC,KAAK,EAAE,CAAA;QACb,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare const telegramBotApiCommand: () => Command;
3
+ //# sourceMappingURL=bot-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bot-api.d.ts","sourceRoot":"","sources":["../../src/commands/bot-api.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAiBxC,eAAO,MAAM,qBAAqB,QAAO,OAyGrC,CAAA"}