teledzik 1.0.5 → 1.0.6

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/README.md CHANGED
@@ -588,9 +588,9 @@ await ctx.sendRichMessage(msg, {
588
588
 
589
589
  ---
590
590
 
591
- ### Universal `editRichMessage` (Omni-Format Support)
591
+ ### Native `editRichMessage` (Preserving 100% Rich UI)
592
592
 
593
- Update existing messages or media captions in-place with **any** content format. It automatically detects Text vs Media (Photo/Video/Audio/Doc) and silently handles Telegram's `message is not modified` without throwing errors:
593
+ Edit a rich message in-place while preserving 100% Native Rich UI layout (tables, headings, cards, collapsibles):
594
594
 
595
595
  ```ts
596
596
  import { Telegraf, RichHTMLBuilder, Markup } from 'teledzik'
@@ -605,23 +605,12 @@ bot.action('btn:update', async (ctx) => {
605
605
  ['VPS-02', '7.2 GB', 'ONLINE 🟢']
606
606
  ], { bordered: true, striped: true, hasHeader: true })
607
607
 
608
+ // Edit in-place with native Rich UI preservation
608
609
  await ctx.editRichMessage(rich, {
609
610
  reply_markup: Markup.inlineKeyboard([
610
611
  [Markup.button.primary('🔄 Refresh', 'btn:update')]
611
612
  ]).reply_markup
612
613
  })
613
-
614
- // 2. Or using an Object
615
- await ctx.editRichMessage({
616
- html: '<b>New Content</b>',
617
- reply_markup: { inline_keyboard: [] }
618
- })
619
-
620
- // 3. Or using Raw HTML String
621
- await ctx.editRichMessage('<b>Updated via raw string</b>')
622
-
623
- // 4. Or specifying a custom messageId
624
- await ctx.editRichMessage(12345, '<b>Edit specific message ID</b>')
625
614
  })
626
615
  ```
627
616
 
package/lib/context.js CHANGED
@@ -1069,39 +1069,21 @@ class Context {
1069
1069
  this.assert(this.chat, 'sendRichMessageDraft');
1070
1070
  return this.telegram.sendRichMessageDraft(this.chat.id, draftId, richMessage, extra);
1071
1071
  }
1072
- async editRichMessage(a, b, c) {
1073
- let targetMsgId;
1074
- let content;
1075
- let extra = {};
1076
- if (typeof a === 'number' ||
1077
- (typeof a === 'string' && !isNaN(Number(a)) && b !== undefined)) {
1078
- targetMsgId = a;
1079
- content = b;
1080
- extra = c || {};
1081
- }
1082
- else {
1083
- targetMsgId =
1084
- this.callbackQuery?.message?.message_id ??
1085
- (this.message && 'message_id' in this.message ? this.message.message_id : undefined) ??
1086
- (this.update && 'edited_message' in this.update && this.update.edited_message
1087
- ? this.update.edited_message.message_id
1088
- : undefined) ??
1089
- this.msgId;
1090
- content = a;
1091
- extra = b || {};
1092
- }
1093
- const chatId = this.chat?.id ??
1094
- (this.callbackQuery?.message && 'chat' in this.callbackQuery.message
1095
- ? this.callbackQuery.message.chat.id
1096
- : undefined);
1097
- const inlineMsgId = this.inlineMessageId ?? extra?.inline_message_id;
1098
- if (!inlineMsgId && (!chatId || targetMsgId == null)) {
1099
- throw new Error('[teledzik] Tidak dapat menemukan chatId atau messageId dari konteks pesan saat ini.');
1100
- }
1101
- if (inlineMsgId && !extra.inline_message_id) {
1102
- extra.inline_message_id = inlineMsgId;
1072
+ /**
1073
+ * Context-aware shorthand for {@link Telegram.editRichMessage}.
1074
+ */
1075
+ editRichMessage(richMessage, extra) {
1076
+ this.assert(this.chat, 'editRichMessage');
1077
+ const messageId = this.callbackQuery?.message?.message_id ||
1078
+ (this.message && 'message_id' in this.message ? this.message.message_id : undefined) ||
1079
+ (this.update && 'edited_message' in this.update && this.update.edited_message
1080
+ ? this.update.edited_message.message_id
1081
+ : undefined) ||
1082
+ this.msgId;
1083
+ if (!messageId) {
1084
+ throw new Error('[teledzik] Tidak dapat menemukan message_id untuk diedit.');
1103
1085
  }
1104
- return this.telegram.editRichMessage(chatId, targetMsgId, content, extra);
1086
+ return this.telegram.editRichMessage(this.chat.id, messageId, richMessage, extra);
1105
1087
  }
1106
1088
  /**
1107
1089
  * Enqueue a Telegram API call for the current chat to prevent 429 Too Many Requests errors.
package/lib/telegram.js CHANGED
@@ -1271,92 +1271,23 @@ class Telegram extends client_1.default {
1271
1271
  ...extra,
1272
1272
  });
1273
1273
  }
1274
- async editRichMessage(chatId, messageId, contentOrInline, contentOrExtra, maybeExtra) {
1275
- let inlineMessageId;
1276
- let content;
1277
- let extra = {};
1278
- if (typeof contentOrInline === 'string' &&
1279
- (typeof contentOrExtra === 'object' || typeof contentOrExtra === 'string') &&
1280
- maybeExtra !== undefined) {
1281
- inlineMessageId = contentOrInline;
1282
- content = contentOrExtra;
1283
- extra = maybeExtra || {};
1284
- }
1285
- else {
1286
- content = contentOrInline;
1287
- extra = contentOrExtra || {};
1288
- inlineMessageId = extra?.inline_message_id;
1289
- }
1290
- let htmlText = '';
1291
- let replyMarkup = extra?.reply_markup;
1292
- // 1. Omni-format input extraction
1293
- if (content && typeof content.build === 'function') {
1294
- const built = content.build();
1295
- if (typeof built === 'object' && built !== null) {
1296
- htmlText = built.html || built.text || built.caption || '';
1297
- if (built.reply_markup) {
1298
- replyMarkup = replyMarkup || built.reply_markup;
1299
- }
1300
- }
1301
- else {
1302
- htmlText = String(built || '');
1303
- }
1304
- }
1305
- else if (typeof content === 'object' && content !== null) {
1306
- htmlText = content.html || content.text || content.caption || content.markdown || '';
1307
- if (content.reply_markup) {
1308
- replyMarkup = replyMarkup || content.reply_markup;
1309
- }
1310
- }
1311
- else if (typeof content === 'string') {
1312
- htmlText = content;
1313
- }
1314
- // Sanitize rich HTML formatting (tables, headers, details, etc.)
1315
- htmlText = (0, rich_sanitizer_1.sanitizeRichHtml)(htmlText);
1316
- // 2. Prepare Base Payload
1317
- const isInline = Boolean(inlineMessageId || extra?.inline_message_id);
1318
- const basePayload = {
1319
- parse_mode: 'HTML',
1274
+ /**
1275
+ * Edit a rich message in-place while preserving 100% Native Rich UI layout (tables, headings, cards).
1276
+ * @see https://core.telegram.org/bots/api#editrichmessage
1277
+ */
1278
+ async editRichMessage(chatId, messageId, richMessage, extra) {
1279
+ const payload = {
1280
+ chat_id: chatId,
1281
+ message_id: Number(messageId),
1282
+ rich_message: typeof richMessage?.build === 'function' ? richMessage.build() : richMessage,
1320
1283
  ...extra,
1321
1284
  };
1322
- if (isInline) {
1323
- basePayload.inline_message_id = inlineMessageId || extra.inline_message_id;
1324
- }
1325
- else {
1326
- basePayload.chat_id = chatId;
1327
- basePayload.message_id = messageId != null ? Number(messageId) : undefined;
1328
- }
1329
- if (replyMarkup) {
1330
- basePayload.reply_markup = replyMarkup;
1331
- }
1332
- // 3. Execution with Auto-Detect (Text -> Caption Fallback) and Silent Error Handling
1333
1285
  try {
1334
- return await this.callApi('editMessageText', {
1335
- ...basePayload,
1336
- text: htmlText,
1337
- });
1286
+ return await this.callApi('editRichMessage', payload);
1338
1287
  }
1339
1288
  catch (err) {
1340
1289
  const desc = String(err?.description || err?.message || '');
1341
- // Fallback: If target is a Media message (Photo, Video, Audio, Document, Animation)
1342
- if (desc.includes('no text in the message') ||
1343
- desc.includes('there is no text in the message to edit') ||
1344
- desc.includes('message to edit not found')) {
1345
- try {
1346
- return await this.callApi('editMessageCaption', {
1347
- ...basePayload,
1348
- caption: htmlText,
1349
- });
1350
- }
1351
- catch (captionErr) {
1352
- const capDesc = String(captionErr?.description || captionErr?.message || '');
1353
- if (capDesc.includes('message is not modified')) {
1354
- return false;
1355
- }
1356
- throw captionErr;
1357
- }
1358
- }
1359
- // Gracefully handle 'message is not modified'
1290
+ // Silent ignore jika konten pesan tidak mengalami perubahan
1360
1291
  if (desc.includes('message is not modified')) {
1361
1292
  return false;
1362
1293
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teledzik",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "Modern Telegram Bot Framework",
5
5
  "keywords": [
6
6
  "telekaf",
package/src/context.ts CHANGED
@@ -1407,61 +1407,22 @@ export class Context<U extends Deunionize<tg.Update> = tg.Update> {
1407
1407
  }
1408
1408
 
1409
1409
  /**
1410
- * Universal Context shortcut to edit message with Omni-Format support (RichHTMLBuilder, Object, or String),
1411
- * auto-detection of Text vs Media Caption, and silent 'not modified' error handling.
1412
- */
1413
- editRichMessage(
1414
- content: tg.RichContentInput,
1415
- extra?: tg.EditRichOptions
1416
- ): Promise<any>
1417
- editRichMessage(
1418
- messageId: number | string,
1419
- content: tg.RichContentInput,
1420
- extra?: tg.EditRichOptions
1421
- ): Promise<any>
1422
- async editRichMessage(a: any, b?: any, c?: any): Promise<any> {
1423
- let targetMsgId: number | string | undefined
1424
- let content: any
1425
- let extra: any = {}
1426
-
1427
- if (
1428
- typeof a === 'number' ||
1429
- (typeof a === 'string' && !isNaN(Number(a)) && b !== undefined)
1430
- ) {
1431
- targetMsgId = a
1432
- content = b
1433
- extra = c || {}
1434
- } else {
1435
- targetMsgId =
1436
- this.callbackQuery?.message?.message_id ??
1437
- (this.message && 'message_id' in this.message ? this.message.message_id : undefined) ??
1438
- (this.update && 'edited_message' in this.update && this.update.edited_message
1439
- ? this.update.edited_message.message_id
1440
- : undefined) ??
1441
- this.msgId
1442
- content = a
1443
- extra = b || {}
1410
+ * Context-aware shorthand for {@link Telegram.editRichMessage}.
1411
+ */
1412
+ editRichMessage(richMessage: any, extra?: any): Promise<any> {
1413
+ this.assert(this.chat, 'editRichMessage')
1414
+ const messageId =
1415
+ this.callbackQuery?.message?.message_id ||
1416
+ (this.message && 'message_id' in this.message ? this.message.message_id : undefined) ||
1417
+ (this.update && 'edited_message' in this.update && this.update.edited_message
1418
+ ? this.update.edited_message.message_id
1419
+ : undefined) ||
1420
+ this.msgId
1421
+
1422
+ if (!messageId) {
1423
+ throw new Error('[teledzik] Tidak dapat menemukan message_id untuk diedit.')
1444
1424
  }
1445
-
1446
- const chatId =
1447
- this.chat?.id ??
1448
- (this.callbackQuery?.message && 'chat' in this.callbackQuery.message
1449
- ? this.callbackQuery.message.chat.id
1450
- : undefined)
1451
-
1452
- const inlineMsgId = this.inlineMessageId ?? extra?.inline_message_id
1453
-
1454
- if (!inlineMsgId && (!chatId || targetMsgId == null)) {
1455
- throw new Error(
1456
- '[teledzik] Tidak dapat menemukan chatId atau messageId dari konteks pesan saat ini.'
1457
- )
1458
- }
1459
-
1460
- if (inlineMsgId && !extra.inline_message_id) {
1461
- extra.inline_message_id = inlineMsgId
1462
- }
1463
-
1464
- return this.telegram.editRichMessage(chatId, targetMsgId, content, extra)
1425
+ return this.telegram.editRichMessage(this.chat.id, messageId, richMessage, extra)
1465
1426
  }
1466
1427
 
1467
1428
  /**
package/src/telegram.ts CHANGED
@@ -1680,125 +1680,29 @@ export class Telegram extends ApiClient {
1680
1680
  }
1681
1681
 
1682
1682
  /**
1683
- * Universal editRichMessage to update text or media captions in-place with Omni-Format support.
1684
- * Auto-detects Text vs Media Caption and gracefully handles 'message is not modified'.
1683
+ * Edit a rich message in-place while preserving 100% Native Rich UI layout (tables, headings, cards).
1684
+ * @see https://core.telegram.org/bots/api#editrichmessage
1685
1685
  */
1686
1686
  async editRichMessage(
1687
- chatId: number | string | undefined,
1688
- messageId: number | string | undefined,
1689
- content: any,
1690
- extra?: any
1691
- ): Promise<any>
1692
- async editRichMessage(
1693
- chatId: number | string | undefined,
1694
- messageId: number | string | undefined,
1695
- inlineMessageId: string | undefined,
1696
- content: any,
1687
+ chatId: number | string,
1688
+ messageId: number | string,
1689
+ richMessage: any,
1697
1690
  extra?: any
1698
- ): Promise<any>
1699
- async editRichMessage(
1700
- chatId: number | string | undefined,
1701
- messageId: number | string | undefined,
1702
- contentOrInline: any,
1703
- contentOrExtra?: any,
1704
- maybeExtra?: any
1705
1691
  ): Promise<any> {
1706
- let inlineMessageId: string | undefined
1707
- let content: any
1708
- let extra: any = {}
1709
-
1710
- if (
1711
- typeof contentOrInline === 'string' &&
1712
- (typeof contentOrExtra === 'object' || typeof contentOrExtra === 'string') &&
1713
- maybeExtra !== undefined
1714
- ) {
1715
- inlineMessageId = contentOrInline
1716
- content = contentOrExtra
1717
- extra = maybeExtra || {}
1718
- } else {
1719
- content = contentOrInline
1720
- extra = contentOrExtra || {}
1721
- inlineMessageId = extra?.inline_message_id
1722
- }
1723
-
1724
- let htmlText = ''
1725
- let replyMarkup = extra?.reply_markup
1726
-
1727
- // 1. Omni-format input extraction
1728
- if (content && typeof content.build === 'function') {
1729
- const built = content.build()
1730
- if (typeof built === 'object' && built !== null) {
1731
- htmlText = built.html || built.text || built.caption || ''
1732
- if (built.reply_markup) {
1733
- replyMarkup = replyMarkup || built.reply_markup
1734
- }
1735
- } else {
1736
- htmlText = String(built || '')
1737
- }
1738
- } else if (typeof content === 'object' && content !== null) {
1739
- htmlText = content.html || content.text || content.caption || content.markdown || ''
1740
- if (content.reply_markup) {
1741
- replyMarkup = replyMarkup || content.reply_markup
1742
- }
1743
- } else if (typeof content === 'string') {
1744
- htmlText = content
1745
- }
1746
-
1747
- // Sanitize rich HTML formatting (tables, headers, details, etc.)
1748
- htmlText = sanitizeRichHtml(htmlText)
1749
-
1750
- // 2. Prepare Base Payload
1751
- const isInline = Boolean(inlineMessageId || extra?.inline_message_id)
1752
- const basePayload: any = {
1753
- parse_mode: 'HTML',
1692
+ const payload: Record<string, any> = {
1693
+ chat_id: chatId,
1694
+ message_id: Number(messageId),
1695
+ rich_message: typeof richMessage?.build === 'function' ? richMessage.build() : richMessage,
1754
1696
  ...extra,
1755
1697
  }
1756
-
1757
- if (isInline) {
1758
- basePayload.inline_message_id = inlineMessageId || extra.inline_message_id
1759
- } else {
1760
- basePayload.chat_id = chatId
1761
- basePayload.message_id = messageId != null ? Number(messageId) : undefined
1762
- }
1763
-
1764
- if (replyMarkup) {
1765
- basePayload.reply_markup = replyMarkup
1766
- }
1767
-
1768
- // 3. Execution with Auto-Detect (Text -> Caption Fallback) and Silent Error Handling
1769
1698
  try {
1770
- return await this.callApi('editMessageText' as never, {
1771
- ...basePayload,
1772
- text: htmlText,
1773
- } as never)
1699
+ return await this.callApi('editRichMessage' as never, payload as never)
1774
1700
  } catch (err: any) {
1775
1701
  const desc = String(err?.description || err?.message || '')
1776
-
1777
- // Fallback: If target is a Media message (Photo, Video, Audio, Document, Animation)
1778
- if (
1779
- desc.includes('no text in the message') ||
1780
- desc.includes('there is no text in the message to edit') ||
1781
- desc.includes('message to edit not found')
1782
- ) {
1783
- try {
1784
- return await this.callApi('editMessageCaption' as never, {
1785
- ...basePayload,
1786
- caption: htmlText,
1787
- } as never)
1788
- } catch (captionErr: any) {
1789
- const capDesc = String(captionErr?.description || captionErr?.message || '')
1790
- if (capDesc.includes('message is not modified')) {
1791
- return false
1792
- }
1793
- throw captionErr
1794
- }
1795
- }
1796
-
1797
- // Gracefully handle 'message is not modified'
1702
+ // Silent ignore jika konten pesan tidak mengalami perubahan
1798
1703
  if (desc.includes('message is not modified')) {
1799
1704
  return false
1800
1705
  }
1801
-
1802
1706
  throw err
1803
1707
  }
1804
1708
  }
@@ -591,11 +591,9 @@ export declare class Context<U extends Deunionize<tg.Update> = tg.Update> {
591
591
  */
592
592
  sendRichMessageDraft(draftId: number, richMessage: tg.InputRichMessage, extra?: tt.ExtraSendRichMessageDraft): Promise<never>;
593
593
  /**
594
- * Universal Context shortcut to edit message with Omni-Format support (RichHTMLBuilder, Object, or String),
595
- * auto-detection of Text vs Media Caption, and silent 'not modified' error handling.
594
+ * Context-aware shorthand for {@link Telegram.editRichMessage}.
596
595
  */
597
- editRichMessage(content: tg.RichContentInput, extra?: tg.EditRichOptions): Promise<any>;
598
- editRichMessage(messageId: number | string, content: tg.RichContentInput, extra?: tg.EditRichOptions): Promise<any>;
596
+ editRichMessage(richMessage: any, extra?: any): Promise<any>;
599
597
  /**
600
598
  * Enqueue a Telegram API call for the current chat to prevent 429 Too Many Requests errors.
601
599
  */
@@ -690,10 +690,9 @@ export declare class Telegram extends ApiClient {
690
690
  */
691
691
  sendRichMessageDraft(chatId: number, draftId: number, richMessage: tg.InputRichMessage, extra?: tt.ExtraSendRichMessageDraft): Promise<never>;
692
692
  /**
693
- * Universal editRichMessage to update text or media captions in-place with Omni-Format support.
694
- * Auto-detects Text vs Media Caption and gracefully handles 'message is not modified'.
693
+ * Edit a rich message in-place while preserving 100% Native Rich UI layout (tables, headings, cards).
694
+ * @see https://core.telegram.org/bots/api#editrichmessage
695
695
  */
696
- editRichMessage(chatId: number | string | undefined, messageId: number | string | undefined, content: any, extra?: any): Promise<any>;
697
- editRichMessage(chatId: number | string | undefined, messageId: number | string | undefined, inlineMessageId: string | undefined, content: any, extra?: any): Promise<any>;
696
+ editRichMessage(chatId: number | string, messageId: number | string, richMessage: any, extra?: any): Promise<any>;
698
697
  }
699
698
  export default Telegram;