@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.
Files changed (39) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/LICENSE +1 -1
  3. package/NOTICE.md +15 -8
  4. package/README.id.md +312 -43
  5. package/README.md +312 -43
  6. package/examples/08-rich-message.js +34 -0
  7. package/index.d.ts +303 -96
  8. package/index.js +8 -2
  9. package/lib/api.js +20 -6
  10. package/lib/composer.js +14 -2
  11. package/lib/context.js +83 -21
  12. package/lib/file.js +8 -1
  13. package/lib/inline-query.js +6 -1
  14. package/lib/logger.js +44 -14
  15. package/lib/ratelimit.js +16 -3
  16. package/lib/rich.js +175 -0
  17. package/lib/runner.js +14 -5
  18. package/lib/session.js +12 -4
  19. package/lib/telebibz.js +40 -24
  20. package/lib/telegram-methods.js +192 -0
  21. package/package.json +14 -10
  22. package/test/audit.test.js +355 -0
  23. package/test/types.test.ts +40 -0
  24. package/types/telegram-bot-api/LICENSE +21 -0
  25. package/types/telegram-bot-api/api.d.ts +22 -0
  26. package/types/telegram-bot-api/checklist.d.ts +72 -0
  27. package/types/telegram-bot-api/inline.d.ts +692 -0
  28. package/types/telegram-bot-api/langs.d.ts +193 -0
  29. package/types/telegram-bot-api/manage.d.ts +1153 -0
  30. package/types/telegram-bot-api/markup.d.ts +278 -0
  31. package/types/telegram-bot-api/message.d.ts +1557 -0
  32. package/types/telegram-bot-api/methods.d.ts +2860 -0
  33. package/types/telegram-bot-api/mod.d.ts +14 -0
  34. package/types/telegram-bot-api/passport.d.ts +163 -0
  35. package/types/telegram-bot-api/payment.d.ts +576 -0
  36. package/types/telegram-bot-api/rich.d.ts +1198 -0
  37. package/types/telegram-bot-api/settings.d.ts +120 -0
  38. package/types/telegram-bot-api/story.d.ts +89 -0
  39. 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
  [![npm version](https://img.shields.io/npm/v/@xbibzlibrary/telebibz?style=for-the-badge&logo=npm&logoColor=white&color=CB3837&label=telebibz)](https://www.npmjs.com/package/@xbibzlibrary/telebibz)
20
20
  [![downloads](https://img.shields.io/npm/dm/@xbibzlibrary/telebibz?style=for-the-badge&logo=npm&logoColor=white&color=green&label=downloads%2Fmonth)](https://www.npmjs.com/package/@xbibzlibrary/telebibz)
21
21
  [![node](https://img.shields.io/node/v/@xbibzlibrary/telebibz?style=for-the-badge&logo=node.js&logoColor=white&color=339933&label=node)](https://nodejs.org)
22
- [![tests](https://img.shields.io/badge/tests-30%2F30%20passing-brightgreen?style=for-the-badge&logo=checkmarx&logoColor=white)](#-testing--live-proof)
23
- [![size](https://img.shields.io/badge/code-1.7k%20lines-orange?style=for-the-badge&logo=codeigniter&logoColor=white)](#-analytics--statistics)
22
+ [![tests](https://img.shields.io/badge/tests-48%2F48%20passing-brightgreen?style=for-the-badge&logo=checkmarx&logoColor=white)](#-testing--live-proof)
23
+ [![size](https://img.shields.io/badge/code-2.1k%20lines-orange?style=for-the-badge&logo=codeigniter&logoColor=white)](#-analytics--statistics)
24
24
  [![license](https://img.shields.io/npm/l/@xbibzlibrary/telebibz?style=for-the-badge&color=blue)](LICENSE)
25
25
  [![views](https://komarev.com/ghpvc/?username=XbibzOfficial777&repo=telebibz&style=for-the-badge&color=blueviolet&label=repo+views)](https://github.com/XbibzOfficial777/telebibz)
26
26
 
27
27
  <br>
28
28
 
29
- `//—Xbibz Official—//`
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) | 🔘 [Keyboards & buttons](#keyboards) |
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 | loose d.ts (JS-first) |
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
- │ 🤖 TeleBibz ON │
142
- │ bot : @yourbot (id 123456) │
143
- │ mode : long-polling │
144
- │ library : telebibz 3.1.0 │
145
- │ brand : //—Xbibz Official—// │
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 | **16 files** in `lib/` |
515
- | 📝 Total lines of code | **~1,700** (no build step) |
516
- | 🔌 Bot API methods | **90+** — 75 typed shortcuts + unbounded Proxy |
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 | **30/30 passing**, zero network |
519
- | 🧩 Ready examples | **7** in `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
- wizard.js █████████████████████████ 247 ← forms + buttons + edit/delete
533
- telebibz.js ███████████████████▎ 193 ← main class & lifecycle
534
- context.js ███████████████████ 190 ← ctx + 50-ish shortcuts
535
- composer.js █████████████████▍ 174 ← middleware engine & filters
536
- api.js ███████████████▍ 154 ← 75 shortcuts + Proxy + transformers
537
- net.js ███████████▌ 115 ← axios transport + multipart
538
- menus.js █████████ 90 ← Menu/MenuContainer
539
- keyboard.js ████████▎ 83 ← btn/url/kb + fluent classes
540
- ratelimit.js ██████ 61 ← autoRetry · throttler · limiter
541
- runner.js ████▌ 45 ← 409-resilient polling
542
- file.js ████ 41 ← InputFile + InputMediaBuilder
543
- logger.js ███▊ 38 ← logs + banner
544
- session.js ███▌ 36 ← swappable sessions
545
- errors.js ███▌ 35 ← humanized errors 🇮
546
- broadcast.js ███ 35 ← rate-limit-safe blast
547
- inline-query.js██▊ 28 ← matcher + result builders
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 # 30 cases, NO network (transport injected)
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
- Validated **30/30 offline + 10 live** on the production bot `@xbibzrat_bot`:
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 (16 core files)
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
- | `index.js` / `index.d.ts` | export door + TypeScript types |
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 Official — architecture inspired by [grammY](https://grammy.dev) (MIT, see [`NOTICE.md`](NOTICE.md)).
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 //—Xbibz Official—//**
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();