teledzik 1.0.6 → 1.0.7
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.
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Converts Rich HTML strings (containing unsupported Telegram HTML tags like
|
|
4
|
-
* <table>, <ul>, <ol>, <li>, <details>, <h1>-<h6>, <aside>, <p>, <hr>, etc.)
|
|
5
|
-
* into standard Telegram HTML compatible with parse_mode: 'HTML' (editMessageText/sendMessage).
|
|
6
|
-
*/
|
|
7
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
3
|
exports.sanitizeRichHtml = void 0;
|
|
9
|
-
function
|
|
4
|
+
function formatTableToCard(tableHtml) {
|
|
10
5
|
const rows = [];
|
|
11
6
|
const rowMatches = tableHtml.match(/<tr[^>]*>([\s\S]*?)<\/tr>/gi) || [];
|
|
12
7
|
for (const row of rowMatches) {
|
|
@@ -21,45 +16,37 @@ function convertTableToText(tableHtml) {
|
|
|
21
16
|
}
|
|
22
17
|
if (rows.length === 0)
|
|
23
18
|
return '';
|
|
24
|
-
//
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
// Header vs Row handling (Format sebagai Kartu Elegan)
|
|
20
|
+
const isKeyValue = rows.length > 1 && rows.every((r) => r.length === 2);
|
|
21
|
+
let cardText = '';
|
|
22
|
+
if (isKeyValue) {
|
|
23
|
+
const lines = rows.slice(1).map((r) => `• <b>${r[0]}:</b> ${r[1]}`);
|
|
24
|
+
cardText = `<blockquote>\n${lines.join('\n')}\n</blockquote>\n\n`;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
const lines = rows.map((r, idx) => {
|
|
28
|
+
if (idx === 0)
|
|
29
|
+
return `<b>${r.join(' │ ')}</b>`;
|
|
30
|
+
return `${r.join(' │ ')}`;
|
|
30
31
|
});
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const line = r
|
|
35
|
-
.map((c, colIdx) => {
|
|
36
|
-
const textLen = c.replace(/<[^>]+>/g, '').length;
|
|
37
|
-
const pad = ' '.repeat(Math.max(0, (colWidths[colIdx] || 0) - textLen));
|
|
38
|
-
return `${c}${pad}`;
|
|
39
|
-
})
|
|
40
|
-
.join(' │ ');
|
|
41
|
-
if (rowIdx === 0 && rows.length > 1) {
|
|
42
|
-
const sep = colWidths.map((w) => '─'.repeat(w)).join('─┼─');
|
|
43
|
-
return `${line}\n${sep}`;
|
|
44
|
-
}
|
|
45
|
-
return line;
|
|
46
|
-
});
|
|
47
|
-
return `<pre>\n${formattedRows.join('\n')}\n</pre>\n\n`;
|
|
32
|
+
cardText = `<blockquote>\n${lines.join('\n')}\n</blockquote>\n\n`;
|
|
33
|
+
}
|
|
34
|
+
return cardText;
|
|
48
35
|
}
|
|
49
36
|
function sanitizeRichHtml(html) {
|
|
50
37
|
if (!html)
|
|
51
38
|
return html;
|
|
52
39
|
let result = html;
|
|
53
|
-
// 1. Convert Tables
|
|
54
|
-
result = result.replace(/<table[^>]*>([\s\S]*?)<\/table>/gi, (_, content) =>
|
|
55
|
-
// 2. Convert Details
|
|
40
|
+
// 1. Convert Tables to Clean Modern Cards
|
|
41
|
+
result = result.replace(/<table[^>]*>([\s\S]*?)<\/table>/gi, (_, content) => formatTableToCard(content));
|
|
42
|
+
// 2. Convert Details to Telegram Native Expandable Blockquotes
|
|
56
43
|
result = result.replace(/<details[^>]*>\s*<summary[^>]*>(.*?)<\/summary>([\s\S]*?)<\/details>/gi, (_, title, body) => {
|
|
57
|
-
return `<b>▶ ${title.trim()}</b>\n
|
|
44
|
+
return `<blockquote expandable><b>▶ ${title.trim()}</b>\n${body.trim()}</blockquote>\n\n`;
|
|
58
45
|
});
|
|
59
|
-
// 3.
|
|
60
|
-
result = result.replace(/<h1[^>]*>([\s\S]*?)<\/h1>/gi, (_, c) => `<b>${c.trim()
|
|
46
|
+
// 3. Clean Headings
|
|
47
|
+
result = result.replace(/<h1[^>]*>([\s\S]*?)<\/h1>/gi, (_, c) => `<b>${c.trim()}</b>\n\n`);
|
|
61
48
|
result = result.replace(/<h[2-6][^>]*>([\s\S]*?)<\/h[2-6]>/gi, (_, c) => `<b>${c.trim()}</b>\n\n`);
|
|
62
|
-
// 4.
|
|
49
|
+
// 4. Task Lists & Bullet Lists
|
|
63
50
|
result = result.replace(/<ul[^>]*>([\s\S]*?)<\/ul>/gi, (_, listContent) => {
|
|
64
51
|
return (listContent
|
|
65
52
|
.replace(/<li[^>]*>\s*<input[^>]*type="checkbox"[^>]*checked[^>]*>\s*([\s\S]*?)<\/li>/gi, '☑ $1\n')
|
|
@@ -73,29 +60,24 @@ function sanitizeRichHtml(html) {
|
|
|
73
60
|
.replace(/<li[^>]*>([\s\S]*?)<\/li>/gi, (_match, item) => `${index++}. ${item.trim()}\n`)
|
|
74
61
|
.trim() + '\n\n');
|
|
75
62
|
});
|
|
76
|
-
// 5.
|
|
63
|
+
// 5. Clean Blockquotes & Dividers
|
|
77
64
|
result = result.replace(/<aside[^>]*>([\s\S]*?)(?:<cite[^>]*>([\s\S]*?)<\/cite>)?<\/aside>/gi, (_, quote, cite) => {
|
|
78
65
|
return `<blockquote>${quote.trim()}${cite ? `\n— <i>${cite.trim()}</i>` : ''}</blockquote>\n\n`;
|
|
79
66
|
});
|
|
80
|
-
// 6. Convert Special Bot API 10.1 tags
|
|
81
67
|
result = result.replace(/<tg-thinking[^>]*>([\s\S]*?)<\/tg-thinking>/gi, (_, c) => `<blockquote>💭 <i>${c.trim()}</i></blockquote>\n\n`);
|
|
82
68
|
result = result.replace(/<tg-math-block[^>]*>([\s\S]*?)<\/tg-math-block>/gi, (_, c) => `<pre><code>${c.trim()}</code></pre>\n\n`);
|
|
83
69
|
result = result.replace(/<tg-reference[^>]*>([\s\S]*?)<\/tg-reference>/gi, (_, c) => `<i>${c.trim()}</i>`);
|
|
84
70
|
result = result.replace(/<mark[^>]*>([\s\S]*?)<\/mark>/gi, (_, c) => `<b>[${c.trim()}]</b>`);
|
|
85
|
-
// 7. Convert Figures & Captions
|
|
86
71
|
result = result.replace(/<figure[^>]*>[\s\S]*?<figcaption[^>]*>([\s\S]*?)<\/figcaption><\/figure>/gi, (_, cap) => `\n<i>📷 ${cap.trim()}</i>\n`);
|
|
87
|
-
// 8. Convert Paragraphs & Linebreaks
|
|
88
72
|
result = result.replace(/<p[^>]*>([\s\S]*?)<\/p>/gi, (_, c) => `${c.trim()}\n\n`);
|
|
89
73
|
result = result.replace(/<footer[^>]*>([\s\S]*?)<\/footer>/gi, (_, c) => `<i>${c.trim()}</i>\n`);
|
|
90
74
|
result = result.replace(/<br\s*\/?>/gi, '\n');
|
|
91
|
-
result = result.replace(/<hr\s*\/?>/gi, '
|
|
92
|
-
//
|
|
75
|
+
result = result.replace(/<hr\s*\/?>/gi, '\n');
|
|
76
|
+
// Strip unsupported tags
|
|
93
77
|
result = result.replace(/<sub[^>]*>([\s\S]*?)<\/sub>/gi, '$1');
|
|
94
78
|
result = result.replace(/<sup[^>]*>([\s\S]*?)<\/sup>/gi, '$1');
|
|
95
79
|
result = result.replace(/<tg-(map|collage|slideshow)[^>]*>([\s\S]*?)<\/tg-\1>/gi, '$2');
|
|
96
80
|
result = result.replace(/<(img|video|audio|tg-map)[^>]*\/?>/gi, '');
|
|
97
|
-
|
|
98
|
-
result = result.replace(/\n{3,}/g, '\n\n');
|
|
99
|
-
return result.trim();
|
|
81
|
+
return result.replace(/\n{3,}/g, '\n\n').trim();
|
|
100
82
|
}
|
|
101
83
|
exports.sanitizeRichHtml = sanitizeRichHtml;
|
package/lib/telegram.js
CHANGED
|
@@ -1272,22 +1272,66 @@ class Telegram extends client_1.default {
|
|
|
1272
1272
|
});
|
|
1273
1273
|
}
|
|
1274
1274
|
/**
|
|
1275
|
-
*
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1275
|
+
* Universal in-place message editor with Modern Rich UI formatting.
|
|
1276
|
+
*/
|
|
1277
|
+
async editRichMessage(chatId, messageId, content, extra) {
|
|
1278
|
+
let htmlText = '';
|
|
1279
|
+
let replyMarkup = extra?.reply_markup;
|
|
1280
|
+
if (typeof content?.build === 'function') {
|
|
1281
|
+
const built = content.build();
|
|
1282
|
+
if (typeof built === 'object' && built !== null) {
|
|
1283
|
+
htmlText = built.html || built.text || built.caption || '';
|
|
1284
|
+
if (built.reply_markup) {
|
|
1285
|
+
replyMarkup = replyMarkup || built.reply_markup;
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
else {
|
|
1289
|
+
htmlText = String(built || '');
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
else if (typeof content === 'object' && content !== null) {
|
|
1293
|
+
htmlText = content.html || content.text || content.caption || '';
|
|
1294
|
+
if (content.reply_markup) {
|
|
1295
|
+
replyMarkup = replyMarkup || content.reply_markup;
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
else if (typeof content === 'string') {
|
|
1299
|
+
htmlText = content;
|
|
1300
|
+
}
|
|
1301
|
+
// Format ke Telegram Modern HTML
|
|
1302
|
+
htmlText = (0, rich_sanitizer_1.sanitizeRichHtml)(htmlText);
|
|
1279
1303
|
const payload = {
|
|
1280
1304
|
chat_id: chatId,
|
|
1281
1305
|
message_id: Number(messageId),
|
|
1282
|
-
|
|
1306
|
+
text: htmlText,
|
|
1307
|
+
parse_mode: 'HTML',
|
|
1283
1308
|
...extra,
|
|
1284
1309
|
};
|
|
1310
|
+
if (replyMarkup)
|
|
1311
|
+
payload.reply_markup = replyMarkup;
|
|
1285
1312
|
try {
|
|
1286
|
-
return await this.callApi('
|
|
1313
|
+
return await this.callApi('editMessageText', payload);
|
|
1287
1314
|
}
|
|
1288
1315
|
catch (err) {
|
|
1289
1316
|
const desc = String(err?.description || err?.message || '');
|
|
1290
|
-
//
|
|
1317
|
+
// Fallback jika pesan berupa Media (Foto/Video)
|
|
1318
|
+
if (desc.includes('no text in the message') || desc.includes('message to edit not found')) {
|
|
1319
|
+
try {
|
|
1320
|
+
return await this.callApi('editMessageCaption', {
|
|
1321
|
+
chat_id: chatId,
|
|
1322
|
+
message_id: Number(messageId),
|
|
1323
|
+
caption: htmlText,
|
|
1324
|
+
parse_mode: 'HTML',
|
|
1325
|
+
reply_markup: replyMarkup,
|
|
1326
|
+
...extra,
|
|
1327
|
+
});
|
|
1328
|
+
}
|
|
1329
|
+
catch (captionErr) {
|
|
1330
|
+
if (String(captionErr?.description).includes('message is not modified'))
|
|
1331
|
+
return false;
|
|
1332
|
+
throw captionErr;
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1291
1335
|
if (desc.includes('message is not modified')) {
|
|
1292
1336
|
return false;
|
|
1293
1337
|
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
* Converts Rich HTML strings (containing unsupported Telegram HTML tags like
|
|
3
|
-
* <table>, <ul>, <ol>, <li>, <details>, <h1>-<h6>, <aside>, <p>, <hr>, etc.)
|
|
4
|
-
* into standard Telegram HTML compatible with parse_mode: 'HTML' (editMessageText/sendMessage).
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
function convertTableToText(tableHtml: string): string {
|
|
1
|
+
function formatTableToCard(tableHtml: string): string {
|
|
8
2
|
const rows: string[][] = []
|
|
9
3
|
const rowMatches = tableHtml.match(/<tr[^>]*>([\s\S]*?)<\/tr>/gi) || []
|
|
10
|
-
|
|
11
4
|
for (const row of rowMatches) {
|
|
12
5
|
const cells: string[] = []
|
|
13
6
|
const cellMatches = row.match(/<(th|td)[^>]*>([\s\S]*?)<\/\1>/gi) || []
|
|
@@ -17,56 +10,41 @@ function convertTableToText(tableHtml: string): string {
|
|
|
17
10
|
}
|
|
18
11
|
if (cells.length > 0) rows.push(cells)
|
|
19
12
|
}
|
|
20
|
-
|
|
21
13
|
if (rows.length === 0) return ''
|
|
22
14
|
|
|
23
|
-
//
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
15
|
+
// Header vs Row handling (Format sebagai Kartu Elegan)
|
|
16
|
+
const isKeyValue = rows.length > 1 && rows.every((r) => r.length === 2)
|
|
17
|
+
let cardText = ''
|
|
18
|
+
if (isKeyValue) {
|
|
19
|
+
const lines = rows.slice(1).map((r) => `• <b>${r[0]}:</b> ${r[1]}`)
|
|
20
|
+
cardText = `<blockquote>\n${lines.join('\n')}\n</blockquote>\n\n`
|
|
21
|
+
} else {
|
|
22
|
+
const lines = rows.map((r, idx) => {
|
|
23
|
+
if (idx === 0) return `<b>${r.join(' │ ')}</b>`
|
|
24
|
+
return `${r.join(' │ ')}`
|
|
29
25
|
})
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const formattedRows = rows.map((r, rowIdx) => {
|
|
34
|
-
const line = r
|
|
35
|
-
.map((c, colIdx) => {
|
|
36
|
-
const textLen = c.replace(/<[^>]+>/g, '').length
|
|
37
|
-
const pad = ' '.repeat(Math.max(0, (colWidths[colIdx] || 0) - textLen))
|
|
38
|
-
return `${c}${pad}`
|
|
39
|
-
})
|
|
40
|
-
.join(' │ ')
|
|
41
|
-
|
|
42
|
-
if (rowIdx === 0 && rows.length > 1) {
|
|
43
|
-
const sep = colWidths.map((w) => '─'.repeat(w)).join('─┼─')
|
|
44
|
-
return `${line}\n${sep}`
|
|
45
|
-
}
|
|
46
|
-
return line
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
return `<pre>\n${formattedRows.join('\n')}\n</pre>\n\n`
|
|
26
|
+
cardText = `<blockquote>\n${lines.join('\n')}\n</blockquote>\n\n`
|
|
27
|
+
}
|
|
28
|
+
return cardText
|
|
50
29
|
}
|
|
51
30
|
|
|
52
31
|
export function sanitizeRichHtml(html: string): string {
|
|
53
32
|
if (!html) return html
|
|
54
|
-
|
|
55
33
|
let result = html
|
|
56
34
|
|
|
57
|
-
// 1. Convert Tables
|
|
58
|
-
result = result.replace(/<table[^>]*>([\s\S]*?)<\/table>/gi, (_, content) =>
|
|
35
|
+
// 1. Convert Tables to Clean Modern Cards
|
|
36
|
+
result = result.replace(/<table[^>]*>([\s\S]*?)<\/table>/gi, (_, content) => formatTableToCard(content))
|
|
59
37
|
|
|
60
|
-
// 2. Convert Details
|
|
38
|
+
// 2. Convert Details to Telegram Native Expandable Blockquotes
|
|
61
39
|
result = result.replace(/<details[^>]*>\s*<summary[^>]*>(.*?)<\/summary>([\s\S]*?)<\/details>/gi, (_, title, body) => {
|
|
62
|
-
return `<b>▶ ${title.trim()}</b>\n
|
|
40
|
+
return `<blockquote expandable><b>▶ ${title.trim()}</b>\n${body.trim()}</blockquote>\n\n`
|
|
63
41
|
})
|
|
64
42
|
|
|
65
|
-
// 3.
|
|
66
|
-
result = result.replace(/<h1[^>]*>([\s\S]*?)<\/h1>/gi, (_, c) => `<b>${c.trim()
|
|
43
|
+
// 3. Clean Headings
|
|
44
|
+
result = result.replace(/<h1[^>]*>([\s\S]*?)<\/h1>/gi, (_, c) => `<b>${c.trim()}</b>\n\n`)
|
|
67
45
|
result = result.replace(/<h[2-6][^>]*>([\s\S]*?)<\/h[2-6]>/gi, (_, c) => `<b>${c.trim()}</b>\n\n`)
|
|
68
46
|
|
|
69
|
-
// 4.
|
|
47
|
+
// 4. Task Lists & Bullet Lists
|
|
70
48
|
result = result.replace(/<ul[^>]*>([\s\S]*?)<\/ul>/gi, (_, listContent) => {
|
|
71
49
|
return (
|
|
72
50
|
listContent
|
|
@@ -86,34 +64,28 @@ export function sanitizeRichHtml(html: string): string {
|
|
|
86
64
|
)
|
|
87
65
|
})
|
|
88
66
|
|
|
89
|
-
// 5.
|
|
67
|
+
// 5. Clean Blockquotes & Dividers
|
|
90
68
|
result = result.replace(/<aside[^>]*>([\s\S]*?)(?:<cite[^>]*>([\s\S]*?)<\/cite>)?<\/aside>/gi, (_, quote, cite) => {
|
|
91
69
|
return `<blockquote>${quote.trim()}${cite ? `\n— <i>${cite.trim()}</i>` : ''}</blockquote>\n\n`
|
|
92
70
|
})
|
|
93
71
|
|
|
94
|
-
// 6. Convert Special Bot API 10.1 tags
|
|
95
72
|
result = result.replace(/<tg-thinking[^>]*>([\s\S]*?)<\/tg-thinking>/gi, (_, c) => `<blockquote>💭 <i>${c.trim()}</i></blockquote>\n\n`)
|
|
96
73
|
result = result.replace(/<tg-math-block[^>]*>([\s\S]*?)<\/tg-math-block>/gi, (_, c) => `<pre><code>${c.trim()}</code></pre>\n\n`)
|
|
97
74
|
result = result.replace(/<tg-reference[^>]*>([\s\S]*?)<\/tg-reference>/gi, (_, c) => `<i>${c.trim()}</i>`)
|
|
98
75
|
result = result.replace(/<mark[^>]*>([\s\S]*?)<\/mark>/gi, (_, c) => `<b>[${c.trim()}]</b>`)
|
|
99
76
|
|
|
100
|
-
// 7. Convert Figures & Captions
|
|
101
77
|
result = result.replace(/<figure[^>]*>[\s\S]*?<figcaption[^>]*>([\s\S]*?)<\/figcaption><\/figure>/gi, (_, cap) => `\n<i>📷 ${cap.trim()}</i>\n`)
|
|
102
78
|
|
|
103
|
-
// 8. Convert Paragraphs & Linebreaks
|
|
104
79
|
result = result.replace(/<p[^>]*>([\s\S]*?)<\/p>/gi, (_, c) => `${c.trim()}\n\n`)
|
|
105
80
|
result = result.replace(/<footer[^>]*>([\s\S]*?)<\/footer>/gi, (_, c) => `<i>${c.trim()}</i>\n`)
|
|
106
81
|
result = result.replace(/<br\s*\/?>/gi, '\n')
|
|
107
|
-
result = result.replace(/<hr\s*\/?>/gi, '
|
|
82
|
+
result = result.replace(/<hr\s*\/?>/gi, '\n')
|
|
108
83
|
|
|
109
|
-
//
|
|
84
|
+
// Strip unsupported tags
|
|
110
85
|
result = result.replace(/<sub[^>]*>([\s\S]*?)<\/sub>/gi, '$1')
|
|
111
86
|
result = result.replace(/<sup[^>]*>([\s\S]*?)<\/sup>/gi, '$1')
|
|
112
87
|
result = result.replace(/<tg-(map|collage|slideshow)[^>]*>([\s\S]*?)<\/tg-\1>/gi, '$2')
|
|
113
88
|
result = result.replace(/<(img|video|audio|tg-map)[^>]*\/?>/gi, '')
|
|
114
89
|
|
|
115
|
-
|
|
116
|
-
result = result.replace(/\n{3,}/g, '\n\n')
|
|
117
|
-
|
|
118
|
-
return result.trim()
|
|
90
|
+
return result.replace(/\n{3,}/g, '\n\n').trim()
|
|
119
91
|
}
|
package/src/telegram.ts
CHANGED
|
@@ -1680,26 +1680,69 @@ export class Telegram extends ApiClient {
|
|
|
1680
1680
|
}
|
|
1681
1681
|
|
|
1682
1682
|
/**
|
|
1683
|
-
*
|
|
1684
|
-
* @see https://core.telegram.org/bots/api#editrichmessage
|
|
1683
|
+
* Universal in-place message editor with Modern Rich UI formatting.
|
|
1685
1684
|
*/
|
|
1686
1685
|
async editRichMessage(
|
|
1687
1686
|
chatId: number | string,
|
|
1688
1687
|
messageId: number | string,
|
|
1689
|
-
|
|
1688
|
+
content: any,
|
|
1690
1689
|
extra?: any
|
|
1691
1690
|
): Promise<any> {
|
|
1691
|
+
let htmlText = ''
|
|
1692
|
+
let replyMarkup = extra?.reply_markup
|
|
1693
|
+
|
|
1694
|
+
if (typeof content?.build === 'function') {
|
|
1695
|
+
const built = content.build()
|
|
1696
|
+
if (typeof built === 'object' && built !== null) {
|
|
1697
|
+
htmlText = built.html || built.text || built.caption || ''
|
|
1698
|
+
if (built.reply_markup) {
|
|
1699
|
+
replyMarkup = replyMarkup || built.reply_markup
|
|
1700
|
+
}
|
|
1701
|
+
} else {
|
|
1702
|
+
htmlText = String(built || '')
|
|
1703
|
+
}
|
|
1704
|
+
} else if (typeof content === 'object' && content !== null) {
|
|
1705
|
+
htmlText = content.html || content.text || content.caption || ''
|
|
1706
|
+
if (content.reply_markup) {
|
|
1707
|
+
replyMarkup = replyMarkup || content.reply_markup
|
|
1708
|
+
}
|
|
1709
|
+
} else if (typeof content === 'string') {
|
|
1710
|
+
htmlText = content
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
// Format ke Telegram Modern HTML
|
|
1714
|
+
htmlText = sanitizeRichHtml(htmlText)
|
|
1715
|
+
|
|
1692
1716
|
const payload: Record<string, any> = {
|
|
1693
1717
|
chat_id: chatId,
|
|
1694
1718
|
message_id: Number(messageId),
|
|
1695
|
-
|
|
1719
|
+
text: htmlText,
|
|
1720
|
+
parse_mode: 'HTML',
|
|
1696
1721
|
...extra,
|
|
1697
1722
|
}
|
|
1723
|
+
|
|
1724
|
+
if (replyMarkup) payload.reply_markup = replyMarkup
|
|
1725
|
+
|
|
1698
1726
|
try {
|
|
1699
|
-
return await this.callApi('
|
|
1727
|
+
return await this.callApi('editMessageText' as never, payload as never)
|
|
1700
1728
|
} catch (err: any) {
|
|
1701
1729
|
const desc = String(err?.description || err?.message || '')
|
|
1702
|
-
//
|
|
1730
|
+
// Fallback jika pesan berupa Media (Foto/Video)
|
|
1731
|
+
if (desc.includes('no text in the message') || desc.includes('message to edit not found')) {
|
|
1732
|
+
try {
|
|
1733
|
+
return await this.callApi('editMessageCaption' as never, {
|
|
1734
|
+
chat_id: chatId,
|
|
1735
|
+
message_id: Number(messageId),
|
|
1736
|
+
caption: htmlText,
|
|
1737
|
+
parse_mode: 'HTML',
|
|
1738
|
+
reply_markup: replyMarkup,
|
|
1739
|
+
...extra,
|
|
1740
|
+
} as never)
|
|
1741
|
+
} catch (captionErr: any) {
|
|
1742
|
+
if (String(captionErr?.description).includes('message is not modified')) return false
|
|
1743
|
+
throw captionErr
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1703
1746
|
if (desc.includes('message is not modified')) {
|
|
1704
1747
|
return false
|
|
1705
1748
|
}
|
|
@@ -1,6 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Converts Rich HTML strings (containing unsupported Telegram HTML tags like
|
|
3
|
-
* <table>, <ul>, <ol>, <li>, <details>, <h1>-<h6>, <aside>, <p>, <hr>, etc.)
|
|
4
|
-
* into standard Telegram HTML compatible with parse_mode: 'HTML' (editMessageText/sendMessage).
|
|
5
|
-
*/
|
|
6
1
|
export declare function sanitizeRichHtml(html: string): string;
|
package/typings/telegram.d.ts
CHANGED
|
@@ -690,9 +690,8 @@ 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
|
-
*
|
|
694
|
-
* @see https://core.telegram.org/bots/api#editrichmessage
|
|
693
|
+
* Universal in-place message editor with Modern Rich UI formatting.
|
|
695
694
|
*/
|
|
696
|
-
editRichMessage(chatId: number | string, messageId: number | string,
|
|
695
|
+
editRichMessage(chatId: number | string, messageId: number | string, content: any, extra?: any): Promise<any>;
|
|
697
696
|
}
|
|
698
697
|
export default Telegram;
|