@icanseeuanywhere/telekaf 4.16.5 → 4.16.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +422 -385
- package/lib/telegraf.js +29 -0
- package/package.json +1 -1
- package/src/telegraf.ts +29 -0
- package/typings/telegraf.d.ts +2 -0
- package/typings/telegraf.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
> Developed & maintained by **[@kafk6](https://t.me/kafk6)**
|
|
4
|
+
|
|
5
|
+
</div>
|
|
6
|
+
|
|
1
7
|
<header>
|
|
2
8
|
|
|
3
9
|
<div align="center">
|
|
@@ -26,40 +32,55 @@
|
|
|
26
32
|
> This package tracks the latest Telegram Bot API releases and ships features ahead of the upstream package.
|
|
27
33
|
> It is a drop-in replacement: just swap `npm install telegraf` → `npm install @icanseeuanywhere/telekaf` and change your imports from `'telegraf'` to `'@icanseeuanywhere/telekaf'`.
|
|
28
34
|
|
|
35
|
+
|
|
29
36
|
---
|
|
30
37
|
|
|
31
38
|
## 🆕 Rich Messages — Bot API 10.1
|
|
32
39
|
|
|
33
|
-
> Added in **Bot API 10.1** (June 11, 2026). Rich Messages
|
|
40
|
+
> Added in **Bot API 10.1** (June 11, 2026). Rich Messages let bots send highly structured content using HTML or Markdown — headings, lists, tables, media collages, code blocks, math expressions, AI thinking blocks, and more — with streaming support for AI-generated replies.
|
|
34
41
|
|
|
35
42
|
### Table of Contents
|
|
36
43
|
|
|
37
|
-
- [Quick Start](#
|
|
44
|
+
- [Quick Start](#quick-start)
|
|
38
45
|
- [Sending Methods](#sending-methods)
|
|
39
|
-
- [
|
|
40
|
-
- [
|
|
41
|
-
- [
|
|
42
|
-
- [
|
|
46
|
+
- [InputRichMessage Format](#inputrichmessage-format)
|
|
47
|
+
- [RichHTMLBuilder](#richhtmlbuilder)
|
|
48
|
+
- [Text Formatting](#text-formatting-html)
|
|
49
|
+
- [Headings & Paragraphs](#headings--paragraphs)
|
|
50
|
+
- [Lists](#lists-html)
|
|
51
|
+
- [Code Blocks](#code-blocks)
|
|
52
|
+
- [Blockquote & Pull Quote](#blockquote--pull-quote)
|
|
53
|
+
- [Math](#math-html)
|
|
54
|
+
- [Media — Photo, Video, Audio](#media--photo-video-audio)
|
|
55
|
+
- [Collage & Slideshow](#collage--slideshow)
|
|
56
|
+
- [Map](#map)
|
|
57
|
+
- [Table](#table-html)
|
|
58
|
+
- [Details (Expandable)](#details-expandable)
|
|
59
|
+
- [Footnote References](#footnote-references-html)
|
|
60
|
+
- [Anchors & In-document Links](#anchors--in-document-links)
|
|
61
|
+
- [Special Elements](#special-elements)
|
|
62
|
+
- [RichMarkdownBuilder](#richmarkdownbuilder)
|
|
43
63
|
- [Streaming with sendRichMessageDraft](#streaming-with-sendrichmessagedraft)
|
|
64
|
+
- [reply\_markup with Rich Messages](#reply_markup-with-rich-messages)
|
|
44
65
|
- [Inline / Web App Queries](#inline--web-app-queries)
|
|
45
|
-
- [TypeScript
|
|
66
|
+
- [TypeScript](#typescript)
|
|
46
67
|
|
|
47
68
|
---
|
|
48
69
|
|
|
49
|
-
###
|
|
70
|
+
### Quick Start
|
|
50
71
|
|
|
51
72
|
```ts
|
|
52
73
|
import { Telegraf, RichMessage } from '@icanseeuanywhere/telekaf'
|
|
53
|
-
const {
|
|
74
|
+
const { RichHTMLBuilder: HTML } = RichMessage
|
|
54
75
|
|
|
55
76
|
const bot = new Telegraf(process.env.BOT_TOKEN)
|
|
56
77
|
|
|
57
78
|
bot.command('hello', async (ctx) => {
|
|
58
|
-
const msg = new
|
|
59
|
-
.heading(1,
|
|
60
|
-
.paragraph(
|
|
79
|
+
const msg = new HTML()
|
|
80
|
+
.heading(1, 'Hello World!')
|
|
81
|
+
.paragraph(HTML.bold('Rich Messages') + ' are now supported in Bot API 10.1.')
|
|
61
82
|
.divider()
|
|
62
|
-
.
|
|
83
|
+
.ul('Headings', 'Lists', 'Tables', 'Media', 'Math', 'and more')
|
|
63
84
|
.build()
|
|
64
85
|
|
|
65
86
|
await ctx.sendRichMessage(msg)
|
|
@@ -74,478 +95,506 @@ process.once('SIGTERM', () => bot.stop('SIGTERM'))
|
|
|
74
95
|
|
|
75
96
|
### Sending Methods
|
|
76
97
|
|
|
77
|
-
There are three ways to send rich messages:
|
|
78
|
-
|
|
79
98
|
| Method | Description |
|
|
80
99
|
|---|---|
|
|
81
100
|
| `ctx.sendRichMessage(msg, extra?)` | Send a rich message to the current chat |
|
|
82
|
-
| `ctx.replyWithRichMessageContent(msg, extra?)` |
|
|
83
|
-
| `ctx.sendRichMessageDraft(msg, extra?)` | Stream a partial
|
|
84
|
-
| `ctx.telegram.sendRichMessage(chatId, msg, extra?)` | Explicit
|
|
85
|
-
| `ctx.telegram.sendRichMessageDraft(chatId, msg, extra?)` | Explicit streaming with chat ID |
|
|
101
|
+
| `ctx.replyWithRichMessageContent(msg, extra?)` | Send a rich message quoting the current message |
|
|
102
|
+
| `ctx.sendRichMessageDraft(draftId, msg, extra?)` | Stream a partial draft (private chats only) |
|
|
103
|
+
| `ctx.telegram.sendRichMessage(chatId, msg, extra?)` | Explicit call with chat ID |
|
|
104
|
+
| `ctx.telegram.sendRichMessageDraft(chatId, draftId, msg, extra?)` | Explicit streaming with chat ID |
|
|
86
105
|
|
|
87
|
-
|
|
88
|
-
bot.on('message', async (ctx) => {
|
|
89
|
-
const msg = new Builder()
|
|
90
|
-
.paragraph(RT.plain('I am replying to your message!'))
|
|
91
|
-
.build()
|
|
106
|
+
**`extra` options for `sendRichMessage`:**
|
|
92
107
|
|
|
93
|
-
|
|
94
|
-
|
|
108
|
+
```ts
|
|
109
|
+
await ctx.sendRichMessage(msg, {
|
|
110
|
+
message_thread_id: 123, // for forum topics
|
|
111
|
+
direct_messages_topic_id: 456, // for DM topics
|
|
112
|
+
disable_notification: true,
|
|
113
|
+
protect_content: true,
|
|
114
|
+
allow_paid_broadcast: false,
|
|
115
|
+
message_effect_id: 'effect_id',
|
|
116
|
+
reply_parameters: { message_id: ctx.message.message_id },
|
|
117
|
+
reply_markup: { inline_keyboard: [[{ text: 'OK', callback_data: 'ok' }]] },
|
|
95
118
|
})
|
|
96
119
|
```
|
|
97
120
|
|
|
98
|
-
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
### InputRichMessage Format
|
|
124
|
+
|
|
125
|
+
`InputRichMessage` uses **either** `html` or `markdown` — not both:
|
|
99
126
|
|
|
100
127
|
```ts
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
128
|
+
// HTML format
|
|
129
|
+
const msg: InputRichMessage = {
|
|
130
|
+
html: '<h1>Title</h1><p>Body text</p>',
|
|
131
|
+
is_rtl: false,
|
|
132
|
+
skip_entity_detection: false,
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Markdown format
|
|
136
|
+
const msg: InputRichMessage = {
|
|
137
|
+
markdown: '# Title\n\nBody text',
|
|
107
138
|
}
|
|
108
139
|
```
|
|
109
140
|
|
|
110
|
-
|
|
141
|
+
Use the builders — `RichHTMLBuilder` or `RichMarkdownBuilder` — to construct these conveniently.
|
|
111
142
|
|
|
112
|
-
|
|
143
|
+
---
|
|
113
144
|
|
|
114
|
-
|
|
145
|
+
### RichHTMLBuilder
|
|
115
146
|
|
|
116
|
-
|
|
147
|
+
Import and instantiate:
|
|
117
148
|
|
|
118
149
|
```ts
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
RT.italic(RT.plain('italic'))
|
|
122
|
-
RT.underline(RT.plain('underlined'))
|
|
123
|
-
RT.strikethrough(RT.plain('crossed out'))
|
|
124
|
-
RT.spoiler(RT.plain('hidden until tapped'))
|
|
125
|
-
RT.marked(RT.plain('highlighted')) // like a text marker
|
|
126
|
-
RT.subscript(RT.plain('₂'))
|
|
127
|
-
RT.superscript(RT.plain('²'))
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
Nesting is supported:
|
|
150
|
+
import { RichMessage } from '@icanseeuanywhere/telekaf'
|
|
151
|
+
const { RichHTMLBuilder: HTML } = RichMessage
|
|
131
152
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
153
|
+
const msg = new HTML()
|
|
154
|
+
.heading(1, 'Title')
|
|
155
|
+
.paragraph('Content')
|
|
156
|
+
.build() // returns InputRichMessage { html: '...' }
|
|
135
157
|
```
|
|
136
158
|
|
|
137
|
-
####
|
|
138
|
-
|
|
139
|
-
```ts
|
|
140
|
-
RT.code(RT.plain('const x = 1'), 'javascript') // inline code with language
|
|
141
|
-
RT.math('E = mc^2') // inline mathematical expression
|
|
142
|
-
```
|
|
159
|
+
#### Text Formatting (HTML)
|
|
143
160
|
|
|
144
|
-
|
|
161
|
+
Static inline helpers — return strings to embed inside block methods:
|
|
145
162
|
|
|
146
163
|
```ts
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
164
|
+
HTML.bold('bold text') // <b>bold text</b>
|
|
165
|
+
HTML.italic('italic text') // <i>italic text</i>
|
|
166
|
+
HTML.underline('underlined') // <u>underlined</u>
|
|
167
|
+
HTML.strikethrough('crossed out') // <s>crossed out</s>
|
|
168
|
+
HTML.spoiler('hidden until tapped') // <tg-spoiler>hidden</tg-spoiler>
|
|
169
|
+
HTML.code('inline code') // <code>inline code</code>
|
|
170
|
+
HTML.marked('highlighted') // <mark>highlighted</mark>
|
|
171
|
+
HTML.sub('subscript') // <sub>subscript</sub>
|
|
172
|
+
HTML.sup('superscript') // <sup>superscript</sup>
|
|
173
|
+
|
|
174
|
+
HTML.url('https://t.me', 'Telegram') // <a href="...">Telegram</a>
|
|
175
|
+
HTML.email('hi@bot.com', 'Email us') // <a href="mailto:...">Email us</a>
|
|
176
|
+
HTML.phone('+6281234567', 'Call us') // <a href="tel:...">Call us</a>
|
|
177
|
+
HTML.mention(123456789, 'Alice') // <a href="tg://user?id=...">Alice</a>
|
|
178
|
+
HTML.customEmoji('5368324170671202286', '👍') // <tg-emoji emoji-id="...">👍</tg-emoji>
|
|
179
|
+
HTML.time(1647531900, 'wDT', '22:45 tomorrow') // <tg-time unix="..." format="...">...</tg-time>
|
|
180
|
+
HTML.inlineMath('E = mc^2') // $E = mc^2$
|
|
181
|
+
|
|
182
|
+
// Nesting
|
|
183
|
+
HTML.bold(HTML.italic('bold italic'))
|
|
184
|
+
HTML.underline(HTML.spoiler('underlined spoiler'))
|
|
152
185
|
```
|
|
153
186
|
|
|
154
|
-
####
|
|
187
|
+
#### Headings & Paragraphs
|
|
155
188
|
|
|
156
189
|
```ts
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
190
|
+
new HTML()
|
|
191
|
+
.heading(1, 'Main Title')
|
|
192
|
+
.heading(2, 'Subtitle')
|
|
193
|
+
.heading(3, HTML.bold('Bold heading'))
|
|
194
|
+
.heading(4, 'H4')
|
|
195
|
+
.heading(5, 'H5')
|
|
196
|
+
.heading(6, 'H6')
|
|
197
|
+
.paragraph('Normal paragraph text.')
|
|
198
|
+
.paragraph(HTML.bold('Bold') + ' and ' + HTML.italic('italic') + ' combined.')
|
|
199
|
+
.footer('Footer text — smaller and muted')
|
|
200
|
+
.divider() // <hr/>
|
|
201
|
+
.build()
|
|
163
202
|
```
|
|
164
203
|
|
|
165
|
-
####
|
|
204
|
+
#### Lists (HTML)
|
|
166
205
|
|
|
167
206
|
```ts
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
207
|
+
new HTML()
|
|
208
|
+
// Unordered list
|
|
209
|
+
.ul('First item', 'Second item', HTML.bold('Bold item'))
|
|
210
|
+
|
|
211
|
+
// Ordered list
|
|
212
|
+
.ol('Step one', 'Step two', 'Step three')
|
|
213
|
+
|
|
214
|
+
// Task list (checkboxes)
|
|
215
|
+
.taskList(
|
|
216
|
+
{ text: 'Completed task', checked: true },
|
|
217
|
+
{ text: 'Pending task', checked: false },
|
|
218
|
+
{ text: HTML.bold('Important task'), checked: false },
|
|
219
|
+
)
|
|
220
|
+
.build()
|
|
171
221
|
```
|
|
172
222
|
|
|
173
|
-
####
|
|
223
|
+
#### Code Blocks
|
|
174
224
|
|
|
175
225
|
```ts
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
)
|
|
186
|
-
|
|
187
|
-
await ctx.sendRichMessage(builder.build())
|
|
226
|
+
new HTML()
|
|
227
|
+
.pre('npm install @icanseeuanywhere/telekaf', 'bash')
|
|
228
|
+
.pre('SELECT * FROM users WHERE active = 1;', 'sql')
|
|
229
|
+
.pre(
|
|
230
|
+
`const bot = new Telegraf(token)
|
|
231
|
+
bot.launch()`,
|
|
232
|
+
'javascript'
|
|
233
|
+
)
|
|
234
|
+
.pre('plain preformatted block without language')
|
|
235
|
+
.build()
|
|
188
236
|
```
|
|
189
237
|
|
|
190
|
-
|
|
238
|
+
Supported language identifiers: `javascript`, `typescript`, `python`, `bash`, `sql`, `json`, `html`, `css`, etc.
|
|
191
239
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
`RichBlock` types are block-level elements that form the structure of a rich message.
|
|
195
|
-
|
|
196
|
-
#### Text Blocks
|
|
240
|
+
#### Blockquote & Pull Quote
|
|
197
241
|
|
|
198
242
|
```ts
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
.
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
// Preformatted / code block
|
|
209
|
-
new Builder().preformatted('SELECT * FROM users;', 'sql')
|
|
210
|
-
new Builder().preformatted('plain preformatted block')
|
|
243
|
+
new HTML()
|
|
244
|
+
// Standard block quotation
|
|
245
|
+
.blockQuote(HTML.italic('"To be or not to be."'))
|
|
246
|
+
|
|
247
|
+
// Pull quotation with attribution (cite)
|
|
248
|
+
.pullQuote(
|
|
249
|
+
HTML.italic('"Design is not just what it looks like."'),
|
|
250
|
+
'Steve Jobs'
|
|
251
|
+
)
|
|
211
252
|
|
|
212
|
-
//
|
|
213
|
-
|
|
214
|
-
|
|
253
|
+
// Nested formatting inside quote
|
|
254
|
+
.blockQuote(
|
|
255
|
+
HTML.bold('Telekaf') + ' supports ' + HTML.marked('highlighted') +
|
|
256
|
+
' and ' + HTML.spoiler('spoiler') + ' text inside quotes.'
|
|
257
|
+
)
|
|
258
|
+
.build()
|
|
215
259
|
```
|
|
216
260
|
|
|
217
|
-
|
|
218
|
-
import type { RichBlock } from '@icanseeuanywhere/telekaf/types'
|
|
261
|
+
#### Math (HTML)
|
|
219
262
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
263
|
+
```ts
|
|
264
|
+
new HTML()
|
|
265
|
+
// Inline math (embed inside paragraph)
|
|
266
|
+
.paragraph(
|
|
267
|
+
'The formula is: ' + HTML.inlineMath('a^2 + b^2 = c^2')
|
|
268
|
+
)
|
|
224
269
|
|
|
225
|
-
|
|
226
|
-
.
|
|
227
|
-
.
|
|
228
|
-
.
|
|
270
|
+
// Block math expression
|
|
271
|
+
.mathBlock('\\int_{-\\infty}^{\\infty} e^{-x^2} dx = \\sqrt{\\pi}')
|
|
272
|
+
.mathBlock('F(x) = \\int_{-\\infty}^{x} f(t)\\,dt')
|
|
273
|
+
.mathBlock('E = mc^2')
|
|
229
274
|
.build()
|
|
230
|
-
|
|
231
|
-
// Append footer manually
|
|
232
|
-
msg.blocks.push(footer)
|
|
233
|
-
await ctx.sendRichMessage(msg)
|
|
234
275
|
```
|
|
235
276
|
|
|
236
|
-
####
|
|
277
|
+
#### Media — Photo, Video, Audio
|
|
237
278
|
|
|
238
279
|
```ts
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
)
|
|
280
|
+
new HTML()
|
|
281
|
+
// Photo
|
|
282
|
+
.photo('https://example.com/photo.jpg')
|
|
283
|
+
.photo('https://example.com/photo.jpg', 'Caption text')
|
|
284
|
+
.photo('https://example.com/photo.jpg', 'Spoiler photo', /* spoiler */ true)
|
|
285
|
+
|
|
286
|
+
// Video
|
|
287
|
+
.video('https://example.com/video.mp4')
|
|
288
|
+
.video('https://example.com/video.mp4', 'Caption text')
|
|
289
|
+
.video('https://example.com/video.mp4', 'Spoiler video', /* spoiler */ true)
|
|
290
|
+
|
|
291
|
+
// Audio / Voice note (.ogg for voice)
|
|
292
|
+
.audio('https://example.com/audio.mp3')
|
|
293
|
+
.audio('https://example.com/audio.mp3', 'Audio caption')
|
|
294
|
+
|
|
295
|
+
// With figcaption (HTML figure)
|
|
296
|
+
.raw('<figure><img src="https://example.com/photo.jpg"/><figcaption>Caption <b>bold</b></figcaption></figure>')
|
|
297
|
+
.build()
|
|
251
298
|
```
|
|
252
299
|
|
|
253
|
-
|
|
300
|
+
You can also use a Telegram `file_id` in place of a URL once the file is uploaded.
|
|
254
301
|
|
|
255
|
-
|
|
256
|
-
// Block quotation
|
|
257
|
-
new Builder().blockQuote(
|
|
258
|
-
{ type: 'paragraph', texts: [RT.italic(RT.plain('To be or not to be.'))] },
|
|
259
|
-
)
|
|
302
|
+
#### Collage & Slideshow
|
|
260
303
|
|
|
261
|
-
|
|
262
|
-
|
|
304
|
+
```ts
|
|
305
|
+
const img = (src) => `<img src="${src}"/>`
|
|
306
|
+
const vid = (src) => `<video src="${src}"></video>`
|
|
307
|
+
|
|
308
|
+
new HTML()
|
|
309
|
+
// Collage — displays as a grid
|
|
310
|
+
.collage(
|
|
311
|
+
img('https://example.com/photo1.jpg'),
|
|
312
|
+
img('https://example.com/photo2.jpg'),
|
|
313
|
+
vid('https://example.com/clip.mp4'),
|
|
314
|
+
)
|
|
263
315
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
316
|
+
// Slideshow — swipeable carousel
|
|
317
|
+
.slideshow(
|
|
318
|
+
img('https://example.com/photo1.jpg'),
|
|
319
|
+
img('https://example.com/photo2.jpg'),
|
|
320
|
+
img('https://example.com/photo3.jpg'),
|
|
321
|
+
)
|
|
322
|
+
.build()
|
|
269
323
|
```
|
|
270
324
|
|
|
271
|
-
####
|
|
325
|
+
#### Map
|
|
272
326
|
|
|
273
327
|
```ts
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
//
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
// Single audio
|
|
281
|
-
new Builder().audio('CQACAgIAAxk...')
|
|
282
|
-
|
|
283
|
-
// Voice note
|
|
284
|
-
import type { RichBlock } from '@icanseeuanywhere/telekaf/types'
|
|
285
|
-
const voiceBlock: RichBlock = {
|
|
286
|
-
type: 'voice_note',
|
|
287
|
-
file_id: 'AwACAgIAAxk...',
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// Collage (multiple photos/videos in a grid)
|
|
291
|
-
import type { RichBlock } from '@icanseeuanywhere/telekaf/types'
|
|
292
|
-
const collage: RichBlock = {
|
|
293
|
-
type: 'collage',
|
|
294
|
-
media: [
|
|
295
|
-
{ type: 'photo', file_id: 'AgACAgIA...' },
|
|
296
|
-
{ type: 'photo', file_id: 'AgACAgIB...' },
|
|
297
|
-
{ type: 'video', file_id: 'BAACAgIA...' },
|
|
298
|
-
],
|
|
299
|
-
caption: { type: 'caption', texts: [RT.plain('Our gallery')] },
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
// Slideshow (swipeable gallery)
|
|
303
|
-
const slideshow: RichBlock = {
|
|
304
|
-
type: 'slideshow',
|
|
305
|
-
media: [
|
|
306
|
-
{ type: 'photo', file_id: 'AgACAgIA...' },
|
|
307
|
-
{ type: 'photo', file_id: 'AgACAgIB...' },
|
|
308
|
-
],
|
|
309
|
-
}
|
|
328
|
+
new HTML()
|
|
329
|
+
.map(-6.2088, 106.8456) // Jakarta
|
|
330
|
+
.map(48.8584, 2.2945, 16) // Paris, zoom 16
|
|
331
|
+
.map(51.5074, -0.1278, 14, 'Our office in London') // with caption
|
|
332
|
+
.build()
|
|
310
333
|
```
|
|
311
334
|
|
|
312
|
-
#### Table
|
|
335
|
+
#### Table (HTML)
|
|
313
336
|
|
|
314
337
|
```ts
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
const table: RichBlock = {
|
|
318
|
-
type: 'table',
|
|
319
|
-
is_bordered: true,
|
|
320
|
-
is_striped: true,
|
|
321
|
-
cells: [
|
|
322
|
-
// Header row
|
|
323
|
-
[
|
|
324
|
-
{ type: 'table_cell', is_header: true, content: [{ type: 'paragraph', texts: [RT.plain('Name')] }] },
|
|
325
|
-
{ type: 'table_cell', is_header: true, content: [{ type: 'paragraph', texts: [RT.plain('Score')] }] },
|
|
326
|
-
],
|
|
327
|
-
// Data rows
|
|
328
|
-
[
|
|
329
|
-
{ type: 'table_cell', content: [{ type: 'paragraph', texts: [RT.plain('Alice')] }] },
|
|
330
|
-
{ type: 'table_cell', content: [{ type: 'paragraph', texts: [RT.plain('98')] }] },
|
|
331
|
-
],
|
|
338
|
+
new HTML()
|
|
339
|
+
.table(
|
|
332
340
|
[
|
|
333
|
-
|
|
334
|
-
|
|
341
|
+
['Name', 'Version', 'Downloads'], // header row (hasHeader: true)
|
|
342
|
+
['telekaf', '4.16.5', '—' ],
|
|
343
|
+
['telegraf','4.16.3', '~120k/wk' ],
|
|
335
344
|
],
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
await ctx.sendRichMessage({ blocks: [table] })
|
|
345
|
+
{ bordered: true, striped: true, hasHeader: true }
|
|
346
|
+
)
|
|
347
|
+
.build()
|
|
340
348
|
```
|
|
341
349
|
|
|
342
|
-
|
|
350
|
+
For advanced table markup (colspan, rowspan, alignment), use `.raw()`:
|
|
343
351
|
|
|
344
352
|
```ts
|
|
345
|
-
|
|
346
|
-
|
|
353
|
+
new HTML()
|
|
354
|
+
.raw(
|
|
355
|
+
'<table bordered striped>' +
|
|
356
|
+
'<tr><th>Name</th><th colspan="2">Details</th></tr>' +
|
|
357
|
+
'<tr><td>Alice</td><td align="center">98</td><td align="right">Pass</td></tr>' +
|
|
358
|
+
'</table>'
|
|
359
|
+
)
|
|
360
|
+
.build()
|
|
347
361
|
```
|
|
348
362
|
|
|
349
|
-
#### Expandable
|
|
363
|
+
#### Details (Expandable)
|
|
350
364
|
|
|
351
365
|
```ts
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
366
|
+
new HTML()
|
|
367
|
+
// Collapsed by default
|
|
368
|
+
.details('Click to expand', '<p>Hidden content here.</p>')
|
|
369
|
+
|
|
370
|
+
// Open by default
|
|
371
|
+
.details(
|
|
372
|
+
HTML.bold('Changelog v4.16.5'),
|
|
373
|
+
'<ul><li>Fix InputRichMessage format</li><li>Add RichHTMLBuilder</li></ul>',
|
|
374
|
+
/* open */ true
|
|
375
|
+
)
|
|
376
|
+
.build()
|
|
361
377
|
```
|
|
362
378
|
|
|
363
|
-
####
|
|
379
|
+
#### Footnote References (HTML)
|
|
364
380
|
|
|
365
381
|
```ts
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
}
|
|
382
|
+
new HTML()
|
|
383
|
+
.paragraph(
|
|
384
|
+
'Telekaf ' + HTML.ref('note-1', '[1]') + ' is based on Telegraf ' + HTML.ref('note-2', '[2]') + '.'
|
|
385
|
+
)
|
|
386
|
+
.divider()
|
|
387
|
+
.referenceDefinition('note-1', HTML.url('https://npmjs.com/package/@icanseeuanywhere/telekaf', 'telekaf on npm'))
|
|
388
|
+
.referenceDefinition('note-2', HTML.url('https://github.com/telegraf/telegraf', 'telegraf on GitHub'))
|
|
389
|
+
.build()
|
|
375
390
|
```
|
|
376
391
|
|
|
377
|
-
####
|
|
392
|
+
#### Anchors & In-document Links
|
|
378
393
|
|
|
379
394
|
```ts
|
|
380
|
-
new
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
395
|
+
new HTML()
|
|
396
|
+
.raw(HTML.anchor('section-intro')) // invisible anchor target
|
|
397
|
+
.heading(2, 'Introduction')
|
|
398
|
+
.paragraph('Jump to: ' + HTML.anchorLink('section-api', 'API Reference'))
|
|
399
|
+
.raw(HTML.anchor('section-api'))
|
|
400
|
+
.heading(2, 'API Reference')
|
|
401
|
+
.build()
|
|
384
402
|
```
|
|
385
403
|
|
|
386
|
-
####
|
|
404
|
+
#### Special Elements
|
|
387
405
|
|
|
388
406
|
```ts
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
expression: '\\int_{-\\infty}^{\\infty} e^{-x^2} dx = \\sqrt{\\pi}',
|
|
393
|
-
}
|
|
394
|
-
```
|
|
395
|
-
|
|
396
|
-
#### Thinking Block (AI reasoning)
|
|
407
|
+
new HTML()
|
|
408
|
+
// AI thinking block (visible in sendRichMessageDraft)
|
|
409
|
+
.thinking(HTML.italic('Analyzing your request...'))
|
|
397
410
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
{ type: 'paragraph', texts: [RT.plain('Let me reason through this step by step...')] },
|
|
403
|
-
{ type: 'paragraph', texts: [RT.plain('First, I consider the user intent.')] },
|
|
404
|
-
)
|
|
411
|
+
// Raw HTML for anything not covered by builder methods
|
|
412
|
+
.raw('<tg-map lat="41.9" long="12.5" zoom="14"/>')
|
|
413
|
+
.raw('<aside>Pull quote<cite>The Author</cite></aside>')
|
|
414
|
+
.build()
|
|
405
415
|
```
|
|
406
416
|
|
|
407
417
|
---
|
|
408
418
|
|
|
409
|
-
###
|
|
419
|
+
### RichMarkdownBuilder
|
|
410
420
|
|
|
411
|
-
|
|
421
|
+
Same API surface as `RichHTMLBuilder` but produces Markdown output:
|
|
412
422
|
|
|
413
423
|
```ts
|
|
414
424
|
import { RichMessage } from '@icanseeuanywhere/telekaf'
|
|
415
|
-
const {
|
|
416
|
-
|
|
417
|
-
const msg = new
|
|
418
|
-
.heading(1,
|
|
419
|
-
.paragraph(
|
|
420
|
-
|
|
425
|
+
const { RichMarkdownBuilder: MD } = RichMessage
|
|
426
|
+
|
|
427
|
+
const msg = new MD()
|
|
428
|
+
.heading(1, 'Rich Markdown')
|
|
429
|
+
.paragraph(
|
|
430
|
+
MD.bold('bold') + ' ' +
|
|
431
|
+
MD.italic('italic') + ' ' +
|
|
432
|
+
MD.strikethrough('strike') + ' ' +
|
|
433
|
+
MD.marked('==highlighted==') + ' ' +
|
|
434
|
+
MD.spoiler('||spoiler||') + ' ' +
|
|
435
|
+
MD.code('`code`')
|
|
436
|
+
)
|
|
421
437
|
.divider()
|
|
422
|
-
.
|
|
423
|
-
|
|
424
|
-
|
|
438
|
+
.ul('Item 1', 'Item 2', MD.bold('Bold item'))
|
|
439
|
+
.ol('Step 1', 'Step 2', 'Step 3')
|
|
440
|
+
.taskList(
|
|
441
|
+
{ text: 'Done', checked: true },
|
|
442
|
+
{ text: 'Pending', checked: false },
|
|
425
443
|
)
|
|
426
|
-
.
|
|
427
|
-
.
|
|
428
|
-
.
|
|
429
|
-
.
|
|
430
|
-
|
|
431
|
-
|
|
444
|
+
.divider()
|
|
445
|
+
.pre('console.log("hello")', 'javascript')
|
|
446
|
+
.divider()
|
|
447
|
+
.table(
|
|
448
|
+
['Name', 'Score'],
|
|
449
|
+
[['Alice', '98'], ['Bob', '87']],
|
|
450
|
+
['left', 'center'],
|
|
451
|
+
)
|
|
452
|
+
.divider()
|
|
453
|
+
.mathBlock('E = mc^2')
|
|
454
|
+
.divider()
|
|
455
|
+
.blockQuote(MD.italic('"Quote text"'), '— Author')
|
|
456
|
+
.divider()
|
|
457
|
+
.photo('https://example.com/photo.jpg', 'Photo caption')
|
|
458
|
+
.collage('https://example.com/1.jpg', 'https://example.com/2.jpg')
|
|
459
|
+
.slideshow('https://example.com/1.jpg', 'https://example.com/2.jpg')
|
|
460
|
+
.divider()
|
|
461
|
+
.details('Expand me', '### Hidden heading\n\n- item 1\n- item 2')
|
|
462
|
+
.divider()
|
|
463
|
+
.paragraph('See footnote' + MD.sup('[1]'))
|
|
464
|
+
.footnote('1', MD.url('https://t.me/kafk6', '@kafka'))
|
|
465
|
+
.build()
|
|
432
466
|
```
|
|
433
467
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
| Method | Description |
|
|
437
|
-
|---|---|
|
|
438
|
-
| `.paragraph(...texts)` | Add a paragraph block |
|
|
439
|
-
| `.heading(level, ...texts)` | Add a heading (h1–h6) |
|
|
440
|
-
| `.preformatted(text, language?)` | Add a code/preformatted block |
|
|
441
|
-
| `.divider()` | Add a horizontal divider |
|
|
442
|
-
| `.list(isOrdered, ...items)` | Add an ordered or unordered list |
|
|
443
|
-
| `.blockQuote(...blocks)` | Add a block quotation |
|
|
444
|
-
| `.thinking(...blocks)` | Add an AI thinking block |
|
|
445
|
-
| `.photo(fileId, caption?)` | Add a photo block |
|
|
446
|
-
| `.video(fileId, caption?)` | Add a video block |
|
|
447
|
-
| `.audio(fileId, caption?)` | Add an audio block |
|
|
448
|
-
| `.reference(richText)` | Register a footnote, returns its numeric ID |
|
|
449
|
-
| `.build()` | Returns the final `InputRichMessage` |
|
|
450
|
-
|
|
451
|
-
---
|
|
452
|
-
|
|
453
|
-
### RT Helpers
|
|
454
|
-
|
|
455
|
-
`RT` is a collection of factory functions for creating `RichText` nodes concisely.
|
|
468
|
+
**All Markdown inline helpers:**
|
|
456
469
|
|
|
457
470
|
```ts
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
RT.phone('+1234567890')
|
|
475
|
-
RT.bankCard('4111111111111111')
|
|
476
|
-
RT.mention(RT.plain('Alice'), 123456789)
|
|
477
|
-
RT.mention(RT.plain('@alice'), undefined, 'alice')
|
|
478
|
-
RT.botCommand('/start')
|
|
479
|
-
RT.botCommand('/help', 'mybot')
|
|
480
|
-
RT.hashtag('news')
|
|
481
|
-
RT.cashtag('ETH')
|
|
482
|
-
RT.dateTime(1750000000)
|
|
483
|
-
RT.customEmoji('5368324170671202286')
|
|
484
|
-
RT.anchor('section-id')
|
|
485
|
-
RT.anchorLink('section-id', RT.plain('Go to section'))
|
|
486
|
-
RT.reference(1) // footnote number
|
|
487
|
-
RT.referenceLink(1, RT.plain('[1]')) // clickable footnote
|
|
471
|
+
MD.bold('text') // **text**
|
|
472
|
+
MD.italic('text') // *text*
|
|
473
|
+
MD.underline('text') // <u>text</u>
|
|
474
|
+
MD.strikethrough('text') // ~~text~~
|
|
475
|
+
MD.spoiler('text') // ||text||
|
|
476
|
+
MD.code('text') // `text`
|
|
477
|
+
MD.marked('text') // ==text==
|
|
478
|
+
MD.sub('text') // <sub>text</sub>
|
|
479
|
+
MD.sup('text') // <sup>text</sup>
|
|
480
|
+
MD.url('https://...', 'label') // [label](url)
|
|
481
|
+
MD.email('a@b.com', 'label') // [label](mailto:a@b.com)
|
|
482
|
+
MD.phone('+123', 'label') // [label](tel:+123)
|
|
483
|
+
MD.mention(123456789, 'Alice') // [Alice](tg://user?id=123456789)
|
|
484
|
+
MD.customEmoji('id', '👍') // 
|
|
485
|
+
MD.time(1647531900, 'wDT') // 
|
|
486
|
+
MD.inlineMath('a^2') // $a^2$
|
|
488
487
|
```
|
|
489
488
|
|
|
490
489
|
---
|
|
491
490
|
|
|
492
|
-
### Streaming with
|
|
491
|
+
### Streaming with sendRichMessageDraft
|
|
493
492
|
|
|
494
|
-
`sendRichMessageDraft`
|
|
493
|
+
`sendRichMessageDraft` streams a partial rich message in private chats. The draft is ephemeral (30-second preview). You **must** finalize with `sendRichMessage` to persist it.
|
|
495
494
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
const { RichMessageBuilder: Builder, RT } = RichMessage
|
|
495
|
+
- `chat_id` — private chat only (integer)
|
|
496
|
+
- `draft_id` — non-zero integer; updates with the same `draft_id` are animated
|
|
499
497
|
|
|
498
|
+
```ts
|
|
500
499
|
bot.command('ai', async (ctx) => {
|
|
501
|
-
|
|
502
|
-
await ctx.sendRichMessageDraft(
|
|
503
|
-
new Builder()
|
|
504
|
-
.thinking({ type: 'paragraph', texts: [RT.plain('Analyzing your request...')] })
|
|
505
|
-
.build()
|
|
506
|
-
)
|
|
500
|
+
const DRAFT_ID = 1 // any non-zero integer
|
|
507
501
|
|
|
508
|
-
// Simulate streaming by sending updated drafts
|
|
509
502
|
const steps = [
|
|
510
|
-
'
|
|
511
|
-
'
|
|
512
|
-
'Composing
|
|
503
|
+
'Reading your request...',
|
|
504
|
+
'Searching knowledge base...',
|
|
505
|
+
'Composing answer...',
|
|
513
506
|
]
|
|
514
507
|
|
|
508
|
+
// Stream thinking blocks
|
|
515
509
|
for (const step of steps) {
|
|
516
|
-
await new Promise((r) => setTimeout(r, 800))
|
|
517
510
|
await ctx.sendRichMessageDraft(
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
.build()
|
|
511
|
+
DRAFT_ID,
|
|
512
|
+
new HTML().thinking(HTML.italic(step)).build()
|
|
521
513
|
)
|
|
514
|
+
await new Promise((r) => setTimeout(r, 900))
|
|
522
515
|
}
|
|
523
516
|
|
|
524
|
-
//
|
|
517
|
+
// Finalize — must call sendRichMessage after streaming
|
|
525
518
|
await ctx.sendRichMessage(
|
|
526
|
-
new
|
|
527
|
-
.heading(2,
|
|
528
|
-
.paragraph(
|
|
519
|
+
new HTML()
|
|
520
|
+
.heading(2, '🤖 AI Response')
|
|
521
|
+
.paragraph('Here is the final answer from the AI.')
|
|
522
|
+
.divider()
|
|
523
|
+
.footer(HTML.url('https://t.me/kafk6', '@kafka'))
|
|
529
524
|
.build()
|
|
530
525
|
)
|
|
531
526
|
})
|
|
532
527
|
```
|
|
533
528
|
|
|
529
|
+
You can also call `sendRichMessageDraft` explicitly:
|
|
530
|
+
|
|
531
|
+
```ts
|
|
532
|
+
// Explicit
|
|
533
|
+
await ctx.telegram.sendRichMessageDraft(
|
|
534
|
+
ctx.chat.id, // private chat integer ID
|
|
535
|
+
42, // draft_id
|
|
536
|
+
new HTML().thinking('Processing...').build(),
|
|
537
|
+
{ message_thread_id: 123 }
|
|
538
|
+
)
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
---
|
|
542
|
+
|
|
543
|
+
### reply_markup with Rich Messages
|
|
544
|
+
|
|
545
|
+
All `sendRichMessage` calls accept a `reply_markup` option with inline keyboards:
|
|
546
|
+
|
|
547
|
+
```ts
|
|
548
|
+
import { Markup } from '@icanseeuanywhere/telekaf'
|
|
549
|
+
|
|
550
|
+
const msg = new HTML()
|
|
551
|
+
.heading(2, 'Choose an option')
|
|
552
|
+
.paragraph('Tap a button below:')
|
|
553
|
+
.build()
|
|
554
|
+
|
|
555
|
+
await ctx.sendRichMessage(msg, {
|
|
556
|
+
reply_markup: Markup.inlineKeyboard([
|
|
557
|
+
[
|
|
558
|
+
Markup.button.callback('✅ Yes', 'answer:yes'),
|
|
559
|
+
Markup.button.callback('❌ No', 'answer:no'),
|
|
560
|
+
],
|
|
561
|
+
[Markup.button.url('🌐 Visit', 'https://t.me/kafk6')],
|
|
562
|
+
]).reply_markup,
|
|
563
|
+
})
|
|
564
|
+
|
|
565
|
+
bot.action('answer:yes', async (ctx) => {
|
|
566
|
+
await ctx.answerCbQuery('You chose Yes!')
|
|
567
|
+
})
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
Or use `reply_markup` directly:
|
|
571
|
+
|
|
572
|
+
```ts
|
|
573
|
+
await ctx.sendRichMessage(msg, {
|
|
574
|
+
reply_markup: {
|
|
575
|
+
inline_keyboard: [
|
|
576
|
+
[{ text: 'Button 1', callback_data: 'btn1' }],
|
|
577
|
+
[{ text: 'Open URL', url: 'https://telegram.org' }],
|
|
578
|
+
],
|
|
579
|
+
},
|
|
580
|
+
})
|
|
581
|
+
```
|
|
582
|
+
|
|
534
583
|
---
|
|
535
584
|
|
|
536
585
|
### Inline / Web App Queries
|
|
537
586
|
|
|
538
|
-
`InputRichMessageContent`
|
|
587
|
+
Use `InputRichMessageContent` as `input_message_content` in inline query results:
|
|
539
588
|
|
|
540
589
|
```ts
|
|
541
590
|
import { RichMessage } from '@icanseeuanywhere/telekaf'
|
|
542
|
-
const {
|
|
591
|
+
const { RichHTMLBuilder: HTML } = RichMessage
|
|
543
592
|
|
|
544
593
|
bot.on('inline_query', async (ctx) => {
|
|
545
594
|
const richContent: RichMessage.InputRichMessageContent = {
|
|
546
|
-
rich_message: new
|
|
547
|
-
.heading(1,
|
|
548
|
-
.paragraph(
|
|
595
|
+
rich_message: new HTML()
|
|
596
|
+
.heading(1, 'Result from Inline Query')
|
|
597
|
+
.paragraph('Sent via ' + HTML.url('https://t.me/kafk6', '@kafka') + '.')
|
|
549
598
|
.build(),
|
|
550
599
|
}
|
|
551
600
|
|
|
@@ -562,47 +611,35 @@ bot.on('inline_query', async (ctx) => {
|
|
|
562
611
|
|
|
563
612
|
---
|
|
564
613
|
|
|
565
|
-
### TypeScript
|
|
614
|
+
### TypeScript
|
|
566
615
|
|
|
567
|
-
All types are exported
|
|
616
|
+
All types are exported under the `RichMessage` namespace:
|
|
568
617
|
|
|
569
618
|
```ts
|
|
570
619
|
import { RichMessage } from '@icanseeuanywhere/telekaf'
|
|
620
|
+
import type { ExtraSendRichMessage, ExtraSendRichMessageDraft } from '@icanseeuanywhere/telekaf/types'
|
|
571
621
|
|
|
572
|
-
//
|
|
573
|
-
const
|
|
574
|
-
const
|
|
575
|
-
const msg: RichMessage.InputRichMessage = { blocks: [block] }
|
|
576
|
-
const received: RichMessage.RichMessage = ctx.message.rich_message // on incoming messages
|
|
577
|
-
|
|
578
|
-
// All RichText types
|
|
579
|
-
type RichText = RichMessage.RichText
|
|
580
|
-
type RichTextBold = RichMessage.RichTextBold
|
|
581
|
-
type RichTextItalic = RichMessage.RichTextItalic
|
|
582
|
-
// ... etc
|
|
622
|
+
// Builder types
|
|
623
|
+
const builder: RichMessage.RichHTMLBuilder = new RichMessage.RichHTMLBuilder()
|
|
624
|
+
const mdBuilder: RichMessage.RichMarkdownBuilder = new RichMessage.RichMarkdownBuilder()
|
|
583
625
|
|
|
584
|
-
//
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
// ... etc
|
|
589
|
-
|
|
590
|
-
// Extra types for sendRichMessage
|
|
591
|
-
import type { ExtraSendRichMessage } from '@icanseeuanywhere/telekaf/types'
|
|
592
|
-
```
|
|
626
|
+
// Message types
|
|
627
|
+
const input: RichMessage.InputRichMessage = { html: '<p>hello</p>' }
|
|
628
|
+
const content: RichMessage.InputRichMessageContent = { rich_message: input }
|
|
629
|
+
const received: RichMessage.RichMessage = ctx.message.rich_message
|
|
593
630
|
|
|
594
|
-
|
|
631
|
+
// Extra types
|
|
632
|
+
const extra: ExtraSendRichMessage = {
|
|
633
|
+
disable_notification: true,
|
|
634
|
+
reply_markup: { inline_keyboard: [] },
|
|
635
|
+
}
|
|
595
636
|
|
|
596
|
-
|
|
597
|
-
import
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
InputRichMessageContent,
|
|
603
|
-
RichMessageBuilder,
|
|
604
|
-
RT,
|
|
605
|
-
} from '@icanseeuanywhere/telekaf/core/types/rich-message'
|
|
637
|
+
// Custom context with rich message
|
|
638
|
+
import { Context, Telegraf } from '@icanseeuanywhere/telekaf'
|
|
639
|
+
interface MyCtx extends Context {
|
|
640
|
+
session?: { lastDraftId: number }
|
|
641
|
+
}
|
|
642
|
+
const bot = new Telegraf<MyCtx>(process.env.BOT_TOKEN)
|
|
606
643
|
```
|
|
607
644
|
|
|
608
645
|
---
|
|
@@ -795,7 +832,7 @@ process.once('SIGTERM', () => bot.stop('SIGTERM'))
|
|
|
795
832
|
### Webhooks
|
|
796
833
|
|
|
797
834
|
```TS
|
|
798
|
-
import { Telegraf } from "
|
|
835
|
+
import { Telegraf } from "@icanseeuanywhere/telekaf";
|
|
799
836
|
import { message } from '@icanseeuanywhere/telekaf/filters';
|
|
800
837
|
|
|
801
838
|
const bot = new Telegraf(token);
|
package/lib/telegraf.js
CHANGED
|
@@ -96,6 +96,34 @@ class Telegraf extends composer_1.Composer {
|
|
|
96
96
|
};
|
|
97
97
|
this.telegram = new telegram_1.default(token, this.options.telegram);
|
|
98
98
|
debug('Created a `Telegraf` instance');
|
|
99
|
+
Telegraf.printBanner();
|
|
100
|
+
}
|
|
101
|
+
static printBanner() {
|
|
102
|
+
if (Telegraf._bannerPrinted)
|
|
103
|
+
return;
|
|
104
|
+
Telegraf._bannerPrinted = true;
|
|
105
|
+
const reset = '\x1b[0m';
|
|
106
|
+
const bold = '\x1b[1m';
|
|
107
|
+
const dim = '\x1b[2m';
|
|
108
|
+
const cyan = '\x1b[36m';
|
|
109
|
+
const white = '\x1b[37m';
|
|
110
|
+
console.log(`
|
|
111
|
+
${cyan}${bold} ╭─╮${reset}
|
|
112
|
+
${cyan}${bold} │ │${reset}
|
|
113
|
+
${cyan}${bold} ╰┬╯${reset}
|
|
114
|
+
${cyan}${bold} │ ╭─╮${reset}
|
|
115
|
+
${cyan}${bold} ╭─╮ ├─────────┤ │${reset}
|
|
116
|
+
${cyan}${bold} │ ├──┤ ╰─╯${reset}
|
|
117
|
+
${cyan}${bold} ╰─╯ │ ╭─╮${reset}
|
|
118
|
+
${cyan}${bold} ╭┴╮ ╭─────┤ │${reset}
|
|
119
|
+
${cyan}${bold} │ │ │ ╰─╯${reset}
|
|
120
|
+
${cyan}${bold} ╰─╯ │${reset}
|
|
121
|
+
${reset}
|
|
122
|
+
${bold}${white} @icanseeuanywhere/telekaf${reset} ${dim}v4.16.6${reset}
|
|
123
|
+
${reset}
|
|
124
|
+
${dim} thanks for using my package${reset}
|
|
125
|
+
${dim} ~kafk6 ${cyan}t.me/kafk6${reset}
|
|
126
|
+
`);
|
|
99
127
|
}
|
|
100
128
|
get token() {
|
|
101
129
|
return this.telegram.token;
|
|
@@ -244,3 +272,4 @@ class Telegraf extends composer_1.Composer {
|
|
|
244
272
|
}
|
|
245
273
|
}
|
|
246
274
|
exports.Telegraf = Telegraf;
|
|
275
|
+
Telegraf._bannerPrinted = false;
|
package/package.json
CHANGED
package/src/telegraf.ts
CHANGED
|
@@ -151,6 +151,35 @@ export class Telegraf<C extends Context = Context> extends Composer<C> {
|
|
|
151
151
|
}
|
|
152
152
|
this.telegram = new Telegram(token, this.options.telegram)
|
|
153
153
|
debug('Created a `Telegraf` instance')
|
|
154
|
+
Telegraf.printBanner()
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
private static _bannerPrinted = false
|
|
158
|
+
private static printBanner() {
|
|
159
|
+
if (Telegraf._bannerPrinted) return
|
|
160
|
+
Telegraf._bannerPrinted = true
|
|
161
|
+
const reset = '\x1b[0m'
|
|
162
|
+
const bold = '\x1b[1m'
|
|
163
|
+
const dim = '\x1b[2m'
|
|
164
|
+
const cyan = '\x1b[36m'
|
|
165
|
+
const white = '\x1b[37m'
|
|
166
|
+
console.log(`
|
|
167
|
+
${cyan}${bold} ╭─╮${reset}
|
|
168
|
+
${cyan}${bold} │ │${reset}
|
|
169
|
+
${cyan}${bold} ╰┬╯${reset}
|
|
170
|
+
${cyan}${bold} │ ╭─╮${reset}
|
|
171
|
+
${cyan}${bold} ╭─╮ ├─────────┤ │${reset}
|
|
172
|
+
${cyan}${bold} │ ├──┤ ╰─╯${reset}
|
|
173
|
+
${cyan}${bold} ╰─╯ │ ╭─╮${reset}
|
|
174
|
+
${cyan}${bold} ╭┴╮ ╭─────┤ │${reset}
|
|
175
|
+
${cyan}${bold} │ │ │ ╰─╯${reset}
|
|
176
|
+
${cyan}${bold} ╰─╯ │${reset}
|
|
177
|
+
${reset}
|
|
178
|
+
${bold}${white} @icanseeuanywhere/telekaf${reset} ${dim}v4.16.6${reset}
|
|
179
|
+
${reset}
|
|
180
|
+
${dim} thanks for using my package${reset}
|
|
181
|
+
${dim} ~kafk6 ${cyan}t.me/kafk6${reset}
|
|
182
|
+
`)
|
|
154
183
|
}
|
|
155
184
|
|
|
156
185
|
private get token() {
|
package/typings/telegraf.d.ts
CHANGED
|
@@ -76,6 +76,8 @@ export declare class Telegraf<C extends Context = Context> extends Composer<C> {
|
|
|
76
76
|
}, req: http.IncomingMessage) => boolean;
|
|
77
77
|
private handleError;
|
|
78
78
|
constructor(token: string, options?: Partial<Telegraf.Options<C>>);
|
|
79
|
+
private static _bannerPrinted;
|
|
80
|
+
private static printBanner;
|
|
79
81
|
private get token();
|
|
80
82
|
/** @deprecated use `ctx.telegram.webhookReply` */
|
|
81
83
|
set webhookReply(webhookReply: boolean);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telegraf.d.ts","sourceRoot":"","sources":["../src/telegraf.ts"],"names":[],"mappings":";;AACA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAE5B,OAAO,KAAK,EAAE,MAAM,uBAAuB,CAAA;AAC3C,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAA;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,SAAS,MAAM,uBAAuB,CAAA;AAE7C,OAAO,OAAO,MAAM,WAAW,CAAA;AAK/B,OAAO,QAAQ,MAAM,YAAY,CAAA;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAiBhC,yBAAiB,QAAQ,CAAC;IACxB,UAAiB,OAAO,CAAC,QAAQ,SAAS,OAAO;QAC/C,WAAW,EAAE,KACX,GAAG,IAAI,EAAE,qBAAqB,CAAC,OAAO,OAAO,CAAC,KAC3C,QAAQ,CAAA;QACb,cAAc,EAAE,MAAM,CAAA;QACtB,QAAQ,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;KACtC;IAED,UAAiB,aAAa;QAC5B,kBAAkB,CAAC,EAAE,OAAO,CAAA;QAC5B,6DAA6D;QAC7D,cAAc,CAAC,EAAE,EAAE,CAAC,UAAU,EAAE,CAAA;QAChC,iEAAiE;QACjE,OAAO,CAAC,EAAE;YACR,iCAAiC;YACjC,MAAM,EAAE,MAAM,CAAA;YAEd;;;iBAGK;YACL,QAAQ,CAAC,EAAE,MAAM,CAAA;YAEjB,yEAAyE;YACzE,IAAI,CAAC,EAAE,MAAM,CAAA;YAEb,IAAI,CAAC,EAAE,MAAM,CAAA;YACb,IAAI,CAAC,EAAE,MAAM,CAAA;YAEb,sHAAsH;YACtH,SAAS,CAAC,EAAE,MAAM,CAAA;YAElB;;;eAGG;YACH,cAAc,CAAC,EAAE,MAAM,CAAA;YAEvB,4CAA4C;YAC5C,UAAU,CAAC,EAAE,UAAU,CAAA;YAEvB;;;;eAIG;YACH,WAAW,CAAC,EAAE,MAAM,CAAA;YAEpB;;;eAGG;YACH,WAAW,CAAC,EAAE,EAAE,CAAC,SAAS,CAAA;YAE1B,EAAE,CAAC,EAAE,IAAI,CAAC,eAAe,CAAA;SAC1B,CAAA;KACF;CACF;AAID,qBAAa,QAAQ,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,CAAE,SAAQ,QAAQ,CAAC,CAAC,CAAC;IACpE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,aAAa,CAAC,CAA4B;IAClD,OAAO,CAAC,OAAO,CAAC,CAAS;IACzB,mFAAmF;IAC5E,OAAO,CAAC,EAAE,EAAE,CAAC,aAAa,CAAA;IAC1B,QAAQ,EAAE,QAAQ,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAK;IAEjC;;;OAGG;IACI,aAAa,SAGZ;QACJ,mCAAmC;QACnC,QAAQ,EAAE,MAAM,CAAA;QAChB,IAAI,EAAE,MAAM,CAAA;QACZ,WAAW,CAAC,EAAE,MAAM,CAAA;KACrB,OACI,KAAK,eAAe,aAiB1B;IAED,OAAO,CAAC,WAAW,CAOlB;gBAEW,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"telegraf.d.ts","sourceRoot":"","sources":["../src/telegraf.ts"],"names":[],"mappings":"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"}
|