telegix 1.1.1
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/LICENSE +21 -0
- package/README.md +1534 -0
- package/index.d.ts +539 -0
- package/index.js +38 -0
- package/lib/album.js +57 -0
- package/lib/api.js +1840 -0
- package/lib/chataction.js +40 -0
- package/lib/cluster.js +68 -0
- package/lib/composer.js +419 -0
- package/lib/context.js +970 -0
- package/lib/errors.js +67 -0
- package/lib/format.js +115 -0
- package/lib/i18n.js +158 -0
- package/lib/inline-debounce.js +49 -0
- package/lib/inline.js +79 -0
- package/lib/markdownv2.js +29 -0
- package/lib/markup.js +321 -0
- package/lib/payment.js +91 -0
- package/lib/polling.js +101 -0
- package/lib/prompt.js +62 -0
- package/lib/ratelimit.js +59 -0
- package/lib/rich.js +609 -0
- package/lib/scenes.js +206 -0
- package/lib/serialize.js +141 -0
- package/lib/session.js +145 -0
- package/lib/telegix.js +176 -0
- package/lib/webapp.js +65 -0
- package/lib/webhook.js +86 -0
- package/package.json +42 -0
package/lib/rich.js
ADDED
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telegix - Rich Message & Draft Builder Suite
|
|
3
|
+
* Modern structured rich messages, cards, drafts, and layout blocks for Telegram Bot API.
|
|
4
|
+
* @module telegix/rich
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { escapeHtml, html } from './format.js';
|
|
8
|
+
import { Markup } from './markup.js';
|
|
9
|
+
|
|
10
|
+
export class RichMessageBuilder {
|
|
11
|
+
constructor(initialText = '') {
|
|
12
|
+
this.blocks = [];
|
|
13
|
+
this._text = initialText ? String(initialText) : '';
|
|
14
|
+
this._parseMode = 'HTML';
|
|
15
|
+
this._inlineKeyboard = [];
|
|
16
|
+
this._draftId = null;
|
|
17
|
+
this._ephemeral = null;
|
|
18
|
+
this._media = null;
|
|
19
|
+
this._extra = {};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Set parse mode ('HTML', 'MarkdownV2', etc.)
|
|
24
|
+
* @param {string} mode
|
|
25
|
+
* @returns {this}
|
|
26
|
+
*/
|
|
27
|
+
parseMode(mode) {
|
|
28
|
+
this._parseMode = mode;
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Set primary text
|
|
34
|
+
* @param {string} text
|
|
35
|
+
* @returns {this}
|
|
36
|
+
*/
|
|
37
|
+
text(text) {
|
|
38
|
+
this._text = String(text);
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Add a header block with optional emoji
|
|
44
|
+
* @param {string} text
|
|
45
|
+
* @param {string} [emoji]
|
|
46
|
+
* @returns {this}
|
|
47
|
+
*/
|
|
48
|
+
header(text, emoji = '') {
|
|
49
|
+
const formatted = emoji ? `${emoji} ${text}` : text;
|
|
50
|
+
this.blocks.push({
|
|
51
|
+
type: 'header',
|
|
52
|
+
content: formatted,
|
|
53
|
+
rawHtml: `<b>${escapeHtml(formatted)}</b>`,
|
|
54
|
+
});
|
|
55
|
+
return this;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Add a paragraph block
|
|
60
|
+
* @param {string} text
|
|
61
|
+
* @returns {this}
|
|
62
|
+
*/
|
|
63
|
+
paragraph(text) {
|
|
64
|
+
this.blocks.push({
|
|
65
|
+
type: 'paragraph',
|
|
66
|
+
content: text,
|
|
67
|
+
rawHtml: escapeHtml(text),
|
|
68
|
+
});
|
|
69
|
+
return this;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Add bold text block
|
|
74
|
+
* @param {string} text
|
|
75
|
+
* @returns {this}
|
|
76
|
+
*/
|
|
77
|
+
bold(text) {
|
|
78
|
+
this.blocks.push({
|
|
79
|
+
type: 'bold',
|
|
80
|
+
content: text,
|
|
81
|
+
rawHtml: `<b>${escapeHtml(text)}</b>`,
|
|
82
|
+
});
|
|
83
|
+
return this;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Add italic text block
|
|
88
|
+
* @param {string} text
|
|
89
|
+
* @returns {this}
|
|
90
|
+
*/
|
|
91
|
+
italic(text) {
|
|
92
|
+
this.blocks.push({
|
|
93
|
+
type: 'italic',
|
|
94
|
+
content: text,
|
|
95
|
+
rawHtml: `<i>${escapeHtml(text)}</i>`,
|
|
96
|
+
});
|
|
97
|
+
return this;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Add underline text block
|
|
102
|
+
* @param {string} text
|
|
103
|
+
* @returns {this}
|
|
104
|
+
*/
|
|
105
|
+
underline(text) {
|
|
106
|
+
this.blocks.push({
|
|
107
|
+
type: 'underline',
|
|
108
|
+
content: text,
|
|
109
|
+
rawHtml: `<u>${escapeHtml(text)}</u>`,
|
|
110
|
+
});
|
|
111
|
+
return this;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Add strikethrough text block
|
|
116
|
+
* @param {string} text
|
|
117
|
+
* @returns {this}
|
|
118
|
+
*/
|
|
119
|
+
strikethrough(text) {
|
|
120
|
+
this.blocks.push({
|
|
121
|
+
type: 'strikethrough',
|
|
122
|
+
content: text,
|
|
123
|
+
rawHtml: `<s>${escapeHtml(text)}</s>`,
|
|
124
|
+
});
|
|
125
|
+
return this;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Add code block or inline code
|
|
130
|
+
* @param {string} codeText
|
|
131
|
+
* @param {string} [language]
|
|
132
|
+
* @returns {this}
|
|
133
|
+
*/
|
|
134
|
+
code(codeText, language = '') {
|
|
135
|
+
const isMultiline = String(codeText).includes('\n') || Boolean(language);
|
|
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
|
+
});
|
|
144
|
+
return this;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Add a blockquote block
|
|
149
|
+
* @param {string} text
|
|
150
|
+
* @param {boolean} [expandable=false]
|
|
151
|
+
* @returns {this}
|
|
152
|
+
*/
|
|
153
|
+
quote(text, expandable = false) {
|
|
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
|
+
});
|
|
162
|
+
return this;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Add an expandable blockquote
|
|
167
|
+
* @param {string} text
|
|
168
|
+
* @returns {this}
|
|
169
|
+
*/
|
|
170
|
+
expandableQuote(text) {
|
|
171
|
+
return this.quote(text, true);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Add spoiler block
|
|
176
|
+
* @param {string} text
|
|
177
|
+
* @returns {this}
|
|
178
|
+
*/
|
|
179
|
+
spoiler(text) {
|
|
180
|
+
this.blocks.push({
|
|
181
|
+
type: 'spoiler',
|
|
182
|
+
content: text,
|
|
183
|
+
rawHtml: `<span class="tg-spoiler">${escapeHtml(text)}</span>`,
|
|
184
|
+
});
|
|
185
|
+
return this;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Add formatted link
|
|
190
|
+
* @param {string} text
|
|
191
|
+
* @param {string} url
|
|
192
|
+
* @returns {this}
|
|
193
|
+
*/
|
|
194
|
+
link(text, url) {
|
|
195
|
+
this.blocks.push({
|
|
196
|
+
type: 'link',
|
|
197
|
+
text,
|
|
198
|
+
url,
|
|
199
|
+
rawHtml: `<a href="${escapeHtml(url)}">${escapeHtml(text)}</a>`,
|
|
200
|
+
});
|
|
201
|
+
return this;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Add user mention
|
|
206
|
+
* @param {string} text
|
|
207
|
+
* @param {number|string} userId
|
|
208
|
+
* @returns {this}
|
|
209
|
+
*/
|
|
210
|
+
mention(text, userId) {
|
|
211
|
+
this.blocks.push({
|
|
212
|
+
type: 'mention',
|
|
213
|
+
text,
|
|
214
|
+
userId,
|
|
215
|
+
rawHtml: `<a href="tg://user?id=${userId}">${escapeHtml(text)}</a>`,
|
|
216
|
+
});
|
|
217
|
+
return this;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Add bullet list
|
|
222
|
+
* @param {Array<string>} items
|
|
223
|
+
* @param {string} [bullet='•']
|
|
224
|
+
* @returns {this}
|
|
225
|
+
*/
|
|
226
|
+
list(items, bullet = '•') {
|
|
227
|
+
const listItems = Array.isArray(items) ? items : [items];
|
|
228
|
+
const htmlLines = listItems.map((item) => `${bullet} ${escapeHtml(item)}`).join('\n');
|
|
229
|
+
this.blocks.push({
|
|
230
|
+
type: 'list',
|
|
231
|
+
items: listItems,
|
|
232
|
+
bullet,
|
|
233
|
+
rawHtml: htmlLines,
|
|
234
|
+
});
|
|
235
|
+
return this;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Add numbered list
|
|
240
|
+
* @param {Array<string>} items
|
|
241
|
+
* @returns {this}
|
|
242
|
+
*/
|
|
243
|
+
numberedList(items) {
|
|
244
|
+
const listItems = Array.isArray(items) ? items : [items];
|
|
245
|
+
const htmlLines = listItems.map((item, idx) => `<b>${idx + 1}.</b> ${escapeHtml(item)}`).join('\n');
|
|
246
|
+
this.blocks.push({
|
|
247
|
+
type: 'numbered_list',
|
|
248
|
+
items: listItems,
|
|
249
|
+
rawHtml: htmlLines,
|
|
250
|
+
});
|
|
251
|
+
return this;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Add badge / stat item
|
|
256
|
+
* @param {string} label
|
|
257
|
+
* @param {string|number} value
|
|
258
|
+
* @param {string} [icon]
|
|
259
|
+
* @returns {this}
|
|
260
|
+
*/
|
|
261
|
+
badge(label, value, icon = '') {
|
|
262
|
+
const iconPrefix = icon ? `${icon} ` : '';
|
|
263
|
+
this.blocks.push({
|
|
264
|
+
type: 'badge',
|
|
265
|
+
label,
|
|
266
|
+
value,
|
|
267
|
+
rawHtml: `${iconPrefix}<b>${escapeHtml(label)}:</b> <code>${escapeHtml(value)}</code>`,
|
|
268
|
+
});
|
|
269
|
+
return this;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Add divider line
|
|
274
|
+
* @returns {this}
|
|
275
|
+
*/
|
|
276
|
+
divider() {
|
|
277
|
+
this.blocks.push({
|
|
278
|
+
type: 'divider',
|
|
279
|
+
rawHtml: '───────────────',
|
|
280
|
+
});
|
|
281
|
+
return this;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Attach photo or media
|
|
286
|
+
* @param {string} url
|
|
287
|
+
* @param {string} [caption]
|
|
288
|
+
* @returns {this}
|
|
289
|
+
*/
|
|
290
|
+
photo(url, caption = '') {
|
|
291
|
+
this._media = { type: 'photo', url, caption };
|
|
292
|
+
return this;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Set ephemeral parameters (disappearing message)
|
|
297
|
+
* @param {number|object} lifetimeSecondsOrParams
|
|
298
|
+
* @returns {this}
|
|
299
|
+
*/
|
|
300
|
+
ephemeral(lifetimeSecondsOrParams = 60) {
|
|
301
|
+
if (typeof lifetimeSecondsOrParams === 'number') {
|
|
302
|
+
this._ephemeral = { lifetime: lifetimeSecondsOrParams };
|
|
303
|
+
} else {
|
|
304
|
+
this._ephemeral = lifetimeSecondsOrParams;
|
|
305
|
+
}
|
|
306
|
+
return this;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Set draft ID or configure as draft
|
|
311
|
+
* @param {number} [draftId]
|
|
312
|
+
* @returns {this}
|
|
313
|
+
*/
|
|
314
|
+
draftId(draftId) {
|
|
315
|
+
this._draftId = draftId ?? Math.floor(Math.random() * 2147483647) + 1;
|
|
316
|
+
return this;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Mark as draft with auto-generated ID
|
|
321
|
+
* @returns {this}
|
|
322
|
+
*/
|
|
323
|
+
asDraft() {
|
|
324
|
+
return this.draftId();
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Add a single inline button or row of buttons
|
|
329
|
+
* @param {object|Array<object>} buttons
|
|
330
|
+
* @returns {this}
|
|
331
|
+
*/
|
|
332
|
+
button(buttons) {
|
|
333
|
+
if (Array.isArray(buttons)) {
|
|
334
|
+
this._inlineKeyboard.push(buttons);
|
|
335
|
+
} else {
|
|
336
|
+
this._inlineKeyboard.push([buttons]);
|
|
337
|
+
}
|
|
338
|
+
return this;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Add a row of inline buttons
|
|
343
|
+
* @param {...object} buttons
|
|
344
|
+
* @returns {this}
|
|
345
|
+
*/
|
|
346
|
+
row(...buttons) {
|
|
347
|
+
if (buttons.length > 0) {
|
|
348
|
+
this._inlineKeyboard.push(buttons);
|
|
349
|
+
}
|
|
350
|
+
return this;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Add callback query button
|
|
355
|
+
* @param {string} text
|
|
356
|
+
* @param {string} data
|
|
357
|
+
* @returns {this}
|
|
358
|
+
*/
|
|
359
|
+
callback(text, data) {
|
|
360
|
+
return this.button(Markup.button.callback(text, data));
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Add URL button
|
|
365
|
+
* @param {string} text
|
|
366
|
+
* @param {string} url
|
|
367
|
+
* @returns {this}
|
|
368
|
+
*/
|
|
369
|
+
url(text, url) {
|
|
370
|
+
return this.button(Markup.button.url(text, url));
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Add Bot API 10.3 disabled button
|
|
375
|
+
* @param {string} text
|
|
376
|
+
* @returns {this}
|
|
377
|
+
*/
|
|
378
|
+
disabled(text) {
|
|
379
|
+
return this.button(Markup.button.disabled(text));
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Add Web App button
|
|
384
|
+
* @param {string} text
|
|
385
|
+
* @param {string} webAppUrl
|
|
386
|
+
* @returns {this}
|
|
387
|
+
*/
|
|
388
|
+
webApp(text, webAppUrl) {
|
|
389
|
+
return this.button(Markup.button.webApp(text, webAppUrl));
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Add Copy Text button
|
|
394
|
+
* @param {string} text
|
|
395
|
+
* @param {string} textToCopy
|
|
396
|
+
* @returns {this}
|
|
397
|
+
*/
|
|
398
|
+
copyText(text, textToCopy) {
|
|
399
|
+
return this.button(Markup.button.copyText(text, textToCopy));
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Add full inline keyboard matrix
|
|
404
|
+
* @param {Array<Array<object>>} matrix
|
|
405
|
+
* @returns {this}
|
|
406
|
+
*/
|
|
407
|
+
keyboard(matrix) {
|
|
408
|
+
if (Array.isArray(matrix)) {
|
|
409
|
+
this._inlineKeyboard = matrix;
|
|
410
|
+
}
|
|
411
|
+
return this;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Set custom reply markup (e.g. from Markup helper)
|
|
416
|
+
* @param {object} markup
|
|
417
|
+
* @returns {this}
|
|
418
|
+
*/
|
|
419
|
+
replyMarkup(markup) {
|
|
420
|
+
this._customReplyMarkup = markup;
|
|
421
|
+
return this;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Set extra options
|
|
426
|
+
* @param {object} extra
|
|
427
|
+
* @returns {this}
|
|
428
|
+
*/
|
|
429
|
+
extra(extra) {
|
|
430
|
+
this._extra = { ...this._extra, ...extra };
|
|
431
|
+
return this;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Compile all rich blocks into standard HTML text for compatibility
|
|
436
|
+
* @returns {string}
|
|
437
|
+
*/
|
|
438
|
+
compileHtml() {
|
|
439
|
+
const parts = [];
|
|
440
|
+
if (this._text) {
|
|
441
|
+
parts.push(this._text);
|
|
442
|
+
}
|
|
443
|
+
for (const block of this.blocks) {
|
|
444
|
+
if (block.rawHtml) {
|
|
445
|
+
parts.push(block.rawHtml);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
return parts.join('\n\n');
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Compile payload ready for Telegram Bot API
|
|
453
|
+
* @returns {object}
|
|
454
|
+
*/
|
|
455
|
+
compile() {
|
|
456
|
+
const compiledText = this.compileHtml();
|
|
457
|
+
const replyMarkup =
|
|
458
|
+
this._customReplyMarkup ||
|
|
459
|
+
(this._inlineKeyboard.length > 0
|
|
460
|
+
? { inline_keyboard: this._inlineKeyboard }
|
|
461
|
+
: undefined);
|
|
462
|
+
|
|
463
|
+
const payload = {
|
|
464
|
+
text: compiledText || ' ',
|
|
465
|
+
parse_mode: this._parseMode,
|
|
466
|
+
blocks: this.blocks.map((b) => ({
|
|
467
|
+
type: b.type,
|
|
468
|
+
content: b.content,
|
|
469
|
+
language: b.language,
|
|
470
|
+
expandable: b.expandable,
|
|
471
|
+
items: b.items,
|
|
472
|
+
label: b.label,
|
|
473
|
+
value: b.value,
|
|
474
|
+
})),
|
|
475
|
+
...this._extra,
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
if (replyMarkup) {
|
|
479
|
+
payload.reply_markup = replyMarkup;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
if (this._ephemeral) {
|
|
483
|
+
payload.ephemeral_parameters = this._ephemeral;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (this._draftId !== null) {
|
|
487
|
+
payload.draft_id = this._draftId;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
return payload;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Build plain structured Rich Message object
|
|
495
|
+
* @returns {object}
|
|
496
|
+
*/
|
|
497
|
+
build() {
|
|
498
|
+
return this.compile();
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* JSON serialization
|
|
503
|
+
*/
|
|
504
|
+
toJSON() {
|
|
505
|
+
return this.compile();
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Send this rich message to a chat
|
|
510
|
+
* @param {import('./context.js').Context} ctx
|
|
511
|
+
* @param {number|string} [chatId]
|
|
512
|
+
* @param {object} [extra]
|
|
513
|
+
*/
|
|
514
|
+
async send(ctx, chatId, extra = {}) {
|
|
515
|
+
const targetChatId = chatId || ctx.chat?.id || ctx.chatId;
|
|
516
|
+
if (!targetChatId) {
|
|
517
|
+
throw new Error('RichMessage.send() requires a target chatId or active Context.');
|
|
518
|
+
}
|
|
519
|
+
const compiled = this.compile();
|
|
520
|
+
return ctx.telegram.sendRichMessage(targetChatId, compiled, extra);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Send this rich message as a draft
|
|
525
|
+
* @param {import('./context.js').Context} ctx
|
|
526
|
+
* @param {number|string} [chatId]
|
|
527
|
+
* @param {object} [extra]
|
|
528
|
+
*/
|
|
529
|
+
async sendDraft(ctx, chatId, extra = {}) {
|
|
530
|
+
const targetChatId = chatId || ctx.chat?.id || ctx.chatId;
|
|
531
|
+
if (!targetChatId) {
|
|
532
|
+
throw new Error('RichMessage.sendDraft() requires a target chatId or active Context.');
|
|
533
|
+
}
|
|
534
|
+
const compiled = this.compile();
|
|
535
|
+
return ctx.telegram.sendRichMessageDraft(targetChatId, compiled, extra);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Edit an existing message with this rich message
|
|
540
|
+
* @param {import('./context.js').Context} ctx
|
|
541
|
+
* @param {number} [messageId]
|
|
542
|
+
* @param {object} [extra]
|
|
543
|
+
*/
|
|
544
|
+
async edit(ctx, messageId, extra = {}) {
|
|
545
|
+
const targetChatId = ctx.chat?.id || ctx.chatId;
|
|
546
|
+
const targetMessageId = messageId || ctx.message?.id || ctx.msg?.id;
|
|
547
|
+
if (!targetChatId || !targetMessageId) {
|
|
548
|
+
throw new Error('RichMessage.edit() requires chatId and messageId.');
|
|
549
|
+
}
|
|
550
|
+
const compiled = this.compile();
|
|
551
|
+
return ctx.telegram.editRichMessageText(targetChatId, targetMessageId, compiled, extra);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// ==========================================
|
|
555
|
+
// Static Factory Methods
|
|
556
|
+
// ==========================================
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Create a new RichMessage instance
|
|
560
|
+
* @param {string} [initialText]
|
|
561
|
+
* @returns {RichMessageBuilder}
|
|
562
|
+
*/
|
|
563
|
+
static create(initialText) {
|
|
564
|
+
return new RichMessageBuilder(initialText);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* Create a pre-configured interactive Card
|
|
569
|
+
* @param {string} title
|
|
570
|
+
* @param {string} description
|
|
571
|
+
* @param {Array<object>} [buttons=[]]
|
|
572
|
+
* @returns {RichMessageBuilder}
|
|
573
|
+
*/
|
|
574
|
+
static card(title, description, buttons = []) {
|
|
575
|
+
const builder = new RichMessageBuilder();
|
|
576
|
+
builder.header(title);
|
|
577
|
+
if (description) {
|
|
578
|
+
builder.paragraph(description);
|
|
579
|
+
}
|
|
580
|
+
if (buttons.length > 0) {
|
|
581
|
+
builder.row(...buttons);
|
|
582
|
+
}
|
|
583
|
+
return builder;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* Create a draft message builder
|
|
588
|
+
* @param {string} text
|
|
589
|
+
* @param {number} [draftId]
|
|
590
|
+
* @returns {RichMessageBuilder}
|
|
591
|
+
*/
|
|
592
|
+
static draft(text, draftId) {
|
|
593
|
+
const builder = new RichMessageBuilder(text);
|
|
594
|
+
return builder.draftId(draftId);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* Create an ephemeral disappearing message builder
|
|
599
|
+
* @param {string} text
|
|
600
|
+
* @param {number} [lifetimeSeconds=60]
|
|
601
|
+
* @returns {RichMessageBuilder}
|
|
602
|
+
*/
|
|
603
|
+
static ephemeral(text, lifetimeSeconds = 60) {
|
|
604
|
+
const builder = new RichMessageBuilder(text);
|
|
605
|
+
return builder.ephemeral(lifetimeSeconds);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
export const RichMessage = RichMessageBuilder;
|