@xbibzlibrary/telebibz 3.1.2 → 3.1.4
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 +31 -0
- package/LICENSE +1 -1
- package/NOTICE.md +15 -8
- package/README.id.md +312 -43
- package/README.md +312 -43
- package/examples/08-rich-message.js +34 -0
- package/index.d.ts +303 -96
- package/index.js +8 -2
- package/lib/api.js +20 -6
- package/lib/composer.js +14 -2
- package/lib/context.js +83 -21
- package/lib/file.js +8 -1
- package/lib/inline-query.js +6 -1
- package/lib/logger.js +44 -14
- package/lib/ratelimit.js +16 -3
- package/lib/rich.js +175 -0
- package/lib/runner.js +14 -5
- package/lib/session.js +12 -4
- package/lib/telebibz.js +40 -24
- package/lib/telegram-methods.js +192 -0
- package/package.json +14 -10
- package/test/audit.test.js +355 -0
- package/test/types.test.ts +40 -0
- package/types/telegram-bot-api/LICENSE +21 -0
- package/types/telegram-bot-api/api.d.ts +22 -0
- package/types/telegram-bot-api/checklist.d.ts +72 -0
- package/types/telegram-bot-api/inline.d.ts +692 -0
- package/types/telegram-bot-api/langs.d.ts +193 -0
- package/types/telegram-bot-api/manage.d.ts +1153 -0
- package/types/telegram-bot-api/markup.d.ts +278 -0
- package/types/telegram-bot-api/message.d.ts +1557 -0
- package/types/telegram-bot-api/methods.d.ts +2860 -0
- package/types/telegram-bot-api/mod.d.ts +14 -0
- package/types/telegram-bot-api/passport.d.ts +163 -0
- package/types/telegram-bot-api/payment.d.ts +576 -0
- package/types/telegram-bot-api/rich.d.ts +1198 -0
- package/types/telegram-bot-api/settings.d.ts +120 -0
- package/types/telegram-bot-api/story.d.ts +89 -0
- package/types/telegram-bot-api/update.d.ts +86 -0
package/README.md
CHANGED
|
@@ -19,14 +19,14 @@ dependencies that are *actually used*, and an Indonesia-first community.
|
|
|
19
19
|
[](https://www.npmjs.com/package/@xbibzlibrary/telebibz)
|
|
20
20
|
[](https://www.npmjs.com/package/@xbibzlibrary/telebibz)
|
|
21
21
|
[](https://nodejs.org)
|
|
22
|
-
[](#-testing--live-proof)
|
|
23
|
+
[](#-analytics--statistics)
|
|
24
24
|
[](LICENSE)
|
|
25
25
|
[](https://github.com/XbibzOfficial777/telebibz)
|
|
26
26
|
|
|
27
27
|
<br>
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
`Xbibz Technology ID`
|
|
30
30
|
|
|
31
31
|
</div>
|
|
32
32
|
|
|
@@ -38,7 +38,7 @@ dependencies that are *actually used*, and an Indonesia-first community.
|
|
|
38
38
|
|---|---|---|
|
|
39
39
|
| ⚡ [Why telebibz?](#why) | 📊 [Feature matrix vs grammY](#matrix) | 📥 [Installation & requirements](#install) |
|
|
40
40
|
| 🚀 [Quick start](#quickstart) | 🧠 [How it works (architecture)](#architecture) | 📖 [Full documentation](#docs) |
|
|
41
|
-
| 🎛️ [Handlers & filters](#handlers) | 💬 [Context shortcuts](#context) |
|
|
41
|
+
| 🎛️ [Handlers & filters](#handlers) | 💬 [Context shortcuts](#context) | 🧱 [Rich Messages & Bot API 10.3](#rich-messages) |
|
|
42
42
|
| ️ [Interactive menus](#menus) | 🧙 [Wizard (forms + buttons + edit/delete)](#wizard) | ❓ [Inline mode](#inline) |
|
|
43
43
|
| 📣 [Broadcast](#broadcast) | 📎 [Files & media](#files) | 🛡️ [Reliability & rate limiting](#ratelimit) |
|
|
44
44
|
| 🗃️ [Sessions](#sessions) | 🇮🇩 [Human-readable errors](#errors) | 🕸️ [Webhooks & serverless](#webhook) |
|
|
@@ -66,6 +66,8 @@ dependencies that are *actually used*, and an Indonesia-first community.
|
|
|
66
66
|
| Feature | grammY | telebibz |
|
|
67
67
|
|---|:---:|:---:|
|
|
68
68
|
| Proxy API for **any method** (auto-generated) | ✅ | ✅ |
|
|
69
|
+
| **185 method-specific Bot API payload signatures** (`callApi`) | ✅ | ✅ |
|
|
70
|
+
| Rich Messages: blocks, entities, drafts, media, animated emoji | varies by API | ✅ built-in |
|
|
69
71
|
| ~60 typed shortcuts (sendMessage, banChatMember…) | ✅ | ✅ |
|
|
70
72
|
| Full Context (~70 shortcuts reply/edit/admin/react) | ✅ | ✅ |
|
|
71
73
|
| Business flavor (`business_connection_id` automatic) | plugin | ✅ built-in |
|
|
@@ -89,7 +91,7 @@ dependencies that are *actually used*, and an Indonesia-first community.
|
|
|
89
91
|
| Humanized errors + suggestions | ❌ | ✅ `humanize()` |
|
|
90
92
|
| Boot banner + debug logging | ❌ | ✅ (`DEBUG=telebibz*`) |
|
|
91
93
|
| HTTP(S) proxy for VPS | ⚠️ manual | ✅ `proxy` transport option |
|
|
92
|
-
| TypeScript | ✅ full |
|
|
94
|
+
| TypeScript | ✅ full | ✅ method-specific types for 185 Bot API methods |
|
|
93
95
|
| Documentation language | en | **🇬🇧 + 🇮🇩** |
|
|
94
96
|
|
|
95
97
|
<a id="install"></a>
|
|
@@ -137,13 +139,14 @@ BOT_TOKEN=123:abc node index.js
|
|
|
137
139
|
```
|
|
138
140
|
|
|
139
141
|
```
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
142
|
+
◆ DEVELOPER Xbibz Technology ID
|
|
143
|
+
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
144
|
+
┃ 🤖 TeleBibz ON ┃
|
|
145
|
+
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
146
|
+
┃ bot : @yourbot (id 123456) ┃
|
|
147
|
+
┃ mode : long-polling ┃
|
|
148
|
+
┃ library : telebibz 3.1.2 (Node.js) ┃
|
|
149
|
+
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
147
150
|
✔ waiting for updates… (Ctrl+C to stop)
|
|
148
151
|
```
|
|
149
152
|
|
|
@@ -265,6 +268,258 @@ inline…) with unified accessors: `chat`, `from`, `chatId`, `msgId`, `msg`,
|
|
|
265
268
|
Business accounts: replies inside a business context automatically carry
|
|
266
269
|
`business_connection_id`.
|
|
267
270
|
|
|
271
|
+
<a id="rich-messages"></a>
|
|
272
|
+
### 🧱 Rich Messages, animated emoji, media & drafts (Bot API 10.3)
|
|
273
|
+
|
|
274
|
+
A **Rich Message** is Telegram's structured message format: one message can combine rich-text entities, headings, lists, quotations, tables, maps, buttons, media blocks, and more. TeleBibz provides builders and Context shortcuts; the official [Telegram Bot API reference](https://core.telegram.org/bots/api) remains authoritative for current limits and eligibility.
|
|
275
|
+
|
|
276
|
+
> **Coverage note:** the package includes a type-level registry for **185 Bot API methods** and typed payloads through `api.callApi()`. This does not mean all 185 endpoints can be safely or meaningfully tested live: many require real updates, admin rights, payments, or specific chats. See [`VERIFIKASI-MENDALAM.md`](VERIFIKASI-MENDALAM.md) for the live-test matrix and known limitations.
|
|
277
|
+
|
|
278
|
+
#### 1. Choose exactly one content mode
|
|
279
|
+
|
|
280
|
+
A rich message has exactly one content source: `html`, `markdown`, or `blocks`. Optional settings such as `media`, `is_rtl`, and `skip_entity_detection` do not count as content modes.
|
|
281
|
+
|
|
282
|
+
```js
|
|
283
|
+
const { TeleBibz, rich, RichMessageBuilder } = require('@xbibzlibrary/telebibz');
|
|
284
|
+
const bot = new TeleBibz(process.env.BOT_TOKEN);
|
|
285
|
+
|
|
286
|
+
bot.cmd('rich', async (ctx) => {
|
|
287
|
+
const message = rich.blocks([
|
|
288
|
+
rich.heading('Weekly report', 2),
|
|
289
|
+
rich.paragraph(['Orders: ', rich.bold('42'), ' · status ', rich.italic('ready')]),
|
|
290
|
+
rich.table([
|
|
291
|
+
[
|
|
292
|
+
{ text: 'Metric', is_header: true, align: 'left', valign: 'middle' },
|
|
293
|
+
{ text: 'Value', is_header: true, align: 'right', valign: 'middle' },
|
|
294
|
+
],
|
|
295
|
+
[
|
|
296
|
+
{ text: 'Revenue', align: 'left', valign: 'middle' },
|
|
297
|
+
{ text: '$1,250', align: 'right', valign: 'middle' },
|
|
298
|
+
],
|
|
299
|
+
], { bordered: true, striped: true, compact: true, caption: 'This week' }),
|
|
300
|
+
rich.details('More information', [rich.paragraph('This section can be expanded.')]),
|
|
301
|
+
rich.buttons([
|
|
302
|
+
rich.button('Open dashboard', { url: 'https://example.com' }, 'primary'),
|
|
303
|
+
rich.button('Acknowledge', { callback_data: 'report:ack' }, 'success'),
|
|
304
|
+
], 'center'),
|
|
305
|
+
]);
|
|
306
|
+
return ctx.replyWithRichMessage(message);
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
bot.launch();
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
The lower-level constructors are `rich.html(html, options)`, `rich.markdown(markdown, options)`, and `rich.blocks(blocks, options)`. `inputRichMessage(content, options)` validates that one content mode is selected. `RichMessageBuilder` is useful when assembling a message incrementally:
|
|
313
|
+
|
|
314
|
+
```js
|
|
315
|
+
const message = new RichMessageBuilder()
|
|
316
|
+
.blocks([rich.heading('Notice', 2)])
|
|
317
|
+
.add(rich.paragraph('More blocks can be appended.'))
|
|
318
|
+
.rtl(false)
|
|
319
|
+
.skipEntityDetection()
|
|
320
|
+
.build();
|
|
321
|
+
await ctx.replyWithRichMessage(message);
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
Calling `.html()`, `.markdown()`, or `.blocks()` more than once on the same builder is an error: create a new builder when you want a different mode. `.media()` is intended for HTML/Markdown content that references media by `tg://...` links.
|
|
325
|
+
|
|
326
|
+
#### 2. Rich-text entities
|
|
327
|
+
|
|
328
|
+
Rich text can be a plain string, an array mixing strings and entity objects, or a nested rich-text object. Common entity helpers include:
|
|
329
|
+
|
|
330
|
+
| Helper | Entity produced | Typical use |
|
|
331
|
+
|---|---|---|
|
|
332
|
+
| `rich.bold(text)`, `rich.italic(text)`, `rich.underline(text)`, `rich.strikethrough(text)` | emphasis | inline formatting |
|
|
333
|
+
| `rich.spoiler(text)`, `rich.marked(text)`, `rich.code(text)` | spoiler / marked / code | hidden or technical text |
|
|
334
|
+
| `rich.subscript(text)`, `rich.superscript(text)` | script position | formulas and references |
|
|
335
|
+
| `rich.dateTime(text, unixTime, format)` | date/time | localized or relative timestamp |
|
|
336
|
+
| `rich.url(text, url)`, `rich.email(text, email)`, `rich.phone(text, phone)` | explicit links/contact | clickable or recognized values |
|
|
337
|
+
| `rich.mention(text, username)`, `rich.textMention(text, user)` | user mention | username or user object |
|
|
338
|
+
| `rich.hashtag(text, value)`, `rich.cashtag(text, value)`, `rich.botCommand(text, value)` | Telegram entities | searchable tags/commands |
|
|
339
|
+
| `rich.customEmoji(customEmojiId, alternativeText)` | custom emoji | standard or animated custom emoji |
|
|
340
|
+
| `rich.mathText(expression)`, `rich.anchorText(name)`, `rich.anchorLink(text, name)`, `rich.reference(text, name)`, `rich.referenceLink(text, name)` | formula/navigation | structured long-form text |
|
|
341
|
+
| `rich.buttonText(text, action, style)` | inline rich-text button entity | a button inside a rich-text run |
|
|
342
|
+
|
|
343
|
+
Example with an animated custom emoji (use a **real** custom emoji ID that Telegram returns for your bot):
|
|
344
|
+
|
|
345
|
+
```js
|
|
346
|
+
const emojiId = 'CUSTOM_EMOJI_ID';
|
|
347
|
+
const [sticker] = await ctx.api.callApi('getCustomEmojiStickers', {
|
|
348
|
+
custom_emoji_ids: [emojiId],
|
|
349
|
+
});
|
|
350
|
+
if (!sticker) throw new Error('Unknown custom emoji ID');
|
|
351
|
+
await ctx.replyWithRichMessage(rich.blocks([
|
|
352
|
+
rich.paragraph(['Build status: ', rich.bold('passed'), ' ', rich.customEmoji(emojiId, '👍')]),
|
|
353
|
+
]));
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
A regular Unicode emoji is not automatically an animated custom emoji. The custom ID must be valid and usable by the bot; Telegram may reject unavailable IDs or features the bot is not eligible to use.
|
|
357
|
+
|
|
358
|
+
#### 3. Structured block catalog
|
|
359
|
+
|
|
360
|
+
Each block helper returns an `InputRichBlock` object. Blocks can be nested where the schema permits it.
|
|
361
|
+
|
|
362
|
+
| Block family | Helpers | Notes |
|
|
363
|
+
|---|---|---|
|
|
364
|
+
| Text | `paragraph(text)`, `heading(text, size)`, `pre(text, language)`, `footer(text)`, `divider()` | heading size is 1–6; preformatted blocks can name a language |
|
|
365
|
+
| Math/navigation | `mathBlock(expression)`, `anchor(name)` | use the corresponding rich-text formula/reference helpers for inline content |
|
|
366
|
+
| Lists/quotes | `list(items)`, `quote(blocks, credit)`, `expandableQuote(text, credit)`, `pullQuote(text, credit)` | a list item may be a string or a structured item; quotations can contain nested blocks |
|
|
367
|
+
| Tables/disclosure | `table(cells, options)`, `details(summary, blocks, open)` | each cell supplies `align` and `valign`; options: `bordered`, `striped`, `compact`, `caption` |
|
|
368
|
+
| Location | `map(location, zoom, width, height, caption, credit)` | `location` is `{ latitude, longitude }` |
|
|
369
|
+
| Media | `animation(media, caption)`, `audio(media, caption)`, `document(media, caption)`, `photo(media, caption)`, `video(media, caption)`, `voiceNote(media, caption)` | `media` is an `InputMedia*` object; `File` uploads are collected recursively into multipart `attach://` fields |
|
|
370
|
+
| Layout | `collage(blocks, caption, credit)`, `slideshow(blocks, caption, credit)` | compose allowed media blocks into a gallery or sequence |
|
|
371
|
+
| Buttons | `buttons(buttons, align)`, `button(text, action, style)` | 1–8 buttons; alignment is `left`, `center`, or `right` |
|
|
372
|
+
| Draft-only | `thinking(text)` | use only in `sendRichMessageDraft`, not a persisted rich message |
|
|
373
|
+
|
|
374
|
+
For `table`, each cell should look like `{ text, align: 'left'|'center'|'right', valign: 'top'|'middle'|'bottom' }`; header cells may set `is_header: true`. A button action must provide exactly one supported action field, such as `url`, `callback_data`, `web_app`, `copy_text`, or `disabled`. `rich.button()` returns the button object for a buttons block. `rich.buttonText()` returns the distinct inline entity shape. Link style is only valid for callback buttons.
|
|
375
|
+
|
|
376
|
+
#### 4. Uploading media inside rich messages
|
|
377
|
+
|
|
378
|
+
Use Telegram `file_id`s for files already on Telegram, or wrap bytes/path/stream in `File` (or `InputFile`) for multipart upload:
|
|
379
|
+
|
|
380
|
+
```js
|
|
381
|
+
const fs = require('node:fs');
|
|
382
|
+
const { File, InputMediaBuilder } = require('@xbibzlibrary/telebibz');
|
|
383
|
+
const image = new File(fs.readFileSync('./hero.png'), 'hero.png');
|
|
384
|
+
const video = new File(fs.readFileSync('./clip.mp4'), 'clip.mp4');
|
|
385
|
+
|
|
386
|
+
await ctx.replyWithRichMessage(rich.blocks([
|
|
387
|
+
rich.paragraph('Uploaded media blocks:'),
|
|
388
|
+
rich.photo(InputMediaBuilder.photo(image)),
|
|
389
|
+
rich.video(InputMediaBuilder.video(video)),
|
|
390
|
+
]));
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
HTML/Markdown can refer to media by a unique ID and a matching `media` entry:
|
|
394
|
+
|
|
395
|
+
```js
|
|
396
|
+
const photo = new File(fs.readFileSync('./hero.png'), 'hero.png');
|
|
397
|
+
await ctx.replyWithRichMessage(rich.html(
|
|
398
|
+
'<b>Hero image</b><br><a href="tg://photo?id=hero">Open photo</a>',
|
|
399
|
+
{ media: [{ id: 'hero', media: InputMediaBuilder.photo(photo) }] },
|
|
400
|
+
));
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
A successful live smoke test confirmed nested multipart media, photo/audio/document/video/voice-note blocks, collage/slideshow, and a rich HTML media reference. On the tested Bot API server, an MP4 worked in a rich `animation` block; a GIF in that block returned `RICH_MESSAGE_VIDEO_INVALID`. The standalone `sendAnimation` method did accept the same GIF. If a rich animation block is rejected, try MP4. Live-photo video/photo pairing is a separate API operation, not an `InputRichBlock` type.
|
|
404
|
+
|
|
405
|
+
#### 5. Drafts and streaming previews
|
|
406
|
+
|
|
407
|
+
Drafts are temporary previews, not stored chat messages. Send a final message separately to persist the completed answer. `thinking` blocks are for rich drafts only. Draft helpers reject `File` uploads; use existing Telegram file IDs if a draft needs media.
|
|
408
|
+
|
|
409
|
+
```js
|
|
410
|
+
bot.cmd('stream-preview', async (ctx) => {
|
|
411
|
+
const draftId = Date.now(); // non-zero and unique for this draft
|
|
412
|
+
await ctx.sendMessageDraft(draftId, 'Preparing a response…', { can_stop: true });
|
|
413
|
+
await ctx.sendRichMessageDraft(draftId + 1, rich.draftBlocks([
|
|
414
|
+
rich.paragraph(['Working on ', rich.bold('your report'), '…']),
|
|
415
|
+
rich.thinking('Collecting data'),
|
|
416
|
+
]), { can_stop: true, keep_on_stop: true });
|
|
417
|
+
// Persist the final answer explicitly:
|
|
418
|
+
return ctx.replyWithRichMessage(rich.markdown('**Report ready**'));
|
|
419
|
+
});
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
Draft constructors are `rich.draftHtml()`, `rich.draftMarkdown()`, `rich.draftBlocks()`, and `new RichMessageBuilder()...buildDraft()`. Their return types match `sendRichMessageDraft`'s no-new-upload schema. `sendMessageDraft` and `sendRichMessageDraft` also accept exact object payloads through `ctx.api.callApi()`.
|
|
423
|
+
|
|
424
|
+
#### 6. Live photos, paid media, ephemeral messages, and editing
|
|
425
|
+
|
|
426
|
+
**Live photo** sends a video and its corresponding still image. Both can be file IDs or `File`/`InputFile` values; URLs are not supported by the current method schema.
|
|
427
|
+
|
|
428
|
+
```js
|
|
429
|
+
await ctx.replyWithLivePhoto('VIDEO_FILE_ID', 'PHOTO_FILE_ID', { caption: 'A moment' });
|
|
430
|
+
// Or raw typed API:
|
|
431
|
+
await ctx.api.sendLivePhoto({ chat_id: ctx.chatId, live_photo: videoFile, photo: photoFile });
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
`InputMediaBuilder.livePhoto(video, photo)` and `InputPaidMediaBuilder.livePhoto(video, photo)` build media objects. `sendPaidMedia` requires a `star_count` from 1 to 25,000:
|
|
435
|
+
|
|
436
|
+
```js
|
|
437
|
+
const fs = require('node:fs');
|
|
438
|
+
const { File, InputPaidMediaBuilder } = require('@xbibzlibrary/telebibz');
|
|
439
|
+
const paidPhoto = new File(fs.readFileSync('./paid.png'), 'paid.png');
|
|
440
|
+
await ctx.api.callApi('sendPaidMedia', {
|
|
441
|
+
chat_id: ctx.chatId,
|
|
442
|
+
star_count: 1,
|
|
443
|
+
media: [InputPaidMediaBuilder.photo(paidPhoto)],
|
|
444
|
+
caption: 'Paid photo sample',
|
|
445
|
+
});
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
This is a real payment/paywall feature: do not test it on users without consent, and account for Telegram Stars before publishing paid content.
|
|
449
|
+
|
|
450
|
+
An **ephemeral message** is addressed to a recipient using `ephemeral_message_parameters`; availability depends on Telegram's bot/chat eligibility and permissions. Context helpers include `replyEphemeral(text, receiverUserId)`, `editEphemeralMessageText`, `editEphemeralRichMessage`, `editEphemeralMessageMedia`, `editEphemeralMessageCaption`, `editEphemeralMessageReplyMarkup`, and `deleteEphemeralMessage`.
|
|
451
|
+
|
|
452
|
+
```js
|
|
453
|
+
await ctx.replyEphemeral('Temporary notice', ctx.from.id);
|
|
454
|
+
const sent = await ctx.api.callApi('sendRichMessage', {
|
|
455
|
+
chat_id: ctx.chatId,
|
|
456
|
+
rich_message: rich.blocks([rich.paragraph('Private rich preview')]),
|
|
457
|
+
ephemeral_message_parameters: { receiver_user_id: ctx.from.id },
|
|
458
|
+
});
|
|
459
|
+
// If Telegram returns an ephemeral_message_id, it can be used with the edit/delete helpers.
|
|
460
|
+
if (sent.ephemeral_message_id) {
|
|
461
|
+
await ctx.editEphemeralRichMessage(ctx.from.id, sent.ephemeral_message_id,
|
|
462
|
+
rich.blocks([rich.paragraph('Updated temporary notice')]));
|
|
463
|
+
}
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
Telegram can reject requests with `BOT_NOT_ADMIN` or other permission errors; inspect the returned `ApiError` and do not treat a local payload test as proof of eligibility.
|
|
467
|
+
|
|
468
|
+
Rich edits use `ctx.editRichMessage(content, extra)`. The underlying Bot API is `editMessageText` with `rich_message` and a target `chat_id`/`message_id` (or `inline_message_id`). These operations modify an existing message; use a message created for testing when validating them.
|
|
469
|
+
|
|
470
|
+
#### 7. Context helpers and modern Bot API methods
|
|
471
|
+
|
|
472
|
+
| Helper | Effect / arguments |
|
|
473
|
+
|---|---|
|
|
474
|
+
| `ctx.replyWithRichMessage(content, extra?)` | sends a persisted rich message to the current chat |
|
|
475
|
+
| `ctx.editRichMessage(content, extra?)` | rich-edits the current message; callback and inline targets are handled |
|
|
476
|
+
| `ctx.replyWithLivePhoto(video, photo, extra?)` | sends a live photo to the current chat |
|
|
477
|
+
| `ctx.sendMessageDraft(draftId, text, extra?)` | streams a plain-text preview |
|
|
478
|
+
| `ctx.sendRichMessageDraft(draftId, richMessage, extra?)` | streams a rich preview |
|
|
479
|
+
| `ctx.replyEphemeral(text, receiverUserId, extra?)` | sends an ephemeral plain-text message |
|
|
480
|
+
| `ctx.guestQueryId`, `ctx.answerGuestQuery(result)` | handles a real incoming `guest_message` update |
|
|
481
|
+
| `ctx.editEphemeralRichMessage(...)`, `ctx.deleteEphemeralMessage(...)` | edits/deletes a recipient's ephemeral message |
|
|
482
|
+
|
|
483
|
+
Guest query answers require the `guest_query_id` from an actual incoming guest update; it cannot be fabricated for a meaningful live test. Inline rich articles can be built with `iq.richArticle(id, title, richMessage, extra)` and returned while handling an actual inline query.
|
|
484
|
+
|
|
485
|
+
#### 8. Complete typed Bot API access
|
|
486
|
+
|
|
487
|
+
All **185 method names and payload signatures** in the vendored Bot API schema are available in TypeScript through `api.callApi()` and `api.raw()`:
|
|
488
|
+
|
|
489
|
+
```js
|
|
490
|
+
// JavaScript or TypeScript: method name + payload object
|
|
491
|
+
await ctx.api.callApi('sendRichMessage', {
|
|
492
|
+
chat_id: ctx.chatId,
|
|
493
|
+
rich_message: rich.markdown('**Hello**'),
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
await ctx.api.callApi('sendMessageDraft', {
|
|
497
|
+
chat_id: ctx.chatId,
|
|
498
|
+
draft_id: Date.now(),
|
|
499
|
+
text: 'Preview',
|
|
500
|
+
can_stop: false,
|
|
501
|
+
});
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
The `TelegramTypes` namespace exports the vendored Telegram object types. Useful type aliases include `TelegramMethodName`, `TelegramMethodPayload<M>`, `TelegramMethodResult<M>`, `TelegramApiMethods`, and `TelegramApiPayloads`. The runtime proxy also permits `ctx.api.anyMethod({ ...payload })` for newly added methods, but that dynamic shorthand has no runtime schema validation. TypeScript checks happen at compile time only. Run `npm run typecheck` to validate declarations and consumer examples.
|
|
505
|
+
|
|
506
|
+
The declarations are vendored from `@grammyjs/types@5.0.0` under MIT (see [`NOTICE.md`](NOTICE.md) and the vendored license); they add no runtime dependency. Telegram's official reference/changelog—not the vendored package—remains the authority when a field, permission, or limit differs.
|
|
507
|
+
|
|
508
|
+
#### Limits and troubleshooting
|
|
509
|
+
|
|
510
|
+
The Bot API 10.3 type schema documents these Rich Message ceilings: **32,768 UTF-8 characters**, **500 blocks** (including nested/list/table/quotation/details content), **16 nesting levels**, **50 media attachments**, and **20 table columns**. Map blocks use zoom 0–24 and width/height 0–10,000; the buttons block allows 1–8 buttons. Telegram can update limits, so check the [official reference](https://core.telegram.org/bots/api) before building large payloads. The server remains the final validator.
|
|
511
|
+
|
|
512
|
+
Common failures:
|
|
513
|
+
|
|
514
|
+
- `RICH_MESSAGE_VIDEO_INVALID`: the tested server rejected a GIF in a Rich Message `animation` block; try MP4. The standalone `sendAnimation` endpoint accepted the GIF.
|
|
515
|
+
- `BOT_NOT_ADMIN` on ephemeral sends: this is a Telegram eligibility/permission response, not proof that the JSON shape is invalid. Verify bot/chat access and official method requirements.
|
|
516
|
+
- `chat not found`: in a private chat, the user usually needs to open the bot and press **Start** before the bot can initiate a message.
|
|
517
|
+
- Upload errors: wrap bytes, paths, or streams in `File`/`InputFile`; confirm the media helper's type matches the file.
|
|
518
|
+
|
|
519
|
+
#### Live verification and limits
|
|
520
|
+
|
|
521
|
+
On 2026-09-28, a live smoke test against a user-provided bot succeeded for rich blocks, HTML, Markdown, animated custom emoji, plain/rich drafts, multipart media, photo/audio/document/video/voice-note blocks, collage/slideshow, live photo, GIF via `sendAnimation`, and HTML media references. Ephemeral `sendMessage`/`sendRichMessage` failed with Telegram's `BOT_NOT_ADMIN`; paid media was not sent because it can involve Stars; callback buttons were not clicked; all 185 endpoints were not exercised live. See [`VERIFIKASI-MENDALAM.md`](VERIFIKASI-MENDALAM.md) for the exact outcomes and test boundaries.
|
|
522
|
+
|
|
268
523
|
<a id="keyboards"></a>
|
|
269
524
|
### 🔘 Keyboards & buttons
|
|
270
525
|
|
|
@@ -511,12 +766,12 @@ await bot.api.sendDiceCustom({ chat_id: 1, emoji: '🎲' });
|
|
|
511
766
|
|
|
512
767
|
| Metric | Value |
|
|
513
768
|
|---|---|
|
|
514
|
-
| 📦 Source modules | **
|
|
515
|
-
| 📝 Total lines of code |
|
|
516
|
-
| 🔌 Bot API methods | **
|
|
769
|
+
| 📦 Source modules | **18 files** in `lib/` |
|
|
770
|
+
| 📝 Total lines of code | **2,105** in `lib/` (no build step) |
|
|
771
|
+
| 🔌 Bot API methods | **185 typed method signatures** via `api.callApi()` + dynamic Proxy |
|
|
517
772
|
| ⌨️ Context shortcuts | **50+** (reply/edit/delete/admin/react…) |
|
|
518
|
-
| 🧪 Offline tests | **
|
|
519
|
-
| 🧩 Ready examples | **
|
|
773
|
+
| 🧪 Offline tests | **48/48 passing**, including local HTTP transport and Bot API 10.3 tests |
|
|
774
|
+
| 🧩 Ready examples | **8** in `examples/` |
|
|
520
775
|
| 📦 Runtime dependencies | **4** — all used, all tested |
|
|
521
776
|
|
|
522
777
|
### ⬇️ Downloads & popularity (live from npm)
|
|
@@ -528,23 +783,27 @@ await bot.api.sendDiceCustom({ chat_id: 1, emoji: '🎲' });
|
|
|
528
783
|
|
|
529
784
|
### 📏 Module size map (lines of code)
|
|
530
785
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
context.js
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
786
|
+
The figures below are generated from the current `lib/*.js` source. They are informational, not bundle-size measurements.
|
|
787
|
+
|
|
788
|
+
```text
|
|
789
|
+
context.js 250 Context accessors, replies, edits and helpers
|
|
790
|
+
wizard.js 247 Guided forms, buttons, edit/delete modes
|
|
791
|
+
telebibz.js 209 Bot class, lifecycle, update dispatch
|
|
792
|
+
telegram-methods.js 192 Runtime registry for 185 API method names
|
|
793
|
+
composer.js 185 Middleware composition and filters
|
|
794
|
+
rich.js 175 Rich Message, entity and block builders
|
|
795
|
+
api.js 168 Typed API adapters, Proxy and transformers
|
|
796
|
+
net.js 115 HTTP transport and multipart upload
|
|
797
|
+
menus.js 90 Menu and MenuContainer
|
|
798
|
+
keyboard.js 83 Keyboard builders and fluent classes
|
|
799
|
+
ratelimit.js 74 Retry, throttler and limiter
|
|
800
|
+
logger.js 68 Logs and boot banner
|
|
801
|
+
runner.js 54 Polling and retry handling
|
|
802
|
+
file.js 48 File/InputFile and media builders
|
|
803
|
+
session.js 44 Swappable session storage
|
|
804
|
+
errors.js 35 Error translations
|
|
805
|
+
broadcast.js 35 Broadcast helper
|
|
806
|
+
inline-query.js 33 Inline matching and result builders
|
|
548
807
|
```
|
|
549
808
|
|
|
550
809
|
### 🗺️ Repo health
|
|
@@ -574,6 +833,7 @@ inline-query.js██▊ 28 ← matcher + result builder
|
|
|
574
833
|
| `05-kirim-file.js` | photos & documents from buffers |
|
|
575
834
|
| `06-menu.js` | interactive menus + submenus |
|
|
576
835
|
| `07-inline-query.js` | inline mode with result builders |
|
|
836
|
+
| `08-rich-message.js` | rich messages, live photo, drafts, ephemeral messages, raw API |
|
|
577
837
|
|
|
578
838
|
Run any of them with `BOT_TOKEN=123:abc node examples/01-quickstart.js`.
|
|
579
839
|
|
|
@@ -581,23 +841,23 @@ Run any of them with `BOT_TOKEN=123:abc node examples/01-quickstart.js`.
|
|
|
581
841
|
## 🔬 Testing & Live Proof
|
|
582
842
|
|
|
583
843
|
```bash
|
|
584
|
-
npm test
|
|
844
|
+
npm test # 48 offline checks, including local HTTP transport + Bot API 10.3 tests
|
|
845
|
+
npm run typecheck # verify declarations and method-specific Bot API payload types
|
|
585
846
|
```
|
|
586
847
|
|
|
587
|
-
|
|
588
|
-
getMe · colored keyboards & real animated icons · multipart uploads
|
|
589
|
-
(photo+document) · keyboard editing · broadcast · deleteMessage · polling 409
|
|
590
|
-
retry · wizard buttons & edit/delete.
|
|
848
|
+
The 48 automated checks and `npm run typecheck` are offline/mocked and do not need a bot token. A separate live smoke test was performed with the owner's test bot: rich blocks, HTML/Markdown, animated custom emoji, drafts, media blocks, collage/slideshow, live photo, and multipart media references passed. Ephemeral sends were rejected by Telegram with `BOT_NOT_ADMIN`; paid media and all 185 endpoints were not tested live. See [`VERIFIKASI-MENDALAM.md`](VERIFIKASI-MENDALAM.md) for the exact matrix, known limits, and failures.
|
|
591
849
|
|
|
592
850
|
Debug logging: `DEBUG=telebibz:net,telebibz:ratelimit node yourbot.js`.
|
|
593
851
|
|
|
594
852
|
<a id="structure"></a>
|
|
595
|
-
## 📂 Repo Structure (
|
|
853
|
+
## 📂 Repo Structure (18 JavaScript modules + vendored API types)
|
|
596
854
|
|
|
597
855
|
| File | Role |
|
|
598
856
|
|---|---|
|
|
599
857
|
| `lib/net.js` | axios keep-alive transport + multipart `attach://` |
|
|
600
858
|
| `lib/api.js` | Bot API methods + any-method Proxy + transformers |
|
|
859
|
+
| `lib/rich.js` | Rich Message entities, block builders, draft-safe helpers |
|
|
860
|
+
| `lib/telegram-methods.js` | registry of 185 Bot API method names |
|
|
601
861
|
| `lib/composer.js` | middleware, `on('message:photo')` filters, `errorBoundary` |
|
|
602
862
|
| `lib/context.js` | ctx object + 50-ish reply/edit/delete/callback shortcuts |
|
|
603
863
|
| `lib/session.js` | per user:chat sessions (swappable storage) |
|
|
@@ -611,11 +871,13 @@ Debug logging: `DEBUG=telebibz:net,telebibz:ratelimit node yourbot.js`.
|
|
|
611
871
|
| `lib/inline-query.js` | query matcher + inline result builders |
|
|
612
872
|
| `lib/errors.js` | humanized errors + suggestions |
|
|
613
873
|
| `lib/logger.js` | framed logs + boot banner |
|
|
614
|
-
| `
|
|
874
|
+
| `types/telegram-bot-api/` | vendored Bot API types (MIT); no runtime code |
|
|
875
|
+
| `index.js` / `index.d.ts` | export door + typed method/payload surface |
|
|
615
876
|
|
|
616
877
|
<a id="changelog"></a>
|
|
617
878
|
## 🕐 Changelog
|
|
618
879
|
|
|
880
|
+
- **Unreleased — Bot API 10.3** — rich messages, animated emoji, drafts, live photos, all 185 typed method payloads; 48 offline checks and richer live verification. Details: [`CHANGELOG.md`](CHANGELOG.md).
|
|
619
881
|
- **3.1.0** — wizard: choice buttons (reply/inline), `edit`/`delete` modes, auto cleanup, programmatic helpers · tests 24 → 30
|
|
620
882
|
- **3.0.0** — production-grade grammY parity: axios keep-alive, transformers, menus, inline query, limiter
|
|
621
883
|
- **2.0.0** — engine rewritten from scratch, multipart transport, native Node webhook
|
|
@@ -623,16 +885,23 @@ Debug logging: `DEBUG=telebibz:net,telebibz:ratelimit node yourbot.js`.
|
|
|
623
885
|
|
|
624
886
|
> Full details in [`CHANGELOG.md`](CHANGELOG.md). Deep architecture study (🇮): [`ANALISIS-telebibz.md`](ANALISIS-telebibz.md).
|
|
625
887
|
|
|
888
|
+
<a id="publishing"></a>
|
|
889
|
+
## 📦 Automated npm publishing
|
|
890
|
+
|
|
891
|
+
`.github/workflows/auto-publish.yml` publishes on pushes to `main` (except release commits tagged with `[skip release]`) or manually on the `main` branch via **Actions → Auto publish to npm → Run workflow** (the job rejects dispatches from other branches). Before enabling it, configure a GitHub Actions Environment named `npm-release` and add the repository/environment secret **`NPM_TOKEN`** with permission to publish `@xbibzlibrary/telebibz`. No credential is stored in this repository.
|
|
892
|
+
|
|
893
|
+
The workflow derives the next patch version from the greater of the checked-in version and npm's latest version, then runs runtime tests, TypeScript checks, JS syntax checks, package dry-run, and production dependency audit. It publishes publicly, commits the bumped `package.json`/lockfile, creates an annotated `vX.Y.Z` tag, and a GitHub release. A failed validation stops before publish. The CI/release workflows have been reviewed locally; a real GitHub Actions run and npm publish still require repository access and the secret.
|
|
894
|
+
|
|
626
895
|
<a id="license"></a>
|
|
627
896
|
## 📄 License
|
|
628
897
|
|
|
629
|
-
**MIT** © Xbibz
|
|
898
|
+
**MIT** © Xbibz Technology ID — architecture inspired by [grammY](https://grammy.dev) (MIT, see [`NOTICE.md`](NOTICE.md)).
|
|
630
899
|
|
|
631
900
|
---
|
|
632
901
|
|
|
633
902
|
<div align="center">
|
|
634
903
|
|
|
635
|
-
**Made with ❤️ by
|
|
904
|
+
**Made with ❤️ by Xbibz Technology ID**
|
|
636
905
|
|
|
637
906
|
If telebibz helps you, a ⭐ on this repo means a lot.
|
|
638
907
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { TeleBibz, rich } = require('..');
|
|
4
|
+
const bot = new TeleBibz(process.env.BOT_TOKEN);
|
|
5
|
+
|
|
6
|
+
bot.cmd('rich', (ctx) => ctx.replyWithRichMessage(rich.blocks([
|
|
7
|
+
rich.heading('Ringkasan transaksi', 2),
|
|
8
|
+
rich.paragraph(['Status: ', rich.bold('berhasil'), ' · ', rich.customEmoji('5368324170671202286', '✅')]),
|
|
9
|
+
rich.table([
|
|
10
|
+
[{ text: 'Item', is_header: true, align: 'left', valign: 'middle' }, { text: 'Jumlah', is_header: true, align: 'right', valign: 'middle' }],
|
|
11
|
+
[{ text: 'Pesanan #42', align: 'left', valign: 'middle' }, { text: 'Rp 125.000', align: 'right', valign: 'middle' }],
|
|
12
|
+
], { bordered: true, striped: true, compact: true }),
|
|
13
|
+
rich.details('Rincian', [rich.paragraph('Diproses otomatis oleh bot.')]),
|
|
14
|
+
rich.buttons([
|
|
15
|
+
rich.button('Buka web', { url: 'https://example.com' }, 'primary'),
|
|
16
|
+
rich.button('Konfirmasi', { callback_data: 'confirm:42' }, 'success'),
|
|
17
|
+
], 'center'),
|
|
18
|
+
])));
|
|
19
|
+
|
|
20
|
+
bot.action(/^confirm:\d+$/, (ctx) => ctx.answerCallbackQuery('Terkonfirmasi'));
|
|
21
|
+
|
|
22
|
+
bot.cmd('draft', async (ctx) => {
|
|
23
|
+
const draftId = 1;
|
|
24
|
+
await ctx.sendRichMessageDraft(draftId, rich.draftBlocks([
|
|
25
|
+
rich.paragraph('Sedang menyusun jawaban…'),
|
|
26
|
+
rich.thinking('Menganalisis permintaan'),
|
|
27
|
+
]), { can_stop: true, keep_on_stop: true });
|
|
28
|
+
// Draft Bot API hanya preview sementara. Kirim pesan final agar tersimpan.
|
|
29
|
+
await ctx.replyWithRichMessage(rich.markdown('**Jawaban final**\nSelesai diproses.'));
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
bot.cmd('privat', (ctx) => ctx.replyEphemeral('Pesan ini hanya terlihat oleh Anda.', ctx.from.id));
|
|
33
|
+
|
|
34
|
+
bot.launch();
|