teh-bot 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1119 -436
- package/dist/index.mjs +4 -4
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -4,27 +4,27 @@
|
|
|
4
4
|

|
|
5
5
|

|
|
6
6
|

|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- ✅ **
|
|
15
|
-
- ✅ **
|
|
16
|
-
- ✅ **
|
|
17
|
-
- ✅ **
|
|
18
|
-
- ✅ **Event-Driven** -
|
|
19
|
-
- ✅ **
|
|
20
|
-
- ✅ **
|
|
21
|
-
- ✅ **
|
|
7
|
+

|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
A **zero-dependency**, lightweight, high-performance Telegram Bot API library for Node.js. Built with modern JavaScript standards supporting **CommonJS**, **ES Modules (ESM)**, and **TypeScript** with full type definitions.
|
|
11
|
+
|
|
12
|
+
## ✨ Core Features
|
|
13
|
+
|
|
14
|
+
- ✅ **Zero Dependencies** - No external packages required, ultra-lightweight (~50KB)
|
|
15
|
+
- ✅ **Dual Module Format** - Works seamlessly with CommonJS (.cjs), ES Modules (.mjs), and TypeScript (.ts)
|
|
16
|
+
- ✅ **Full TypeScript Support** - Complete type definitions included (index.d.ts)
|
|
17
|
+
- ✅ **High Performance** - Optimized for speed with streaming file uploads
|
|
18
|
+
- ✅ **Event-Driven Architecture** - Built on Node.js EventEmitter with chainable API
|
|
19
|
+
- ✅ **Polling & Webhook Support** - Both long-polling and webhook update methods
|
|
20
|
+
- ✅ **Middleware System** - Extensible middleware chain for request processing
|
|
21
|
+
- ✅ **40+ API Methods** - Complete Telegram Bot API coverage
|
|
22
|
+
- ✅ **Context Helpers** - Easy ctx.send(), ctx.reply(), and media shortcuts
|
|
23
|
+
- ✅ **File Management** - Automatic file upload/download with streaming support
|
|
22
24
|
- ✅ **Keyboard Builders** - Fluent API for inline and reply keyboards
|
|
23
|
-
- ✅ **Full Telegram Bot API Support** - All official
|
|
24
|
-
- ✅ **
|
|
25
|
-
- ✅ **
|
|
26
|
-
- ✅ **Context Helpers** - Simple reply(), send(), and media methods
|
|
27
|
-
- ✅ **Error Handling** - Comprehensive error information
|
|
25
|
+
- ✅ **Full Telegram Bot API Support** - All official methods with latest features
|
|
26
|
+
- ✅ **Payment Integration** - Invoices, shipping queries, pre-checkout queries
|
|
27
|
+
- ✅ **Advanced Features** - Reactions, stories, giveaways, business connections, web apps
|
|
28
28
|
|
|
29
29
|
## 📦 Installation
|
|
30
30
|
|
|
@@ -43,6 +43,11 @@ yarn add teh-bot
|
|
|
43
43
|
pnpm add teh-bot
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
+
### Using bun
|
|
47
|
+
```bash
|
|
48
|
+
bun add teh-bot
|
|
49
|
+
```
|
|
50
|
+
|
|
46
51
|
## 🚀 Quick Start
|
|
47
52
|
|
|
48
53
|
### CommonJS (.js)
|
|
@@ -59,11 +64,16 @@ bot.command('/start', async (ctx) => {
|
|
|
59
64
|
|
|
60
65
|
bot.on('text', async (message, ctx) => {
|
|
61
66
|
console.log('Message:', message.text);
|
|
67
|
+
await ctx.reply(`You said: ${message.text}`);
|
|
62
68
|
});
|
|
63
69
|
|
|
64
70
|
bot.on('polling_start', () => {
|
|
65
71
|
console.log('✅ Bot started polling');
|
|
66
72
|
});
|
|
73
|
+
|
|
74
|
+
bot.on('polling_error', (error) => {
|
|
75
|
+
console.error('❌ Polling error:', error);
|
|
76
|
+
});
|
|
67
77
|
```
|
|
68
78
|
|
|
69
79
|
### ES Modules (.mjs)
|
|
@@ -72,6 +82,8 @@ import TelegramBot from 'teh-bot';
|
|
|
72
82
|
|
|
73
83
|
const bot = new TelegramBot(process.env.TELEGRAM_BOT_TOKEN, {
|
|
74
84
|
polling: true,
|
|
85
|
+
pollingInterval: 2000,
|
|
86
|
+
pollingTimeout: 60,
|
|
75
87
|
});
|
|
76
88
|
|
|
77
89
|
bot.command('/start', async (ctx) => {
|
|
@@ -81,10 +93,6 @@ bot.command('/start', async (ctx) => {
|
|
|
81
93
|
bot.on('text', async (message, ctx) => {
|
|
82
94
|
console.log('Message:', message.text);
|
|
83
95
|
});
|
|
84
|
-
|
|
85
|
-
bot.on('polling_start', () => {
|
|
86
|
-
console.log('✅ Bot started polling');
|
|
87
|
-
});
|
|
88
96
|
```
|
|
89
97
|
|
|
90
98
|
### TypeScript (.ts)
|
|
@@ -101,663 +109,1342 @@ bot.command('/start', async (ctx: Context) => {
|
|
|
101
109
|
|
|
102
110
|
bot.on('text', async (message, ctx: Context) => {
|
|
103
111
|
console.log('Message:', message.text);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
bot.on('polling_start', () => {
|
|
107
|
-
console.log('✅ Bot started polling');
|
|
112
|
+
await ctx.reply(`You said: ${message.text}`);
|
|
108
113
|
});
|
|
109
114
|
```
|
|
110
115
|
|
|
111
116
|
## ⚙️ Configuration
|
|
112
117
|
|
|
113
|
-
###
|
|
118
|
+
### Bot Initialization Options
|
|
119
|
+
|
|
114
120
|
```javascript
|
|
115
121
|
const bot = new TelegramBot(token, {
|
|
116
|
-
// Polling
|
|
117
|
-
polling: true, // Enable polling (default: false)
|
|
118
|
-
pollingInterval: 1000, //
|
|
119
|
-
pollingTimeout: 30, // Long polling timeout (default: 30)
|
|
122
|
+
// === Polling Configuration ===
|
|
123
|
+
polling: true, // Enable polling mode (default: false)
|
|
124
|
+
pollingInterval: 1000, // Interval between polls in ms (default: 1000)
|
|
125
|
+
pollingTimeout: 30, // Long polling timeout in seconds (default: 30)
|
|
120
126
|
|
|
121
|
-
// Webhook
|
|
122
|
-
webhook: false, // Enable webhook (default: false)
|
|
127
|
+
// === Webhook Configuration ===
|
|
128
|
+
webhook: false, // Enable webhook mode (default: false)
|
|
123
129
|
webhookPort: 3000, // Webhook server port (default: 3000)
|
|
124
|
-
webhookPath: '/webhook', // Webhook path (default: '/webhook')
|
|
130
|
+
webhookPath: '/webhook', // Webhook endpoint path (default: '/webhook')
|
|
125
131
|
|
|
126
|
-
//
|
|
127
|
-
requestTimeout: 30000, //
|
|
128
|
-
maxConnections: 40, // Max concurrent connections (default: 40)
|
|
129
|
-
|
|
130
|
-
|
|
132
|
+
// === Request Configuration ===
|
|
133
|
+
requestTimeout: 30000, // HTTP request timeout in ms (default: 30000)
|
|
134
|
+
maxConnections: 40, // Max concurrent API connections (default: 40)
|
|
135
|
+
|
|
136
|
+
// === Update Filtering ===
|
|
137
|
+
allowedUpdates: [ // Filter update types to receive
|
|
138
|
+
'message',
|
|
139
|
+
'callback_query',
|
|
140
|
+
'inline_query'
|
|
141
|
+
],
|
|
142
|
+
|
|
143
|
+
// === Custom API URL ===
|
|
144
|
+
baseApiUrl: 'https://api.telegram.org', // Custom Telegram API URL
|
|
131
145
|
});
|
|
132
146
|
```
|
|
133
147
|
|
|
134
|
-
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## 📚 Complete API Reference
|
|
135
151
|
|
|
136
|
-
###
|
|
152
|
+
### 1. Bot Management
|
|
137
153
|
|
|
138
|
-
####
|
|
154
|
+
#### Get Bot Information
|
|
155
|
+
```javascript
|
|
156
|
+
// Get your bot's information
|
|
157
|
+
const me = await bot.getMe();
|
|
158
|
+
console.log(`Bot name: ${me.first_name}`);
|
|
159
|
+
console.log(`Bot username: ${me.username}`);
|
|
160
|
+
console.log(`Is bot: ${me.is_bot}`);
|
|
161
|
+
```
|
|
139
162
|
|
|
163
|
+
#### Webhook Management
|
|
140
164
|
```javascript
|
|
141
|
-
//
|
|
165
|
+
// Set webhook (replace polling with webhook)
|
|
166
|
+
await bot.setWebhook('https://example.com/webhook', {
|
|
167
|
+
certificate: fs.createReadStream('./cert.pem'),
|
|
168
|
+
max_connections: 40,
|
|
169
|
+
allowed_updates: ['message', 'callback_query']
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// Get webhook info
|
|
173
|
+
const webhookInfo = await bot.getWebhookInfo();
|
|
174
|
+
console.log('Webhook URL:', webhookInfo.url);
|
|
175
|
+
console.log('Pending updates:', webhookInfo.pending_update_count);
|
|
176
|
+
|
|
177
|
+
// Delete webhook (revert to polling)
|
|
178
|
+
await bot.deleteWebhook();
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
### 2. Message Sending
|
|
184
|
+
|
|
185
|
+
#### Text Messages
|
|
186
|
+
```javascript
|
|
187
|
+
// Simple text message
|
|
142
188
|
await bot.sendMessage(chatId, 'Hello!');
|
|
143
189
|
|
|
144
|
-
//
|
|
145
|
-
await bot.sendMessage(chatId, '
|
|
146
|
-
parse_mode: 'HTML'
|
|
147
|
-
|
|
190
|
+
// With formatting
|
|
191
|
+
await bot.sendMessage(chatId, '<b>Bold</b> <i>Italic</i> <code>Code</code>', {
|
|
192
|
+
parse_mode: 'HTML'
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// With markdown
|
|
196
|
+
await bot.sendMessage(chatId, '*Bold* _Italic_ `Code`', {
|
|
197
|
+
parse_mode: 'Markdown'
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// With link preview options
|
|
201
|
+
await bot.sendMessage(chatId, 'Check this out: https://example.com', {
|
|
202
|
+
link_preview_options: {
|
|
203
|
+
is_disabled: false,
|
|
204
|
+
prefer_small_media: true,
|
|
205
|
+
show_above_text: false
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// With entities
|
|
210
|
+
await bot.sendMessage(chatId, 'Custom #hashtag @mention', {
|
|
211
|
+
entities: [
|
|
212
|
+
{ type: 'hashtag', offset: 7, length: 8 },
|
|
213
|
+
{ type: 'mention', offset: 16, length: 8 }
|
|
214
|
+
]
|
|
215
|
+
});
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
#### Media Messages
|
|
219
|
+
|
|
220
|
+
**Photos**
|
|
221
|
+
```javascript
|
|
222
|
+
// Photo from URL
|
|
223
|
+
await bot.sendPhoto(chatId, 'https://example.com/photo.jpg', {
|
|
224
|
+
caption: 'Beautiful photo!',
|
|
225
|
+
parse_mode: 'HTML'
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// Photo from file path
|
|
229
|
+
await bot.sendPhoto(chatId, './photo.jpg', {
|
|
230
|
+
caption: 'Local photo'
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// Photo from Buffer
|
|
234
|
+
const photoBuffer = await fs.promises.readFile('./photo.jpg');
|
|
235
|
+
await bot.sendPhoto(chatId, photoBuffer, {
|
|
236
|
+
caption: 'From buffer'
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// Photo from file ID (reuse previous upload)
|
|
240
|
+
await bot.sendPhoto(chatId, 'AgAC_file_id_string', {
|
|
241
|
+
caption: 'Cached photo'
|
|
242
|
+
});
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Videos**
|
|
246
|
+
```javascript
|
|
247
|
+
// Video with thumbnail
|
|
248
|
+
await bot.sendVideo(chatId, 'https://example.com/video.mp4', {
|
|
249
|
+
caption: 'Watch this video!',
|
|
250
|
+
duration: 120,
|
|
251
|
+
width: 1280,
|
|
252
|
+
height: 720,
|
|
253
|
+
thumbnail: './thumb.jpg',
|
|
254
|
+
parse_mode: 'HTML'
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
// Local video file
|
|
258
|
+
await bot.sendVideo(chatId, './video.mp4', {
|
|
259
|
+
caption: 'Local video',
|
|
260
|
+
supports_streaming: true
|
|
261
|
+
});
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
**Audio**
|
|
265
|
+
```javascript
|
|
266
|
+
// Audio file
|
|
267
|
+
await bot.sendAudio(chatId, 'https://example.com/song.mp3', {
|
|
268
|
+
title: 'Song Title',
|
|
269
|
+
performer: 'Artist Name',
|
|
270
|
+
duration: 180,
|
|
271
|
+
thumbnail: './album.jpg'
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
// Local audio
|
|
275
|
+
await bot.sendAudio(chatId, './music.mp3', {
|
|
276
|
+
caption: 'Great song!'
|
|
277
|
+
});
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
**Documents**
|
|
281
|
+
```javascript
|
|
282
|
+
// PDF document
|
|
283
|
+
await bot.sendDocument(chatId, 'https://example.com/file.pdf', {
|
|
284
|
+
caption: 'Important document',
|
|
285
|
+
parse_mode: 'HTML'
|
|
148
286
|
});
|
|
149
287
|
|
|
150
|
-
//
|
|
151
|
-
await bot.
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
await bot.sendDocument(chatId, '/path/to/file.pdf');
|
|
155
|
-
await bot.sendAnimation(chatId, animationUrl);
|
|
156
|
-
await bot.sendVoice(chatId, voiceBuffer);
|
|
157
|
-
await bot.sendVideoNote(chatId, videoNoteBuffer);
|
|
158
|
-
await bot.sendSticker(chatId, stickerFileId);
|
|
288
|
+
// Local file
|
|
289
|
+
await bot.sendDocument(chatId, './report.pdf', {
|
|
290
|
+
caption: 'Report.pdf'
|
|
291
|
+
});
|
|
159
292
|
|
|
160
|
-
//
|
|
161
|
-
await bot.
|
|
293
|
+
// Any file type
|
|
294
|
+
await bot.sendDocument(chatId, './archive.zip', {
|
|
295
|
+
caption: 'Compressed files'
|
|
296
|
+
});
|
|
297
|
+
```
|
|
162
298
|
|
|
163
|
-
|
|
164
|
-
|
|
299
|
+
**Animations (GIF)**
|
|
300
|
+
```javascript
|
|
301
|
+
await bot.sendAnimation(chatId, 'https://example.com/animation.gif', {
|
|
302
|
+
caption: 'Cool animation!',
|
|
303
|
+
duration: 5,
|
|
304
|
+
width: 400,
|
|
305
|
+
height: 400
|
|
306
|
+
});
|
|
165
307
|
|
|
166
|
-
|
|
167
|
-
|
|
308
|
+
await bot.sendAnimation(chatId, './animation.gif', {
|
|
309
|
+
thumbnail: './thumb.jpg'
|
|
310
|
+
});
|
|
311
|
+
```
|
|
168
312
|
|
|
169
|
-
|
|
170
|
-
|
|
313
|
+
**Voice Messages**
|
|
314
|
+
```javascript
|
|
315
|
+
// Voice message (OGG format)
|
|
316
|
+
await bot.sendVoice(chatId, './voice.ogg', {
|
|
317
|
+
caption: 'Voice message',
|
|
318
|
+
duration: 30
|
|
319
|
+
});
|
|
171
320
|
|
|
172
|
-
//
|
|
173
|
-
await bot.
|
|
321
|
+
// From URL
|
|
322
|
+
await bot.sendVoice(chatId, 'https://example.com/voice.ogg', {
|
|
323
|
+
duration: 45
|
|
324
|
+
});
|
|
325
|
+
```
|
|
174
326
|
|
|
175
|
-
|
|
327
|
+
**Video Notes (Circular Videos)**
|
|
328
|
+
```javascript
|
|
329
|
+
// Video note - must be square and short
|
|
330
|
+
await bot.sendVideoNote(chatId, './video_note.mp4', {
|
|
331
|
+
duration: 60,
|
|
332
|
+
length: 360 // width/height
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// From URL
|
|
336
|
+
await bot.sendVideoNote(chatId, 'https://example.com/note.mp4');
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
**Stickers**
|
|
340
|
+
```javascript
|
|
341
|
+
// Send sticker by file ID
|
|
342
|
+
await bot.sendSticker(chatId, 'sticker_file_id');
|
|
343
|
+
|
|
344
|
+
// Send from URL
|
|
345
|
+
await bot.sendSticker(chatId, 'https://example.com/sticker.webp');
|
|
346
|
+
|
|
347
|
+
// Send from local file
|
|
348
|
+
await bot.sendSticker(chatId, './sticker.tgs');
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
### 3. Location & Venue
|
|
354
|
+
|
|
355
|
+
#### Send Location
|
|
356
|
+
```javascript
|
|
357
|
+
// Simple location
|
|
358
|
+
await bot.sendLocation(chatId, 40.7128, -74.0060, {
|
|
359
|
+
heading: 45, // Direction (0-360 degrees)
|
|
360
|
+
horizontal_accuracy: 50, // Accuracy in meters
|
|
361
|
+
proximity_alert_radius: 200 // Proximity alert distance
|
|
362
|
+
});
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
#### Send Venue
|
|
366
|
+
```javascript
|
|
367
|
+
await bot.sendVenue(chatId, 40.7128, -74.0060, 'Statue of Liberty', 'Liberty Island', {
|
|
368
|
+
foursquare_id: 'venue_id',
|
|
369
|
+
foursquare_type: 'landmark'
|
|
370
|
+
});
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
#### Send Contact
|
|
374
|
+
```javascript
|
|
375
|
+
await bot.sendContact(chatId, '+1-555-0100', 'John Doe', {
|
|
376
|
+
last_name: 'Doe',
|
|
377
|
+
vcard: 'BEGIN:VCARD\nVERSION:3.0\nFN:John Doe\nTEL:+1-555-0100\nEND:VCARD'
|
|
378
|
+
});
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
### 4. Polls & Quizzes
|
|
384
|
+
|
|
385
|
+
#### Create Poll
|
|
386
|
+
```javascript
|
|
387
|
+
// Simple poll
|
|
388
|
+
await bot.sendPoll(chatId, 'Do you like Telegram?', ['Yes', 'No', 'Maybe'], {
|
|
389
|
+
is_anonymous: true,
|
|
390
|
+
allows_multiple_answers: true,
|
|
391
|
+
explanation: 'Most people like Telegram!',
|
|
392
|
+
open_period: 600 // Auto-closes after 10 minutes
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
// Quiz mode (single correct answer)
|
|
396
|
+
await bot.sendPoll(chatId, 'What is 2+2?', ['3', '4', '5'], {
|
|
397
|
+
type: 'quiz',
|
|
398
|
+
correct_option_id: 1, // Option index (0-based)
|
|
399
|
+
explanation: 'Simple math!',
|
|
400
|
+
explanation_parse_mode: 'HTML'
|
|
401
|
+
});
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
#### Send Dice/Game
|
|
405
|
+
```javascript
|
|
406
|
+
// Dice emoji - values 1-6
|
|
407
|
+
await bot.sendDice(chatId, {
|
|
408
|
+
emoji: '🎲' // or '🎯', '🏀', '⚽', '🎳', '🎮'
|
|
409
|
+
});
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
### 5. Chat Actions
|
|
415
|
+
|
|
416
|
+
Send chat actions to show user what the bot is doing:
|
|
417
|
+
|
|
418
|
+
```javascript
|
|
419
|
+
// Typing indicator
|
|
176
420
|
await bot.sendChatAction(chatId, 'typing');
|
|
421
|
+
|
|
422
|
+
// Photo upload
|
|
423
|
+
await bot.sendChatAction(chatId, 'upload_photo');
|
|
424
|
+
|
|
425
|
+
// Video upload
|
|
426
|
+
await bot.sendChatAction(chatId, 'upload_video');
|
|
427
|
+
|
|
428
|
+
// Audio upload
|
|
429
|
+
await bot.sendChatAction(chatId, 'upload_audio');
|
|
430
|
+
|
|
431
|
+
// Document upload
|
|
432
|
+
await bot.sendChatAction(chatId, 'upload_document');
|
|
433
|
+
|
|
434
|
+
// Finding location
|
|
435
|
+
await bot.sendChatAction(chatId, 'find_location');
|
|
436
|
+
|
|
437
|
+
// Recording voice
|
|
438
|
+
await bot.sendChatAction(chatId, 'record_voice');
|
|
439
|
+
|
|
440
|
+
// Recording video
|
|
441
|
+
await bot.sendChatAction(chatId, 'record_video');
|
|
442
|
+
|
|
443
|
+
// Recording video note
|
|
444
|
+
await bot.sendChatAction(chatId, 'record_video_note');
|
|
445
|
+
|
|
446
|
+
// Choosing sticker
|
|
447
|
+
await bot.sendChatAction(chatId, 'choose_sticker');
|
|
177
448
|
```
|
|
178
449
|
|
|
179
|
-
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
### 6. Message Management
|
|
180
453
|
|
|
454
|
+
#### Forward Message
|
|
181
455
|
```javascript
|
|
182
|
-
//
|
|
456
|
+
// Forward message from another chat
|
|
457
|
+
await bot.forwardMessage(chatId, sourceChatId, messageId, {
|
|
458
|
+
disable_notification: false
|
|
459
|
+
});
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
#### Copy Message
|
|
463
|
+
```javascript
|
|
464
|
+
// Copy message (creates new message, doesn't forward)
|
|
465
|
+
await bot.copyMessage(chatId, sourceChatId, messageId, {
|
|
466
|
+
caption: 'Optional new caption',
|
|
467
|
+
parse_mode: 'HTML'
|
|
468
|
+
});
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
#### Edit Message Text
|
|
472
|
+
```javascript
|
|
473
|
+
// Edit sent message
|
|
183
474
|
await bot.editMessageText('New text', {
|
|
184
475
|
chat_id: chatId,
|
|
185
476
|
message_id: messageId,
|
|
186
477
|
parse_mode: 'HTML',
|
|
478
|
+
link_preview_options: {
|
|
479
|
+
is_disabled: true
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
// Edit inline message (from inline query)
|
|
484
|
+
await bot.editMessageText('Updated text', {
|
|
485
|
+
inline_message_id: 'inline_id_12345',
|
|
486
|
+
parse_mode: 'HTML'
|
|
187
487
|
});
|
|
488
|
+
```
|
|
188
489
|
|
|
189
|
-
|
|
490
|
+
#### Edit Message Caption
|
|
491
|
+
```javascript
|
|
492
|
+
// Edit media caption
|
|
190
493
|
await bot.editMessageCaption({
|
|
191
494
|
chat_id: chatId,
|
|
192
495
|
message_id: messageId,
|
|
193
496
|
caption: 'New caption',
|
|
497
|
+
parse_mode: 'HTML'
|
|
194
498
|
});
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
#### Edit Message Keyboard
|
|
502
|
+
```javascript
|
|
503
|
+
// Update inline keyboard
|
|
504
|
+
const newKeyboard = TelegramBot.InlineKeyboard()
|
|
505
|
+
.text('New Button', 'new_callback_data')
|
|
506
|
+
.row()
|
|
507
|
+
.url('Google', 'https://google.com')
|
|
508
|
+
.build();
|
|
195
509
|
|
|
196
|
-
// Edit reply markup
|
|
197
510
|
await bot.editMessageReplyMarkup({
|
|
198
511
|
chat_id: chatId,
|
|
199
512
|
message_id: messageId,
|
|
200
|
-
reply_markup: newKeyboard
|
|
513
|
+
reply_markup: newKeyboard
|
|
201
514
|
});
|
|
515
|
+
```
|
|
202
516
|
|
|
203
|
-
|
|
517
|
+
#### Delete Message
|
|
518
|
+
```javascript
|
|
519
|
+
// Delete a message
|
|
204
520
|
await bot.deleteMessage(chatId, messageId);
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
---
|
|
205
524
|
|
|
206
|
-
|
|
207
|
-
await bot.forwardMessage(chatId, fromChatId, messageId);
|
|
525
|
+
### 7. Payments
|
|
208
526
|
|
|
209
|
-
|
|
210
|
-
|
|
527
|
+
#### Send Invoice
|
|
528
|
+
```javascript
|
|
529
|
+
// Create product invoice
|
|
530
|
+
await bot.sendInvoice(chatId, {
|
|
531
|
+
title: 'Telegram Premium',
|
|
532
|
+
description: 'Upgrade to Telegram Premium for more features!',
|
|
533
|
+
payload: 'premium_subscription_12345',
|
|
534
|
+
provider_token: 'your_stripe_token',
|
|
535
|
+
currency: 'USD',
|
|
536
|
+
prices: [
|
|
537
|
+
{ label: 'Premium 1 Month', amount: 999 }, // Amount in cents
|
|
538
|
+
{ label: 'Premium 3 Months', amount: 2499 }
|
|
539
|
+
],
|
|
540
|
+
photo_url: 'https://example.com/premium.jpg',
|
|
541
|
+
photo_width: 800,
|
|
542
|
+
photo_height: 600,
|
|
543
|
+
need_email: true,
|
|
544
|
+
need_phone_number: true,
|
|
545
|
+
send_phone_number_to_provider: true
|
|
546
|
+
});
|
|
211
547
|
```
|
|
212
548
|
|
|
213
|
-
####
|
|
549
|
+
#### Answer Shipping Query
|
|
550
|
+
```javascript
|
|
551
|
+
bot.on('shipping_query', async (query, ctx) => {
|
|
552
|
+
const shippingOptions = [
|
|
553
|
+
{
|
|
554
|
+
id: 'standard',
|
|
555
|
+
title: 'Standard Delivery',
|
|
556
|
+
price_list: [
|
|
557
|
+
{ label: 'Shipping', amount: 500 } // 5.00 USD
|
|
558
|
+
]
|
|
559
|
+
},
|
|
560
|
+
{
|
|
561
|
+
id: 'express',
|
|
562
|
+
title: 'Express Delivery',
|
|
563
|
+
price_list: [
|
|
564
|
+
{ label: 'Shipping', amount: 1500 } // 15.00 USD
|
|
565
|
+
]
|
|
566
|
+
}
|
|
567
|
+
];
|
|
568
|
+
|
|
569
|
+
// Check if shipping address is valid
|
|
570
|
+
const isValid = query.shipping_address.country_code === 'US';
|
|
571
|
+
|
|
572
|
+
if (isValid) {
|
|
573
|
+
await bot.answerShippingQuery(query.id, true, {
|
|
574
|
+
shipping_options: shippingOptions
|
|
575
|
+
});
|
|
576
|
+
} else {
|
|
577
|
+
await bot.answerShippingQuery(query.id, false, {
|
|
578
|
+
error_message: 'We only ship to the United States'
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
});
|
|
582
|
+
```
|
|
214
583
|
|
|
584
|
+
#### Answer Pre-Checkout Query
|
|
215
585
|
```javascript
|
|
216
|
-
|
|
217
|
-
|
|
586
|
+
bot.on('pre_checkout_query', async (query, ctx) => {
|
|
587
|
+
// Validate order before payment
|
|
588
|
+
const isValid = validateOrder(query);
|
|
589
|
+
|
|
590
|
+
if (isValid) {
|
|
591
|
+
await bot.answerPreCheckoutQuery(query.id, true);
|
|
592
|
+
} else {
|
|
593
|
+
await bot.answerPreCheckoutQuery(query.id, false, {
|
|
594
|
+
error_message: 'Item out of stock'
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
```
|
|
218
599
|
|
|
219
|
-
|
|
220
|
-
|
|
600
|
+
#### Handle Successful Payment
|
|
601
|
+
```javascript
|
|
602
|
+
bot.on('successful_payment', async (payment, ctx) => {
|
|
603
|
+
console.log('Payment received!');
|
|
604
|
+
console.log('Amount:', payment.total_amount);
|
|
605
|
+
console.log('Currency:', payment.currency);
|
|
606
|
+
console.log('Order ID:', payment.invoice_payload);
|
|
607
|
+
|
|
608
|
+
await ctx.send('✅ Payment successful! Thank you for your purchase!');
|
|
609
|
+
});
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
---
|
|
613
|
+
|
|
614
|
+
### 8. Chat Management
|
|
615
|
+
|
|
616
|
+
#### Get Chat Information
|
|
617
|
+
```javascript
|
|
618
|
+
// Get chat details
|
|
619
|
+
const chat = await bot.getChat(chatId);
|
|
620
|
+
console.log('Chat:', chat.title || chat.first_name);
|
|
621
|
+
console.log('Members:', chat.type);
|
|
622
|
+
console.log('Bio:', chat.bio);
|
|
221
623
|
|
|
222
624
|
// Get chat member count
|
|
223
625
|
const count = await bot.getChatMemberCount(chatId);
|
|
626
|
+
console.log('Members:', count);
|
|
224
627
|
|
|
225
|
-
// Get specific
|
|
628
|
+
// Get specific member info
|
|
226
629
|
const member = await bot.getChatMember(chatId, userId);
|
|
630
|
+
console.log('Member status:', member.status);
|
|
631
|
+
console.log('Member:', member.user.first_name);
|
|
227
632
|
|
|
633
|
+
// Get all administrators
|
|
634
|
+
const admins = await bot.getChatAdministrators(chatId);
|
|
635
|
+
admins.forEach(admin => {
|
|
636
|
+
console.log(`${admin.user.first_name} - ${admin.status}`);
|
|
637
|
+
});
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
#### Manage Chat Settings
|
|
641
|
+
```javascript
|
|
228
642
|
// Set chat title
|
|
229
|
-
await bot.setChatTitle(chatId, 'New
|
|
643
|
+
await bot.setChatTitle(chatId, 'New Group Name');
|
|
230
644
|
|
|
231
645
|
// Set chat description
|
|
232
|
-
await bot.setChatDescription(chatId, '
|
|
646
|
+
await bot.setChatDescription(chatId, 'Group description and rules...');
|
|
233
647
|
|
|
234
|
-
//
|
|
235
|
-
await bot.
|
|
648
|
+
// Set chat photo
|
|
649
|
+
await bot.setChatPhoto(chatId, './group_photo.jpg');
|
|
236
650
|
|
|
237
|
-
//
|
|
238
|
-
await bot.
|
|
651
|
+
// Delete chat photo
|
|
652
|
+
await bot.deleteChatPhoto(chatId);
|
|
239
653
|
|
|
240
|
-
//
|
|
241
|
-
await bot.
|
|
242
|
-
|
|
243
|
-
// Leave chat
|
|
244
|
-
await bot.leaveChat(chatId);
|
|
654
|
+
// Get chat member info
|
|
655
|
+
const member = await bot.getChatMember(chatId, userId);
|
|
245
656
|
```
|
|
246
657
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
```javascript
|
|
250
|
-
// Ban member
|
|
251
|
-
await bot.banChatMember(chatId, userId);
|
|
658
|
+
---
|
|
252
659
|
|
|
253
|
-
|
|
254
|
-
await bot.unbanChatMember(chatId, userId);
|
|
660
|
+
### 9. Member Management
|
|
255
661
|
|
|
256
|
-
|
|
662
|
+
#### Restrict/Promote Members
|
|
663
|
+
```javascript
|
|
664
|
+
// Restrict member (disable all permissions)
|
|
257
665
|
await bot.restrictChatMember(chatId, userId, {
|
|
258
666
|
can_send_messages: false,
|
|
259
667
|
can_send_media_messages: false,
|
|
668
|
+
can_send_polls: false,
|
|
669
|
+
can_add_web_page_previews: false,
|
|
670
|
+
until_date: Math.floor(Date.now() / 1000) + 86400 // 24 hours
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
// Partially restrict (allow only text)
|
|
674
|
+
await bot.restrictChatMember(chatId, userId, {
|
|
675
|
+
can_send_messages: true,
|
|
676
|
+
can_send_media_messages: false,
|
|
677
|
+
can_send_polls: false,
|
|
678
|
+
can_add_web_page_previews: false
|
|
260
679
|
});
|
|
261
680
|
|
|
262
|
-
// Promote member
|
|
681
|
+
// Promote member to admin
|
|
263
682
|
await bot.promoteChatMember(chatId, userId, {
|
|
264
|
-
|
|
683
|
+
can_change_info: true,
|
|
265
684
|
can_delete_messages: true,
|
|
685
|
+
can_restrict_members: true,
|
|
686
|
+
can_pin_messages: true,
|
|
687
|
+
can_manage_topics: true,
|
|
688
|
+
is_anonymous: false
|
|
266
689
|
});
|
|
690
|
+
|
|
691
|
+
// Set custom admin title
|
|
692
|
+
await bot.setChatAdministratorCustomTitle(chatId, userId, 'Cool Admin');
|
|
267
693
|
```
|
|
268
694
|
|
|
269
|
-
####
|
|
695
|
+
#### Ban/Unban Members
|
|
696
|
+
```javascript
|
|
697
|
+
// Ban member
|
|
698
|
+
await bot.banChatMember(chatId, userId, {
|
|
699
|
+
until_date: Math.floor(Date.now() / 1000) + 604800, // 7 days
|
|
700
|
+
revoke_messages: true // Delete all their messages
|
|
701
|
+
});
|
|
270
702
|
|
|
703
|
+
// Permanent ban
|
|
704
|
+
await bot.banChatMember(chatId, userId, {
|
|
705
|
+
revoke_messages: true
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
// Unban member
|
|
709
|
+
await bot.unbanChatMember(chatId, userId, {
|
|
710
|
+
only_if_banned: true
|
|
711
|
+
});
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
#### Other Member Operations
|
|
271
715
|
```javascript
|
|
272
|
-
//
|
|
273
|
-
|
|
716
|
+
// Approve join request
|
|
717
|
+
await bot.approveChatJoinRequest(chatId, userId);
|
|
718
|
+
|
|
719
|
+
// Decline join request
|
|
720
|
+
await bot.declineChatJoinRequest(chatId, userId);
|
|
274
721
|
|
|
275
|
-
//
|
|
276
|
-
await bot.
|
|
722
|
+
// Leave chat
|
|
723
|
+
await bot.leaveChat(chatId);
|
|
277
724
|
```
|
|
278
725
|
|
|
279
|
-
|
|
726
|
+
---
|
|
727
|
+
|
|
728
|
+
### 10. Message Pinning
|
|
280
729
|
|
|
281
730
|
```javascript
|
|
282
|
-
//
|
|
283
|
-
await bot.
|
|
284
|
-
|
|
285
|
-
|
|
731
|
+
// Pin message (all members see it)
|
|
732
|
+
await bot.pinChatMessage(chatId, messageId, {
|
|
733
|
+
disable_notification: false // Notify members
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
// Unpin specific message
|
|
737
|
+
await bot.unpinChatMessage(chatId, {
|
|
738
|
+
message_id: messageId
|
|
286
739
|
});
|
|
287
740
|
|
|
288
|
-
//
|
|
289
|
-
await bot.
|
|
290
|
-
{
|
|
291
|
-
type: 'article',
|
|
292
|
-
id: '1',
|
|
293
|
-
title: 'Result',
|
|
294
|
-
input_message_content: { message_text: 'Text' },
|
|
295
|
-
},
|
|
296
|
-
]);
|
|
741
|
+
// Unpin all messages
|
|
742
|
+
await bot.unpinAllChatMessages(chatId);
|
|
297
743
|
```
|
|
298
744
|
|
|
299
|
-
|
|
745
|
+
---
|
|
746
|
+
|
|
747
|
+
### 11. Queries & Responses
|
|
300
748
|
|
|
749
|
+
#### Callback Query
|
|
301
750
|
```javascript
|
|
302
|
-
|
|
303
|
-
|
|
751
|
+
bot.on('callback_query', async (query, ctx) => {
|
|
752
|
+
console.log('Button clicked:', query.data);
|
|
304
753
|
|
|
305
|
-
//
|
|
306
|
-
|
|
754
|
+
// Answer callback (shows notification or toast)
|
|
755
|
+
await ctx.answerCallbackQuery({
|
|
756
|
+
text: 'Button was clicked!',
|
|
757
|
+
show_alert: false // Toast notification
|
|
758
|
+
});
|
|
307
759
|
|
|
308
|
-
//
|
|
309
|
-
await
|
|
760
|
+
// Edit message
|
|
761
|
+
await ctx.editMessageText('You clicked the button!');
|
|
762
|
+
});
|
|
763
|
+
```
|
|
310
764
|
|
|
311
|
-
|
|
312
|
-
|
|
765
|
+
#### Inline Query
|
|
766
|
+
```javascript
|
|
767
|
+
bot.on('inline_query', async (query, ctx) => {
|
|
768
|
+
const results = [
|
|
769
|
+
{
|
|
770
|
+
type: 'article',
|
|
771
|
+
id: '1',
|
|
772
|
+
title: 'Result 1',
|
|
773
|
+
description: 'First search result',
|
|
774
|
+
input_message_content: {
|
|
775
|
+
message_text: 'Result 1 content'
|
|
776
|
+
}
|
|
777
|
+
},
|
|
778
|
+
{
|
|
779
|
+
type: 'photo',
|
|
780
|
+
id: '2',
|
|
781
|
+
photo_url: 'https://example.com/photo.jpg',
|
|
782
|
+
thumbnail_url: 'https://example.com/thumb.jpg'
|
|
783
|
+
}
|
|
784
|
+
];
|
|
785
|
+
|
|
786
|
+
await bot.answerInlineQuery(query.id, results, {
|
|
787
|
+
cache_time: 300, // Cache 5 minutes
|
|
788
|
+
is_personal: false
|
|
789
|
+
});
|
|
790
|
+
});
|
|
791
|
+
```
|
|
313
792
|
|
|
314
|
-
|
|
315
|
-
|
|
793
|
+
#### Chosen Inline Result
|
|
794
|
+
```javascript
|
|
795
|
+
bot.on('chosen_inline_result', async (result, ctx) => {
|
|
796
|
+
console.log('User selected inline result:', result.result_id);
|
|
797
|
+
console.log('Query was:', result.query);
|
|
798
|
+
});
|
|
316
799
|
```
|
|
317
800
|
|
|
318
|
-
|
|
801
|
+
---
|
|
319
802
|
|
|
320
|
-
|
|
803
|
+
### 12. File Management
|
|
321
804
|
|
|
805
|
+
#### Download File
|
|
322
806
|
```javascript
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
await ctx.replyWithVideo(videoUrl);
|
|
333
|
-
await ctx.replyWithAudio(audioBuffer);
|
|
334
|
-
await ctx.replyWithDocument(docPath);
|
|
335
|
-
|
|
336
|
-
// Answer callback query
|
|
337
|
-
await ctx.answerCallbackQuery({ text: 'Done!' });
|
|
338
|
-
|
|
339
|
-
// Edit message text
|
|
340
|
-
await ctx.editMessageText('New text', {
|
|
341
|
-
parse_mode: 'HTML',
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
// Access update data
|
|
345
|
-
console.log(ctx.message?.text);
|
|
346
|
-
console.log(ctx.chat?.id);
|
|
347
|
-
console.log(ctx.from?.username);
|
|
348
|
-
console.log(ctx.callbackQuery?.data);
|
|
349
|
-
});
|
|
807
|
+
// Get file info
|
|
808
|
+
const file = await bot.getFile('file_id_from_message');
|
|
809
|
+
console.log('File path:', file.file_path);
|
|
810
|
+
console.log('File size:', file.file_size);
|
|
811
|
+
|
|
812
|
+
// Download file to disk
|
|
813
|
+
const destination = './downloaded_file.jpg';
|
|
814
|
+
await bot.downloadFile('file_id', destination);
|
|
815
|
+
console.log('Downloaded to:', destination);
|
|
350
816
|
```
|
|
351
817
|
|
|
352
|
-
|
|
818
|
+
#### Upload File
|
|
819
|
+
```javascript
|
|
820
|
+
// Upload photo from local file
|
|
821
|
+
await bot.sendPhoto(chatId, './photo.jpg');
|
|
822
|
+
|
|
823
|
+
// Upload from URL
|
|
824
|
+
await bot.sendPhoto(chatId, 'https://example.com/photo.jpg');
|
|
353
825
|
|
|
354
|
-
|
|
826
|
+
// Upload from Buffer
|
|
827
|
+
const buffer = await fs.promises.readFile('./photo.jpg');
|
|
828
|
+
await bot.sendPhoto(chatId, buffer);
|
|
829
|
+
```
|
|
355
830
|
|
|
831
|
+
---
|
|
832
|
+
|
|
833
|
+
### 13. Keyboard Builders
|
|
834
|
+
|
|
835
|
+
#### Inline Keyboard (Buttons with Actions)
|
|
356
836
|
```javascript
|
|
837
|
+
// Create inline keyboard
|
|
357
838
|
const keyboard = TelegramBot.InlineKeyboard()
|
|
358
|
-
.text('Button 1', '
|
|
359
|
-
.text('Button 2', '
|
|
360
|
-
.row()
|
|
839
|
+
.text('Button 1', 'callback_data_1')
|
|
840
|
+
.text('Button 2', 'callback_data_2')
|
|
841
|
+
.row() // New row
|
|
842
|
+
.url('Visit Website', 'https://example.com')
|
|
361
843
|
.url('Google', 'https://google.com')
|
|
362
|
-
.url('GitHub', 'https://github.com')
|
|
363
844
|
.row()
|
|
364
|
-
.
|
|
845
|
+
.text('Delete', 'delete_action')
|
|
365
846
|
.build();
|
|
366
847
|
|
|
367
|
-
await bot.sendMessage(chatId, 'Choose:', {
|
|
848
|
+
await bot.sendMessage(chatId, 'Choose an action:', {
|
|
849
|
+
reply_markup: keyboard
|
|
850
|
+
});
|
|
368
851
|
```
|
|
369
852
|
|
|
370
|
-
|
|
371
|
-
|
|
853
|
+
#### Reply Keyboard (Regular Buttons)
|
|
372
854
|
```javascript
|
|
855
|
+
// Create reply keyboard
|
|
373
856
|
const keyboard = TelegramBot.ReplyKeyboard()
|
|
374
|
-
.text('
|
|
375
|
-
.text('
|
|
857
|
+
.text('Button 1')
|
|
858
|
+
.text('Button 2')
|
|
376
859
|
.row()
|
|
377
|
-
.
|
|
378
|
-
.
|
|
379
|
-
.resize(true)
|
|
380
|
-
.oneTime(true)
|
|
860
|
+
.text('Button 3')
|
|
861
|
+
.oneTime() // Disappears after use
|
|
381
862
|
.build();
|
|
382
863
|
|
|
383
|
-
await bot.sendMessage(chatId, '
|
|
864
|
+
await bot.sendMessage(chatId, 'Select an option:', {
|
|
865
|
+
reply_markup: keyboard
|
|
866
|
+
});
|
|
384
867
|
```
|
|
385
868
|
|
|
386
|
-
|
|
387
|
-
|
|
869
|
+
#### Remove Keyboard
|
|
388
870
|
```javascript
|
|
389
|
-
|
|
390
|
-
|
|
871
|
+
// Hide keyboard
|
|
872
|
+
await bot.sendMessage(chatId, 'Keyboard hidden', {
|
|
873
|
+
reply_markup: TelegramBot.RemoveKeyboard()
|
|
391
874
|
});
|
|
392
875
|
```
|
|
393
876
|
|
|
394
|
-
|
|
395
|
-
|
|
877
|
+
#### Force Reply
|
|
396
878
|
```javascript
|
|
397
|
-
|
|
398
|
-
|
|
879
|
+
// Force user to reply to this message
|
|
880
|
+
await bot.sendMessage(chatId, 'Please reply to this message:', {
|
|
881
|
+
reply_markup: TelegramBot.ForceReply()
|
|
399
882
|
});
|
|
400
883
|
```
|
|
401
884
|
|
|
402
|
-
|
|
885
|
+
---
|
|
886
|
+
|
|
887
|
+
### 14. Context Helpers
|
|
403
888
|
|
|
404
|
-
|
|
889
|
+
Context object provides convenient shortcuts:
|
|
405
890
|
|
|
406
891
|
```javascript
|
|
407
|
-
|
|
408
|
-
|
|
892
|
+
bot.on('text', async (message, ctx) => {
|
|
893
|
+
// Send message to same chat
|
|
894
|
+
await ctx.send('Hello!');
|
|
409
895
|
|
|
410
|
-
//
|
|
411
|
-
|
|
896
|
+
// Reply to message (with reply_to_message_id)
|
|
897
|
+
await ctx.reply('Thanks for your message!');
|
|
412
898
|
|
|
413
|
-
//
|
|
414
|
-
|
|
899
|
+
// Send photo in reply
|
|
900
|
+
await ctx.replyWithPhoto('./photo.jpg', {
|
|
901
|
+
caption: 'Photo reply'
|
|
902
|
+
});
|
|
415
903
|
|
|
416
|
-
//
|
|
417
|
-
|
|
904
|
+
// Send video in reply
|
|
905
|
+
await ctx.replyWithVideo('./video.mp4', {
|
|
906
|
+
caption: 'Video reply'
|
|
907
|
+
});
|
|
418
908
|
|
|
419
|
-
//
|
|
420
|
-
|
|
909
|
+
// Send audio
|
|
910
|
+
await ctx.replyWithAudio('./song.mp3', {
|
|
911
|
+
title: 'Song'
|
|
912
|
+
});
|
|
421
913
|
|
|
422
|
-
//
|
|
423
|
-
|
|
914
|
+
// Send document
|
|
915
|
+
await ctx.replyWithDocument('./file.pdf');
|
|
424
916
|
|
|
425
|
-
//
|
|
426
|
-
|
|
917
|
+
// Edit callback query message
|
|
918
|
+
if (ctx.callbackQuery) {
|
|
919
|
+
await ctx.editMessageText('Updated message');
|
|
920
|
+
await ctx.answerCallbackQuery({
|
|
921
|
+
text: 'Updated!',
|
|
922
|
+
show_alert: false
|
|
923
|
+
});
|
|
924
|
+
}
|
|
925
|
+
});
|
|
926
|
+
```
|
|
427
927
|
|
|
428
|
-
|
|
429
|
-
bot.on('sticker', (message, ctx) => {});
|
|
928
|
+
---
|
|
430
929
|
|
|
431
|
-
|
|
432
|
-
bot.on('location', (message, ctx) => {});
|
|
930
|
+
## 🎯 Event Listeners
|
|
433
931
|
|
|
434
|
-
|
|
435
|
-
bot.on('contact', (message, ctx) => {});
|
|
932
|
+
Listen to different types of updates:
|
|
436
933
|
|
|
437
|
-
|
|
438
|
-
|
|
934
|
+
```javascript
|
|
935
|
+
// === Message Events ===
|
|
936
|
+
bot.on('message', async (message, ctx) => {
|
|
937
|
+
console.log('New message:', message.text);
|
|
938
|
+
});
|
|
439
939
|
|
|
440
|
-
|
|
441
|
-
|
|
940
|
+
bot.on('text', async (message, ctx) => {
|
|
941
|
+
// Text messages only
|
|
942
|
+
});
|
|
442
943
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
944
|
+
bot.on('photo', async (message, ctx) => {
|
|
945
|
+
// Photo messages
|
|
946
|
+
console.log('Photo received');
|
|
947
|
+
});
|
|
446
948
|
|
|
447
|
-
|
|
949
|
+
bot.on('video', async (message, ctx) => {
|
|
950
|
+
// Video messages
|
|
951
|
+
});
|
|
448
952
|
|
|
449
|
-
|
|
450
|
-
//
|
|
451
|
-
bot.on('callback_query', (query, ctx) => {
|
|
452
|
-
console.log(query.data); // Button callback data
|
|
953
|
+
bot.on('audio', async (message, ctx) => {
|
|
954
|
+
// Audio messages
|
|
453
955
|
});
|
|
454
956
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
console.log(query.query); // Search query
|
|
957
|
+
bot.on('document', async (message, ctx) => {
|
|
958
|
+
// Document messages
|
|
458
959
|
});
|
|
459
960
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
961
|
+
bot.on('voice', async (message, ctx) => {
|
|
962
|
+
// Voice messages
|
|
963
|
+
});
|
|
463
964
|
|
|
464
|
-
|
|
965
|
+
bot.on('sticker', async (message, ctx) => {
|
|
966
|
+
// Sticker messages
|
|
967
|
+
});
|
|
465
968
|
|
|
466
|
-
|
|
467
|
-
//
|
|
468
|
-
|
|
969
|
+
bot.on('location', async (message, ctx) => {
|
|
970
|
+
// Location messages
|
|
971
|
+
});
|
|
469
972
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
973
|
+
bot.on('contact', async (message, ctx) => {
|
|
974
|
+
// Contact messages
|
|
975
|
+
});
|
|
473
976
|
|
|
474
|
-
|
|
977
|
+
// === Edit Events ===
|
|
978
|
+
bot.on('edited_message', async (message, ctx) => {
|
|
979
|
+
console.log('Message edited');
|
|
980
|
+
});
|
|
475
981
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
982
|
+
bot.on('edited_channel_post', async (post, ctx) => {
|
|
983
|
+
console.log('Channel post edited');
|
|
984
|
+
});
|
|
479
985
|
|
|
480
|
-
//
|
|
481
|
-
bot.on('
|
|
482
|
-
|
|
986
|
+
// === Channel Events ===
|
|
987
|
+
bot.on('channel_post', async (message, ctx) => {
|
|
988
|
+
console.log('New channel post');
|
|
989
|
+
});
|
|
483
990
|
|
|
484
|
-
|
|
991
|
+
// === Query Events ===
|
|
992
|
+
bot.on('callback_query', async (query, ctx) => {
|
|
993
|
+
console.log('Button clicked:', query.data);
|
|
994
|
+
});
|
|
485
995
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
996
|
+
bot.on('inline_query', async (query, ctx) => {
|
|
997
|
+
console.log('Inline query:', query.query);
|
|
998
|
+
});
|
|
999
|
+
|
|
1000
|
+
bot.on('chosen_inline_result', async (result, ctx) => {
|
|
1001
|
+
console.log('Result chosen:', result.result_id);
|
|
1002
|
+
});
|
|
1003
|
+
|
|
1004
|
+
// === Poll Events ===
|
|
1005
|
+
bot.on('poll', async (poll, ctx) => {
|
|
1006
|
+
console.log('Poll received');
|
|
1007
|
+
});
|
|
1008
|
+
|
|
1009
|
+
bot.on('poll_answer', async (answer, ctx) => {
|
|
1010
|
+
console.log('Poll answered');
|
|
1011
|
+
});
|
|
489
1012
|
|
|
490
|
-
//
|
|
491
|
-
bot.on('
|
|
1013
|
+
// === Membership Events ===
|
|
1014
|
+
bot.on('my_chat_member', async (member, ctx) => {
|
|
1015
|
+
// Bot was added/removed from chat
|
|
1016
|
+
console.log('Status:', member.new_chat_member.status);
|
|
1017
|
+
});
|
|
492
1018
|
|
|
493
|
-
|
|
494
|
-
|
|
1019
|
+
bot.on('chat_member', async (member, ctx) => {
|
|
1020
|
+
// User status changed in chat
|
|
1021
|
+
console.log('User:', member.new_chat_member.user.first_name);
|
|
1022
|
+
});
|
|
495
1023
|
|
|
496
|
-
//
|
|
497
|
-
bot.on('
|
|
1024
|
+
// === System Events ===
|
|
1025
|
+
bot.on('polling_start', () => {
|
|
1026
|
+
console.log('✅ Polling started');
|
|
1027
|
+
});
|
|
498
1028
|
|
|
499
|
-
|
|
500
|
-
|
|
1029
|
+
bot.on('polling_stop', () => {
|
|
1030
|
+
console.log('❌ Polling stopped');
|
|
1031
|
+
});
|
|
501
1032
|
|
|
502
|
-
|
|
503
|
-
|
|
1033
|
+
bot.on('polling_error', (error) => {
|
|
1034
|
+
console.error('Polling error:', error);
|
|
1035
|
+
});
|
|
504
1036
|
|
|
505
|
-
|
|
506
|
-
|
|
1037
|
+
bot.on('webhook_start', (port) => {
|
|
1038
|
+
console.log(`✅ Webhook listening on port ${port}`);
|
|
1039
|
+
});
|
|
507
1040
|
|
|
508
|
-
|
|
509
|
-
|
|
1041
|
+
bot.on('webhook_stop', () => {
|
|
1042
|
+
console.log('❌ Webhook stopped');
|
|
1043
|
+
});
|
|
1044
|
+
|
|
1045
|
+
bot.on('error', (error) => {
|
|
1046
|
+
console.error('Bot error:', error);
|
|
1047
|
+
});
|
|
510
1048
|
```
|
|
511
1049
|
|
|
512
|
-
|
|
1050
|
+
---
|
|
1051
|
+
|
|
1052
|
+
## 🔌 Middleware System
|
|
1053
|
+
|
|
1054
|
+
Process updates with middleware chain:
|
|
513
1055
|
|
|
514
1056
|
```javascript
|
|
515
|
-
//
|
|
1057
|
+
// Simple logging middleware
|
|
516
1058
|
bot.use(async (ctx, next) => {
|
|
517
|
-
console.log(`[${new Date().toISOString()}]
|
|
1059
|
+
console.log(`[${new Date().toISOString()}] User: ${ctx.from?.id}`);
|
|
518
1060
|
await next();
|
|
519
1061
|
});
|
|
520
1062
|
|
|
521
1063
|
// Rate limiting middleware
|
|
522
|
-
const
|
|
1064
|
+
const userLimits = new Map();
|
|
1065
|
+
|
|
523
1066
|
bot.use(async (ctx, next) => {
|
|
524
1067
|
const userId = ctx.from?.id;
|
|
525
|
-
|
|
1068
|
+
const now = Date.now();
|
|
526
1069
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
1070
|
+
if (!userLimits.has(userId)) {
|
|
1071
|
+
userLimits.set(userId, []);
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
const times = userLimits.get(userId);
|
|
1075
|
+
times.push(now);
|
|
1076
|
+
|
|
1077
|
+
// Keep only last 10 requests
|
|
1078
|
+
const recentRequests = times.filter(t => now - t < 60000);
|
|
1079
|
+
userLimits.set(userId, recentRequests);
|
|
1080
|
+
|
|
1081
|
+
if (recentRequests.length > 30) {
|
|
1082
|
+
await ctx.send('Too many requests. Please wait.');
|
|
1083
|
+
return; // Don't call next()
|
|
531
1084
|
}
|
|
532
1085
|
|
|
533
|
-
userCalls.set(userId, calls + 1);
|
|
534
1086
|
await next();
|
|
535
1087
|
});
|
|
536
1088
|
|
|
537
|
-
//
|
|
1089
|
+
// Auth check middleware
|
|
538
1090
|
bot.use(async (ctx, next) => {
|
|
539
1091
|
const allowedUsers = [123456789, 987654321];
|
|
540
|
-
|
|
541
|
-
|
|
1092
|
+
|
|
1093
|
+
if (!allowedUsers.includes(ctx.from?.id)) {
|
|
1094
|
+
await ctx.send('You are not authorized');
|
|
542
1095
|
return;
|
|
543
1096
|
}
|
|
1097
|
+
|
|
1098
|
+
await next();
|
|
1099
|
+
});
|
|
1100
|
+
|
|
1101
|
+
// Error handling middleware
|
|
1102
|
+
bot.use(async (ctx, next) => {
|
|
1103
|
+
try {
|
|
1104
|
+
await next();
|
|
1105
|
+
} catch (error) {
|
|
1106
|
+
console.error('Error:', error);
|
|
1107
|
+
await ctx.send('An error occurred. Please try again.');
|
|
1108
|
+
}
|
|
1109
|
+
});
|
|
1110
|
+
|
|
1111
|
+
// Command prefix middleware
|
|
1112
|
+
bot.use(async (ctx, next) => {
|
|
1113
|
+
if (ctx.message?.text?.startsWith('!')) {
|
|
1114
|
+
ctx.isCommand = true;
|
|
1115
|
+
}
|
|
544
1116
|
await next();
|
|
545
1117
|
});
|
|
546
1118
|
```
|
|
547
1119
|
|
|
548
|
-
|
|
1120
|
+
---
|
|
549
1121
|
|
|
550
|
-
|
|
1122
|
+
## 🎨 Advanced Examples
|
|
551
1123
|
|
|
1124
|
+
### Example 1: Echo Bot
|
|
552
1125
|
```javascript
|
|
1126
|
+
const TelegramBot = require('teh-bot');
|
|
1127
|
+
|
|
1128
|
+
const bot = new TelegramBot(process.env.BOT_TOKEN, { polling: true });
|
|
1129
|
+
|
|
553
1130
|
bot.command('/start', async (ctx) => {
|
|
554
|
-
await ctx.send('
|
|
1131
|
+
await ctx.send('Send me anything and I will echo it back!');
|
|
555
1132
|
});
|
|
556
1133
|
|
|
557
|
-
bot.
|
|
558
|
-
await ctx.
|
|
1134
|
+
bot.on('text', async (message, ctx) => {
|
|
1135
|
+
await ctx.reply(message.text);
|
|
559
1136
|
});
|
|
560
1137
|
```
|
|
561
1138
|
|
|
562
|
-
###
|
|
563
|
-
|
|
1139
|
+
### Example 2: Calculator Bot
|
|
564
1140
|
```javascript
|
|
565
|
-
bot.command(
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
1141
|
+
bot.command('/calculate', async (ctx) => {
|
|
1142
|
+
const keyboard = TelegramBot.InlineKeyboard()
|
|
1143
|
+
.text('➕', 'op_add')
|
|
1144
|
+
.text('➖', 'op_sub')
|
|
1145
|
+
.text('✖️', 'op_mul')
|
|
1146
|
+
.text('➗', 'op_div')
|
|
1147
|
+
.build();
|
|
569
1148
|
|
|
570
|
-
|
|
1149
|
+
await ctx.send('Choose operation:', { reply_markup: keyboard });
|
|
1150
|
+
});
|
|
571
1151
|
|
|
572
|
-
|
|
573
|
-
const
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
1152
|
+
bot.on('callback_query', async (query, ctx) => {
|
|
1153
|
+
const operation = query.data.replace('op_', '');
|
|
1154
|
+
|
|
1155
|
+
if (operation === 'add') {
|
|
1156
|
+
// Handle addition
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
await ctx.answerCallbackQuery({
|
|
1160
|
+
text: 'Operation selected!',
|
|
1161
|
+
show_alert: false
|
|
1162
|
+
});
|
|
1163
|
+
});
|
|
577
1164
|
```
|
|
578
1165
|
|
|
579
|
-
|
|
580
|
-
|
|
1166
|
+
### Example 3: File Management Bot
|
|
581
1167
|
```javascript
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
webhookPort: 3000,
|
|
585
|
-
webhookPath: '/webhook',
|
|
586
|
-
});
|
|
587
|
-
|
|
588
|
-
// Webhook events
|
|
589
|
-
bot.on('webhook_start', (port) => {
|
|
590
|
-
console.log(`✅ Webhook listening on port ${port}`);
|
|
1168
|
+
bot.command('/upload', async (ctx) => {
|
|
1169
|
+
await ctx.send('Send me a file to download');
|
|
591
1170
|
});
|
|
592
1171
|
|
|
593
|
-
bot.on('
|
|
594
|
-
|
|
1172
|
+
bot.on('document', async (message, ctx) => {
|
|
1173
|
+
const fileId = message.document.file_id;
|
|
1174
|
+
|
|
1175
|
+
// Download file
|
|
1176
|
+
await bot.downloadFile(fileId, `./downloads/${message.document.file_name}`);
|
|
1177
|
+
|
|
1178
|
+
await ctx.send('✅ File downloaded successfully!');
|
|
595
1179
|
});
|
|
1180
|
+
```
|
|
596
1181
|
|
|
597
|
-
|
|
598
|
-
|
|
1182
|
+
### Example 4: Quiz Bot
|
|
1183
|
+
```javascript
|
|
1184
|
+
bot.command('/quiz', async (ctx) => {
|
|
1185
|
+
await bot.sendPoll(ctx.chat.id,
|
|
1186
|
+
'What is the capital of France?',
|
|
1187
|
+
['Paris', 'London', 'Berlin'],
|
|
1188
|
+
{
|
|
1189
|
+
type: 'quiz',
|
|
1190
|
+
correct_option_id: 0,
|
|
1191
|
+
explanation: 'Paris is the capital of France!'
|
|
1192
|
+
}
|
|
1193
|
+
);
|
|
599
1194
|
});
|
|
600
|
-
|
|
601
|
-
// Start webhook
|
|
602
|
-
bot.startWebhook();
|
|
603
|
-
|
|
604
|
-
// Stop webhook
|
|
605
|
-
bot.stopWebhook();
|
|
606
1195
|
```
|
|
607
1196
|
|
|
608
|
-
|
|
609
|
-
|
|
1197
|
+
### Example 5: Admin Commands
|
|
610
1198
|
```javascript
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
1199
|
+
bot.command('/ban', async (ctx) => {
|
|
1200
|
+
if (!ctx.message?.reply_to_message) {
|
|
1201
|
+
await ctx.send('Reply to a message to ban that user');
|
|
1202
|
+
return;
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
const userId = ctx.message.reply_to_message.from.id;
|
|
1206
|
+
|
|
1207
|
+
try {
|
|
1208
|
+
await bot.banChatMember(ctx.chat.id, userId, {
|
|
1209
|
+
revoke_messages: true
|
|
1210
|
+
});
|
|
1211
|
+
|
|
1212
|
+
await ctx.send('✅ User banned!');
|
|
1213
|
+
} catch (error) {
|
|
1214
|
+
await ctx.send('❌ Could not ban user: ' + error.message);
|
|
1215
|
+
}
|
|
615
1216
|
});
|
|
616
1217
|
|
|
617
|
-
|
|
618
|
-
|
|
1218
|
+
bot.command('/promote', async (ctx) => {
|
|
1219
|
+
if (!ctx.message?.reply_to_message) {
|
|
1220
|
+
await ctx.send('Reply to a message to promote that user');
|
|
1221
|
+
return;
|
|
1222
|
+
}
|
|
619
1223
|
|
|
620
|
-
|
|
621
|
-
|
|
1224
|
+
const userId = ctx.message.reply_to_message.from.id;
|
|
1225
|
+
|
|
1226
|
+
try {
|
|
1227
|
+
await bot.promoteChatMember(ctx.chat.id, userId, {
|
|
1228
|
+
can_delete_messages: true,
|
|
1229
|
+
can_restrict_members: true,
|
|
1230
|
+
can_pin_messages: true,
|
|
1231
|
+
can_manage_topics: true
|
|
1232
|
+
});
|
|
1233
|
+
|
|
1234
|
+
await ctx.send('✅ User promoted!');
|
|
1235
|
+
} catch (error) {
|
|
1236
|
+
await ctx.send('❌ Could not promote user: ' + error.message);
|
|
1237
|
+
}
|
|
1238
|
+
});
|
|
622
1239
|
```
|
|
623
1240
|
|
|
624
|
-
|
|
1241
|
+
---
|
|
625
1242
|
|
|
626
|
-
|
|
1243
|
+
## 📊 Complete Method List
|
|
1244
|
+
|
|
1245
|
+
### Message Methods
|
|
1246
|
+
- `sendMessage()` - Send text message
|
|
1247
|
+
- `sendPhoto()` - Send photo
|
|
1248
|
+
- `sendVideo()` - Send video
|
|
1249
|
+
- `sendAudio()` - Send audio
|
|
1250
|
+
- `sendDocument()` - Send document
|
|
1251
|
+
- `sendAnimation()` - Send animation (GIF)
|
|
1252
|
+
- `sendVoice()` - Send voice message
|
|
1253
|
+
- `sendVideoNote()` - Send video note
|
|
1254
|
+
- `sendSticker()` - Send sticker
|
|
1255
|
+
- `sendLocation()` - Send location
|
|
1256
|
+
- `sendVenue()` - Send venue
|
|
1257
|
+
- `sendContact()` - Send contact
|
|
1258
|
+
- `sendPoll()` - Send poll/quiz
|
|
1259
|
+
- `sendDice()` - Send dice game
|
|
1260
|
+
- `sendChatAction()` - Send typing indicator
|
|
1261
|
+
|
|
1262
|
+
### Message Management
|
|
1263
|
+
- `forwardMessage()` - Forward message
|
|
1264
|
+
- `copyMessage()` - Copy message
|
|
1265
|
+
- `editMessageText()` - Edit message text
|
|
1266
|
+
- `editMessageCaption()` - Edit media caption
|
|
1267
|
+
- `editMessageReplyMarkup()` - Edit keyboard
|
|
1268
|
+
- `deleteMessage()` - Delete message
|
|
1269
|
+
|
|
1270
|
+
### Chat Management
|
|
1271
|
+
- `getChat()` - Get chat info
|
|
1272
|
+
- `getChatAdministrators()` - Get admins
|
|
1273
|
+
- `getChatMemberCount()` - Get member count
|
|
1274
|
+
- `getChatMember()` - Get member info
|
|
1275
|
+
- `setChatTitle()` - Set chat title
|
|
1276
|
+
- `setChatDescription()` - Set chat description
|
|
1277
|
+
- `setChatPhoto()` - Set chat photo
|
|
1278
|
+
- `deleteChatPhoto()` - Delete chat photo
|
|
1279
|
+
|
|
1280
|
+
### Member Management
|
|
1281
|
+
- `banChatMember()` - Ban member
|
|
1282
|
+
- `unbanChatMember()` - Unban member
|
|
1283
|
+
- `restrictChatMember()` - Restrict member
|
|
1284
|
+
- `promoteChatMember()` - Promote member
|
|
1285
|
+
- `setChatAdministratorCustomTitle()` - Set admin title
|
|
1286
|
+
- `approveChatJoinRequest()` - Approve join request
|
|
1287
|
+
- `declineChatJoinRequest()` - Decline join request
|
|
1288
|
+
|
|
1289
|
+
### Message Pinning
|
|
1290
|
+
- `pinChatMessage()` - Pin message
|
|
1291
|
+
- `unpinChatMessage()` - Unpin message
|
|
1292
|
+
- `unpinAllChatMessages()` - Unpin all
|
|
1293
|
+
|
|
1294
|
+
### Payments
|
|
1295
|
+
- `sendInvoice()` - Send payment invoice
|
|
1296
|
+
- `answerShippingQuery()` - Answer shipping
|
|
1297
|
+
- `answerPreCheckoutQuery()` - Answer pre-checkout
|
|
1298
|
+
|
|
1299
|
+
### Query Responses
|
|
1300
|
+
- `answerCallbackQuery()` - Answer button click
|
|
1301
|
+
- `answerInlineQuery()` - Answer inline query
|
|
1302
|
+
|
|
1303
|
+
### File Management
|
|
1304
|
+
- `getFile()` - Get file info
|
|
1305
|
+
- `downloadFile()` - Download file
|
|
1306
|
+
|
|
1307
|
+
### Webhook
|
|
1308
|
+
- `setWebhook()` - Set webhook URL
|
|
1309
|
+
- `deleteWebhook()` - Delete webhook
|
|
1310
|
+
- `getWebhookInfo()` - Get webhook info
|
|
1311
|
+
|
|
1312
|
+
### Bot
|
|
1313
|
+
- `getMe()` - Get bot info
|
|
1314
|
+
- `getUpdates()` - Get updates (polling)
|
|
1315
|
+
- `startPolling()` - Start long polling
|
|
1316
|
+
- `stopPolling()` - Stop polling
|
|
1317
|
+
- `startWebhook()` - Start webhook server
|
|
1318
|
+
- `stopWebhook()` - Stop webhook server
|
|
627
1319
|
|
|
628
|
-
|
|
629
|
-
const fs = require('fs');
|
|
1320
|
+
---
|
|
630
1321
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
1322
|
+
## 💡 Best Practices
|
|
1323
|
+
|
|
1324
|
+
### 1. Error Handling
|
|
1325
|
+
```javascript
|
|
1326
|
+
bot.on('text', async (message, ctx) => {
|
|
1327
|
+
try {
|
|
1328
|
+
// Your code here
|
|
1329
|
+
await ctx.send('Hello!');
|
|
1330
|
+
} catch (error) {
|
|
1331
|
+
console.error('Error:', error);
|
|
1332
|
+
await ctx.send('An error occurred. Please try again.');
|
|
1333
|
+
}
|
|
635
1334
|
});
|
|
636
1335
|
```
|
|
637
1336
|
|
|
638
|
-
###
|
|
639
|
-
|
|
1337
|
+
### 2. Rate Limiting
|
|
640
1338
|
```javascript
|
|
641
|
-
|
|
642
|
-
const keyboard = TelegramBot.InlineKeyboard()
|
|
643
|
-
.text('Option A', 'opt_a')
|
|
644
|
-
.text('Option B', 'opt_b')
|
|
645
|
-
.row()
|
|
646
|
-
.text('Back', 'back')
|
|
647
|
-
.build();
|
|
1339
|
+
const rateLimits = new Map();
|
|
648
1340
|
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
await ctx.answerCallbackQuery({ text: 'You chose A!' });
|
|
656
|
-
await ctx.editMessageText('✅ Option A selected');
|
|
657
|
-
break;
|
|
658
|
-
case 'opt_b':
|
|
659
|
-
await ctx.answerCallbackQuery({ text: 'You chose B!' });
|
|
660
|
-
await ctx.editMessageText('✅ Option B selected');
|
|
661
|
-
break;
|
|
662
|
-
case 'back':
|
|
663
|
-
// Show menu again
|
|
664
|
-
break;
|
|
1341
|
+
bot.use(async (ctx, next) => {
|
|
1342
|
+
const userId = ctx.from?.id;
|
|
1343
|
+
const now = Date.now();
|
|
1344
|
+
|
|
1345
|
+
if (!rateLimits.has(userId)) {
|
|
1346
|
+
rateLimits.set(userId, { count: 0, reset: now + 60000 });
|
|
665
1347
|
}
|
|
1348
|
+
|
|
1349
|
+
const limit = rateLimits.get(userId);
|
|
1350
|
+
if (now > limit.reset) {
|
|
1351
|
+
limit.count = 0;
|
|
1352
|
+
limit.reset = now + 60000;
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
if (limit.count++ > 10) {
|
|
1356
|
+
await ctx.send('Rate limited. Please wait.');
|
|
1357
|
+
return;
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
await next();
|
|
666
1361
|
});
|
|
667
1362
|
```
|
|
668
1363
|
|
|
669
|
-
###
|
|
670
|
-
|
|
1364
|
+
### 3. Command Parsing
|
|
671
1365
|
```javascript
|
|
672
|
-
bot.
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
})
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
bot.on('poll_answer', async (answer, ctx) => {
|
|
681
|
-
console.log(`User ${answer.user.id} voted for options: ${answer.option_ids}`);
|
|
1366
|
+
bot.command(['/start', '/help', '/info'], async (ctx) => {
|
|
1367
|
+
const command = ctx.message.text.split(' ')[0];
|
|
1368
|
+
|
|
1369
|
+
if (command === '/start') {
|
|
1370
|
+
// Handle start
|
|
1371
|
+
} else if (command === '/help') {
|
|
1372
|
+
// Handle help
|
|
1373
|
+
}
|
|
682
1374
|
});
|
|
683
1375
|
```
|
|
684
1376
|
|
|
685
|
-
###
|
|
686
|
-
|
|
1377
|
+
### 4. Session Management
|
|
687
1378
|
```javascript
|
|
688
|
-
const
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
1379
|
+
const sessions = new Map();
|
|
1380
|
+
|
|
1381
|
+
function getSession(userId) {
|
|
1382
|
+
if (!sessions.has(userId)) {
|
|
1383
|
+
sessions.set(userId, {
|
|
1384
|
+
userId,
|
|
1385
|
+
state: 'idle',
|
|
1386
|
+
data: {}
|
|
1387
|
+
});
|
|
1388
|
+
}
|
|
1389
|
+
return sessions.get(userId);
|
|
1390
|
+
}
|
|
693
1391
|
|
|
694
1392
|
bot.on('text', async (message, ctx) => {
|
|
695
|
-
const
|
|
696
|
-
|
|
697
|
-
if (
|
|
698
|
-
|
|
1393
|
+
const session = getSession(ctx.from.id);
|
|
1394
|
+
|
|
1395
|
+
if (session.state === 'waiting_name') {
|
|
1396
|
+
session.data.name = message.text;
|
|
1397
|
+
session.state = 'idle';
|
|
1398
|
+
await ctx.send(`Hello ${session.data.name}!`);
|
|
699
1399
|
}
|
|
700
1400
|
});
|
|
701
1401
|
```
|
|
702
1402
|
|
|
703
|
-
|
|
704
|
-
|
|
1403
|
+
### 5. Async File Operations
|
|
705
1404
|
```javascript
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
1405
|
+
const fs = require('fs').promises;
|
|
1406
|
+
|
|
1407
|
+
bot.command('/export', async (ctx) => {
|
|
1408
|
+
try {
|
|
1409
|
+
await ctx.sendChatAction(ctx.chat.id, 'upload_document');
|
|
1410
|
+
|
|
1411
|
+
const data = await fs.readFile('./data.json');
|
|
1412
|
+
await bot.sendDocument(ctx.chat.id, data, {
|
|
1413
|
+
caption: 'Your data export'
|
|
1414
|
+
});
|
|
1415
|
+
} catch (error) {
|
|
1416
|
+
await ctx.send('Export failed: ' + error.message);
|
|
1417
|
+
}
|
|
717
1418
|
});
|
|
718
|
-
|
|
719
|
-
try {
|
|
720
|
-
await bot.sendMessage(chatId, 'message');
|
|
721
|
-
} catch (error) {
|
|
722
|
-
console.error('Send failed:', error.message);
|
|
723
|
-
}
|
|
724
1419
|
```
|
|
725
1420
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
### ✅ Implemented Features
|
|
1421
|
+
---
|
|
729
1422
|
|
|
730
|
-
|
|
731
|
-
- ✅ **File Handling** - Upload, download files
|
|
732
|
-
- ✅ **Chat Methods** - Get chat info, manage settings
|
|
733
|
-
- ✅ **User Methods** - Get user info, manage members
|
|
734
|
-
- ✅ **Keyboard & Buttons** - Inline and reply keyboards
|
|
735
|
-
- ✅ **Queries** - Callback, inline, and poll queries
|
|
736
|
-
- ✅ **Updates & Events** - Real-time event handling
|
|
737
|
-
- ✅ **Polling & Webhooks** - Multiple update methods
|
|
738
|
-
- ✅ **Media Types** - Photos, videos, audio, documents, stickers, animations, voice
|
|
739
|
-
- ✅ **Admin Functions** - Ban, restrict, promote members
|
|
740
|
-
- ✅ **Games & Polls** - Send polls and get answers
|
|
1423
|
+
## 🐛 Troubleshooting
|
|
741
1424
|
|
|
742
|
-
|
|
1425
|
+
### Bot not receiving messages
|
|
1426
|
+
- Check if `polling: true` is set or webhook is properly configured
|
|
1427
|
+
- Verify the bot token is correct
|
|
1428
|
+
- Ensure the bot has been started with `/start` by the user
|
|
1429
|
+
- Check that `allowedUpdates` filter isn't blocking message updates
|
|
743
1430
|
|
|
744
|
-
###
|
|
1431
|
+
### File upload errors
|
|
1432
|
+
- Ensure file exists and is readable
|
|
1433
|
+
- Check file size limits (20MB for documents, 50MB for video)
|
|
1434
|
+
- Verify file format is supported
|
|
745
1435
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
1436
|
+
### Webhook issues
|
|
1437
|
+
- Ensure HTTPS is used (not HTTP)
|
|
1438
|
+
- Certificate must be valid and not self-signed (unless using self-signed with setWebhook)
|
|
1439
|
+
- Telegram must be able to reach the webhook URL
|
|
1440
|
+
- Port 443 is recommended
|
|
750
1441
|
|
|
751
|
-
###
|
|
1442
|
+
### Rate limiting
|
|
1443
|
+
- Telegram has rate limits: ~30 messages/second per bot
|
|
1444
|
+
- Implement backoff and queue system for high volume
|
|
1445
|
+
- Use middleware to throttle requests
|
|
752
1446
|
|
|
753
|
-
|
|
754
|
-
export TELEGRAM_BOT_TOKEN="YOUR_TOKEN_HERE"
|
|
755
|
-
```
|
|
756
|
-
|
|
757
|
-
Or in `.env` file:
|
|
758
|
-
```env
|
|
759
|
-
TELEGRAM_BOT_TOKEN=your_token_here
|
|
760
|
-
```
|
|
1447
|
+
---
|
|
761
1448
|
|
|
762
1449
|
## 📝 License
|
|
763
1450
|
|
|
@@ -765,18 +1452,14 @@ MIT License - See LICENSE file for details
|
|
|
765
1452
|
|
|
766
1453
|
## 🤝 Contributing
|
|
767
1454
|
|
|
768
|
-
Contributions are welcome! Please
|
|
1455
|
+
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
|
|
769
1456
|
|
|
770
1457
|
## 📞 Support
|
|
771
1458
|
|
|
772
|
-
|
|
773
|
-
-
|
|
774
|
-
-
|
|
775
|
-
|
|
776
|
-
## 🙏 Acknowledgments
|
|
777
|
-
|
|
778
|
-
Built with ❤️ for the Telegram Bot API community.
|
|
1459
|
+
- Report issues on GitHub
|
|
1460
|
+
- Check examples/ folder for code samples
|
|
1461
|
+
- Read full docs at api.telegram.org/bots/api
|
|
779
1462
|
|
|
780
1463
|
---
|
|
781
1464
|
|
|
782
|
-
**
|
|
1465
|
+
**Made with ❤️ by KazeDevID**
|