telegix 1.1.2 → 1.1.3
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 +615 -14
- package/index.cjs +6657 -3272
- package/index.js +66 -2
- package/lib/api.js +270 -18
- package/lib/context.js +201 -2
- package/lib/ephemeral.js +353 -0
- package/lib/rich.js +1992 -159
- package/lib/serialize.js +11 -0
- package/lib/table.js +1124 -0
- package/package.json +1 -1
package/lib/rich.js
CHANGED
|
@@ -1,12 +1,1373 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Telegix - Rich Message & Draft Builder Suite
|
|
3
|
-
* Modern structured rich messages, cards, drafts, and layout blocks
|
|
2
|
+
* Telegix - Rich Message & Draft Builder Suite (Telegram Bot API 10.3+)
|
|
3
|
+
* Modern structured rich messages, cards, drafts, tables, buttons, and layout blocks.
|
|
4
4
|
* @module telegix/rich
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { escapeHtml, html } from './format.js';
|
|
8
8
|
import { Markup } from './markup.js';
|
|
9
|
+
import { Table, InputRichBlockTable, RichBlockTable } from './table.js';
|
|
10
|
+
import { EphemeralMessageParameters } from './ephemeral.js';
|
|
9
11
|
|
|
12
|
+
export { Table, InputRichBlockTable, RichBlockTable } from './table.js';
|
|
13
|
+
export { EphemeralMessageParameters } from './ephemeral.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Telegram Bot API 10.3 RichMessageButton class
|
|
17
|
+
* Represents a button in a RichMessage
|
|
18
|
+
*/
|
|
19
|
+
export class RichMessageButton {
|
|
20
|
+
/**
|
|
21
|
+
* @param {string} text
|
|
22
|
+
* @param {object} [options]
|
|
23
|
+
*/
|
|
24
|
+
constructor(text, options = {}) {
|
|
25
|
+
this.text = String(text);
|
|
26
|
+
this.options = options;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Convert to Telegram button object
|
|
31
|
+
*/
|
|
32
|
+
toJSON() {
|
|
33
|
+
return {
|
|
34
|
+
text: this.text,
|
|
35
|
+
...this.options,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static url(text, url) {
|
|
40
|
+
return new RichMessageButton(text, { url });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static callback(text, data) {
|
|
44
|
+
return new RichMessageButton(text, { callback_data: String(data) });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static copyText(text, copyText) {
|
|
48
|
+
return new RichMessageButton(text, { copy_text: { text: String(copyText) } });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static webApp(text, url) {
|
|
52
|
+
return new RichMessageButton(text, { web_app: { url } });
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
static primary(text, dataOrUrl, options = {}) {
|
|
56
|
+
return new RichMessageButton(text, {
|
|
57
|
+
style: 'primary',
|
|
58
|
+
...RichMessageButton._resolveDataOrUrl(dataOrUrl),
|
|
59
|
+
...options,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
static danger(text, dataOrUrl, options = {}) {
|
|
64
|
+
return new RichMessageButton(text, {
|
|
65
|
+
style: 'danger',
|
|
66
|
+
...RichMessageButton._resolveDataOrUrl(dataOrUrl),
|
|
67
|
+
...options,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static success(text, dataOrUrl, options = {}) {
|
|
72
|
+
return new RichMessageButton(text, {
|
|
73
|
+
style: 'success',
|
|
74
|
+
...RichMessageButton._resolveDataOrUrl(dataOrUrl),
|
|
75
|
+
...options,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
static colored(text, style, dataOrUrl, options = {}) {
|
|
80
|
+
return new RichMessageButton(text, {
|
|
81
|
+
style,
|
|
82
|
+
...RichMessageButton._resolveDataOrUrl(dataOrUrl),
|
|
83
|
+
...options,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
static disabled(text) {
|
|
88
|
+
return new RichMessageButton(text, { disabled: true });
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static document(text, documentId) {
|
|
92
|
+
return new RichMessageButton(text, { url: `tg://document?id=${documentId}` });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
static _resolveDataOrUrl(dataOrUrl) {
|
|
96
|
+
if (!dataOrUrl) return {};
|
|
97
|
+
if (typeof dataOrUrl === 'string') {
|
|
98
|
+
if (/^(https?:\/\/|tg:\/\/)/i.test(dataOrUrl)) {
|
|
99
|
+
return { url: dataOrUrl };
|
|
100
|
+
}
|
|
101
|
+
return { callback_data: dataOrUrl };
|
|
102
|
+
}
|
|
103
|
+
if (typeof dataOrUrl === 'number') {
|
|
104
|
+
return { callback_data: String(dataOrUrl) };
|
|
105
|
+
}
|
|
106
|
+
if (typeof dataOrUrl === 'object') {
|
|
107
|
+
return dataOrUrl;
|
|
108
|
+
}
|
|
109
|
+
return {};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Telegram Bot API 10.3 RichTextButton class
|
|
115
|
+
* Represents an inline text button / link inside rich text or blocks
|
|
116
|
+
*/
|
|
117
|
+
export class RichTextButton {
|
|
118
|
+
/**
|
|
119
|
+
* @param {string} text
|
|
120
|
+
* @param {object} [options]
|
|
121
|
+
*/
|
|
122
|
+
constructor(text, options = {}) {
|
|
123
|
+
this.text = String(text);
|
|
124
|
+
this.options = options;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
toJSON() {
|
|
128
|
+
return {
|
|
129
|
+
type: 'rich_text_button',
|
|
130
|
+
text: this.text,
|
|
131
|
+
...this.options,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
toHtml() {
|
|
136
|
+
if (this.options.url) {
|
|
137
|
+
return `<a href="${escapeHtml(this.options.url)}">${escapeHtml(this.text)}</a>`;
|
|
138
|
+
}
|
|
139
|
+
if (this.options.callback_data) {
|
|
140
|
+
return `<b>[${escapeHtml(this.text)}]</b>`;
|
|
141
|
+
}
|
|
142
|
+
return escapeHtml(this.text);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
static url(text, url) {
|
|
146
|
+
return new RichTextButton(text, { url });
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
static callback(text, data) {
|
|
150
|
+
return new RichTextButton(text, { callback_data: String(data) });
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
static document(text, documentId) {
|
|
154
|
+
return new RichTextButton(text, { url: `tg://document?id=${documentId}` });
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
static user(text, userId) {
|
|
158
|
+
return new RichTextButton(text, { url: `tg://user?id=${userId}` });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Telegram Bot API 10.3 InputRichBlockButtons class
|
|
164
|
+
* Represents a block containing button rows in a rich message
|
|
165
|
+
*/
|
|
166
|
+
export class InputRichBlockButtons {
|
|
167
|
+
/**
|
|
168
|
+
* @param {Array<Array<object>>|Array<object>} [buttons=[]]
|
|
169
|
+
*/
|
|
170
|
+
constructor(buttons = []) {
|
|
171
|
+
this.type = 'buttons';
|
|
172
|
+
this.buttons = Array.isArray(buttons) ? buttons : [buttons];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
addRow(...buttons) {
|
|
176
|
+
this.buttons.push(buttons.flat());
|
|
177
|
+
return this;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
addButton(button) {
|
|
181
|
+
if (this.buttons.length === 0) {
|
|
182
|
+
this.buttons.push([button]);
|
|
183
|
+
} else {
|
|
184
|
+
this.buttons[this.buttons.length - 1].push(button);
|
|
185
|
+
}
|
|
186
|
+
return this;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
toJSON() {
|
|
190
|
+
return {
|
|
191
|
+
type: 'buttons',
|
|
192
|
+
buttons: this.buttons.map((row) =>
|
|
193
|
+
Array.isArray(row)
|
|
194
|
+
? row.map((btn) => (typeof btn?.toJSON === 'function' ? btn.toJSON() : btn))
|
|
195
|
+
: typeof row?.toJSON === 'function'
|
|
196
|
+
? row.toJSON()
|
|
197
|
+
: row
|
|
198
|
+
),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
toHtml() {
|
|
203
|
+
const lines = [];
|
|
204
|
+
for (const row of this.buttons) {
|
|
205
|
+
if (Array.isArray(row)) {
|
|
206
|
+
const rowTexts = row.map((btn) => {
|
|
207
|
+
const text = btn.text || String(btn);
|
|
208
|
+
if (btn.url) {
|
|
209
|
+
return `<a href="${escapeHtml(btn.url)}">${escapeHtml(text)}</a>`;
|
|
210
|
+
}
|
|
211
|
+
return `[${escapeHtml(text)}]`;
|
|
212
|
+
});
|
|
213
|
+
lines.push(rowTexts.join(' '));
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return lines.join('\n');
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
static create(buttons) {
|
|
220
|
+
return new InputRichBlockButtons(buttons);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export const RichBlockButtons = InputRichBlockButtons;
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Telegram Bot API 10.3 InputRichBlockExpandableBlockQuotation class
|
|
228
|
+
* Represents a block quotation, which can be expanded or collapsed back
|
|
229
|
+
*/
|
|
230
|
+
export class InputRichBlockExpandableBlockQuotation {
|
|
231
|
+
/**
|
|
232
|
+
* @param {string} text
|
|
233
|
+
* @param {object} [options]
|
|
234
|
+
*/
|
|
235
|
+
constructor(text, options = {}) {
|
|
236
|
+
this.type = 'expandable_block_quotation';
|
|
237
|
+
this.text = String(text || '');
|
|
238
|
+
this.options = options;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
toJSON() {
|
|
242
|
+
return {
|
|
243
|
+
type: 'expandable_block_quotation',
|
|
244
|
+
text: this.text,
|
|
245
|
+
...this.options,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
toHtml() {
|
|
250
|
+
return `<blockquote expandable>${escapeHtml(this.text)}</blockquote>`;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
static create(text, options) {
|
|
254
|
+
return new InputRichBlockExpandableBlockQuotation(text, options);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export const RichBlockExpandableBlockQuotation = InputRichBlockExpandableBlockQuotation;
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Telegram Bot API 10.3 InputRichBlockDocument class
|
|
262
|
+
* Represents a block containing a file or document link
|
|
263
|
+
*/
|
|
264
|
+
export class InputRichBlockDocument {
|
|
265
|
+
/**
|
|
266
|
+
* @param {string|object} document
|
|
267
|
+
* @param {string} [caption='']
|
|
268
|
+
* @param {object} [options={}]
|
|
269
|
+
*/
|
|
270
|
+
constructor(document, caption = '', options = {}) {
|
|
271
|
+
this.type = 'document';
|
|
272
|
+
this.document = document;
|
|
273
|
+
this.caption = String(caption || '');
|
|
274
|
+
this.options = options;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
toJSON() {
|
|
278
|
+
return {
|
|
279
|
+
type: 'document',
|
|
280
|
+
document: this.document,
|
|
281
|
+
caption: this.caption,
|
|
282
|
+
...this.options,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
toHtml() {
|
|
287
|
+
if (typeof this.document === 'string' && this.document.startsWith('tg://')) {
|
|
288
|
+
return `<a href="${escapeHtml(this.document)}">📄 ${escapeHtml(this.caption || 'Document')}</a>`;
|
|
289
|
+
}
|
|
290
|
+
return `📄 <b>Document:</b> ${escapeHtml(this.caption || String(this.document))}`;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
static create(document, caption, options) {
|
|
294
|
+
return new InputRichBlockDocument(document, caption, options);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export const RichBlockDocument = InputRichBlockDocument;
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Telegram Bot API 10.2 InputRichBlockParagraph class
|
|
302
|
+
* Represents a standard paragraph of rich text
|
|
303
|
+
*/
|
|
304
|
+
export class InputRichBlockParagraph {
|
|
305
|
+
/**
|
|
306
|
+
* @param {string} text
|
|
307
|
+
* @param {object} [options={}]
|
|
308
|
+
*/
|
|
309
|
+
constructor(text, options = {}) {
|
|
310
|
+
this.type = 'paragraph';
|
|
311
|
+
this.text = String(text ?? '');
|
|
312
|
+
this.options = options;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
toJSON() {
|
|
316
|
+
return {
|
|
317
|
+
type: 'paragraph',
|
|
318
|
+
text: this.text,
|
|
319
|
+
...this.options,
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
toHtml() {
|
|
324
|
+
return `<p>${escapeHtml(this.text)}</p>`;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
static create(text, options) {
|
|
328
|
+
return new InputRichBlockParagraph(text, options);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
export const RichBlockParagraph = InputRichBlockParagraph;
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Telegram Bot API 10.2 InputRichBlockSectionHeading class
|
|
335
|
+
* Represents a section heading with level 1-6
|
|
336
|
+
*/
|
|
337
|
+
export class InputRichBlockSectionHeading {
|
|
338
|
+
/**
|
|
339
|
+
* @param {string} text
|
|
340
|
+
* @param {number} [level=2]
|
|
341
|
+
* @param {object} [options={}]
|
|
342
|
+
*/
|
|
343
|
+
constructor(text, level = 2, options = {}) {
|
|
344
|
+
this.type = 'section_heading';
|
|
345
|
+
this.text = String(text ?? '');
|
|
346
|
+
this.level = Math.max(1, Math.min(6, Number(level) || 2));
|
|
347
|
+
this.options = options;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
toJSON() {
|
|
351
|
+
return {
|
|
352
|
+
type: 'section_heading',
|
|
353
|
+
text: this.text,
|
|
354
|
+
level: this.level,
|
|
355
|
+
...this.options,
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
toHtml() {
|
|
360
|
+
return `<b>${escapeHtml(this.text)}</b>`;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
static create(text, level, options) {
|
|
364
|
+
return new InputRichBlockSectionHeading(text, level, options);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
export const RichBlockSectionHeading = InputRichBlockSectionHeading;
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Telegram Bot API 10.2 InputRichBlockPreformatted class
|
|
371
|
+
* Represents preformatted code or text with optional programming language syntax
|
|
372
|
+
*/
|
|
373
|
+
export class InputRichBlockPreformatted {
|
|
374
|
+
/**
|
|
375
|
+
* @param {string} text
|
|
376
|
+
* @param {string} [language='']
|
|
377
|
+
* @param {object} [options={}]
|
|
378
|
+
*/
|
|
379
|
+
constructor(text, language = '', options = {}) {
|
|
380
|
+
this.type = 'preformatted';
|
|
381
|
+
this.text = String(text ?? '');
|
|
382
|
+
this.language = String(language || '');
|
|
383
|
+
this.options = options;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
toJSON() {
|
|
387
|
+
return {
|
|
388
|
+
type: 'preformatted',
|
|
389
|
+
text: this.text,
|
|
390
|
+
...(this.language ? { language: this.language } : {}),
|
|
391
|
+
...this.options,
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
toHtml() {
|
|
396
|
+
if (this.language) {
|
|
397
|
+
return `<pre><code class="language-${escapeHtml(this.language)}">${escapeHtml(this.text)}</code></pre>`;
|
|
398
|
+
}
|
|
399
|
+
return `<pre>${escapeHtml(this.text)}</pre>`;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
static create(text, language, options) {
|
|
403
|
+
return new InputRichBlockPreformatted(text, language, options);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
export const RichBlockPreformatted = InputRichBlockPreformatted;
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Telegram Bot API 10.2 InputRichBlockFooter class
|
|
410
|
+
* Represents small footer or timestamp text
|
|
411
|
+
*/
|
|
412
|
+
export class InputRichBlockFooter {
|
|
413
|
+
/**
|
|
414
|
+
* @param {string} text
|
|
415
|
+
* @param {object} [options={}]
|
|
416
|
+
*/
|
|
417
|
+
constructor(text, options = {}) {
|
|
418
|
+
this.type = 'footer';
|
|
419
|
+
this.text = String(text ?? '');
|
|
420
|
+
this.options = options;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
toJSON() {
|
|
424
|
+
return {
|
|
425
|
+
type: 'footer',
|
|
426
|
+
text: this.text,
|
|
427
|
+
...this.options,
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
toHtml() {
|
|
432
|
+
return `<i>${escapeHtml(this.text)}</i>`;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
static create(text, options) {
|
|
436
|
+
return new InputRichBlockFooter(text, options);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
export const RichBlockFooter = InputRichBlockFooter;
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Telegram Bot API 10.2 InputRichBlockDivider class
|
|
443
|
+
* Represents a horizontal divider / separator
|
|
444
|
+
*/
|
|
445
|
+
export class InputRichBlockDivider {
|
|
446
|
+
/**
|
|
447
|
+
* @param {object} [options={}]
|
|
448
|
+
*/
|
|
449
|
+
constructor(options = {}) {
|
|
450
|
+
this.type = 'divider';
|
|
451
|
+
this.options = options;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
toJSON() {
|
|
455
|
+
return {
|
|
456
|
+
type: 'divider',
|
|
457
|
+
...this.options,
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
toHtml() {
|
|
462
|
+
return '──────────────────────────────';
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
static create(options) {
|
|
466
|
+
return new InputRichBlockDivider(options);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
export const RichBlockDivider = InputRichBlockDivider;
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Telegram Bot API 10.2 InputRichBlockMathematicalExpression class
|
|
473
|
+
* Represents LaTeX or mathematical expression
|
|
474
|
+
*/
|
|
475
|
+
export class InputRichBlockMathematicalExpression {
|
|
476
|
+
/**
|
|
477
|
+
* @param {string} expression
|
|
478
|
+
* @param {object} [options={}]
|
|
479
|
+
*/
|
|
480
|
+
constructor(expression, options = {}) {
|
|
481
|
+
this.type = 'mathematical_expression';
|
|
482
|
+
this.expression = String(expression ?? '');
|
|
483
|
+
this.options = options;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
toJSON() {
|
|
487
|
+
return {
|
|
488
|
+
type: 'mathematical_expression',
|
|
489
|
+
expression: this.expression,
|
|
490
|
+
...this.options,
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
toHtml() {
|
|
495
|
+
return `<tg-math>${escapeHtml(this.expression)}</tg-math>`;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
static create(expression, options) {
|
|
499
|
+
return new InputRichBlockMathematicalExpression(expression, options);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
export const RichBlockMathematicalExpression = InputRichBlockMathematicalExpression;
|
|
503
|
+
export const RichBlockMath = InputRichBlockMathematicalExpression;
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Telegram Bot API 10.2 InputRichBlockAnchor class
|
|
507
|
+
* Represents an in-message anchor point for internal linking
|
|
508
|
+
*/
|
|
509
|
+
export class InputRichBlockAnchor {
|
|
510
|
+
/**
|
|
511
|
+
* @param {string} name
|
|
512
|
+
* @param {string} [text='']
|
|
513
|
+
* @param {object} [options={}]
|
|
514
|
+
*/
|
|
515
|
+
constructor(name, text = '', options = {}) {
|
|
516
|
+
this.type = 'anchor';
|
|
517
|
+
this.name = String(name ?? '');
|
|
518
|
+
this.text = String(text ?? '');
|
|
519
|
+
this.options = options;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
toJSON() {
|
|
523
|
+
return {
|
|
524
|
+
type: 'anchor',
|
|
525
|
+
name: this.name,
|
|
526
|
+
...(this.text ? { text: this.text } : {}),
|
|
527
|
+
...this.options,
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
toHtml() {
|
|
532
|
+
return `<a name="${escapeHtml(this.name)}">${escapeHtml(this.text)}</a>`;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
static create(name, text, options) {
|
|
536
|
+
return new InputRichBlockAnchor(name, text, options);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
export const RichBlockAnchor = InputRichBlockAnchor;
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Telegram Bot API 10.2 InputRichBlockListItem class
|
|
543
|
+
* Represents a single item inside an InputRichBlockList (bullet, numbered, or checklist)
|
|
544
|
+
*/
|
|
545
|
+
export class InputRichBlockListItem {
|
|
546
|
+
/**
|
|
547
|
+
* @param {string} text
|
|
548
|
+
* @param {object} [options={}]
|
|
549
|
+
* @param {boolean|null} [options.is_checked] - True for checked checkbox, false for unchecked, null for bullet
|
|
550
|
+
* @param {number|null} [options.number] - Numeric index for numbered lists
|
|
551
|
+
* @param {string} [options.type] - Item type override
|
|
552
|
+
*/
|
|
553
|
+
constructor(text, options = {}) {
|
|
554
|
+
this.text = String(text ?? '');
|
|
555
|
+
this.is_checked = options.is_checked ?? options.isChecked ?? null;
|
|
556
|
+
this.number = options.number !== undefined && options.number !== null ? Number(options.number) : null;
|
|
557
|
+
this.type = options.type ?? null;
|
|
558
|
+
this.options = options;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* Check this item (for checklists)
|
|
563
|
+
* @param {boolean} [checked=true]
|
|
564
|
+
* @returns {this}
|
|
565
|
+
*/
|
|
566
|
+
check(checked = true) {
|
|
567
|
+
this.is_checked = Boolean(checked);
|
|
568
|
+
return this;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Uncheck this item
|
|
573
|
+
* @returns {this}
|
|
574
|
+
*/
|
|
575
|
+
uncheck() {
|
|
576
|
+
this.is_checked = false;
|
|
577
|
+
return this;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
toJSON() {
|
|
581
|
+
const res = {
|
|
582
|
+
text: this.text,
|
|
583
|
+
};
|
|
584
|
+
if (this.is_checked !== null && this.is_checked !== undefined) {
|
|
585
|
+
res.is_checked = Boolean(this.is_checked);
|
|
586
|
+
}
|
|
587
|
+
if (this.number !== null && this.number !== undefined) {
|
|
588
|
+
res.number = Number(this.number);
|
|
589
|
+
}
|
|
590
|
+
if (this.type) {
|
|
591
|
+
res.type = this.type;
|
|
592
|
+
}
|
|
593
|
+
return res;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
toHtml() {
|
|
597
|
+
if (this.is_checked === true) {
|
|
598
|
+
return `☑️ ${escapeHtml(this.text)}`;
|
|
599
|
+
}
|
|
600
|
+
if (this.is_checked === false) {
|
|
601
|
+
return `◻️ ${escapeHtml(this.text)}`;
|
|
602
|
+
}
|
|
603
|
+
if (this.number !== null) {
|
|
604
|
+
return `${this.number}. ${escapeHtml(this.text)}`;
|
|
605
|
+
}
|
|
606
|
+
return `• ${escapeHtml(this.text)}`;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
static checked(text, options = {}) {
|
|
610
|
+
return new InputRichBlockListItem(text, { is_checked: true, ...options });
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
static unchecked(text, options = {}) {
|
|
614
|
+
return new InputRichBlockListItem(text, { is_checked: false, ...options });
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
static bullet(text, options = {}) {
|
|
618
|
+
return new InputRichBlockListItem(text, options);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
static numbered(number, text, options = {}) {
|
|
622
|
+
return new InputRichBlockListItem(text, { number, ...options });
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
export const RichBlockListItem = InputRichBlockListItem;
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* Telegram Bot API 10.2 InputRichBlockList class
|
|
629
|
+
* Represents ordered, unordered, or checklist collections
|
|
630
|
+
*/
|
|
631
|
+
export class InputRichBlockList {
|
|
632
|
+
/**
|
|
633
|
+
* @param {Array<InputRichBlockListItem|string|object>} [items=[]]
|
|
634
|
+
* @param {object} [options={}]
|
|
635
|
+
* @param {boolean} [options.ordered=false]
|
|
636
|
+
*/
|
|
637
|
+
constructor(items = [], options = {}) {
|
|
638
|
+
this.type = 'list';
|
|
639
|
+
this.ordered = Boolean(options.ordered);
|
|
640
|
+
this.options = options;
|
|
641
|
+
this.items = [];
|
|
642
|
+
|
|
643
|
+
for (let i = 0; i < items.length; i++) {
|
|
644
|
+
const item = items[i];
|
|
645
|
+
if (item instanceof InputRichBlockListItem) {
|
|
646
|
+
this.items.push(item);
|
|
647
|
+
} else if (typeof item === 'object' && item !== null) {
|
|
648
|
+
const itemNumber = this.ordered && item.number === undefined ? i + 1 : item.number;
|
|
649
|
+
this.items.push(new InputRichBlockListItem(item.text ?? item.title ?? '', { number: itemNumber, ...item }));
|
|
650
|
+
} else {
|
|
651
|
+
const itemNumber = this.ordered ? i + 1 : null;
|
|
652
|
+
this.items.push(new InputRichBlockListItem(String(item), { number: itemNumber }));
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Add an item to the list
|
|
659
|
+
* @param {InputRichBlockListItem|string|object} item
|
|
660
|
+
* @returns {this}
|
|
661
|
+
*/
|
|
662
|
+
addItem(item) {
|
|
663
|
+
if (item instanceof InputRichBlockListItem) {
|
|
664
|
+
this.items.push(item);
|
|
665
|
+
} else if (typeof item === 'object' && item !== null) {
|
|
666
|
+
const itemNumber = this.ordered && item.number === undefined ? this.items.length + 1 : item.number;
|
|
667
|
+
this.items.push(new InputRichBlockListItem(item.text ?? item.title ?? '', { number: itemNumber, ...item }));
|
|
668
|
+
} else {
|
|
669
|
+
const itemNumber = this.ordered ? this.items.length + 1 : null;
|
|
670
|
+
this.items.push(new InputRichBlockListItem(String(item), { number: itemNumber }));
|
|
671
|
+
}
|
|
672
|
+
return this;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
toJSON() {
|
|
676
|
+
return {
|
|
677
|
+
type: 'list',
|
|
678
|
+
items: this.items.map((it) => (typeof it.toJSON === 'function' ? it.toJSON() : it)),
|
|
679
|
+
...(this.ordered ? { ordered: true } : {}),
|
|
680
|
+
...this.options,
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
toHtml() {
|
|
685
|
+
return this.items.map((it) => (typeof it.toHtml === 'function' ? it.toHtml() : `• ${escapeHtml(it.text || String(it))}`)).join('\n');
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
static create(items, options) {
|
|
689
|
+
return new InputRichBlockList(items, options);
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
static ordered(items, options = {}) {
|
|
693
|
+
return new InputRichBlockList(items, { ordered: true, ...options });
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
static checklist(items, options = {}) {
|
|
697
|
+
const listItems = items.map((it) => {
|
|
698
|
+
if (typeof it === 'object' && it !== null && it.is_checked !== undefined) {
|
|
699
|
+
return it;
|
|
700
|
+
}
|
|
701
|
+
return { text: String(it), is_checked: false };
|
|
702
|
+
});
|
|
703
|
+
return new InputRichBlockList(listItems, options);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
export const RichBlockList = InputRichBlockList;
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* Telegram Bot API 10.2 InputRichBlockChecklist
|
|
710
|
+
*/
|
|
711
|
+
export class InputRichBlockChecklist extends InputRichBlockList {
|
|
712
|
+
constructor(items = [], options = {}) {
|
|
713
|
+
super(items, { checklist: true, ...options });
|
|
714
|
+
this.type = 'checklist';
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
toJSON() {
|
|
718
|
+
return {
|
|
719
|
+
type: 'checklist',
|
|
720
|
+
items: this.items.map((it) => (typeof it.toJSON === 'function' ? it.toJSON() : it)),
|
|
721
|
+
...this.options,
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
toHtml() {
|
|
726
|
+
return this.items.map((it) => {
|
|
727
|
+
const isChecked = typeof it === 'object' && it !== null && (it.is_checked || it.checked);
|
|
728
|
+
const mark = isChecked ? '☑️' : '◻️';
|
|
729
|
+
const text = typeof it === 'object' && it !== null ? (it.text || String(it)) : String(it);
|
|
730
|
+
return `${mark} ${escapeHtml(text)}`;
|
|
731
|
+
}).join('\n');
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
static create(items, options) {
|
|
735
|
+
return new InputRichBlockChecklist(items, options);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
export const RichBlockChecklist = InputRichBlockChecklist;
|
|
739
|
+
|
|
740
|
+
/**
|
|
741
|
+
* Telegram Bot API 10.2 InputRichBlockBlockQuotation class
|
|
742
|
+
* Standard block quote block
|
|
743
|
+
*/
|
|
744
|
+
export class InputRichBlockBlockQuotation {
|
|
745
|
+
/**
|
|
746
|
+
* @param {string} text
|
|
747
|
+
* @param {object} [options={}]
|
|
748
|
+
*/
|
|
749
|
+
constructor(text, options = {}) {
|
|
750
|
+
this.type = 'block_quotation';
|
|
751
|
+
this.text = String(text ?? '');
|
|
752
|
+
this.options = options;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
toJSON() {
|
|
756
|
+
return {
|
|
757
|
+
type: 'block_quotation',
|
|
758
|
+
text: this.text,
|
|
759
|
+
...this.options,
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
toHtml() {
|
|
764
|
+
return `<blockquote>${escapeHtml(this.text)}</blockquote>`;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
static create(text, options) {
|
|
768
|
+
return new InputRichBlockBlockQuotation(text, options);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
export const RichBlockBlockQuotation = InputRichBlockBlockQuotation;
|
|
772
|
+
|
|
773
|
+
/**
|
|
774
|
+
* Telegram Bot API 10.2 InputRichBlockPullQuotation class
|
|
775
|
+
* Pull quote with center emphasis
|
|
776
|
+
*/
|
|
777
|
+
export class InputRichBlockPullQuotation {
|
|
778
|
+
/**
|
|
779
|
+
* @param {string} text
|
|
780
|
+
* @param {object} [options={}]
|
|
781
|
+
*/
|
|
782
|
+
constructor(text, options = {}) {
|
|
783
|
+
this.type = 'pull_quotation';
|
|
784
|
+
this.text = String(text ?? '');
|
|
785
|
+
this.options = options;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
toJSON() {
|
|
789
|
+
return {
|
|
790
|
+
type: 'pull_quotation',
|
|
791
|
+
text: this.text,
|
|
792
|
+
...this.options,
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
toHtml() {
|
|
797
|
+
return `<tg-pullquote>${escapeHtml(this.text)}</tg-pullquote>`;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
static create(text, options) {
|
|
801
|
+
return new InputRichBlockPullQuotation(text, options);
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
export const RichBlockPullQuotation = InputRichBlockPullQuotation;
|
|
805
|
+
export const RichBlockPullQuote = InputRichBlockPullQuotation;
|
|
806
|
+
|
|
807
|
+
/**
|
|
808
|
+
* Telegram Bot API 10.2 InputRichBlockCollage class
|
|
809
|
+
* Represents a photo/media collage block
|
|
810
|
+
*/
|
|
811
|
+
export class InputRichBlockCollage {
|
|
812
|
+
/**
|
|
813
|
+
* @param {Array<object|string>} [media=[]]
|
|
814
|
+
* @param {object} [options={}]
|
|
815
|
+
*/
|
|
816
|
+
constructor(media = [], options = {}) {
|
|
817
|
+
this.type = 'collage';
|
|
818
|
+
this.media = Array.isArray(media) ? media : [media];
|
|
819
|
+
this.options = options;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
toJSON() {
|
|
823
|
+
return {
|
|
824
|
+
type: 'collage',
|
|
825
|
+
media: this.media.map((m) => (typeof m?.toJSON === 'function' ? m.toJSON() : m)),
|
|
826
|
+
...this.options,
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
toHtml() {
|
|
831
|
+
return `🖼️ [Collage: ${this.media.length} media items]`;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
static create(media, options) {
|
|
835
|
+
return new InputRichBlockCollage(media, options);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
export const RichBlockCollage = InputRichBlockCollage;
|
|
839
|
+
|
|
840
|
+
/**
|
|
841
|
+
* Telegram Bot API 10.2 InputRichBlockSlideshow class
|
|
842
|
+
* Represents a slideshow media block
|
|
843
|
+
*/
|
|
844
|
+
export class InputRichBlockSlideshow {
|
|
845
|
+
/**
|
|
846
|
+
* @param {Array<object|string>} [media=[]]
|
|
847
|
+
* @param {object} [options={}]
|
|
848
|
+
*/
|
|
849
|
+
constructor(media = [], options = {}) {
|
|
850
|
+
this.type = 'slideshow';
|
|
851
|
+
this.media = Array.isArray(media) ? media : [media];
|
|
852
|
+
this.options = options;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
toJSON() {
|
|
856
|
+
return {
|
|
857
|
+
type: 'slideshow',
|
|
858
|
+
media: this.media.map((m) => (typeof m?.toJSON === 'function' ? m.toJSON() : m)),
|
|
859
|
+
...this.options,
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
toHtml() {
|
|
864
|
+
return `🎞️ [Slideshow: ${this.media.length} items]`;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
static create(media, options) {
|
|
868
|
+
return new InputRichBlockSlideshow(media, options);
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
export const RichBlockSlideshow = InputRichBlockSlideshow;
|
|
872
|
+
|
|
873
|
+
/**
|
|
874
|
+
* Telegram Bot API 10.2 InputRichBlockDetails class
|
|
875
|
+
* Represents a collapsible disclosure widget (summary and content)
|
|
876
|
+
*/
|
|
877
|
+
export class InputRichBlockDetails {
|
|
878
|
+
/**
|
|
879
|
+
* @param {string} title
|
|
880
|
+
* @param {string|Array<object>} [content='']
|
|
881
|
+
* @param {object} [options={}]
|
|
882
|
+
*/
|
|
883
|
+
constructor(title, content = '', options = {}) {
|
|
884
|
+
this.type = 'details';
|
|
885
|
+
this.title = String(title ?? '');
|
|
886
|
+
this.content = content;
|
|
887
|
+
this.is_open = Boolean(options.is_open ?? options.isOpen);
|
|
888
|
+
this.options = options;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
toJSON() {
|
|
892
|
+
return {
|
|
893
|
+
type: 'details',
|
|
894
|
+
title: this.title,
|
|
895
|
+
content: typeof this.content === 'object' && this.content !== null && typeof this.content.toJSON === 'function'
|
|
896
|
+
? this.content.toJSON()
|
|
897
|
+
: this.content,
|
|
898
|
+
is_open: this.is_open,
|
|
899
|
+
...this.options,
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
toHtml() {
|
|
904
|
+
const body = typeof this.content === 'string'
|
|
905
|
+
? escapeHtml(this.content)
|
|
906
|
+
: Array.isArray(this.content)
|
|
907
|
+
? this.content.map((c) => (typeof c?.toHtml === 'function' ? c.toHtml() : String(c))).join('\n')
|
|
908
|
+
: '';
|
|
909
|
+
return `<details${this.is_open ? ' open' : ''}><summary>${escapeHtml(this.title)}</summary>${body}</details>`;
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
static create(title, content, options) {
|
|
913
|
+
return new InputRichBlockDetails(title, content, options);
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
export const RichBlockDetails = InputRichBlockDetails;
|
|
917
|
+
|
|
918
|
+
/**
|
|
919
|
+
* Telegram Bot API 10.2 InputRichBlockMap class
|
|
920
|
+
* Represents an embedded geographical location card with coordinates
|
|
921
|
+
*/
|
|
922
|
+
export class InputRichBlockMap {
|
|
923
|
+
/**
|
|
924
|
+
* @param {number} latitude
|
|
925
|
+
* @param {number} longitude
|
|
926
|
+
* @param {object} [options={}]
|
|
927
|
+
*/
|
|
928
|
+
constructor(latitude, longitude, options = {}) {
|
|
929
|
+
this.type = 'map';
|
|
930
|
+
this.latitude = Number(latitude);
|
|
931
|
+
this.longitude = Number(longitude);
|
|
932
|
+
this.title = options.title || '';
|
|
933
|
+
this.options = options;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
toJSON() {
|
|
937
|
+
return {
|
|
938
|
+
type: 'map',
|
|
939
|
+
latitude: this.latitude,
|
|
940
|
+
longitude: this.longitude,
|
|
941
|
+
...(this.title ? { title: this.title } : {}),
|
|
942
|
+
...this.options,
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
toHtml() {
|
|
947
|
+
return `📍 <b>${escapeHtml(this.title || 'Location')}</b> (${this.latitude.toFixed(4)}, ${this.longitude.toFixed(4)})`;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
static create(latitude, longitude, options) {
|
|
951
|
+
return new InputRichBlockMap(latitude, longitude, options);
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
export const RichBlockMap = InputRichBlockMap;
|
|
955
|
+
|
|
956
|
+
/**
|
|
957
|
+
* Telegram Bot API 10.2 InputRichBlockAnimation class
|
|
958
|
+
* Represents an animation or GIF block
|
|
959
|
+
*/
|
|
960
|
+
export class InputRichBlockAnimation {
|
|
961
|
+
/**
|
|
962
|
+
* @param {string} animation
|
|
963
|
+
* @param {object} [options={}]
|
|
964
|
+
*/
|
|
965
|
+
constructor(animation, options = {}) {
|
|
966
|
+
this.type = 'animation';
|
|
967
|
+
this.animation = animation;
|
|
968
|
+
this.caption = options.caption || '';
|
|
969
|
+
this.options = options;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
toJSON() {
|
|
973
|
+
return {
|
|
974
|
+
type: 'animation',
|
|
975
|
+
animation: this.animation,
|
|
976
|
+
...(this.caption ? { caption: this.caption } : {}),
|
|
977
|
+
...this.options,
|
|
978
|
+
};
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
toHtml() {
|
|
982
|
+
return `🎬 <b>[Animation]</b> ${escapeHtml(this.caption || '')}`;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
static create(animation, options) {
|
|
986
|
+
return new InputRichBlockAnimation(animation, options);
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
export const RichBlockAnimation = InputRichBlockAnimation;
|
|
990
|
+
|
|
991
|
+
/**
|
|
992
|
+
* Telegram Bot API 10.2 InputRichBlockAudio class
|
|
993
|
+
* Represents an audio track block
|
|
994
|
+
*/
|
|
995
|
+
export class InputRichBlockAudio {
|
|
996
|
+
/**
|
|
997
|
+
* @param {string} audio
|
|
998
|
+
* @param {object} [options={}]
|
|
999
|
+
*/
|
|
1000
|
+
constructor(audio, options = {}) {
|
|
1001
|
+
this.type = 'audio';
|
|
1002
|
+
this.audio = audio;
|
|
1003
|
+
this.title = options.title || '';
|
|
1004
|
+
this.performer = options.performer || '';
|
|
1005
|
+
this.duration = options.duration;
|
|
1006
|
+
this.options = options;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
toJSON() {
|
|
1010
|
+
return {
|
|
1011
|
+
type: 'audio',
|
|
1012
|
+
audio: this.audio,
|
|
1013
|
+
...(this.title ? { title: this.title } : {}),
|
|
1014
|
+
...(this.performer ? { performer: this.performer } : {}),
|
|
1015
|
+
...(this.duration !== undefined ? { duration: Number(this.duration) } : {}),
|
|
1016
|
+
...this.options,
|
|
1017
|
+
};
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
toHtml() {
|
|
1021
|
+
const titleStr = this.performer ? `${this.performer} - ${this.title}` : (this.title || 'Audio');
|
|
1022
|
+
return `🎵 <b>${escapeHtml(titleStr)}</b>`;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
static create(audio, options) {
|
|
1026
|
+
return new InputRichBlockAudio(audio, options);
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
export const RichBlockAudio = InputRichBlockAudio;
|
|
1030
|
+
|
|
1031
|
+
/**
|
|
1032
|
+
* Telegram Bot API 10.2 InputRichBlockPhoto class
|
|
1033
|
+
* Represents a photo block
|
|
1034
|
+
*/
|
|
1035
|
+
export class InputRichBlockPhoto {
|
|
1036
|
+
/**
|
|
1037
|
+
* @param {string} photo
|
|
1038
|
+
* @param {string} [caption='']
|
|
1039
|
+
* @param {object} [options={}]
|
|
1040
|
+
*/
|
|
1041
|
+
constructor(photo, caption = '', options = {}) {
|
|
1042
|
+
this.type = 'photo';
|
|
1043
|
+
this.photo = photo;
|
|
1044
|
+
this.caption = String(caption || options.caption || '');
|
|
1045
|
+
this.options = options;
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
toJSON() {
|
|
1049
|
+
return {
|
|
1050
|
+
type: 'photo',
|
|
1051
|
+
photo: this.photo,
|
|
1052
|
+
...(this.caption ? { caption: this.caption } : {}),
|
|
1053
|
+
...this.options,
|
|
1054
|
+
};
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
toHtml() {
|
|
1058
|
+
return `🖼️ <b>[Photo]</b> ${escapeHtml(this.caption || '')}`;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
static create(photo, caption, options) {
|
|
1062
|
+
return new InputRichBlockPhoto(photo, caption, options);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
export const RichBlockPhoto = InputRichBlockPhoto;
|
|
1066
|
+
|
|
1067
|
+
/**
|
|
1068
|
+
* Telegram Bot API 10.2 InputRichBlockVideo class
|
|
1069
|
+
* Represents a video block
|
|
1070
|
+
*/
|
|
1071
|
+
export class InputRichBlockVideo {
|
|
1072
|
+
/**
|
|
1073
|
+
* @param {string} video
|
|
1074
|
+
* @param {object} [options={}]
|
|
1075
|
+
*/
|
|
1076
|
+
constructor(video, options = {}) {
|
|
1077
|
+
this.type = 'video';
|
|
1078
|
+
this.video = video;
|
|
1079
|
+
this.caption = options.caption || '';
|
|
1080
|
+
this.duration = options.duration;
|
|
1081
|
+
this.options = options;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
toJSON() {
|
|
1085
|
+
return {
|
|
1086
|
+
type: 'video',
|
|
1087
|
+
video: this.video,
|
|
1088
|
+
...(this.caption ? { caption: this.caption } : {}),
|
|
1089
|
+
...(this.duration !== undefined ? { duration: Number(this.duration) } : {}),
|
|
1090
|
+
...this.options,
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
toHtml() {
|
|
1095
|
+
return `🎥 <b>[Video]</b> ${escapeHtml(this.caption || '')}`;
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
static create(video, options) {
|
|
1099
|
+
return new InputRichBlockVideo(video, options);
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
export const RichBlockVideo = InputRichBlockVideo;
|
|
1103
|
+
|
|
1104
|
+
/**
|
|
1105
|
+
* Telegram Bot API 10.2 InputRichBlockVoiceNote class
|
|
1106
|
+
* Represents a voice note block
|
|
1107
|
+
*/
|
|
1108
|
+
export class InputRichBlockVoiceNote {
|
|
1109
|
+
/**
|
|
1110
|
+
* @param {string} voiceNote
|
|
1111
|
+
* @param {object} [options={}]
|
|
1112
|
+
*/
|
|
1113
|
+
constructor(voiceNote, options = {}) {
|
|
1114
|
+
this.type = 'voice_note';
|
|
1115
|
+
this.voice_note = voiceNote;
|
|
1116
|
+
this.caption = options.caption || '';
|
|
1117
|
+
this.duration = options.duration;
|
|
1118
|
+
this.options = options;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
toJSON() {
|
|
1122
|
+
return {
|
|
1123
|
+
type: 'voice_note',
|
|
1124
|
+
voice_note: this.voice_note,
|
|
1125
|
+
...(this.caption ? { caption: this.caption } : {}),
|
|
1126
|
+
...(this.duration !== undefined ? { duration: Number(this.duration) } : {}),
|
|
1127
|
+
...this.options,
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
toHtml() {
|
|
1132
|
+
return `🎤 <b>[Voice Note]</b> ${escapeHtml(this.caption || '')}`;
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
static create(voiceNote, options) {
|
|
1136
|
+
return new InputRichBlockVoiceNote(voiceNote, options);
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
export const RichBlockVoiceNote = InputRichBlockVoiceNote;
|
|
1140
|
+
|
|
1141
|
+
/**
|
|
1142
|
+
* Telegram Bot API 10.2 InputRichBlockThinking class
|
|
1143
|
+
* Represents an AI thinking / processing indicator block
|
|
1144
|
+
*/
|
|
1145
|
+
export class InputRichBlockThinking {
|
|
1146
|
+
/**
|
|
1147
|
+
* @param {string} [text='Thinking...']
|
|
1148
|
+
* @param {object} [options={}]
|
|
1149
|
+
*/
|
|
1150
|
+
constructor(text = 'Thinking...', options = {}) {
|
|
1151
|
+
this.type = 'thinking';
|
|
1152
|
+
this.text = String(text ?? 'Thinking...');
|
|
1153
|
+
this.options = options;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
toJSON() {
|
|
1157
|
+
return {
|
|
1158
|
+
type: 'thinking',
|
|
1159
|
+
text: this.text,
|
|
1160
|
+
...this.options,
|
|
1161
|
+
};
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
toHtml() {
|
|
1165
|
+
return `<tg-thinking>${escapeHtml(this.text)}</tg-thinking>`;
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
static create(text, options) {
|
|
1169
|
+
return new InputRichBlockThinking(text, options);
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
export const RichBlockThinking = InputRichBlockThinking;
|
|
1173
|
+
|
|
1174
|
+
/**
|
|
1175
|
+
* Telegram Bot API 10.2 InputRichMessageMedia class
|
|
1176
|
+
* Represents a media attachment in rich messages
|
|
1177
|
+
*/
|
|
1178
|
+
export class InputRichMessageMedia {
|
|
1179
|
+
/**
|
|
1180
|
+
* @param {string} media
|
|
1181
|
+
* @param {string} [type='photo']
|
|
1182
|
+
* @param {object} [options={}]
|
|
1183
|
+
*/
|
|
1184
|
+
constructor(media, type = 'photo', options = {}) {
|
|
1185
|
+
if (typeof media === 'object' && media !== null) {
|
|
1186
|
+
this.media = media.media;
|
|
1187
|
+
this.type = media.type || type || 'photo';
|
|
1188
|
+
this.caption = media.caption || options.caption || '';
|
|
1189
|
+
this.parse_mode = media.parse_mode || media.parseMode || options.parse_mode;
|
|
1190
|
+
this.show_caption_above_media = media.show_caption_above_media ?? media.showCaptionAboveMedia ?? options.show_caption_above_media;
|
|
1191
|
+
this.has_spoiler = media.has_spoiler ?? media.hasSpoiler ?? options.has_spoiler;
|
|
1192
|
+
this.width = media.width ?? options.width;
|
|
1193
|
+
this.height = media.height ?? options.height;
|
|
1194
|
+
this.duration = media.duration ?? options.duration;
|
|
1195
|
+
this.performer = media.performer ?? options.performer;
|
|
1196
|
+
this.title = media.title ?? options.title;
|
|
1197
|
+
this.thumbnail = media.thumbnail ?? options.thumbnail;
|
|
1198
|
+
this.options = { ...options, ...media };
|
|
1199
|
+
} else {
|
|
1200
|
+
this.media = media;
|
|
1201
|
+
this.type = type;
|
|
1202
|
+
this.caption = options.caption || '';
|
|
1203
|
+
this.parse_mode = options.parse_mode || options.parseMode;
|
|
1204
|
+
this.show_caption_above_media = options.show_caption_above_media ?? options.showCaptionAboveMedia;
|
|
1205
|
+
this.has_spoiler = options.has_spoiler ?? options.hasSpoiler;
|
|
1206
|
+
this.width = options.width;
|
|
1207
|
+
this.height = options.height;
|
|
1208
|
+
this.duration = options.duration;
|
|
1209
|
+
this.performer = options.performer;
|
|
1210
|
+
this.title = options.title;
|
|
1211
|
+
this.thumbnail = options.thumbnail;
|
|
1212
|
+
this.options = options;
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
toJSON() {
|
|
1217
|
+
const res = {
|
|
1218
|
+
type: this.type,
|
|
1219
|
+
media: this.media,
|
|
1220
|
+
};
|
|
1221
|
+
if (this.caption) res.caption = this.caption;
|
|
1222
|
+
if (this.parse_mode) res.parse_mode = this.parse_mode;
|
|
1223
|
+
if (this.show_caption_above_media !== undefined) res.show_caption_above_media = Boolean(this.show_caption_above_media);
|
|
1224
|
+
if (this.has_spoiler !== undefined) res.has_spoiler = Boolean(this.has_spoiler);
|
|
1225
|
+
if (this.width !== undefined) res.width = Number(this.width);
|
|
1226
|
+
if (this.height !== undefined) res.height = Number(this.height);
|
|
1227
|
+
if (this.duration !== undefined) res.duration = Number(this.duration);
|
|
1228
|
+
if (this.performer) res.performer = this.performer;
|
|
1229
|
+
if (this.title) res.title = this.title;
|
|
1230
|
+
if (this.thumbnail) res.thumbnail = this.thumbnail;
|
|
1231
|
+
return res;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
static photo(media, caption = '', options = {}) {
|
|
1235
|
+
return new InputRichMessageMedia(media, 'photo', { caption, ...options });
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
static video(media, caption = '', options = {}) {
|
|
1239
|
+
return new InputRichMessageMedia(media, 'video', { caption, ...options });
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
static animation(media, caption = '', options = {}) {
|
|
1243
|
+
return new InputRichMessageMedia(media, 'animation', { caption, ...options });
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
static audio(media, caption = '', options = {}) {
|
|
1247
|
+
return new InputRichMessageMedia(media, 'audio', { caption, ...options });
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
static document(media, caption = '', options = {}) {
|
|
1251
|
+
return new InputRichMessageMedia(media, 'document', { caption, ...options });
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
static voiceNote(media, caption = '', options = {}) {
|
|
1255
|
+
return new InputRichMessageMedia(media, 'voice_note', { caption, ...options });
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
export const RichMessageMedia = InputRichMessageMedia;
|
|
1259
|
+
|
|
1260
|
+
/**
|
|
1261
|
+
* Telegram Bot API 10.2 InputMediaVoiceNote class
|
|
1262
|
+
* Represents a voice note to be sent in media methods
|
|
1263
|
+
*/
|
|
1264
|
+
export class InputMediaVoiceNote {
|
|
1265
|
+
/**
|
|
1266
|
+
* @param {string} media
|
|
1267
|
+
* @param {object} [options={}]
|
|
1268
|
+
*/
|
|
1269
|
+
constructor(media, options = {}) {
|
|
1270
|
+
this.type = 'voice';
|
|
1271
|
+
this.media = media;
|
|
1272
|
+
this.caption = options.caption || '';
|
|
1273
|
+
this.parse_mode = options.parse_mode || options.parseMode;
|
|
1274
|
+
this.duration = options.duration;
|
|
1275
|
+
this.options = options;
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
toJSON() {
|
|
1279
|
+
const res = {
|
|
1280
|
+
type: this.type,
|
|
1281
|
+
media: this.media,
|
|
1282
|
+
};
|
|
1283
|
+
if (this.caption) res.caption = this.caption;
|
|
1284
|
+
if (this.parse_mode) res.parse_mode = this.parse_mode;
|
|
1285
|
+
if (this.duration !== undefined) res.duration = Number(this.duration);
|
|
1286
|
+
return res;
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
static create(media, options = {}) {
|
|
1290
|
+
return new InputMediaVoiceNote(media, options);
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
export const MediaVoiceNote = InputMediaVoiceNote;
|
|
1294
|
+
|
|
1295
|
+
/**
|
|
1296
|
+
* Telegram Bot API 10.2 InputRichMessage class
|
|
1297
|
+
* Root container class for structured rich messages
|
|
1298
|
+
*/
|
|
1299
|
+
export class InputRichMessage {
|
|
1300
|
+
/**
|
|
1301
|
+
* @param {object|string} [options={}]
|
|
1302
|
+
*/
|
|
1303
|
+
constructor(options = {}) {
|
|
1304
|
+
if (typeof options === 'string') {
|
|
1305
|
+
this.text = options;
|
|
1306
|
+
this.blocks = [];
|
|
1307
|
+
this.media = [];
|
|
1308
|
+
this.is_rtl = false;
|
|
1309
|
+
} else {
|
|
1310
|
+
this.text = options.text || options.html || '';
|
|
1311
|
+
this.blocks = options.blocks ? [...options.blocks] : [];
|
|
1312
|
+
this.media = options.media ? [...options.media] : [];
|
|
1313
|
+
this.is_rtl = Boolean(options.is_rtl ?? options.isRtl);
|
|
1314
|
+
this.draft_id = options.draft_id ?? options.draftId;
|
|
1315
|
+
this.ephemeral_message_parameters = options.ephemeral_message_parameters ?? options.ephemeral;
|
|
1316
|
+
this.reply_markup = options.reply_markup;
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
/**
|
|
1321
|
+
* Add a block to the rich message
|
|
1322
|
+
* @param {object} block
|
|
1323
|
+
* @returns {this}
|
|
1324
|
+
*/
|
|
1325
|
+
addBlock(block) {
|
|
1326
|
+
this.blocks.push(block);
|
|
1327
|
+
return this;
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
/**
|
|
1331
|
+
* Add a media attachment
|
|
1332
|
+
* @param {InputRichMessageMedia|object} mediaItem
|
|
1333
|
+
* @returns {this}
|
|
1334
|
+
*/
|
|
1335
|
+
addMedia(mediaItem) {
|
|
1336
|
+
this.media.push(mediaItem);
|
|
1337
|
+
return this;
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
/**
|
|
1341
|
+
* Set right-to-left text direction
|
|
1342
|
+
* @param {boolean} [rtl=true]
|
|
1343
|
+
* @returns {this}
|
|
1344
|
+
*/
|
|
1345
|
+
setRtl(rtl = true) {
|
|
1346
|
+
this.is_rtl = Boolean(rtl);
|
|
1347
|
+
return this;
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
toJSON() {
|
|
1351
|
+
return {
|
|
1352
|
+
text: this.text,
|
|
1353
|
+
blocks: this.blocks.map((b) => (typeof b?.toJSON === 'function' ? b.toJSON() : b)),
|
|
1354
|
+
media: this.media.map((m) => (typeof m?.toJSON === 'function' ? m.toJSON() : m)),
|
|
1355
|
+
...(this.is_rtl ? { is_rtl: true } : {}),
|
|
1356
|
+
...(this.draft_id !== undefined ? { draft_id: this.draft_id } : {}),
|
|
1357
|
+
...(this.ephemeral_message_parameters ? { ephemeral_message_parameters: this.ephemeral_message_parameters } : {}),
|
|
1358
|
+
...(this.reply_markup ? { reply_markup: this.reply_markup } : {}),
|
|
1359
|
+
};
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
static create(options) {
|
|
1363
|
+
return new InputRichMessage(options);
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
|
|
1368
|
+
/**
|
|
1369
|
+
* Comprehensive Rich Message Builder
|
|
1370
|
+
*/
|
|
10
1371
|
export class RichMessageBuilder {
|
|
11
1372
|
constructor(initialText = '') {
|
|
12
1373
|
this.blocks = [];
|
|
@@ -15,232 +1376,501 @@ export class RichMessageBuilder {
|
|
|
15
1376
|
this._inlineKeyboard = [];
|
|
16
1377
|
this._draftId = null;
|
|
17
1378
|
this._ephemeral = null;
|
|
18
|
-
this._media =
|
|
1379
|
+
this._media = [];
|
|
1380
|
+
this._isRtl = false;
|
|
19
1381
|
this._extra = {};
|
|
20
1382
|
}
|
|
21
1383
|
|
|
22
1384
|
/**
|
|
23
|
-
* Set parse mode ('HTML', 'MarkdownV2', etc.)
|
|
24
|
-
* @param {string} mode
|
|
1385
|
+
* Set parse mode ('HTML', 'MarkdownV2', etc.)
|
|
1386
|
+
* @param {string} mode
|
|
1387
|
+
* @returns {this}
|
|
1388
|
+
*/
|
|
1389
|
+
parseMode(mode) {
|
|
1390
|
+
this._parseMode = mode;
|
|
1391
|
+
return this;
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
/**
|
|
1395
|
+
* Set primary text
|
|
1396
|
+
* @param {string} text
|
|
1397
|
+
* @returns {this}
|
|
1398
|
+
*/
|
|
1399
|
+
text(text) {
|
|
1400
|
+
this._text = String(text);
|
|
1401
|
+
return this;
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
/**
|
|
1405
|
+
* Add a header block with optional emoji
|
|
1406
|
+
* @param {string} text
|
|
1407
|
+
* @param {string} [emoji]
|
|
1408
|
+
* @returns {this}
|
|
1409
|
+
*/
|
|
1410
|
+
header(text, emoji = '') {
|
|
1411
|
+
const formatted = emoji ? `${emoji} ${text}` : text;
|
|
1412
|
+
this.blocks.push({
|
|
1413
|
+
type: 'header',
|
|
1414
|
+
content: formatted,
|
|
1415
|
+
rawHtml: `<b>${escapeHtml(formatted)}</b>`,
|
|
1416
|
+
});
|
|
1417
|
+
return this;
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
/**
|
|
1421
|
+
* Add a paragraph block
|
|
1422
|
+
* @param {string} text
|
|
1423
|
+
* @returns {this}
|
|
1424
|
+
*/
|
|
1425
|
+
paragraph(text) {
|
|
1426
|
+
this.blocks.push({
|
|
1427
|
+
type: 'paragraph',
|
|
1428
|
+
content: text,
|
|
1429
|
+
rawHtml: escapeHtml(text),
|
|
1430
|
+
});
|
|
1431
|
+
return this;
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
/**
|
|
1435
|
+
* Add bold text block
|
|
1436
|
+
* @param {string} text
|
|
1437
|
+
* @returns {this}
|
|
1438
|
+
*/
|
|
1439
|
+
bold(text) {
|
|
1440
|
+
this.blocks.push({
|
|
1441
|
+
type: 'bold',
|
|
1442
|
+
content: text,
|
|
1443
|
+
rawHtml: `<b>${escapeHtml(text)}</b>`,
|
|
1444
|
+
});
|
|
1445
|
+
return this;
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
/**
|
|
1449
|
+
* Add italic text block
|
|
1450
|
+
* @param {string} text
|
|
1451
|
+
* @returns {this}
|
|
1452
|
+
*/
|
|
1453
|
+
italic(text) {
|
|
1454
|
+
this.blocks.push({
|
|
1455
|
+
type: 'italic',
|
|
1456
|
+
content: text,
|
|
1457
|
+
rawHtml: `<i>${escapeHtml(text)}</i>`,
|
|
1458
|
+
});
|
|
1459
|
+
return this;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
/**
|
|
1463
|
+
* Add underline text block
|
|
1464
|
+
* @param {string} text
|
|
1465
|
+
* @returns {this}
|
|
1466
|
+
*/
|
|
1467
|
+
underline(text) {
|
|
1468
|
+
this.blocks.push({
|
|
1469
|
+
type: 'underline',
|
|
1470
|
+
content: text,
|
|
1471
|
+
rawHtml: `<u>${escapeHtml(text)}</u>`,
|
|
1472
|
+
});
|
|
1473
|
+
return this;
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
/**
|
|
1477
|
+
* Add strikethrough text block
|
|
1478
|
+
* @param {string} text
|
|
1479
|
+
* @returns {this}
|
|
1480
|
+
*/
|
|
1481
|
+
strikethrough(text) {
|
|
1482
|
+
this.blocks.push({
|
|
1483
|
+
type: 'strikethrough',
|
|
1484
|
+
content: text,
|
|
1485
|
+
rawHtml: `<s>${escapeHtml(text)}</s>`,
|
|
1486
|
+
});
|
|
1487
|
+
return this;
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
/**
|
|
1491
|
+
* Add code block or inline code
|
|
1492
|
+
* @param {string} codeText
|
|
1493
|
+
* @param {string} [language]
|
|
1494
|
+
* @returns {this}
|
|
1495
|
+
*/
|
|
1496
|
+
code(codeText, language = '') {
|
|
1497
|
+
const isMultiline = String(codeText).includes('\n') || Boolean(language);
|
|
1498
|
+
this.blocks.push({
|
|
1499
|
+
type: 'code',
|
|
1500
|
+
content: codeText,
|
|
1501
|
+
language,
|
|
1502
|
+
rawHtml: isMultiline
|
|
1503
|
+
? html.pre(codeText, language)
|
|
1504
|
+
: html.code(codeText),
|
|
1505
|
+
});
|
|
1506
|
+
return this;
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
/**
|
|
1510
|
+
* Add a blockquote block
|
|
1511
|
+
* @param {string} text
|
|
1512
|
+
* @param {boolean} [expandable=false]
|
|
1513
|
+
* @returns {this}
|
|
1514
|
+
*/
|
|
1515
|
+
quote(text, expandable = false) {
|
|
1516
|
+
if (expandable) {
|
|
1517
|
+
return this.expandableBlockQuotation(text);
|
|
1518
|
+
}
|
|
1519
|
+
this.blocks.push({
|
|
1520
|
+
type: 'quote',
|
|
1521
|
+
content: text,
|
|
1522
|
+
expandable: false,
|
|
1523
|
+
rawHtml: `<blockquote>${escapeHtml(text)}</blockquote>`,
|
|
1524
|
+
});
|
|
1525
|
+
return this;
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
/**
|
|
1529
|
+
* Add an expandable blockquote (Telegram Bot API 10.3)
|
|
1530
|
+
* @param {string} text
|
|
1531
|
+
* @returns {this}
|
|
1532
|
+
*/
|
|
1533
|
+
expandableQuote(text) {
|
|
1534
|
+
return this.expandableBlockQuotation(text);
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
/**
|
|
1538
|
+
* Add a collapsible / expandable blockquote (alias)
|
|
1539
|
+
* @param {string} text
|
|
1540
|
+
* @returns {this}
|
|
1541
|
+
*/
|
|
1542
|
+
collapsibleQuote(text) {
|
|
1543
|
+
return this.expandableBlockQuotation(text);
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
/**
|
|
1547
|
+
* Add expandable block quotation (Bot API 10.3 InputRichBlockExpandableBlockQuotation)
|
|
1548
|
+
* @param {string} text
|
|
1549
|
+
* @param {object} [options]
|
|
1550
|
+
* @returns {this}
|
|
1551
|
+
*/
|
|
1552
|
+
expandableBlockQuotation(text, options = {}) {
|
|
1553
|
+
const block = new InputRichBlockExpandableBlockQuotation(text, options);
|
|
1554
|
+
this.blocks.push(block);
|
|
1555
|
+
return this;
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
/**
|
|
1559
|
+
* Add spoiler block
|
|
1560
|
+
* @param {string} text
|
|
1561
|
+
* @returns {this}
|
|
1562
|
+
*/
|
|
1563
|
+
spoiler(text) {
|
|
1564
|
+
this.blocks.push({
|
|
1565
|
+
type: 'spoiler',
|
|
1566
|
+
content: text,
|
|
1567
|
+
rawHtml: `<span class="tg-spoiler">${escapeHtml(text)}</span>`,
|
|
1568
|
+
});
|
|
1569
|
+
return this;
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
/**
|
|
1573
|
+
* Add formatted link
|
|
1574
|
+
* @param {string} text
|
|
1575
|
+
* @param {string} url
|
|
1576
|
+
* @returns {this}
|
|
1577
|
+
*/
|
|
1578
|
+
link(text, url) {
|
|
1579
|
+
this.blocks.push({
|
|
1580
|
+
type: 'link',
|
|
1581
|
+
text,
|
|
1582
|
+
url,
|
|
1583
|
+
rawHtml: `<a href="${escapeHtml(url)}">${escapeHtml(text)}</a>`,
|
|
1584
|
+
});
|
|
1585
|
+
return this;
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
/**
|
|
1589
|
+
* Add user mention
|
|
1590
|
+
* @param {string} text
|
|
1591
|
+
* @param {number|string} userId
|
|
1592
|
+
* @returns {this}
|
|
1593
|
+
*/
|
|
1594
|
+
mention(text, userId) {
|
|
1595
|
+
this.blocks.push({
|
|
1596
|
+
type: 'mention',
|
|
1597
|
+
text,
|
|
1598
|
+
userId,
|
|
1599
|
+
rawHtml: `<a href="tg://user?id=${userId}">${escapeHtml(text)}</a>`,
|
|
1600
|
+
});
|
|
1601
|
+
return this;
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
/**
|
|
1605
|
+
* Add document link using tg://document?id= (Bot API 10.3)
|
|
1606
|
+
* @param {string} documentId
|
|
1607
|
+
* @param {string} [text='Document']
|
|
1608
|
+
* @returns {this}
|
|
1609
|
+
*/
|
|
1610
|
+
documentLink(documentId, text = 'Document') {
|
|
1611
|
+
return this.link(text, `tg://document?id=${documentId}`);
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
/**
|
|
1615
|
+
* Add bullet list
|
|
1616
|
+
* @param {Array<string>} items
|
|
1617
|
+
* @param {string|object} [bulletOrOptions='•']
|
|
1618
|
+
* @returns {this}
|
|
1619
|
+
*/
|
|
1620
|
+
list(items, bulletOrOptions = '•') {
|
|
1621
|
+
if (typeof bulletOrOptions === 'object') {
|
|
1622
|
+
this.blocks.push(new InputRichBlockList(items, bulletOrOptions));
|
|
1623
|
+
return this;
|
|
1624
|
+
}
|
|
1625
|
+
const listItems = Array.isArray(items) ? items : [items];
|
|
1626
|
+
const bullet = typeof bulletOrOptions === 'string' ? bulletOrOptions : '•';
|
|
1627
|
+
const htmlLines = listItems.map((item) => `${bullet} ${escapeHtml(item)}`).join('\n');
|
|
1628
|
+
this.blocks.push(new InputRichBlockList(listItems, { bullet, rawHtml: htmlLines }));
|
|
1629
|
+
return this;
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
/**
|
|
1633
|
+
* Add a checklist block with check states (Bot API 10.2+)
|
|
1634
|
+
* @param {Array<any>} items
|
|
1635
|
+
* @param {object} [options={}]
|
|
25
1636
|
* @returns {this}
|
|
26
1637
|
*/
|
|
27
|
-
|
|
28
|
-
this.
|
|
1638
|
+
checklist(items, options = {}) {
|
|
1639
|
+
this.blocks.push(new InputRichBlockChecklist(items, options));
|
|
29
1640
|
return this;
|
|
30
1641
|
}
|
|
31
1642
|
|
|
32
1643
|
/**
|
|
33
|
-
*
|
|
1644
|
+
* Add section heading block (Bot API 10.2+)
|
|
34
1645
|
* @param {string} text
|
|
1646
|
+
* @param {number} [level=2]
|
|
1647
|
+
* @param {object} [options={}]
|
|
35
1648
|
* @returns {this}
|
|
36
1649
|
*/
|
|
37
|
-
|
|
38
|
-
this.
|
|
1650
|
+
sectionHeading(text, level = 2, options = {}) {
|
|
1651
|
+
this.blocks.push(new InputRichBlockSectionHeading(text, level, options));
|
|
39
1652
|
return this;
|
|
40
1653
|
}
|
|
41
1654
|
|
|
42
1655
|
/**
|
|
43
|
-
* Add
|
|
1656
|
+
* Add heading alias (Bot API 10.2+)
|
|
44
1657
|
* @param {string} text
|
|
45
|
-
* @param {
|
|
1658
|
+
* @param {number} [level=2]
|
|
1659
|
+
* @param {object} [options={}]
|
|
46
1660
|
* @returns {this}
|
|
47
1661
|
*/
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
this.blocks.push({
|
|
51
|
-
type: 'header',
|
|
52
|
-
content: formatted,
|
|
53
|
-
rawHtml: `<b>${escapeHtml(formatted)}</b>`,
|
|
54
|
-
});
|
|
55
|
-
return this;
|
|
1662
|
+
heading(text, level = 2, options = {}) {
|
|
1663
|
+
return this.sectionHeading(text, level, options);
|
|
56
1664
|
}
|
|
57
1665
|
|
|
58
1666
|
/**
|
|
59
|
-
* Add
|
|
1667
|
+
* Add preformatted code/text block (Bot API 10.2+)
|
|
60
1668
|
* @param {string} text
|
|
1669
|
+
* @param {string} [language='']
|
|
1670
|
+
* @param {object} [options={}]
|
|
61
1671
|
* @returns {this}
|
|
62
1672
|
*/
|
|
63
|
-
|
|
64
|
-
this.blocks.push(
|
|
65
|
-
type: 'paragraph',
|
|
66
|
-
content: text,
|
|
67
|
-
rawHtml: escapeHtml(text),
|
|
68
|
-
});
|
|
1673
|
+
preformatted(text, language = '', options = {}) {
|
|
1674
|
+
this.blocks.push(new InputRichBlockPreformatted(text, language, options));
|
|
69
1675
|
return this;
|
|
70
1676
|
}
|
|
71
1677
|
|
|
72
1678
|
/**
|
|
73
|
-
* Add
|
|
1679
|
+
* Add footer block (Bot API 10.2+)
|
|
74
1680
|
* @param {string} text
|
|
1681
|
+
* @param {object} [options={}]
|
|
75
1682
|
* @returns {this}
|
|
76
1683
|
*/
|
|
77
|
-
|
|
78
|
-
this.blocks.push(
|
|
79
|
-
type: 'bold',
|
|
80
|
-
content: text,
|
|
81
|
-
rawHtml: `<b>${escapeHtml(text)}</b>`,
|
|
82
|
-
});
|
|
1684
|
+
footer(text, options = {}) {
|
|
1685
|
+
this.blocks.push(new InputRichBlockFooter(text, options));
|
|
83
1686
|
return this;
|
|
84
1687
|
}
|
|
85
1688
|
|
|
86
1689
|
/**
|
|
87
|
-
* Add
|
|
1690
|
+
* Add horizontal divider block (Bot API 10.2+)
|
|
1691
|
+
* @param {object} [options={}]
|
|
1692
|
+
* @returns {this}
|
|
1693
|
+
*/
|
|
1694
|
+
divider(options = {}) {
|
|
1695
|
+
this.blocks.push(new InputRichBlockDivider(options));
|
|
1696
|
+
return this;
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
/**
|
|
1700
|
+
* Add mathematical expression / LaTeX block (Bot API 10.2+)
|
|
1701
|
+
* @param {string} expression
|
|
1702
|
+
* @param {object} [options={}]
|
|
1703
|
+
* @returns {this}
|
|
1704
|
+
*/
|
|
1705
|
+
math(expression, options = {}) {
|
|
1706
|
+
this.blocks.push(new InputRichBlockMathematicalExpression(expression, options));
|
|
1707
|
+
return this;
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
/**
|
|
1711
|
+
* Add mathematical expression alias (Bot API 10.2+)
|
|
1712
|
+
* @param {string} expression
|
|
1713
|
+
* @param {object} [options={}]
|
|
1714
|
+
* @returns {this}
|
|
1715
|
+
*/
|
|
1716
|
+
mathematicalExpression(expression, options = {}) {
|
|
1717
|
+
return this.math(expression, options);
|
|
1718
|
+
}
|
|
1719
|
+
|
|
1720
|
+
/**
|
|
1721
|
+
* Add in-message anchor block (Bot API 10.2+)
|
|
1722
|
+
* @param {string} name
|
|
1723
|
+
* @param {string} [text='']
|
|
1724
|
+
* @param {object} [options={}]
|
|
1725
|
+
* @returns {this}
|
|
1726
|
+
*/
|
|
1727
|
+
anchor(name, text = '', options = {}) {
|
|
1728
|
+
this.blocks.push(new InputRichBlockAnchor(name, text, options));
|
|
1729
|
+
return this;
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
/**
|
|
1733
|
+
* Add block quotation block (Bot API 10.2+)
|
|
88
1734
|
* @param {string} text
|
|
1735
|
+
* @param {object} [options={}]
|
|
89
1736
|
* @returns {this}
|
|
90
1737
|
*/
|
|
91
|
-
|
|
92
|
-
this.blocks.push(
|
|
93
|
-
type: 'italic',
|
|
94
|
-
content: text,
|
|
95
|
-
rawHtml: `<i>${escapeHtml(text)}</i>`,
|
|
96
|
-
});
|
|
1738
|
+
blockQuotation(text, options = {}) {
|
|
1739
|
+
this.blocks.push(new InputRichBlockBlockQuotation(text, options));
|
|
97
1740
|
return this;
|
|
98
1741
|
}
|
|
99
1742
|
|
|
100
1743
|
/**
|
|
101
|
-
* Add
|
|
1744
|
+
* Add pull quotation block with center emphasis (Bot API 10.2+)
|
|
102
1745
|
* @param {string} text
|
|
1746
|
+
* @param {object} [options={}]
|
|
103
1747
|
* @returns {this}
|
|
104
1748
|
*/
|
|
105
|
-
|
|
106
|
-
this.blocks.push(
|
|
107
|
-
type: 'underline',
|
|
108
|
-
content: text,
|
|
109
|
-
rawHtml: `<u>${escapeHtml(text)}</u>`,
|
|
110
|
-
});
|
|
1749
|
+
pullQuote(text, options = {}) {
|
|
1750
|
+
this.blocks.push(new InputRichBlockPullQuotation(text, options));
|
|
111
1751
|
return this;
|
|
112
1752
|
}
|
|
113
1753
|
|
|
114
1754
|
/**
|
|
115
|
-
* Add
|
|
1755
|
+
* Add pull quotation alias (Bot API 10.2+)
|
|
116
1756
|
* @param {string} text
|
|
1757
|
+
* @param {object} [options={}]
|
|
117
1758
|
* @returns {this}
|
|
118
1759
|
*/
|
|
119
|
-
|
|
120
|
-
this.
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
1760
|
+
pullQuotation(text, options = {}) {
|
|
1761
|
+
return this.pullQuote(text, options);
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
/**
|
|
1765
|
+
* Add collage block (Bot API 10.2+)
|
|
1766
|
+
* @param {Array<any>} media
|
|
1767
|
+
* @param {object} [options={}]
|
|
1768
|
+
* @returns {this}
|
|
1769
|
+
*/
|
|
1770
|
+
collage(media, options = {}) {
|
|
1771
|
+
this.blocks.push(new InputRichBlockCollage(media, options));
|
|
125
1772
|
return this;
|
|
126
1773
|
}
|
|
127
1774
|
|
|
128
1775
|
/**
|
|
129
|
-
* Add
|
|
130
|
-
* @param {
|
|
131
|
-
* @param {
|
|
1776
|
+
* Add slideshow block (Bot API 10.2+)
|
|
1777
|
+
* @param {Array<any>} media
|
|
1778
|
+
* @param {object} [options={}]
|
|
132
1779
|
* @returns {this}
|
|
133
1780
|
*/
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
this.blocks.push({
|
|
137
|
-
type: 'code',
|
|
138
|
-
content: codeText,
|
|
139
|
-
language,
|
|
140
|
-
rawHtml: isMultiline
|
|
141
|
-
? html.pre(codeText, language)
|
|
142
|
-
: html.code(codeText),
|
|
143
|
-
});
|
|
1781
|
+
slideshow(media, options = {}) {
|
|
1782
|
+
this.blocks.push(new InputRichBlockSlideshow(media, options));
|
|
144
1783
|
return this;
|
|
145
1784
|
}
|
|
146
1785
|
|
|
147
1786
|
/**
|
|
148
|
-
* Add
|
|
149
|
-
* @param {string}
|
|
150
|
-
* @param {
|
|
1787
|
+
* Add details / expandable disclosure block (Bot API 10.2+)
|
|
1788
|
+
* @param {string} title
|
|
1789
|
+
* @param {string|Array<any>} [content='']
|
|
1790
|
+
* @param {object} [options={}]
|
|
151
1791
|
* @returns {this}
|
|
152
1792
|
*/
|
|
153
|
-
|
|
154
|
-
this.blocks.push(
|
|
155
|
-
type: 'quote',
|
|
156
|
-
content: text,
|
|
157
|
-
expandable,
|
|
158
|
-
rawHtml: expandable
|
|
159
|
-
? `<blockquote expandable>${escapeHtml(text)}</blockquote>`
|
|
160
|
-
: `<blockquote>${escapeHtml(text)}</blockquote>`,
|
|
161
|
-
});
|
|
1793
|
+
details(title, content = '', options = {}) {
|
|
1794
|
+
this.blocks.push(new InputRichBlockDetails(title, content, options));
|
|
162
1795
|
return this;
|
|
163
1796
|
}
|
|
164
1797
|
|
|
165
1798
|
/**
|
|
166
|
-
* Add
|
|
167
|
-
* @param {
|
|
1799
|
+
* Add interactive map block (Bot API 10.2+)
|
|
1800
|
+
* @param {number} latitude
|
|
1801
|
+
* @param {number} longitude
|
|
1802
|
+
* @param {object} [options={}]
|
|
168
1803
|
* @returns {this}
|
|
169
1804
|
*/
|
|
170
|
-
|
|
171
|
-
|
|
1805
|
+
map(latitude, longitude, options = {}) {
|
|
1806
|
+
this.blocks.push(new InputRichBlockMap(latitude, longitude, options));
|
|
1807
|
+
return this;
|
|
172
1808
|
}
|
|
173
1809
|
|
|
174
1810
|
/**
|
|
175
|
-
* Add
|
|
176
|
-
* @param {string}
|
|
1811
|
+
* Add animation / GIF block (Bot API 10.2+)
|
|
1812
|
+
* @param {string} animation
|
|
1813
|
+
* @param {object} [options={}]
|
|
177
1814
|
* @returns {this}
|
|
178
1815
|
*/
|
|
179
|
-
|
|
180
|
-
|
|
1816
|
+
animation(animation, options = {}) {
|
|
1817
|
+
this.blocks.push(new InputRichBlockAnimation(animation, options));
|
|
1818
|
+
return this;
|
|
181
1819
|
}
|
|
182
1820
|
|
|
183
1821
|
/**
|
|
184
|
-
* Add
|
|
185
|
-
* @param {string}
|
|
1822
|
+
* Add audio track block (Bot API 10.2+)
|
|
1823
|
+
* @param {string} audio
|
|
1824
|
+
* @param {object} [options={}]
|
|
186
1825
|
* @returns {this}
|
|
187
1826
|
*/
|
|
188
|
-
|
|
189
|
-
this.blocks.push(
|
|
190
|
-
type: 'spoiler',
|
|
191
|
-
content: text,
|
|
192
|
-
rawHtml: `<span class="tg-spoiler">${escapeHtml(text)}</span>`,
|
|
193
|
-
});
|
|
1827
|
+
audio(audio, options = {}) {
|
|
1828
|
+
this.blocks.push(new InputRichBlockAudio(audio, options));
|
|
194
1829
|
return this;
|
|
195
1830
|
}
|
|
196
1831
|
|
|
197
1832
|
/**
|
|
198
|
-
* Add
|
|
199
|
-
* @param {string}
|
|
200
|
-
* @param {string}
|
|
1833
|
+
* Add photo block (Bot API 10.2+)
|
|
1834
|
+
* @param {string} photo
|
|
1835
|
+
* @param {string} [caption='']
|
|
1836
|
+
* @param {object} [options={}]
|
|
201
1837
|
* @returns {this}
|
|
202
1838
|
*/
|
|
203
|
-
|
|
204
|
-
this.blocks.push(
|
|
205
|
-
type: 'link',
|
|
206
|
-
text,
|
|
207
|
-
url,
|
|
208
|
-
rawHtml: `<a href="${escapeHtml(url)}">${escapeHtml(text)}</a>`,
|
|
209
|
-
});
|
|
1839
|
+
photo(photo, caption = '', options = {}) {
|
|
1840
|
+
this.blocks.push(new InputRichBlockPhoto(photo, caption, options));
|
|
210
1841
|
return this;
|
|
211
1842
|
}
|
|
212
1843
|
|
|
213
1844
|
/**
|
|
214
|
-
* Add
|
|
215
|
-
* @param {string}
|
|
216
|
-
* @param {
|
|
1845
|
+
* Add video block (Bot API 10.2+)
|
|
1846
|
+
* @param {string} video
|
|
1847
|
+
* @param {object} [options={}]
|
|
217
1848
|
* @returns {this}
|
|
218
1849
|
*/
|
|
219
|
-
|
|
220
|
-
this.blocks.push(
|
|
221
|
-
type: 'mention',
|
|
222
|
-
text,
|
|
223
|
-
userId,
|
|
224
|
-
rawHtml: `<a href="tg://user?id=${userId}">${escapeHtml(text)}</a>`,
|
|
225
|
-
});
|
|
1850
|
+
video(video, options = {}) {
|
|
1851
|
+
this.blocks.push(new InputRichBlockVideo(video, options));
|
|
226
1852
|
return this;
|
|
227
1853
|
}
|
|
228
1854
|
|
|
229
1855
|
/**
|
|
230
|
-
* Add
|
|
231
|
-
* @param {
|
|
232
|
-
* @param {
|
|
1856
|
+
* Add voice note block (Bot API 10.2+)
|
|
1857
|
+
* @param {string} voiceNote
|
|
1858
|
+
* @param {object} [options={}]
|
|
233
1859
|
* @returns {this}
|
|
234
1860
|
*/
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
1861
|
+
voiceNote(voiceNote, options = {}) {
|
|
1862
|
+
this.blocks.push(new InputRichBlockVoiceNote(voiceNote, options));
|
|
1863
|
+
return this;
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
/**
|
|
1867
|
+
* Add AI thinking indicator block (Bot API 10.2+)
|
|
1868
|
+
* @param {string} [text='Thinking...']
|
|
1869
|
+
* @param {object} [options={}]
|
|
1870
|
+
* @returns {this}
|
|
1871
|
+
*/
|
|
1872
|
+
thinking(text = 'Thinking...', options = {}) {
|
|
1873
|
+
this.blocks.push(new InputRichBlockThinking(text, options));
|
|
244
1874
|
return this;
|
|
245
1875
|
}
|
|
246
1876
|
|
|
@@ -279,38 +1909,125 @@ export class RichMessageBuilder {
|
|
|
279
1909
|
}
|
|
280
1910
|
|
|
281
1911
|
/**
|
|
282
|
-
* Add
|
|
1912
|
+
* Add table block (Bot API 10.3 InputRichBlockTable / RichBlockTable)
|
|
1913
|
+
* Supports standard headers, rows, is_bordered, and is_compact mode
|
|
1914
|
+
* @param {Array<string>|Table|InputRichBlockTable|object} headersOrTable
|
|
1915
|
+
* @param {Array<Array<any>>} [rows=[]]
|
|
1916
|
+
* @param {object} [options={}]
|
|
283
1917
|
* @returns {this}
|
|
284
1918
|
*/
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
})
|
|
1919
|
+
table(headersOrTable, rows = [], options = {}) {
|
|
1920
|
+
let block;
|
|
1921
|
+
if (headersOrTable instanceof InputRichBlockTable) {
|
|
1922
|
+
block = headersOrTable;
|
|
1923
|
+
} else if (headersOrTable instanceof Table) {
|
|
1924
|
+
block = new InputRichBlockTable(headersOrTable.headers, headersOrTable.rows, {
|
|
1925
|
+
is_compact: headersOrTable.is_compact,
|
|
1926
|
+
is_bordered: headersOrTable.is_bordered,
|
|
1927
|
+
is_striped: headersOrTable.is_striped,
|
|
1928
|
+
caption: headersOrTable.caption,
|
|
1929
|
+
alignments: headersOrTable._alignments,
|
|
1930
|
+
title: headersOrTable._title,
|
|
1931
|
+
style: headersOrTable._style,
|
|
1932
|
+
col1Width: headersOrTable.col1Width,
|
|
1933
|
+
...options,
|
|
1934
|
+
});
|
|
1935
|
+
} else if (headersOrTable && typeof headersOrTable === 'object' && !Array.isArray(headersOrTable)) {
|
|
1936
|
+
block = new InputRichBlockTable(headersOrTable);
|
|
1937
|
+
} else {
|
|
1938
|
+
block = new InputRichBlockTable(headersOrTable, rows, { is_bordered: true, ...options });
|
|
1939
|
+
}
|
|
1940
|
+
this.blocks.push(block);
|
|
290
1941
|
return this;
|
|
291
1942
|
}
|
|
292
1943
|
|
|
293
1944
|
/**
|
|
294
|
-
*
|
|
295
|
-
* @param {string}
|
|
296
|
-
* @param {
|
|
1945
|
+
* Add a card table block (matching Telegram Bot Card Table UI with rounded container and grid lines)
|
|
1946
|
+
* @param {Array<string>|Table|object} headersOrTable
|
|
1947
|
+
* @param {Array<Array<any>>} [rows=[]]
|
|
1948
|
+
* @param {object} [options={}]
|
|
1949
|
+
* @returns {this}
|
|
1950
|
+
*/
|
|
1951
|
+
cardTable(headersOrTable, rows = [], options = {}) {
|
|
1952
|
+
return this.table(headersOrTable, rows, { is_bordered: true, ...options });
|
|
1953
|
+
}
|
|
1954
|
+
|
|
1955
|
+
/**
|
|
1956
|
+
* Add pre-configured system status card table (matching Telegram bot screenshot)
|
|
1957
|
+
* @param {object} [data={}]
|
|
1958
|
+
* @param {object} [options={}]
|
|
1959
|
+
* @returns {this}
|
|
1960
|
+
*/
|
|
1961
|
+
systemStatus(data = {}, options = {}) {
|
|
1962
|
+
const table = Table.systemStatus(data, options);
|
|
1963
|
+
return this.table(table);
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1966
|
+
/**
|
|
1967
|
+
* Add pre-configured user profile card table (matching Telegram bot screenshot)
|
|
1968
|
+
* @param {object} [data={}]
|
|
1969
|
+
* @param {object} [options={}]
|
|
1970
|
+
* @returns {this}
|
|
1971
|
+
*/
|
|
1972
|
+
userProfile(data = {}, options = {}) {
|
|
1973
|
+
const table = Table.userProfile(data, options);
|
|
1974
|
+
return this.table(table);
|
|
1975
|
+
}
|
|
1976
|
+
|
|
1977
|
+
/**
|
|
1978
|
+
* Add compact table block (Bot API 10.3 is_compact table)
|
|
1979
|
+
* @param {Array<string>} headers
|
|
1980
|
+
* @param {Array<Array<any>>} [rows=[]]
|
|
1981
|
+
* @param {object} [options={}]
|
|
1982
|
+
* @returns {this}
|
|
1983
|
+
*/
|
|
1984
|
+
compactTable(headers, rows = [], options = {}) {
|
|
1985
|
+
return this.table(headers, rows, { ...options, is_compact: true });
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
/**
|
|
1989
|
+
* Add document block (Bot API 10.3 InputRichBlockDocument)
|
|
1990
|
+
* @param {string|object} document
|
|
1991
|
+
* @param {string} [caption='']
|
|
1992
|
+
* @param {object} [options={}]
|
|
1993
|
+
* @returns {this}
|
|
1994
|
+
*/
|
|
1995
|
+
document(document, caption = '', options = {}) {
|
|
1996
|
+
const block = new InputRichBlockDocument(document, caption, options);
|
|
1997
|
+
this.blocks.push(block);
|
|
1998
|
+
return this;
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
/**
|
|
2002
|
+
* Add buttons block to the rich message (Bot API 10.3 InputRichBlockButtons)
|
|
2003
|
+
* @param {Array<Array<object>>|Array<object>} buttonsMatrix
|
|
297
2004
|
* @returns {this}
|
|
298
2005
|
*/
|
|
299
|
-
|
|
300
|
-
|
|
2006
|
+
buttons(buttonsMatrix) {
|
|
2007
|
+
const block = new InputRichBlockButtons(buttonsMatrix);
|
|
2008
|
+
this.blocks.push(block);
|
|
301
2009
|
return this;
|
|
302
2010
|
}
|
|
303
2011
|
|
|
304
2012
|
/**
|
|
305
|
-
*
|
|
306
|
-
|
|
2013
|
+
* Add buttons block (alias)
|
|
2014
|
+
*/
|
|
2015
|
+
addButtonsBlock(buttonsMatrix) {
|
|
2016
|
+
return this.buttons(buttonsMatrix);
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
/**
|
|
2020
|
+
* Set ephemeral parameters (Bot API 10.3 EphemeralMessageParameters)
|
|
2021
|
+
* @param {number|object|EphemeralMessageParameters} lifetimeSecondsOrParams
|
|
307
2022
|
* @returns {this}
|
|
308
2023
|
*/
|
|
309
2024
|
ephemeral(lifetimeSecondsOrParams = 60) {
|
|
310
|
-
if (
|
|
311
|
-
this._ephemeral = { lifetime: lifetimeSecondsOrParams };
|
|
312
|
-
} else {
|
|
2025
|
+
if (lifetimeSecondsOrParams instanceof EphemeralMessageParameters) {
|
|
313
2026
|
this._ephemeral = lifetimeSecondsOrParams;
|
|
2027
|
+
} else if (typeof lifetimeSecondsOrParams === 'number') {
|
|
2028
|
+
this._ephemeral = new EphemeralMessageParameters(lifetimeSecondsOrParams);
|
|
2029
|
+
} else {
|
|
2030
|
+
this._ephemeral = new EphemeralMessageParameters(lifetimeSecondsOrParams);
|
|
314
2031
|
}
|
|
315
2032
|
return this;
|
|
316
2033
|
}
|
|
@@ -486,7 +2203,17 @@ export class RichMessageBuilder {
|
|
|
486
2203
|
}
|
|
487
2204
|
|
|
488
2205
|
/**
|
|
489
|
-
*
|
|
2206
|
+
* Add raw custom block
|
|
2207
|
+
* @param {object} block
|
|
2208
|
+
* @returns {this}
|
|
2209
|
+
*/
|
|
2210
|
+
addBlock(block) {
|
|
2211
|
+
this.blocks.push(block);
|
|
2212
|
+
return this;
|
|
2213
|
+
}
|
|
2214
|
+
|
|
2215
|
+
/**
|
|
2216
|
+
* Compile HTML string representation for Telegram HTML mode
|
|
490
2217
|
* @returns {string}
|
|
491
2218
|
*/
|
|
492
2219
|
compileHtml() {
|
|
@@ -495,7 +2222,9 @@ export class RichMessageBuilder {
|
|
|
495
2222
|
parts.push(this._text);
|
|
496
2223
|
}
|
|
497
2224
|
for (const block of this.blocks) {
|
|
498
|
-
if (block
|
|
2225
|
+
if (typeof block?.toHtml === 'function') {
|
|
2226
|
+
parts.push(block.toHtml());
|
|
2227
|
+
} else if (block?.rawHtml) {
|
|
499
2228
|
parts.push(block.rawHtml);
|
|
500
2229
|
}
|
|
501
2230
|
}
|
|
@@ -517,24 +2246,33 @@ export class RichMessageBuilder {
|
|
|
517
2246
|
const payload = {
|
|
518
2247
|
text: compiledText || ' ',
|
|
519
2248
|
parse_mode: this._parseMode,
|
|
520
|
-
blocks: this.blocks.map((b) =>
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
label: b.label,
|
|
527
|
-
value: b.value,
|
|
528
|
-
})),
|
|
2249
|
+
blocks: this.blocks.map((b) => {
|
|
2250
|
+
if (typeof b?.toJSON === 'function') {
|
|
2251
|
+
return b.toJSON();
|
|
2252
|
+
}
|
|
2253
|
+
return { ...b };
|
|
2254
|
+
}),
|
|
529
2255
|
...this._extra,
|
|
530
2256
|
};
|
|
531
2257
|
|
|
2258
|
+
if (this._media && this._media.length > 0) {
|
|
2259
|
+
payload.media = this._media.map((m) => (typeof m?.toJSON === 'function' ? m.toJSON() : m));
|
|
2260
|
+
}
|
|
2261
|
+
|
|
2262
|
+
if (this._isRtl !== undefined) {
|
|
2263
|
+
payload.is_rtl = Boolean(this._isRtl);
|
|
2264
|
+
}
|
|
2265
|
+
|
|
532
2266
|
if (replyMarkup) {
|
|
533
2267
|
payload.reply_markup = replyMarkup;
|
|
534
2268
|
}
|
|
535
2269
|
|
|
536
2270
|
if (this._ephemeral) {
|
|
537
|
-
|
|
2271
|
+
const ephemeralObj = typeof this._ephemeral.toJSON === 'function'
|
|
2272
|
+
? this._ephemeral.toJSON()
|
|
2273
|
+
: this._ephemeral;
|
|
2274
|
+
payload.ephemeral_message_parameters = ephemeralObj;
|
|
2275
|
+
payload.ephemeral_parameters = ephemeralObj;
|
|
538
2276
|
}
|
|
539
2277
|
|
|
540
2278
|
if (this._draftId !== null) {
|
|
@@ -544,6 +2282,55 @@ export class RichMessageBuilder {
|
|
|
544
2282
|
return payload;
|
|
545
2283
|
}
|
|
546
2284
|
|
|
2285
|
+
/**
|
|
2286
|
+
* Set right-to-left layout mode (Bot API 10.2+)
|
|
2287
|
+
* @param {boolean} [rtl=true]
|
|
2288
|
+
* @returns {this}
|
|
2289
|
+
*/
|
|
2290
|
+
isRtl(rtl = true) {
|
|
2291
|
+
this._isRtl = Boolean(rtl);
|
|
2292
|
+
return this;
|
|
2293
|
+
}
|
|
2294
|
+
|
|
2295
|
+
/**
|
|
2296
|
+
* Add media attachments to the rich message (Bot API 10.2+)
|
|
2297
|
+
* @param {...(object|string|Array<object|string>)} items
|
|
2298
|
+
* @returns {this}
|
|
2299
|
+
*/
|
|
2300
|
+
media(...items) {
|
|
2301
|
+
for (const item of items.flat()) {
|
|
2302
|
+
this.addMedia(item);
|
|
2303
|
+
}
|
|
2304
|
+
return this;
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2307
|
+
/**
|
|
2308
|
+
* Add a single media attachment
|
|
2309
|
+
* @param {object|string} item
|
|
2310
|
+
* @param {object} [options={}]
|
|
2311
|
+
* @returns {this}
|
|
2312
|
+
*/
|
|
2313
|
+
addMedia(item, options = {}) {
|
|
2314
|
+
if (item instanceof InputRichMessageMedia) {
|
|
2315
|
+
this._media.push(item);
|
|
2316
|
+
} else if (typeof item === 'string') {
|
|
2317
|
+
this._media.push(new InputRichMessageMedia(item, options.type || 'photo', options));
|
|
2318
|
+
} else if (typeof item === 'object' && item !== null) {
|
|
2319
|
+
this._media.push(new InputRichMessageMedia(item, item.type || options.type || 'photo', { ...options, ...item }));
|
|
2320
|
+
} else {
|
|
2321
|
+
this._media.push(item);
|
|
2322
|
+
}
|
|
2323
|
+
return this;
|
|
2324
|
+
}
|
|
2325
|
+
|
|
2326
|
+
/**
|
|
2327
|
+
* Export as an InputRichMessage instance
|
|
2328
|
+
* @returns {InputRichMessage}
|
|
2329
|
+
*/
|
|
2330
|
+
toInputRichMessage() {
|
|
2331
|
+
return new InputRichMessage(this.compile());
|
|
2332
|
+
}
|
|
2333
|
+
|
|
547
2334
|
/**
|
|
548
2335
|
* Build plain structured Rich Message object
|
|
549
2336
|
* @returns {object}
|
|
@@ -618,6 +2405,43 @@ export class RichMessageBuilder {
|
|
|
618
2405
|
return new RichMessageBuilder(initialText);
|
|
619
2406
|
}
|
|
620
2407
|
|
|
2408
|
+
/**
|
|
2409
|
+
* Create a rich message pre-populated with a table
|
|
2410
|
+
* @param {Array<string>|Table|InputRichBlockTable} headers
|
|
2411
|
+
* @param {Array<Array<any>>} [rows]
|
|
2412
|
+
* @param {object} [options]
|
|
2413
|
+
* @returns {RichMessageBuilder}
|
|
2414
|
+
*/
|
|
2415
|
+
static table(headers, rows = [], options = {}) {
|
|
2416
|
+
const builder = new RichMessageBuilder();
|
|
2417
|
+
builder.table(headers, rows, options);
|
|
2418
|
+
return builder;
|
|
2419
|
+
}
|
|
2420
|
+
|
|
2421
|
+
/**
|
|
2422
|
+
* Create a rich message pre-populated with a compact table
|
|
2423
|
+
* @param {Array<string>} headers
|
|
2424
|
+
* @param {Array<Array<any>>} [rows]
|
|
2425
|
+
* @param {object} [options]
|
|
2426
|
+
* @returns {RichMessageBuilder}
|
|
2427
|
+
*/
|
|
2428
|
+
static compactTable(headers, rows = [], options = {}) {
|
|
2429
|
+
const builder = new RichMessageBuilder();
|
|
2430
|
+
builder.compactTable(headers, rows, options);
|
|
2431
|
+
return builder;
|
|
2432
|
+
}
|
|
2433
|
+
|
|
2434
|
+
/**
|
|
2435
|
+
* Create a rich message with buttons block
|
|
2436
|
+
* @param {Array<Array<object>>|Array<object>} buttonsMatrix
|
|
2437
|
+
* @returns {RichMessageBuilder}
|
|
2438
|
+
*/
|
|
2439
|
+
static buttons(buttonsMatrix) {
|
|
2440
|
+
const builder = new RichMessageBuilder();
|
|
2441
|
+
builder.buttons(buttonsMatrix);
|
|
2442
|
+
return builder;
|
|
2443
|
+
}
|
|
2444
|
+
|
|
621
2445
|
/**
|
|
622
2446
|
* Create a pre-configured interactive Card
|
|
623
2447
|
* @param {string} title
|
|
@@ -651,12 +2475,21 @@ export class RichMessageBuilder {
|
|
|
651
2475
|
/**
|
|
652
2476
|
* Create an ephemeral disappearing message builder
|
|
653
2477
|
* @param {string} text
|
|
654
|
-
* @param {number} [
|
|
2478
|
+
* @param {number|object|EphemeralMessageParameters} [lifetimeSecondsOrParams=60]
|
|
655
2479
|
* @returns {RichMessageBuilder}
|
|
656
2480
|
*/
|
|
657
|
-
static ephemeral(text,
|
|
2481
|
+
static ephemeral(text, lifetimeSecondsOrParams = 60) {
|
|
658
2482
|
const builder = new RichMessageBuilder(text);
|
|
659
|
-
return builder.ephemeral(
|
|
2483
|
+
return builder.ephemeral(lifetimeSecondsOrParams);
|
|
2484
|
+
}
|
|
2485
|
+
|
|
2486
|
+
/**
|
|
2487
|
+
* Helper to format a tg://document?id= link
|
|
2488
|
+
* @param {string} documentId
|
|
2489
|
+
* @param {string} [text='Document']
|
|
2490
|
+
*/
|
|
2491
|
+
static documentLink(documentId, text = 'Document') {
|
|
2492
|
+
return `<a href="tg://document?id=${escapeHtml(documentId)}">${escapeHtml(text)}</a>`;
|
|
660
2493
|
}
|
|
661
2494
|
}
|
|
662
2495
|
|