@xbibzlibrary/telebibz 0.1.19 → 0.3.1
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/CHANGELOG.md +42 -8
- package/CONTRIBUTING.md +2 -2
- package/README.id.md +44 -5
- package/README.md +45 -6
- package/README.zh-CN.md +44 -5
- package/RELEASE_AUTOMATION.md +17 -5
- package/bin/telebibz.mjs +1 -1
- package/dist/src/api/client.d.ts +3 -1
- package/dist/src/api/client.d.ts.map +1 -1
- package/dist/src/api/client.js +3 -1
- package/dist/src/api/client.js.map +1 -1
- package/dist/src/api/transport.d.ts +18 -1
- package/dist/src/api/transport.d.ts.map +1 -1
- package/dist/src/api/transport.js +26 -2
- package/dist/src/api/transport.js.map +1 -1
- package/dist/src/branding/terminal.d.ts +62 -0
- package/dist/src/branding/terminal.d.ts.map +1 -1
- package/dist/src/branding/terminal.js +258 -0
- package/dist/src/branding/terminal.js.map +1 -1
- package/dist/src/broadcast/broadcast.d.ts +50 -0
- package/dist/src/broadcast/broadcast.d.ts.map +1 -0
- package/dist/src/broadcast/broadcast.js +56 -0
- package/dist/src/broadcast/broadcast.js.map +1 -0
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +7 -3
- package/dist/src/cli.js.map +1 -1
- package/dist/src/context/context.d.ts +24 -1
- package/dist/src/context/context.d.ts.map +1 -1
- package/dist/src/context/context.js +102 -8
- package/dist/src/context/context.js.map +1 -1
- package/dist/src/core/bot.d.ts +61 -2
- package/dist/src/core/bot.d.ts.map +1 -1
- package/dist/src/core/bot.js +180 -31
- package/dist/src/core/bot.js.map +1 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/keyboard/index.d.ts +12 -0
- package/dist/src/keyboard/index.d.ts.map +1 -1
- package/dist/src/keyboard/index.js +13 -1
- package/dist/src/keyboard/index.js.map +1 -1
- package/dist/src/observability/logger.d.ts +28 -1
- package/dist/src/observability/logger.d.ts.map +1 -1
- package/dist/src/observability/logger.js +110 -0
- package/dist/src/observability/logger.js.map +1 -1
- package/dist/src/plugins/plugin.d.ts +2 -0
- package/dist/src/plugins/plugin.d.ts.map +1 -1
- package/dist/src/plugins/plugin.js +11 -4
- package/dist/src/plugins/plugin.js.map +1 -1
- package/dist/src/router/router.d.ts +19 -0
- package/dist/src/router/router.d.ts.map +1 -1
- package/dist/src/router/router.js +125 -23
- package/dist/src/router/router.js.map +1 -1
- package/dist/src/state/forms.d.ts +0 -1
- package/dist/src/state/forms.d.ts.map +1 -1
- package/dist/src/state/forms.js +27 -24
- package/dist/src/state/forms.js.map +1 -1
- package/dist/src/storage/storage.d.ts +10 -0
- package/dist/src/storage/storage.d.ts.map +1 -1
- package/dist/src/storage/storage.js +20 -2
- package/dist/src/storage/storage.js.map +1 -1
- package/dist/src/utils/concurrency.d.ts +25 -0
- package/dist/src/utils/concurrency.d.ts.map +1 -0
- package/dist/src/utils/concurrency.js +52 -0
- package/dist/src/utils/concurrency.js.map +1 -0
- package/dist/src/utils/text.d.ts +22 -0
- package/dist/src/utils/text.d.ts.map +1 -1
- package/dist/src/utils/text.js +0 -0
- package/dist/src/utils/text.js.map +1 -1
- package/dist/src/webhook/handler.d.ts +3 -0
- package/dist/src/webhook/handler.d.ts.map +1 -1
- package/dist/src/webhook/handler.js +85 -0
- package/dist/src/webhook/handler.js.map +1 -1
- package/dist-cjs/src/api/client.js +3 -1
- package/dist-cjs/src/api/transport.js +26 -2
- package/dist-cjs/src/branding/terminal.js +264 -1
- package/dist-cjs/src/broadcast/broadcast.js +58 -0
- package/dist-cjs/src/cli.js +7 -3
- package/dist-cjs/src/context/context.js +102 -8
- package/dist-cjs/src/core/bot.js +178 -29
- package/dist-cjs/src/index.js +2 -0
- package/dist-cjs/src/keyboard/index.js +13 -1
- package/dist-cjs/src/observability/logger.js +113 -1
- package/dist-cjs/src/plugins/plugin.js +11 -4
- package/dist-cjs/src/router/router.js +126 -24
- package/dist-cjs/src/state/forms.js +27 -24
- package/dist-cjs/src/storage/storage.js +20 -2
- package/dist-cjs/src/utils/concurrency.js +57 -0
- package/dist-cjs/src/utils/text.js +0 -0
- package/dist-cjs/src/webhook/handler.js +86 -0
- package/docs/API.id.md +120 -4
- package/docs/API.md +122 -4
- package/docs/API.zh-CN.md +119 -3
- package/package.json +3 -3
package/docs/API.md
CHANGED
|
@@ -67,11 +67,13 @@ type BotStatus =
|
|
|
67
67
|
| `transportOptions` | `Omit<FetchTransportOptions, "baseUrl">` | `{}` | Timeout, retry, backoff, jitter, headers, and fetch implementation. |
|
|
68
68
|
| `session` | `Storage<string, S>` | new storage | Session storage keyed by chat/user; any storage adapter may be used. |
|
|
69
69
|
| `services` | `Record<string, unknown>` | `{}` | Dependencies/services available via `ctx.services`. |
|
|
70
|
+
| `branding` | `boolean` | `true` | Terminal startup experience: typing effect, glass progress bar, animated rainbow "Tele Bibz" banner, and human-readable update lines. Only renders on an interactive TTY. |
|
|
70
71
|
| `polling.timeout` | `number` | `30` | Long-poll timeout in seconds for `getUpdates`. |
|
|
71
72
|
| `polling.limit` | `number` | `100` | Maximum number of updates per polling request. |
|
|
72
73
|
| `polling.allowedUpdates` | `string[]` | `[]` | Telegram update filters. |
|
|
73
74
|
| `polling.retryDelayMs` | `number` | `500` | Initial delay when polling fails. |
|
|
74
75
|
| `polling.maxRetryDelayMs` | `number` | `30000` | Maximum reconnect delay. |
|
|
76
|
+
| `updates.concurrency` | `number` | `Infinity` | Cap on how many updates are processed at the same time. Updates always run in parallel across chats and stay ordered within a single chat, so bursts of 1000+ messages are handled at once. |
|
|
75
77
|
|
|
76
78
|
### Constructor `Bot`
|
|
77
79
|
|
|
@@ -139,6 +141,30 @@ onRegex(expression: RegExp, handler: Middleware<Context<S>>): this
|
|
|
139
141
|
|
|
140
142
|
Handles message text using a `RegExp`. Route parameters are not automatically extracted into `ctx.params`; use a predicate or custom middleware if extraction is needed.
|
|
141
143
|
|
|
144
|
+
### `bot.on(filter, handler)`
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
on(filter: UpdateFilter | UpdateFilter[], handler: Middleware<Context<S>>): this
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Registers a handler for update types, optionally narrowed by a payload field. Examples: `"message"`, `"message:text"`, `"message:photo"`, `"edited_message"`, `"channel_post"`, `"callback_query"`, `"callback_query:data"`, `"inline_query"`, `"chat_member"`, `"message_reaction"`, or an array such as `["message:text", "callback_query:data"]`. Invalid update types throw a `TypeError` at registration time.
|
|
151
|
+
|
|
152
|
+
### `bot.hears(trigger, handler)`
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
hears(trigger: string | RegExp, handler: Middleware<Context<S>>): this
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Handles exact message text (string) or message text matching a `RegExp`.
|
|
159
|
+
|
|
160
|
+
### `bot.catch(handler)`
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
catch(handler: (error: unknown, ctx: Context<S>) => void | Promise<void>): this
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Registers the error boundary for update handlers. When set, a handler failure is logged, emitted as `update:error`/`bot:error`, and passed to this handler instead of rejecting `handleUpdate()` — webhook requests answer `200` and polling continues. Without a boundary, the error is rethrown.
|
|
167
|
+
|
|
142
168
|
### `bot.usePlugin(plugin)`
|
|
143
169
|
|
|
144
170
|
```ts
|
|
@@ -193,7 +219,7 @@ launch(options?: {
|
|
|
193
219
|
}): Promise<void>
|
|
194
220
|
```
|
|
195
221
|
|
|
196
|
-
Runs the bot in polling mode. On start, the lifecycle moves through `starting` to `running`, then the `getUpdates()` loop processes each
|
|
222
|
+
Runs the bot in polling mode. On start, the lifecycle moves through `starting` to `running`, then the `getUpdates()` loop processes each batch of updates concurrently: updates for different chats run in parallel while updates for the same chat keep their arrival order. Polling failures emit `polling:reconnect` and use exponential backoff.
|
|
197
223
|
|
|
198
224
|
Modes other than `"polling"` throw an error and suggest using `createWebhookHandler()` for webhooks.
|
|
199
225
|
|
|
@@ -270,8 +296,54 @@ handleUpdate(update: Update): Promise<void>
|
|
|
270
296
|
|
|
271
297
|
Processes a single update manually. The method determines the session key from `chat.id` and `from.id`, creates a `Context`, emits `update` and `message` events, runs middleware then the router, and saves the session after the pipeline completes.
|
|
272
298
|
|
|
299
|
+
Updates for different chats are processed in parallel; updates for the same chat are serialized in arrival order, so sessions, wizards, and conversations never interleave and session writes are never lost. A burst of concurrent updates triggers exactly one `getMe` initialization.
|
|
300
|
+
|
|
273
301
|
Pipeline errors set the bot status to `error`, emit `bot:error`, and then rethrow the error.
|
|
274
302
|
|
|
303
|
+
### `bot.handleUpdates(updates)`
|
|
304
|
+
|
|
305
|
+
```ts
|
|
306
|
+
handleUpdates(updates: readonly Update[]): Promise<void>
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Handles a whole batch of updates at once: every chat in the batch is processed immediately — parallel across chats, ordered per chat — so a burst of 1000 messages is never stuck behind one slow handler. Individual handler failures are logged, emitted as `update:error`, and passed to the `catch()` error boundary; they never reject this promise. The polling loop uses this method for every `getUpdates` batch.
|
|
310
|
+
|
|
311
|
+
### `bot.broadcast(chatIds, send, options?)`
|
|
312
|
+
|
|
313
|
+
```ts
|
|
314
|
+
broadcast(
|
|
315
|
+
chatIds: readonly ChatId[],
|
|
316
|
+
send: (chatId: ChatId) => Promise<unknown>,
|
|
317
|
+
options?: BroadcastOptions,
|
|
318
|
+
): Promise<BroadcastReport>
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
Sends to many chats in parallel — built for broadcasts to 1000+ users. There is no proactive cooldown: every chat is attempted at once (up to `options.concurrency`, default `Infinity`). When Telegram answers 429, the send is retried automatically after exactly the `retry_after` delay Telegram ordered (up to `options.maxAttempts`, default `10`), so bursts deliver completely instead of failing. Non-retryable errors (for example, a chat the bot cannot message) are recorded per chat in the returned report.
|
|
322
|
+
|
|
323
|
+
```ts
|
|
324
|
+
const report = await bot.broadcast(
|
|
325
|
+
subscriberIds,
|
|
326
|
+
(chatId) => bot.api.methods.sendMessage({ chat_id: chatId, text: "Newsletter #42" }),
|
|
327
|
+
{ onProgress: (progress) => console.log(`${progress.delivered}/${progress.total} delivered`) },
|
|
328
|
+
);
|
|
329
|
+
console.log(`Delivered ${report.delivered} of ${report.total} in ${report.durationMs}ms`);
|
|
330
|
+
for (const failure of report.failures) console.warn(`Failed: ${failure.chatId} — ${failure.error}`);
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
#### `BroadcastOptions` and `BroadcastReport`
|
|
334
|
+
|
|
335
|
+
| Property | Type | Default | Description |
|
|
336
|
+
|---|---|---:|---|
|
|
337
|
+
| `BroadcastOptions.concurrency` | `number` | `Infinity` | How many chats are messaged at the same time. |
|
|
338
|
+
| `BroadcastOptions.maxAttempts` | `number` | `10` | Attempts per chat when Telegram answers 429. |
|
|
339
|
+
| `BroadcastOptions.onProgress` | `(progress: BroadcastProgress) => void` | — | Called after each chat settles. |
|
|
340
|
+
| `BroadcastOptions.signal` | `AbortSignal` | — | Aborts pending sends; delivered messages stay delivered. |
|
|
341
|
+
| `BroadcastReport.total` | `number` | — | Chats in the run. |
|
|
342
|
+
| `BroadcastReport.delivered` | `number` | — | Chats that received the message. |
|
|
343
|
+
| `BroadcastReport.failed` | `number` | — | Chats that did not. |
|
|
344
|
+
| `BroadcastReport.durationMs` | `number` | — | Wall-clock duration of the run. |
|
|
345
|
+
| `BroadcastReport.failures` | `BroadcastFailure[]` | — | Per-chat `{ chatId, attempts, error, errorKind }` records. |
|
|
346
|
+
|
|
275
347
|
### Minimal bot example
|
|
276
348
|
|
|
277
349
|
```ts
|
|
@@ -409,6 +481,7 @@ interface Transport {
|
|
|
409
481
|
| `maxBackoffMs` | `8000` | Transport delay cap. |
|
|
410
482
|
| `jitter` | `0.2` | Random variation ±20% of the exponential delay. |
|
|
411
483
|
| `headers` | `{}` | Additional headers. |
|
|
484
|
+
| `floodGate` | `true` | When Telegram answers 429, pauses NEW requests until the `retry_after` window Telegram ordered has elapsed. Never a proactive cooldown — the only waiting done is what Telegram itself demands. |
|
|
412
485
|
|
|
413
486
|
### `new FetchTransport(options?)`
|
|
414
487
|
|
|
@@ -650,6 +723,23 @@ new Context<S>(options: ContextOptions<S>): Context<S>
|
|
|
650
723
|
| `send` | `send(text, extra?): Promise<Message>` | Sends a message to the update chat without a reply reference. |
|
|
651
724
|
| `edit` | `edit(text, extra?): Promise<Message \| true>` | Edits the update message using `editMessageText`. |
|
|
652
725
|
| `delete` | `delete(): Promise<true>` | Deletes the update message. |
|
|
726
|
+
| `replyWithHTML` | `replyWithHTML(text, extra?): Promise<Message>` | Replies with `parse_mode: "HTML"`. |
|
|
727
|
+
| `replyWithMarkdown` | `replyWithMarkdown(text, extra?): Promise<Message>` | Replies with `parse_mode: "MarkdownV2"`. |
|
|
728
|
+
| `replyWithPhoto` | `replyWithPhoto(photo, extra?): Promise<Message>` | Sends `sendPhoto` with automatic quote-reply. |
|
|
729
|
+
| `replyWithDocument` | `replyWithDocument(document, extra?): Promise<Message>` | Sends `sendDocument` with automatic quote-reply. |
|
|
730
|
+
| `replyWithAudio` | `replyWithAudio(audio, extra?): Promise<Message>` | Sends `sendAudio` with automatic quote-reply. |
|
|
731
|
+
| `replyWithVideo` | `replyWithVideo(video, extra?): Promise<Message>` | Sends `sendVideo` with automatic quote-reply. |
|
|
732
|
+
| `replyWithVoice` | `replyWithVoice(voice, extra?): Promise<Message>` | Sends `sendVoice` with automatic quote-reply. |
|
|
733
|
+
| `replyWithAnimation` | `replyWithAnimation(animation, extra?): Promise<Message>` | Sends `sendAnimation` with automatic quote-reply. |
|
|
734
|
+
| `replyWithVideoNote` | `replyWithVideoNote(videoNote, extra?): Promise<Message>` | Sends `sendVideoNote` with automatic quote-reply. |
|
|
735
|
+
| `replyWithSticker` | `replyWithSticker(sticker, extra?): Promise<Message>` | Sends `sendSticker` with automatic quote-reply. |
|
|
736
|
+
| `replyWithMediaGroup` | `replyWithMediaGroup(media, extra?): Promise<Message[]>` | Sends an album via `sendMediaGroup` with automatic quote-reply. |
|
|
737
|
+
| `replyWithLocation` | `replyWithLocation(latitude, longitude, extra?): Promise<Message>` | Sends `sendLocation` with automatic quote-reply. |
|
|
738
|
+
| `replyWithVenue` | `replyWithVenue(latitude, longitude, title, address, extra?): Promise<Message>` | Sends `sendVenue` with automatic quote-reply. |
|
|
739
|
+
| `replyWithContact` | `replyWithContact(phoneNumber, firstName, extra?): Promise<Message>` | Sends `sendContact` with automatic quote-reply. |
|
|
740
|
+
| `replyWithPoll` | `replyWithPoll(question, options, extra?): Promise<Message>` | Sends `sendPoll` with automatic quote-reply. |
|
|
741
|
+
| `replyWithDice` | `replyWithDice(emoji?, extra?): Promise<Message>` | Sends `sendDice` with automatic quote-reply. |
|
|
742
|
+
| `sendChatAction` | `sendChatAction(action, extra?): Promise<true>` | Sends a chat action such as `typing`. |
|
|
653
743
|
| `copy` | `copy(fromChatId, messageId, extra?): Promise<unknown>` | Calls `copyMessage` to the context chat. |
|
|
654
744
|
| `forward` | `forward(fromChatId, messageId, extra?): Promise<Message>` | Calls `forwardMessage` to the context chat. |
|
|
655
745
|
| `pin` | `pin(messageId?, extra?): Promise<true>` | Calls `pinChatMessage`; defaults to the context message id. |
|
|
@@ -662,7 +752,7 @@ new Context<S>(options: ContextOptions<S>): Context<S>
|
|
|
662
752
|
| `getFile` | `getFile(fileId): Promise<unknown>` | Fetches a file by id. |
|
|
663
753
|
| `withReplyMarkup` | `withReplyMarkup(markup): this` | Stores markup in `ctx.state.reply_markup` and returns the context. This method does not automatically send a message. |
|
|
664
754
|
|
|
665
|
-
`reply`, `send`, `getChat`, and some other helpers throw an error when the update does not have the required chat. `edit` and `delete` require both chat and message.
|
|
755
|
+
All `replyWith*` senders accept the native Telegram parameters as `extra` and automatically quote the incoming message. Passing `reply_parameters` in `extra` merges with the automatic `message_id` instead of replacing it. `reply`, `send`, `getChat`, and some other helpers throw an error when the update does not have the required chat. `edit` and `delete` require both chat and message.
|
|
666
756
|
|
|
667
757
|
---
|
|
668
758
|
|
|
@@ -973,6 +1063,20 @@ new Scheduler(): Scheduler
|
|
|
973
1063
|
|
|
974
1064
|
The full cron format is not supported by the built-in scheduler. Expressions other than `*/N` throw an `Error`.
|
|
975
1065
|
|
|
1066
|
+
### `Limiter` and `mapWithConcurrency`
|
|
1067
|
+
|
|
1068
|
+
```ts
|
|
1069
|
+
new Limiter(limit: number): Limiter
|
|
1070
|
+
|
|
1071
|
+
mapWithConcurrency<T, R>(
|
|
1072
|
+
items: readonly T[],
|
|
1073
|
+
limit: number,
|
|
1074
|
+
worker: (item: T, index: number) => Promise<R>,
|
|
1075
|
+
): Promise<R[]>
|
|
1076
|
+
```
|
|
1077
|
+
|
|
1078
|
+
`Limiter` is a promise semaphore: tasks run immediately while a slot is free and queue FIFO beyond that. `limit` accepts any positive integer or `Infinity` (fully parallel — the library default). `mapWithConcurrency` maps items through an async worker with the same cap while preserving result order; results and errors behave like `Promise.all` mapped arrays. These primitives add no delays of their own — they only bound how many tasks run at the same time. `Limiter` exposes `activeCount` and `queuedCount` for observability.
|
|
1079
|
+
|
|
976
1080
|
## 9. Plugins and services
|
|
977
1081
|
|
|
978
1082
|
### `Plugin<Context>`
|
|
@@ -1281,11 +1385,23 @@ new Menu(id: string): Menu
|
|
|
1281
1385
|
|
|
1282
1386
|
## 12. Terminal Logging
|
|
1283
1387
|
|
|
1284
|
-
|
|
1388
|
+
When stdout is an interactive TTY, every `bot.start()` / `bot.launch()` plays a startup sequence: a typing effect for `Installing Dependencies......`, a glass progress bar with a sweeping highlight, and the animated rainbow ASCII banner `Tele Bibz` (figlet `Speed` font) that keeps flowing until the bot connects, then freezes with `✓ Connected as @<username>`.
|
|
1389
|
+
|
|
1390
|
+
Every update the bot handles is logged on a human-readable line:
|
|
1391
|
+
|
|
1392
|
+
```text
|
|
1393
|
+
[ => ] Message From 123456789 John Doe 29/08/2026 15:04:05
|
|
1394
|
+
↳ Text: /start
|
|
1395
|
+
[ => ] Callback From 123456789 John Doe 29/08/2026 15:04:07
|
|
1396
|
+
↳ Data: menu:open
|
|
1397
|
+
```
|
|
1398
|
+
|
|
1399
|
+
Message and command text is truncated to 50 characters; callback button data is shown in full. Errors are printed in red and include the full stack. Pass `branding: false` to `Bot` to disable the startup sequence, and set `logger.format: "json"` for machine ingestion — in that mode incoming updates are emitted as structured `update.received` entries. Non-interactive stdout (pipes, Docker, CI) automatically falls back to plain, uncolored output without animations.
|
|
1285
1400
|
|
|
1286
1401
|
```ts
|
|
1287
1402
|
const bot = new Bot({
|
|
1288
1403
|
token: process.env.TELEGRAM_BOT_TOKEN!,
|
|
1404
|
+
branding: false, // turn off the startup sequence
|
|
1289
1405
|
logger: {
|
|
1290
1406
|
level: "debug",
|
|
1291
1407
|
format: "pretty",
|
|
@@ -1295,6 +1411,8 @@ const bot = new Bot({
|
|
|
1295
1411
|
});
|
|
1296
1412
|
```
|
|
1297
1413
|
|
|
1414
|
+
Additional branding helpers exported for applications: `runStartupSequence()`, `startTeleBibzBanner()`, `printTeleBibzBanner()`, `paintRainbow()`, and `printStatusLine()`.
|
|
1415
|
+
|
|
1298
1416
|
---
|
|
1299
1417
|
|
|
1300
1418
|
## 13. Text Utilities
|
|
@@ -1723,7 +1841,7 @@ The package vendors MIT-licensed Telegram declarations and exposes them as type-
|
|
|
1723
1841
|
---
|
|
1724
1842
|
## 19. Compatibility and limitations to be aware of
|
|
1725
1843
|
|
|
1726
|
-
The library targets Node.js `>=
|
|
1844
|
+
The library targets Node.js `>=22`, uses ESM as the primary module, and also provides a CommonJS build. Webhooks require a runtime that provides Web `Request`, `Response`, `Headers`, `FormData`, `Blob`, and `AbortController`; modern Node.js provides these natively.
|
|
1727
1845
|
|
|
1728
1846
|
The list of generated API methods and the API method map are not the same. `TelegramMethodName` includes 184 runtime names, but `TelegramMethodMap` only has specially-typed parameters/results for the subset listed in the API client section. For other methods, use `api.raw()` or add a type declaration on the application side.
|
|
1729
1847
|
|
package/docs/API.zh-CN.md
CHANGED
|
@@ -68,11 +68,13 @@ type BotStatus =
|
|
|
68
68
|
| `transportOptions` | `Omit<FetchTransportOptions, "baseUrl">` | `{}` | 超时、重试、退避、jitter、headers 和 fetch 实现。 |
|
|
69
69
|
| `session` | `Storage<string, S>` | 新的存储 | 基于 chat/user key 的会话存储,可使用持久化适配器。 |
|
|
70
70
|
| `services` | `Record<string, unknown>` | `{}` | 通过 `ctx.services` 可用的依赖/服务。 |
|
|
71
|
+
| `branding` | `boolean` | `true` | 终端启动体验:打字效果、glass 进度条、动画彩虹 `Tele Bibz` 横幅以及易读的 update 日志行。仅在交互式 TTY 上渲染。 |
|
|
71
72
|
| `polling.timeout` | `number` | `30` | 用于 `getUpdates` 的长轮询超时(秒)。 |
|
|
72
73
|
| `polling.limit` | `number` | `100` | 每次轮询请求的最大 update 数量。 |
|
|
73
74
|
| `polling.allowedUpdates` | `string[]` | `[]` | Telegram 更新过滤器。 |
|
|
74
75
|
| `polling.retryDelayMs` | `number` | `500` | 轮询失败时的初始延迟(毫秒)。 |
|
|
75
76
|
| `polling.maxRetryDelayMs` | `number` | `30000` | 重连延迟的最大值(毫秒)。 |
|
|
77
|
+
| `updates.concurrency` | `number` | `Infinity` | 同时处理的 update 数量上限。不同 chat 的 update 始终并行,同一 chat 内保持顺序,因此 1000+ 条消息的突发可一次性处理。 |
|
|
76
78
|
|
|
77
79
|
### `Bot` constructor
|
|
78
80
|
|
|
@@ -140,6 +142,30 @@ onRegex(expression: RegExp, handler: Middleware<Context<S>>): this
|
|
|
140
142
|
|
|
141
143
|
使用 `RegExp` 处理消息文本。路由参数不会自动提取到 `ctx.params`;如需提取请使用 predicate 或自定义 middleware。
|
|
142
144
|
|
|
145
|
+
### `bot.on(filter, handler)`
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
on(filter: UpdateFilter | UpdateFilter[], handler: Middleware<Context<S>>): this
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
按更新类型注册处理器,并可用 payload 字段收窄。示例:`"message"`、`"message:text"`、`"message:photo"`、`"edited_message"`、`"channel_post"`、`"callback_query"`、`"callback_query:data"`、`"inline_query"`、`"chat_member"`、`"message_reaction"`,或数组如 `["message:text", "callback_query:data"]`。无效的更新类型会在注册时抛出 `TypeError`。
|
|
152
|
+
|
|
153
|
+
### `bot.hears(trigger, handler)`
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
hears(trigger: string | RegExp, handler: Middleware<Context<S>>): this
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
处理完全匹配的文本(string)或匹配 `RegExp` 的消息文本。
|
|
160
|
+
|
|
161
|
+
### `bot.catch(handler)`
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
catch(handler: (error: unknown, ctx: Context<S>) => void | Promise<void>): this
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
注册更新处理器的错误边界。设置后,处理器失败会被记录、以 `update:error`/`bot:error` 事件发出,并转发给该 handler,而不是让 `handleUpdate()` 拒绝 —— webhook 返回 `200`,轮询继续。未设置边界时错误会被重新抛出。
|
|
168
|
+
|
|
143
169
|
### `bot.usePlugin(plugin)`
|
|
144
170
|
|
|
145
171
|
```ts
|
|
@@ -176,7 +202,7 @@ launch(options?: {
|
|
|
176
202
|
}): Promise<void>
|
|
177
203
|
```
|
|
178
204
|
|
|
179
|
-
以 polling 模式运行 bot。启动时生命周期依次变为 `starting` 然后 `running`,之后 `getUpdates()`
|
|
205
|
+
以 polling 模式运行 bot。启动时生命周期依次变为 `starting` 然后 `running`,之后 `getUpdates()` 循环并发处理每一批 update:不同 chat 的 update 并行执行,同一 chat 的 update 保持到达顺序。轮询失败会触发 `polling:reconnect` 并使用指数退避。
|
|
180
206
|
|
|
181
207
|
除 `"polling"` 外的模式会抛出错误,并建议对 webhook 使用 `createWebhookHandler()`。
|
|
182
208
|
|
|
@@ -253,8 +279,54 @@ handleUpdate(update: Update): Promise<void>
|
|
|
253
279
|
|
|
254
280
|
手动处理单个 update。该方法根据 `chat.id` 和 `from.id` 确定会话 key,创建 `Context`,触发 `update` 和 `message` 事件,执行 middleware 然后路由器,并在流水线完成后保存会话。
|
|
255
281
|
|
|
282
|
+
不同 chat 的 update 并行处理;同一 chat 的 update 按到达顺序串行处理,因此会话、wizard 和 conversation 永远不会交错,会话写入也不会丢失。并发的 update 突发只会触发一次 `getMe` 初始化。
|
|
283
|
+
|
|
256
284
|
流水线错误会将 bot 状态置为 `error`,触发 `bot:error`,然后重新抛出错误。
|
|
257
285
|
|
|
286
|
+
### `bot.handleUpdates(updates)`
|
|
287
|
+
|
|
288
|
+
```ts
|
|
289
|
+
handleUpdates(updates: readonly Update[]): Promise<void>
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
一次性处理整批 update:批次中的每个 chat 立即处理——跨 chat 并行、同一 chat 内按序——因此 1000 条消息的突发绝不会卡在某个慢速 handler 后面。单个 handler 的失败会记录日志、以 `update:error` 触发事件并交给 `catch()` 错误边界;它们永远不会让该 promise 被 reject。轮询循环对每个 `getUpdates` 批次都使用此方法。
|
|
293
|
+
|
|
294
|
+
### `bot.broadcast(chatIds, send, options?)`
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
broadcast(
|
|
298
|
+
chatIds: readonly ChatId[],
|
|
299
|
+
send: (chatId: ChatId) => Promise<unknown>,
|
|
300
|
+
options?: BroadcastOptions,
|
|
301
|
+
): Promise<BroadcastReport>
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
并行向大量 chat 发送消息——专为向 1000+ 用户广播而设计。没有主动冷却:所有 chat(至多 `options.concurrency`,默认 `Infinity`)同时尝试发送。当 Telegram 返回 429 时,会严格按照 Telegram 指定的 `retry_after` 延迟自动重试(至多 `options.maxAttempts` 次,默认 `10`),因此突发流量会完整送达而不是失败。不可重试的错误(例如 bot 无法发送的 chat)会按 chat 记录在返回的报告中。
|
|
305
|
+
|
|
306
|
+
```ts
|
|
307
|
+
const report = await bot.broadcast(
|
|
308
|
+
subscriberIds,
|
|
309
|
+
(chatId) => bot.api.methods.sendMessage({ chat_id: chatId, text: "Newsletter #42" }),
|
|
310
|
+
{ onProgress: (progress) => console.log(`${progress.delivered}/${progress.total} delivered`) },
|
|
311
|
+
);
|
|
312
|
+
console.log(`Delivered ${report.delivered} of ${report.total} in ${report.durationMs}ms`);
|
|
313
|
+
for (const failure of report.failures) console.warn(`Failed: ${failure.chatId} — ${failure.error}`);
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
#### `BroadcastOptions` 和 `BroadcastReport`
|
|
317
|
+
|
|
318
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
319
|
+
|---|---|---:|---|
|
|
320
|
+
| `BroadcastOptions.concurrency` | `number` | `Infinity` | 同时向多少个 chat 发送消息。 |
|
|
321
|
+
| `BroadcastOptions.maxAttempts` | `number` | `10` | Telegram 返回 429 时每个 chat 的尝试次数。 |
|
|
322
|
+
| `BroadcastOptions.onProgress` | `(progress: BroadcastProgress) => void` | — | 每个 chat 结束后调用。 |
|
|
323
|
+
| `BroadcastOptions.signal` | `AbortSignal` | — | 中止待发送的消息;已送达的消息保持送达。 |
|
|
324
|
+
| `BroadcastReport.total` | `number` | — | 本次广播的 chat 总数。 |
|
|
325
|
+
| `BroadcastReport.delivered` | `number` | — | 成功收到消息的 chat 数。 |
|
|
326
|
+
| `BroadcastReport.failed` | `number` | — | 未收到消息的 chat 数。 |
|
|
327
|
+
| `BroadcastReport.durationMs` | `number` | — | 本次广播的实际耗时(毫秒)。 |
|
|
328
|
+
| `BroadcastReport.failures` | `BroadcastFailure[]` | — | 按 chat 记录的 `{ chatId, attempts, error, errorKind }`。 |
|
|
329
|
+
|
|
258
330
|
### 最小 bot 示例
|
|
259
331
|
|
|
260
332
|
```ts
|
|
@@ -391,6 +463,7 @@ interface Transport {
|
|
|
391
463
|
| `backoffMs` | `250` | 初始指数退避延迟(毫秒)。 |
|
|
392
464
|
| `maxBackoffMs` | `8000` | 传输延迟上限(毫秒)。 |
|
|
393
465
|
| `jitter` | `0.2` | 对指数延迟的随机抖动,范围为 ±20%。 |
|
|
466
|
+
| `floodGate` | `true` | 当 Telegram 返回 429 时,暂停新的请求直到 Telegram 指定的 `retry_after` 窗口结束。这不是主动冷却——唯一的等待就是 Telegram 自己要求的等待。 |
|
|
394
467
|
| `headers` | `{}` | 额外的请求头。 |
|
|
395
468
|
|
|
396
469
|
### `new FetchTransport(options?)`
|
|
@@ -633,6 +706,22 @@ new Context<S>(options: ContextOptions<S>): Context<S>
|
|
|
633
706
|
| `send` | `send(text, extra?): Promise<Message>` | 向更新的聊天发送消息,不带回复引用. |
|
|
634
707
|
| `edit` | `edit(text, extra?): Promise<Message \| true>` | 使用 `editMessageText` 编辑更新的消息. |
|
|
635
708
|
| `delete` | `delete(): Promise<true>` | 删除更新的消息. |
|
|
709
|
+
| `replyWithHTML` | `replyWithHTML(text, extra?): Promise<Message>` | 以 `parse_mode: "HTML"` 回复. |
|
|
710
|
+
| `replyWithMarkdown` | `replyWithMarkdown(text, extra?): Promise<Message>` | 以 `parse_mode: "MarkdownV2"` 回复. |
|
|
711
|
+
| `replyWithPhoto` | `replyWithPhoto(photo, extra?): Promise<Message>` | 发送 `sendPhoto`,自动引用回复. |
|
|
712
|
+
| `replyWithDocument` | `replyWithDocument(document, extra?): Promise<Message>` | 发送 `sendDocument`,自动引用回复. |
|
|
713
|
+
| `replyWithAudio` | `replyWithAudio(audio, extra?): Promise<Message>` | 发送 `sendAudio`,自动引用回复. |
|
|
714
|
+
| `replyWithVideo` | `replyWithVideo(video, extra?): Promise<Message>` | 发送 `sendVideo`,自动引用回复. |
|
|
715
|
+
| `replyWithVoice` | `replyWithVoice(voice, extra?): Promise<Message>` | 发送 `sendVoice`,自动引用回复. |
|
|
716
|
+
| `replyWithAnimation` | `replyWithAnimation(animation, extra?): Promise<Message>` | 发送 `sendAnimation`,自动引用回复. |
|
|
717
|
+
| `replyWithVideoNote` | `replyWithVideoNote(videoNote, extra?): Promise<Message>` | 发送 `sendVideoNote`,自动引用回复. |
|
|
718
|
+
| `replyWithSticker` | `replyWithSticker(sticker, extra?): Promise<Message>` | 发送 `sendSticker`,自动引用回复. |
|
|
719
|
+
| `replyWithMediaGroup` | `replyWithMediaGroup(media, extra?): Promise<Message[]>` | 通过 `sendMediaGroup` 发送相册,自动引用回复. |
|
|
720
|
+
| `replyWithLocation` | `replyWithLocation(latitude, longitude, extra?): Promise<Message>` | 发送 `sendLocation`,自动引用回复. |
|
|
721
|
+
| `replyWithVenue` | `replyWithVenue(latitude, longitude, title, address, extra?): Promise<Message>` | 发送 `sendVenue`,自动引用回复. |
|
|
722
|
+
| `replyWithContact` | `replyWithContact(phoneNumber, firstName, extra?): Promise<Message>` | 发送 `sendContact`,自动引用回复. |
|
|
723
|
+
| `replyWithPoll` | `replyWithPoll(question, options, extra?): Promise<Message>` | 发送 `sendPoll`,自动引用回复. |
|
|
724
|
+
| `replyWithDice` | `replyWithDice(emoji?, extra?): Promise<Message>` | 发送 `sendDice`,自动引用回复. |
|
|
636
725
|
| `copy` | `copy(fromChatId, messageId, extra?): Promise<unknown>` | 向上下文聊天调用 `copyMessage`. |
|
|
637
726
|
| `forward` | `forward(fromChatId, messageId, extra?): Promise<Message>` | 向上下文聊天调用 `forwardMessage`. |
|
|
638
727
|
| `pin` | `pin(messageId?, extra?): Promise<true>` | 调用 `pinChatMessage`,默认消息 ID 来自上下文. |
|
|
@@ -948,6 +1037,20 @@ new Scheduler(): Scheduler
|
|
|
948
1037
|
|
|
949
1038
|
内置调度器不支持完整的 cron 格式。除 `*/N` 外的表达式会抛出 `Error`。
|
|
950
1039
|
|
|
1040
|
+
### `Limiter` 和 `mapWithConcurrency`
|
|
1041
|
+
|
|
1042
|
+
```ts
|
|
1043
|
+
new Limiter(limit: number): Limiter
|
|
1044
|
+
|
|
1045
|
+
mapWithConcurrency<T, R>(
|
|
1046
|
+
items: readonly T[],
|
|
1047
|
+
limit: number,
|
|
1048
|
+
worker: (item: T, index: number) => Promise<R>,
|
|
1049
|
+
): Promise<R[]>
|
|
1050
|
+
```
|
|
1051
|
+
|
|
1052
|
+
`Limiter` 是一个 promise 信号量:有空闲槽位时任务立即执行,超出后按 FIFO 排队。`limit` 接受任意正整数或 `Infinity`(完全并行——即本库的默认值)。`mapWithConcurrency` 以相同的并发上限让 item 通过 async worker 映射,同时保持结果顺序。这些原语自身不会添加任何延迟——它们只限制同时运行的任务数量。`Limiter` 暴露 `activeCount` 和 `queuedCount` 用于可观测性。
|
|
1053
|
+
|
|
951
1054
|
---
|
|
952
1055
|
|
|
953
1056
|
## 9. 插件与服务
|
|
@@ -1257,7 +1360,20 @@ new Menu(id: string): Menu
|
|
|
1257
1360
|
|
|
1258
1361
|
## 12. Terminal Logging
|
|
1259
1362
|
|
|
1260
|
-
|
|
1363
|
+
当 stdout 是交互式 TTY 时,每次 `bot.start()` / `bot.launch()` 都会播放启动序列:`Installing Dependencies......` 打字效果、带扫过高光的 glass 进度条,以及动画彩虹 ASCII 横幅 `Tele Bibz`(figlet `Speed` 字体)——持续流动直到 bot 连接成功,随后定格为 `✓ Connected as @<username>`。
|
|
1364
|
+
|
|
1365
|
+
bot 处理的每条 update 都会以易读的行格式记录:
|
|
1366
|
+
|
|
1367
|
+
```text
|
|
1368
|
+
[ => ] Message From 123456789 John Doe 29/08/2026 15:04:05
|
|
1369
|
+
↳ Text: /start
|
|
1370
|
+
[ => ] Callback From 123456789 John Doe 29/08/2026 15:04:07
|
|
1371
|
+
↳ Data: menu:open
|
|
1372
|
+
```
|
|
1373
|
+
|
|
1374
|
+
普通消息与命令文本截断为 50 个字符;回调按钮数据完整显示。错误以红色打印并附带完整堆栈。向 `Bot` 传入 `branding: false` 可关闭启动序列;设置 `logger.format: "json"` 时,进入的 update 会作为结构化 `update.received` entry 输出。非交互 stdout(管道、Docker、CI)自动回退为无动画的纯文本。
|
|
1375
|
+
|
|
1376
|
+
面向应用导出的附加 branding helper:`runStartupSequence()`、`startTeleBibzBanner()`、`printTeleBibzBanner()`、`paintRainbow()` 和 `printStatusLine()`。
|
|
1261
1377
|
|
|
1262
1378
|
## 13. 文本工具
|
|
1263
1379
|
|
|
@@ -1685,7 +1801,7 @@ Package 内置 MIT 许可的 Telegram declaration,并通过 type-only export
|
|
|
1685
1801
|
|
|
1686
1802
|
## 19. 兼容性和需要注意的限制
|
|
1687
1803
|
|
|
1688
|
-
|
|
1804
|
+
本库面向 Node.js `>=22`,使用 ESM 作为主要模块,并提供 CommonJS 构建。Webhook 需要运行时提供 Web `Request`、`Response`、`Headers`、`FormData`、`Blob` 和 `AbortController`;现代 Node.js 原生提供了这些。
|
|
1689
1805
|
|
|
1690
1806
|
API 生成的方法列表(generated method list)和 API 方法映射(API method map)并不相同。`TelegramMethodName` 包含 184 个运行时名称,但 `TelegramMethodMap` 仅对 API 客户端部分列出的子集提供了带类型的参数/结果。对于其他方法,使用 `api.raw()` 或在应用端添加类型声明。
|
|
1691
1807
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xbibzlibrary/telebibz",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "Telegram Bot framework for Node.js and TypeScript with a typed API client, routing, middleware, webhooks, keyboards, conversations, plugins, queues, and a polished terminal experience.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"telegram",
|
|
7
7
|
"telegram-bot",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"url": "https://github.com/XbibzOfficial777/telebibz/issues"
|
|
33
33
|
},
|
|
34
34
|
"engines": {
|
|
35
|
-
"node": ">=
|
|
35
|
+
"node": ">=22"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"generate": "node scripts/generate-api.mjs",
|