teh-bot 1.0.4 → 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 +1228 -323
- package/{index.js → dist/index.cjs} +95 -167
- package/{index.d.ts → dist/index.d.ts} +518 -23
- package/dist/index.mjs +1002 -0
- package/package.json +25 -10
package/README.md
CHANGED
|
@@ -1,560 +1,1465 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
# 🤖 Teh Bot - Lightweight Telegram Bot API Library
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
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
|
|
24
|
+
- ✅ **Keyboard Builders** - Fluent API for inline and reply keyboards
|
|
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
|
+
|
|
29
|
+
## 📦 Installation
|
|
30
|
+
|
|
31
|
+
### Using npm
|
|
32
|
+
```bash
|
|
33
|
+
npm install teh-bot
|
|
34
|
+
```
|
|
9
35
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- **Middleware Support** - Express-style middleware system
|
|
15
|
-
- **Smart Rate Limiting** - Automatic request queuing and retry logic
|
|
16
|
-
- **Both Polling & Webhooks** - Choose your preferred update method
|
|
17
|
-
- **TypeScript Support** - Full TypeScript definitions included
|
|
18
|
-
- **Small Bundle Size** - Minimal footprint for fast deployments
|
|
19
|
-
- **Clean API** - Intuitive, chainable methods
|
|
36
|
+
### Using yarn
|
|
37
|
+
```bash
|
|
38
|
+
yarn add teh-bot
|
|
39
|
+
```
|
|
20
40
|
|
|
21
|
-
|
|
41
|
+
### Using pnpm
|
|
42
|
+
```bash
|
|
43
|
+
pnpm add teh-bot
|
|
44
|
+
```
|
|
22
45
|
|
|
46
|
+
### Using bun
|
|
23
47
|
```bash
|
|
24
|
-
|
|
48
|
+
bun add teh-bot
|
|
25
49
|
```
|
|
26
50
|
|
|
27
|
-
## Quick Start
|
|
51
|
+
## 🚀 Quick Start
|
|
28
52
|
|
|
53
|
+
### CommonJS (.js)
|
|
29
54
|
```javascript
|
|
30
55
|
const TelegramBot = require('teh-bot');
|
|
31
56
|
|
|
32
|
-
const bot = new TelegramBot(
|
|
33
|
-
polling: true
|
|
57
|
+
const bot = new TelegramBot(process.env.TELEGRAM_BOT_TOKEN, {
|
|
58
|
+
polling: true,
|
|
34
59
|
});
|
|
35
60
|
|
|
36
|
-
bot.command('start', async (ctx) => {
|
|
37
|
-
await ctx.
|
|
61
|
+
bot.command('/start', async (ctx) => {
|
|
62
|
+
await ctx.send('👋 Hello! I am Teh Bot!');
|
|
38
63
|
});
|
|
39
64
|
|
|
40
65
|
bot.on('text', async (message, ctx) => {
|
|
66
|
+
console.log('Message:', message.text);
|
|
41
67
|
await ctx.reply(`You said: ${message.text}`);
|
|
42
68
|
});
|
|
69
|
+
|
|
70
|
+
bot.on('polling_start', () => {
|
|
71
|
+
console.log('✅ Bot started polling');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
bot.on('polling_error', (error) => {
|
|
75
|
+
console.error('❌ Polling error:', error);
|
|
76
|
+
});
|
|
43
77
|
```
|
|
44
78
|
|
|
45
|
-
|
|
79
|
+
### ES Modules (.mjs)
|
|
80
|
+
```javascript
|
|
81
|
+
import TelegramBot from 'teh-bot';
|
|
46
82
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
- [Middleware](#middleware)
|
|
53
|
-
- [Events](#events)
|
|
54
|
-
- [File Handling](#file-handling)
|
|
55
|
-
- [Error Handling](#error-handling)
|
|
56
|
-
- [API Reference](#api-reference)
|
|
83
|
+
const bot = new TelegramBot(process.env.TELEGRAM_BOT_TOKEN, {
|
|
84
|
+
polling: true,
|
|
85
|
+
pollingInterval: 2000,
|
|
86
|
+
pollingTimeout: 60,
|
|
87
|
+
});
|
|
57
88
|
|
|
58
|
-
|
|
89
|
+
bot.command('/start', async (ctx) => {
|
|
90
|
+
await ctx.send('👋 Hello! I am Teh Bot!');
|
|
91
|
+
});
|
|
59
92
|
|
|
60
|
-
|
|
93
|
+
bot.on('text', async (message, ctx) => {
|
|
94
|
+
console.log('Message:', message.text);
|
|
95
|
+
});
|
|
96
|
+
```
|
|
61
97
|
|
|
62
|
-
|
|
63
|
-
|
|
98
|
+
### TypeScript (.ts)
|
|
99
|
+
```typescript
|
|
100
|
+
import TelegramBot, { Context } from 'teh-bot';
|
|
64
101
|
|
|
65
|
-
const bot = new TelegramBot('
|
|
102
|
+
const bot = new TelegramBot(process.env.TELEGRAM_BOT_TOKEN || '', {
|
|
66
103
|
polling: true,
|
|
67
|
-
|
|
68
|
-
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
bot.command('/start', async (ctx: Context) => {
|
|
107
|
+
await ctx.send('👋 Hello! I am Teh Bot!');
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
bot.on('text', async (message, ctx: Context) => {
|
|
111
|
+
console.log('Message:', message.text);
|
|
112
|
+
await ctx.reply(`You said: ${message.text}`);
|
|
69
113
|
});
|
|
70
114
|
```
|
|
71
115
|
|
|
72
|
-
|
|
116
|
+
## ⚙️ Configuration
|
|
73
117
|
|
|
74
|
-
|
|
75
|
-
- `pollingInterval` (number) - Polling interval in ms (default: 1000)
|
|
76
|
-
- `pollingTimeout` (number) - Long polling timeout in seconds (default: 30)
|
|
77
|
-
- `webhook` (boolean) - Enable webhook mode (default: false)
|
|
78
|
-
- `webhookPort` (number) - Webhook server port (default: 3000)
|
|
79
|
-
- `webhookPath` (string) - Webhook URL path (default: '/webhook')
|
|
80
|
-
- `requestTimeout` (number) - HTTP request timeout in ms (default: 30000)
|
|
81
|
-
- `allowedUpdates` (array) - List of update types to receive
|
|
118
|
+
### Bot Initialization Options
|
|
82
119
|
|
|
83
|
-
|
|
120
|
+
```javascript
|
|
121
|
+
const bot = new TelegramBot(token, {
|
|
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)
|
|
126
|
+
|
|
127
|
+
// === Webhook Configuration ===
|
|
128
|
+
webhook: false, // Enable webhook mode (default: false)
|
|
129
|
+
webhookPort: 3000, // Webhook server port (default: 3000)
|
|
130
|
+
webhookPath: '/webhook', // Webhook endpoint path (default: '/webhook')
|
|
131
|
+
|
|
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
|
|
145
|
+
});
|
|
146
|
+
```
|
|
84
147
|
|
|
85
|
-
|
|
148
|
+
---
|
|
86
149
|
|
|
150
|
+
## 📚 Complete API Reference
|
|
151
|
+
|
|
152
|
+
### 1. Bot Management
|
|
153
|
+
|
|
154
|
+
#### Get Bot Information
|
|
87
155
|
```javascript
|
|
88
|
-
|
|
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
|
+
```
|
|
89
162
|
|
|
90
|
-
|
|
163
|
+
#### Webhook Management
|
|
164
|
+
```javascript
|
|
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
|
+
});
|
|
91
171
|
|
|
92
|
-
|
|
93
|
-
|
|
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
|
|
188
|
+
await bot.sendMessage(chatId, 'Hello!');
|
|
189
|
+
|
|
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
|
+
]
|
|
94
215
|
});
|
|
95
216
|
```
|
|
96
217
|
|
|
97
|
-
|
|
218
|
+
#### Media Messages
|
|
98
219
|
|
|
220
|
+
**Photos**
|
|
99
221
|
```javascript
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
222
|
+
// Photo from URL
|
|
223
|
+
await bot.sendPhoto(chatId, 'https://example.com/photo.jpg', {
|
|
224
|
+
caption: 'Beautiful photo!',
|
|
225
|
+
parse_mode: 'HTML'
|
|
104
226
|
});
|
|
105
227
|
|
|
106
|
-
|
|
228
|
+
// Photo from file path
|
|
229
|
+
await bot.sendPhoto(chatId, './photo.jpg', {
|
|
230
|
+
caption: 'Local photo'
|
|
231
|
+
});
|
|
107
232
|
|
|
108
|
-
|
|
109
|
-
|
|
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'
|
|
110
242
|
});
|
|
111
243
|
```
|
|
112
244
|
|
|
113
|
-
|
|
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
|
+
});
|
|
114
256
|
|
|
115
|
-
|
|
257
|
+
// Local video file
|
|
258
|
+
await bot.sendVideo(chatId, './video.mp4', {
|
|
259
|
+
caption: 'Local video',
|
|
260
|
+
supports_streaming: true
|
|
261
|
+
});
|
|
262
|
+
```
|
|
116
263
|
|
|
264
|
+
**Audio**
|
|
117
265
|
```javascript
|
|
118
|
-
|
|
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
|
+
});
|
|
119
273
|
|
|
120
|
-
|
|
121
|
-
|
|
274
|
+
// Local audio
|
|
275
|
+
await bot.sendAudio(chatId, './music.mp3', {
|
|
276
|
+
caption: 'Great song!'
|
|
122
277
|
});
|
|
278
|
+
```
|
|
123
279
|
|
|
124
|
-
|
|
280
|
+
**Documents**
|
|
281
|
+
```javascript
|
|
282
|
+
// PDF document
|
|
283
|
+
await bot.sendDocument(chatId, 'https://example.com/file.pdf', {
|
|
284
|
+
caption: 'Important document',
|
|
125
285
|
parse_mode: 'HTML'
|
|
126
286
|
});
|
|
287
|
+
|
|
288
|
+
// Local file
|
|
289
|
+
await bot.sendDocument(chatId, './report.pdf', {
|
|
290
|
+
caption: 'Report.pdf'
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// Any file type
|
|
294
|
+
await bot.sendDocument(chatId, './archive.zip', {
|
|
295
|
+
caption: 'Compressed files'
|
|
296
|
+
});
|
|
297
|
+
```
|
|
298
|
+
|
|
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
|
+
});
|
|
307
|
+
|
|
308
|
+
await bot.sendAnimation(chatId, './animation.gif', {
|
|
309
|
+
thumbnail: './thumb.jpg'
|
|
310
|
+
});
|
|
127
311
|
```
|
|
128
312
|
|
|
129
|
-
|
|
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
|
+
});
|
|
320
|
+
|
|
321
|
+
// From URL
|
|
322
|
+
await bot.sendVoice(chatId, 'https://example.com/voice.ogg', {
|
|
323
|
+
duration: 45
|
|
324
|
+
});
|
|
325
|
+
```
|
|
130
326
|
|
|
327
|
+
**Video Notes (Circular Videos)**
|
|
131
328
|
```javascript
|
|
132
|
-
|
|
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
|
+
```
|
|
133
338
|
|
|
134
|
-
|
|
339
|
+
**Stickers**
|
|
340
|
+
```javascript
|
|
341
|
+
// Send sticker by file ID
|
|
342
|
+
await bot.sendSticker(chatId, 'sticker_file_id');
|
|
135
343
|
|
|
136
|
-
|
|
344
|
+
// Send from URL
|
|
345
|
+
await bot.sendSticker(chatId, 'https://example.com/sticker.webp');
|
|
137
346
|
|
|
138
|
-
|
|
347
|
+
// Send from local file
|
|
348
|
+
await bot.sendSticker(chatId, './sticker.tgs');
|
|
139
349
|
```
|
|
140
350
|
|
|
141
|
-
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
### 3. Location & Venue
|
|
142
354
|
|
|
355
|
+
#### Send Location
|
|
143
356
|
```javascript
|
|
144
|
-
|
|
145
|
-
|
|
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
|
|
146
362
|
});
|
|
147
363
|
```
|
|
148
364
|
|
|
149
|
-
|
|
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
|
+
```
|
|
150
372
|
|
|
373
|
+
#### Send Contact
|
|
151
374
|
```javascript
|
|
152
|
-
await bot.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
await bot.sendAnimation(chatId, gifPath);
|
|
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
|
+
});
|
|
157
379
|
```
|
|
158
380
|
|
|
159
|
-
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
### 4. Polls & Quizzes
|
|
160
384
|
|
|
385
|
+
#### Create Poll
|
|
161
386
|
```javascript
|
|
162
|
-
|
|
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
|
+
});
|
|
163
402
|
```
|
|
164
403
|
|
|
165
|
-
|
|
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:
|
|
166
417
|
|
|
167
418
|
```javascript
|
|
168
|
-
|
|
419
|
+
// Typing indicator
|
|
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');
|
|
169
448
|
```
|
|
170
449
|
|
|
171
|
-
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
### 6. Message Management
|
|
172
453
|
|
|
454
|
+
#### Forward Message
|
|
173
455
|
```javascript
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
'Yellow'
|
|
179
|
-
]);
|
|
456
|
+
// Forward message from another chat
|
|
457
|
+
await bot.forwardMessage(chatId, sourceChatId, messageId, {
|
|
458
|
+
disable_notification: false
|
|
459
|
+
});
|
|
180
460
|
```
|
|
181
461
|
|
|
182
|
-
|
|
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
|
+
```
|
|
183
470
|
|
|
184
|
-
|
|
471
|
+
#### Edit Message Text
|
|
472
|
+
```javascript
|
|
473
|
+
// Edit sent message
|
|
474
|
+
await bot.editMessageText('New text', {
|
|
475
|
+
chat_id: chatId,
|
|
476
|
+
message_id: messageId,
|
|
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'
|
|
487
|
+
});
|
|
488
|
+
```
|
|
185
489
|
|
|
490
|
+
#### Edit Message Caption
|
|
186
491
|
```javascript
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
492
|
+
// Edit media caption
|
|
493
|
+
await bot.editMessageCaption({
|
|
494
|
+
chat_id: chatId,
|
|
495
|
+
message_id: messageId,
|
|
496
|
+
caption: 'New caption',
|
|
497
|
+
parse_mode: 'HTML'
|
|
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')
|
|
190
506
|
.row()
|
|
191
|
-
.url('
|
|
507
|
+
.url('Google', 'https://google.com')
|
|
192
508
|
.build();
|
|
193
509
|
|
|
194
|
-
await bot.
|
|
195
|
-
|
|
510
|
+
await bot.editMessageReplyMarkup({
|
|
511
|
+
chat_id: chatId,
|
|
512
|
+
message_id: messageId,
|
|
513
|
+
reply_markup: newKeyboard
|
|
196
514
|
});
|
|
515
|
+
```
|
|
197
516
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
517
|
+
#### Delete Message
|
|
518
|
+
```javascript
|
|
519
|
+
// Delete a message
|
|
520
|
+
await bot.deleteMessage(chatId, messageId);
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
---
|
|
524
|
+
|
|
525
|
+
### 7. Payments
|
|
526
|
+
|
|
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
|
+
});
|
|
547
|
+
```
|
|
548
|
+
|
|
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
|
+
});
|
|
202
580
|
}
|
|
203
581
|
});
|
|
204
582
|
```
|
|
205
583
|
|
|
206
|
-
|
|
584
|
+
#### Answer Pre-Checkout Query
|
|
585
|
+
```javascript
|
|
586
|
+
bot.on('pre_checkout_query', async (query, ctx) => {
|
|
587
|
+
// Validate order before payment
|
|
588
|
+
const isValid = validateOrder(query);
|
|
207
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
|
+
```
|
|
599
|
+
|
|
600
|
+
#### Handle Successful Payment
|
|
208
601
|
```javascript
|
|
209
|
-
|
|
210
|
-
.
|
|
211
|
-
.
|
|
212
|
-
.
|
|
213
|
-
.
|
|
214
|
-
.resize()
|
|
215
|
-
.oneTime()
|
|
216
|
-
.build();
|
|
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);
|
|
217
607
|
|
|
218
|
-
await
|
|
219
|
-
reply_markup: keyboard
|
|
608
|
+
await ctx.send('✅ Payment successful! Thank you for your purchase!');
|
|
220
609
|
});
|
|
221
610
|
```
|
|
222
611
|
|
|
223
|
-
|
|
612
|
+
---
|
|
613
|
+
|
|
614
|
+
### 8. Chat Management
|
|
224
615
|
|
|
616
|
+
#### Get Chat Information
|
|
225
617
|
```javascript
|
|
226
|
-
|
|
227
|
-
|
|
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);
|
|
623
|
+
|
|
624
|
+
// Get chat member count
|
|
625
|
+
const count = await bot.getChatMemberCount(chatId);
|
|
626
|
+
console.log('Members:', count);
|
|
627
|
+
|
|
628
|
+
// Get specific member info
|
|
629
|
+
const member = await bot.getChatMember(chatId, userId);
|
|
630
|
+
console.log('Member status:', member.status);
|
|
631
|
+
console.log('Member:', member.user.first_name);
|
|
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}`);
|
|
228
637
|
});
|
|
229
638
|
```
|
|
230
639
|
|
|
231
|
-
|
|
640
|
+
#### Manage Chat Settings
|
|
641
|
+
```javascript
|
|
642
|
+
// Set chat title
|
|
643
|
+
await bot.setChatTitle(chatId, 'New Group Name');
|
|
644
|
+
|
|
645
|
+
// Set chat description
|
|
646
|
+
await bot.setChatDescription(chatId, 'Group description and rules...');
|
|
647
|
+
|
|
648
|
+
// Set chat photo
|
|
649
|
+
await bot.setChatPhoto(chatId, './group_photo.jpg');
|
|
650
|
+
|
|
651
|
+
// Delete chat photo
|
|
652
|
+
await bot.deleteChatPhoto(chatId);
|
|
653
|
+
|
|
654
|
+
// Get chat member info
|
|
655
|
+
const member = await bot.getChatMember(chatId, userId);
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
---
|
|
659
|
+
|
|
660
|
+
### 9. Member Management
|
|
232
661
|
|
|
662
|
+
#### Restrict/Promote Members
|
|
233
663
|
```javascript
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
664
|
+
// Restrict member (disable all permissions)
|
|
665
|
+
await bot.restrictChatMember(chatId, userId, {
|
|
666
|
+
can_send_messages: false,
|
|
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
|
+
});
|
|
240
672
|
|
|
241
|
-
|
|
242
|
-
|
|
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
|
|
679
|
+
});
|
|
680
|
+
|
|
681
|
+
// Promote member to admin
|
|
682
|
+
await bot.promoteChatMember(chatId, userId, {
|
|
683
|
+
can_change_info: true,
|
|
684
|
+
can_delete_messages: true,
|
|
685
|
+
can_restrict_members: true,
|
|
686
|
+
can_pin_messages: true,
|
|
687
|
+
can_manage_topics: true,
|
|
688
|
+
is_anonymous: false
|
|
689
|
+
});
|
|
690
|
+
|
|
691
|
+
// Set custom admin title
|
|
692
|
+
await bot.setChatAdministratorCustomTitle(chatId, userId, 'Cool Admin');
|
|
693
|
+
```
|
|
694
|
+
|
|
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
|
|
243
701
|
});
|
|
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
|
|
715
|
+
```javascript
|
|
716
|
+
// Approve join request
|
|
717
|
+
await bot.approveChatJoinRequest(chatId, userId);
|
|
718
|
+
|
|
719
|
+
// Decline join request
|
|
720
|
+
await bot.declineChatJoinRequest(chatId, userId);
|
|
721
|
+
|
|
722
|
+
// Leave chat
|
|
723
|
+
await bot.leaveChat(chatId);
|
|
244
724
|
```
|
|
245
725
|
|
|
246
|
-
|
|
726
|
+
---
|
|
247
727
|
|
|
248
|
-
###
|
|
728
|
+
### 10. Message Pinning
|
|
249
729
|
|
|
250
730
|
```javascript
|
|
251
|
-
|
|
252
|
-
|
|
731
|
+
// Pin message (all members see it)
|
|
732
|
+
await bot.pinChatMessage(chatId, messageId, {
|
|
733
|
+
disable_notification: false // Notify members
|
|
253
734
|
});
|
|
254
735
|
|
|
255
|
-
|
|
256
|
-
|
|
736
|
+
// Unpin specific message
|
|
737
|
+
await bot.unpinChatMessage(chatId, {
|
|
738
|
+
message_id: messageId
|
|
257
739
|
});
|
|
740
|
+
|
|
741
|
+
// Unpin all messages
|
|
742
|
+
await bot.unpinAllChatMessages(chatId);
|
|
258
743
|
```
|
|
259
744
|
|
|
260
|
-
|
|
745
|
+
---
|
|
746
|
+
|
|
747
|
+
### 11. Queries & Responses
|
|
261
748
|
|
|
749
|
+
#### Callback Query
|
|
262
750
|
```javascript
|
|
263
|
-
bot.
|
|
264
|
-
|
|
751
|
+
bot.on('callback_query', async (query, ctx) => {
|
|
752
|
+
console.log('Button clicked:', query.data);
|
|
753
|
+
|
|
754
|
+
// Answer callback (shows notification or toast)
|
|
755
|
+
await ctx.answerCallbackQuery({
|
|
756
|
+
text: 'Button was clicked!',
|
|
757
|
+
show_alert: false // Toast notification
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
// Edit message
|
|
761
|
+
await ctx.editMessageText('You clicked the button!');
|
|
265
762
|
});
|
|
266
763
|
```
|
|
267
764
|
|
|
268
|
-
|
|
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
|
+
```
|
|
269
792
|
|
|
793
|
+
#### Chosen Inline Result
|
|
270
794
|
```javascript
|
|
271
|
-
bot.on('
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
const name = args.join(' ') || 'stranger';
|
|
275
|
-
await ctx.reply(`Hello, ${name}!`);
|
|
276
|
-
}
|
|
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);
|
|
277
798
|
});
|
|
278
799
|
```
|
|
279
800
|
|
|
280
|
-
|
|
801
|
+
---
|
|
281
802
|
|
|
282
|
-
###
|
|
803
|
+
### 12. File Management
|
|
283
804
|
|
|
805
|
+
#### Download File
|
|
284
806
|
```javascript
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
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);
|
|
289
811
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
812
|
+
// Download file to disk
|
|
813
|
+
const destination = './downloaded_file.jpg';
|
|
814
|
+
await bot.downloadFile('file_id', destination);
|
|
815
|
+
console.log('Downloaded to:', destination);
|
|
816
|
+
```
|
|
817
|
+
|
|
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');
|
|
825
|
+
|
|
826
|
+
// Upload from Buffer
|
|
827
|
+
const buffer = await fs.promises.readFile('./photo.jpg');
|
|
828
|
+
await bot.sendPhoto(chatId, buffer);
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
---
|
|
832
|
+
|
|
833
|
+
### 13. Keyboard Builders
|
|
834
|
+
|
|
835
|
+
#### Inline Keyboard (Buttons with Actions)
|
|
836
|
+
```javascript
|
|
837
|
+
// Create inline keyboard
|
|
838
|
+
const keyboard = TelegramBot.InlineKeyboard()
|
|
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')
|
|
843
|
+
.url('Google', 'https://google.com')
|
|
844
|
+
.row()
|
|
845
|
+
.text('Delete', 'delete_action')
|
|
846
|
+
.build();
|
|
847
|
+
|
|
848
|
+
await bot.sendMessage(chatId, 'Choose an action:', {
|
|
849
|
+
reply_markup: keyboard
|
|
295
850
|
});
|
|
296
851
|
```
|
|
297
852
|
|
|
298
|
-
|
|
853
|
+
#### Reply Keyboard (Regular Buttons)
|
|
854
|
+
```javascript
|
|
855
|
+
// Create reply keyboard
|
|
856
|
+
const keyboard = TelegramBot.ReplyKeyboard()
|
|
857
|
+
.text('Button 1')
|
|
858
|
+
.text('Button 2')
|
|
859
|
+
.row()
|
|
860
|
+
.text('Button 3')
|
|
861
|
+
.oneTime() // Disappears after use
|
|
862
|
+
.build();
|
|
299
863
|
|
|
864
|
+
await bot.sendMessage(chatId, 'Select an option:', {
|
|
865
|
+
reply_markup: keyboard
|
|
866
|
+
});
|
|
867
|
+
```
|
|
868
|
+
|
|
869
|
+
#### Remove Keyboard
|
|
300
870
|
```javascript
|
|
301
|
-
|
|
871
|
+
// Hide keyboard
|
|
872
|
+
await bot.sendMessage(chatId, 'Keyboard hidden', {
|
|
873
|
+
reply_markup: TelegramBot.RemoveKeyboard()
|
|
874
|
+
});
|
|
875
|
+
```
|
|
302
876
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
}
|
|
877
|
+
#### Force Reply
|
|
878
|
+
```javascript
|
|
879
|
+
// Force user to reply to this message
|
|
880
|
+
await bot.sendMessage(chatId, 'Please reply to this message:', {
|
|
881
|
+
reply_markup: TelegramBot.ForceReply()
|
|
309
882
|
});
|
|
310
883
|
```
|
|
311
884
|
|
|
312
|
-
|
|
885
|
+
---
|
|
886
|
+
|
|
887
|
+
### 14. Context Helpers
|
|
888
|
+
|
|
889
|
+
Context object provides convenient shortcuts:
|
|
313
890
|
|
|
314
891
|
```javascript
|
|
315
|
-
bot.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
892
|
+
bot.on('text', async (message, ctx) => {
|
|
893
|
+
// Send message to same chat
|
|
894
|
+
await ctx.send('Hello!');
|
|
895
|
+
|
|
896
|
+
// Reply to message (with reply_to_message_id)
|
|
897
|
+
await ctx.reply('Thanks for your message!');
|
|
898
|
+
|
|
899
|
+
// Send photo in reply
|
|
900
|
+
await ctx.replyWithPhoto('./photo.jpg', {
|
|
901
|
+
caption: 'Photo reply'
|
|
902
|
+
});
|
|
903
|
+
|
|
904
|
+
// Send video in reply
|
|
905
|
+
await ctx.replyWithVideo('./video.mp4', {
|
|
906
|
+
caption: 'Video reply'
|
|
907
|
+
});
|
|
908
|
+
|
|
909
|
+
// Send audio
|
|
910
|
+
await ctx.replyWithAudio('./song.mp3', {
|
|
911
|
+
title: 'Song'
|
|
912
|
+
});
|
|
913
|
+
|
|
914
|
+
// Send document
|
|
915
|
+
await ctx.replyWithDocument('./file.pdf');
|
|
916
|
+
|
|
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
|
+
}
|
|
320
925
|
});
|
|
321
926
|
```
|
|
322
927
|
|
|
323
|
-
|
|
928
|
+
---
|
|
929
|
+
|
|
930
|
+
## 🎯 Event Listeners
|
|
324
931
|
|
|
325
|
-
|
|
932
|
+
Listen to different types of updates:
|
|
326
933
|
|
|
327
934
|
```javascript
|
|
328
|
-
|
|
329
|
-
|
|
935
|
+
// === Message Events ===
|
|
936
|
+
bot.on('message', async (message, ctx) => {
|
|
937
|
+
console.log('New message:', message.text);
|
|
330
938
|
});
|
|
331
939
|
|
|
332
940
|
bot.on('text', async (message, ctx) => {
|
|
333
|
-
|
|
941
|
+
// Text messages only
|
|
334
942
|
});
|
|
335
943
|
|
|
336
944
|
bot.on('photo', async (message, ctx) => {
|
|
337
|
-
|
|
945
|
+
// Photo messages
|
|
946
|
+
console.log('Photo received');
|
|
947
|
+
});
|
|
948
|
+
|
|
949
|
+
bot.on('video', async (message, ctx) => {
|
|
950
|
+
// Video messages
|
|
951
|
+
});
|
|
952
|
+
|
|
953
|
+
bot.on('audio', async (message, ctx) => {
|
|
954
|
+
// Audio messages
|
|
338
955
|
});
|
|
339
956
|
|
|
340
957
|
bot.on('document', async (message, ctx) => {
|
|
341
|
-
|
|
958
|
+
// Document messages
|
|
342
959
|
});
|
|
343
960
|
|
|
344
|
-
bot.on('
|
|
345
|
-
|
|
961
|
+
bot.on('voice', async (message, ctx) => {
|
|
962
|
+
// Voice messages
|
|
346
963
|
});
|
|
347
964
|
|
|
348
965
|
bot.on('sticker', async (message, ctx) => {
|
|
349
|
-
|
|
966
|
+
// Sticker messages
|
|
350
967
|
});
|
|
351
968
|
|
|
352
969
|
bot.on('location', async (message, ctx) => {
|
|
353
|
-
|
|
354
|
-
await ctx.reply(`You are at: ${latitude}, ${longitude}`);
|
|
970
|
+
// Location messages
|
|
355
971
|
});
|
|
356
972
|
|
|
357
973
|
bot.on('contact', async (message, ctx) => {
|
|
358
|
-
|
|
974
|
+
// Contact messages
|
|
359
975
|
});
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
### Update Events
|
|
363
976
|
|
|
364
|
-
|
|
365
|
-
bot.on('edited_message', (message, ctx) => {
|
|
977
|
+
// === Edit Events ===
|
|
978
|
+
bot.on('edited_message', async (message, ctx) => {
|
|
366
979
|
console.log('Message edited');
|
|
367
980
|
});
|
|
368
981
|
|
|
982
|
+
bot.on('edited_channel_post', async (post, ctx) => {
|
|
983
|
+
console.log('Channel post edited');
|
|
984
|
+
});
|
|
985
|
+
|
|
986
|
+
// === Channel Events ===
|
|
987
|
+
bot.on('channel_post', async (message, ctx) => {
|
|
988
|
+
console.log('New channel post');
|
|
989
|
+
});
|
|
990
|
+
|
|
991
|
+
// === Query Events ===
|
|
369
992
|
bot.on('callback_query', async (query, ctx) => {
|
|
370
|
-
|
|
993
|
+
console.log('Button clicked:', query.data);
|
|
371
994
|
});
|
|
372
995
|
|
|
373
996
|
bot.on('inline_query', async (query, ctx) => {
|
|
374
997
|
console.log('Inline query:', query.query);
|
|
375
998
|
});
|
|
376
|
-
```
|
|
377
999
|
|
|
378
|
-
|
|
1000
|
+
bot.on('chosen_inline_result', async (result, ctx) => {
|
|
1001
|
+
console.log('Result chosen:', result.result_id);
|
|
1002
|
+
});
|
|
379
1003
|
|
|
380
|
-
|
|
381
|
-
bot.on('
|
|
382
|
-
console.
|
|
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
|
+
});
|
|
1012
|
+
|
|
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
|
+
});
|
|
1018
|
+
|
|
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
|
+
});
|
|
1023
|
+
|
|
1024
|
+
// === System Events ===
|
|
1025
|
+
bot.on('polling_start', () => {
|
|
1026
|
+
console.log('✅ Polling started');
|
|
1027
|
+
});
|
|
1028
|
+
|
|
1029
|
+
bot.on('polling_stop', () => {
|
|
1030
|
+
console.log('❌ Polling stopped');
|
|
383
1031
|
});
|
|
384
1032
|
|
|
385
1033
|
bot.on('polling_error', (error) => {
|
|
386
1034
|
console.error('Polling error:', error);
|
|
387
1035
|
});
|
|
388
1036
|
|
|
389
|
-
bot.on('
|
|
390
|
-
console.
|
|
1037
|
+
bot.on('webhook_start', (port) => {
|
|
1038
|
+
console.log(`✅ Webhook listening on port ${port}`);
|
|
1039
|
+
});
|
|
1040
|
+
|
|
1041
|
+
bot.on('webhook_stop', () => {
|
|
1042
|
+
console.log('❌ Webhook stopped');
|
|
1043
|
+
});
|
|
1044
|
+
|
|
1045
|
+
bot.on('error', (error) => {
|
|
1046
|
+
console.error('Bot error:', error);
|
|
391
1047
|
});
|
|
392
1048
|
```
|
|
393
1049
|
|
|
394
|
-
|
|
1050
|
+
---
|
|
1051
|
+
|
|
1052
|
+
## 🔌 Middleware System
|
|
395
1053
|
|
|
396
|
-
|
|
1054
|
+
Process updates with middleware chain:
|
|
397
1055
|
|
|
398
1056
|
```javascript
|
|
399
|
-
|
|
400
|
-
|
|
1057
|
+
// Simple logging middleware
|
|
1058
|
+
bot.use(async (ctx, next) => {
|
|
1059
|
+
console.log(`[${new Date().toISOString()}] User: ${ctx.from?.id}`);
|
|
1060
|
+
await next();
|
|
1061
|
+
});
|
|
1062
|
+
|
|
1063
|
+
// Rate limiting middleware
|
|
1064
|
+
const userLimits = new Map();
|
|
401
1065
|
|
|
1066
|
+
bot.use(async (ctx, next) => {
|
|
1067
|
+
const userId = ctx.from?.id;
|
|
1068
|
+
const now = Date.now();
|
|
1069
|
+
|
|
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()
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
await next();
|
|
1087
|
+
});
|
|
1088
|
+
|
|
1089
|
+
// Auth check middleware
|
|
1090
|
+
bot.use(async (ctx, next) => {
|
|
1091
|
+
const allowedUsers = [123456789, 987654321];
|
|
1092
|
+
|
|
1093
|
+
if (!allowedUsers.includes(ctx.from?.id)) {
|
|
1094
|
+
await ctx.send('You are not authorized');
|
|
1095
|
+
return;
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
await next();
|
|
1099
|
+
});
|
|
1100
|
+
|
|
1101
|
+
// Error handling middleware
|
|
1102
|
+
bot.use(async (ctx, next) => {
|
|
402
1103
|
try {
|
|
403
|
-
await
|
|
404
|
-
await ctx.reply('File downloaded successfully!');
|
|
1104
|
+
await next();
|
|
405
1105
|
} catch (error) {
|
|
406
|
-
|
|
1106
|
+
console.error('Error:', error);
|
|
1107
|
+
await ctx.send('An error occurred. Please try again.');
|
|
407
1108
|
}
|
|
408
1109
|
});
|
|
1110
|
+
|
|
1111
|
+
// Command prefix middleware
|
|
1112
|
+
bot.use(async (ctx, next) => {
|
|
1113
|
+
if (ctx.message?.text?.startsWith('!')) {
|
|
1114
|
+
ctx.isCommand = true;
|
|
1115
|
+
}
|
|
1116
|
+
await next();
|
|
1117
|
+
});
|
|
409
1118
|
```
|
|
410
1119
|
|
|
411
|
-
|
|
1120
|
+
---
|
|
1121
|
+
|
|
1122
|
+
## 🎨 Advanced Examples
|
|
412
1123
|
|
|
1124
|
+
### Example 1: Echo Bot
|
|
413
1125
|
```javascript
|
|
414
|
-
const
|
|
415
|
-
|
|
416
|
-
|
|
1126
|
+
const TelegramBot = require('teh-bot');
|
|
1127
|
+
|
|
1128
|
+
const bot = new TelegramBot(process.env.BOT_TOKEN, { polling: true });
|
|
1129
|
+
|
|
1130
|
+
bot.command('/start', async (ctx) => {
|
|
1131
|
+
await ctx.send('Send me anything and I will echo it back!');
|
|
1132
|
+
});
|
|
1133
|
+
|
|
1134
|
+
bot.on('text', async (message, ctx) => {
|
|
1135
|
+
await ctx.reply(message.text);
|
|
1136
|
+
});
|
|
1137
|
+
```
|
|
1138
|
+
|
|
1139
|
+
### Example 2: Calculator Bot
|
|
1140
|
+
```javascript
|
|
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();
|
|
1148
|
+
|
|
1149
|
+
await ctx.send('Choose operation:', { reply_markup: keyboard });
|
|
1150
|
+
});
|
|
1151
|
+
|
|
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
|
+
});
|
|
417
1164
|
```
|
|
418
1165
|
|
|
419
|
-
|
|
1166
|
+
### Example 3: File Management Bot
|
|
1167
|
+
```javascript
|
|
1168
|
+
bot.command('/upload', async (ctx) => {
|
|
1169
|
+
await ctx.send('Send me a file to download');
|
|
1170
|
+
});
|
|
1171
|
+
|
|
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!');
|
|
1179
|
+
});
|
|
1180
|
+
```
|
|
420
1181
|
|
|
421
|
-
###
|
|
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
|
+
);
|
|
1194
|
+
});
|
|
1195
|
+
```
|
|
422
1196
|
|
|
1197
|
+
### Example 5: Admin Commands
|
|
423
1198
|
```javascript
|
|
424
|
-
bot.command('
|
|
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
|
+
|
|
425
1207
|
try {
|
|
426
|
-
await ctx.
|
|
1208
|
+
await bot.banChatMember(ctx.chat.id, userId, {
|
|
1209
|
+
revoke_messages: true
|
|
1210
|
+
});
|
|
1211
|
+
|
|
1212
|
+
await ctx.send('✅ User banned!');
|
|
427
1213
|
} catch (error) {
|
|
428
|
-
|
|
1214
|
+
await ctx.send('❌ Could not ban user: ' + error.message);
|
|
429
1215
|
}
|
|
430
1216
|
});
|
|
431
|
-
```
|
|
432
1217
|
|
|
433
|
-
|
|
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
|
+
}
|
|
434
1223
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
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);
|
|
443
1237
|
}
|
|
444
1238
|
});
|
|
445
1239
|
```
|
|
446
1240
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
- `sendMessage(
|
|
453
|
-
- `sendPhoto(
|
|
454
|
-
- `
|
|
455
|
-
- `
|
|
456
|
-
- `
|
|
457
|
-
- `sendAnimation(
|
|
458
|
-
- `sendVoice(
|
|
459
|
-
- `sendVideoNote(
|
|
460
|
-
- `sendSticker(
|
|
461
|
-
- `sendLocation(
|
|
462
|
-
- `sendVenue(
|
|
463
|
-
- `sendContact(
|
|
464
|
-
- `sendPoll(
|
|
465
|
-
- `sendDice(
|
|
466
|
-
- `sendChatAction(
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
- `
|
|
470
|
-
- `
|
|
471
|
-
- `
|
|
472
|
-
- `
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
- `
|
|
480
|
-
- `
|
|
481
|
-
- `
|
|
482
|
-
- `
|
|
483
|
-
- `
|
|
484
|
-
- `
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
- `
|
|
488
|
-
- `
|
|
489
|
-
- `
|
|
490
|
-
- `
|
|
491
|
-
- `
|
|
492
|
-
- `
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
- `
|
|
497
|
-
|
|
498
|
-
|
|
1241
|
+
---
|
|
1242
|
+
|
|
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
|
|
499
1313
|
- `getMe()` - Get bot info
|
|
500
|
-
- `
|
|
501
|
-
- `
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
answerCallbackQuery, // Answer callback query
|
|
522
|
-
deleteMessage // Delete message
|
|
523
|
-
}
|
|
1314
|
+
- `getUpdates()` - Get updates (polling)
|
|
1315
|
+
- `startPolling()` - Start long polling
|
|
1316
|
+
- `stopPolling()` - Stop polling
|
|
1317
|
+
- `startWebhook()` - Start webhook server
|
|
1318
|
+
- `stopWebhook()` - Stop webhook server
|
|
1319
|
+
|
|
1320
|
+
---
|
|
1321
|
+
|
|
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
|
+
}
|
|
1334
|
+
});
|
|
524
1335
|
```
|
|
525
1336
|
|
|
526
|
-
|
|
1337
|
+
### 2. Rate Limiting
|
|
1338
|
+
```javascript
|
|
1339
|
+
const rateLimits = new Map();
|
|
527
1340
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
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 });
|
|
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();
|
|
1361
|
+
});
|
|
1362
|
+
```
|
|
533
1363
|
|
|
534
|
-
|
|
1364
|
+
### 3. Command Parsing
|
|
1365
|
+
```javascript
|
|
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
|
+
}
|
|
1374
|
+
});
|
|
1375
|
+
```
|
|
1376
|
+
|
|
1377
|
+
### 4. Session Management
|
|
1378
|
+
```javascript
|
|
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
|
+
}
|
|
535
1391
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
1392
|
+
bot.on('text', async (message, ctx) => {
|
|
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}!`);
|
|
1399
|
+
}
|
|
1400
|
+
});
|
|
1401
|
+
```
|
|
541
1402
|
|
|
1403
|
+
### 5. Async File Operations
|
|
542
1404
|
```javascript
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
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
|
+
}
|
|
547
1418
|
});
|
|
548
1419
|
```
|
|
549
1420
|
|
|
550
|
-
|
|
1421
|
+
---
|
|
1422
|
+
|
|
1423
|
+
## 🐛 Troubleshooting
|
|
1424
|
+
|
|
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
|
|
1430
|
+
|
|
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
|
|
1435
|
+
|
|
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
|
|
1441
|
+
|
|
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
|
|
1446
|
+
|
|
1447
|
+
---
|
|
1448
|
+
|
|
1449
|
+
## 📝 License
|
|
1450
|
+
|
|
1451
|
+
MIT License - See LICENSE file for details
|
|
1452
|
+
|
|
1453
|
+
## 🤝 Contributing
|
|
551
1454
|
|
|
552
|
-
|
|
1455
|
+
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
|
|
553
1456
|
|
|
554
|
-
##
|
|
1457
|
+
## 📞 Support
|
|
555
1458
|
|
|
556
|
-
|
|
1459
|
+
- Report issues on GitHub
|
|
1460
|
+
- Check examples/ folder for code samples
|
|
1461
|
+
- Read full docs at api.telegram.org/bots/api
|
|
557
1462
|
|
|
558
|
-
|
|
1463
|
+
---
|
|
559
1464
|
|
|
560
|
-
|
|
1465
|
+
**Made with ❤️ by KazeDevID**
|