teh-bot 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +560 -0
- package/index.d.ts +566 -0
- package/index.js +962 -0
- package/package.json +36 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Teh Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
# teh-bot - Lightweight Telegram Bot API
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/teh-bot)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
A lightweight, high-performance Telegram Bot API module with **zero dependencies**. Built for speed, stability, and simplicity.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **Zero Dependencies** - Only native Node.js modules
|
|
11
|
+
- **High Performance** - Optimized HTTP requests with connection pooling
|
|
12
|
+
- **Full API Coverage** - Complete Telegram Bot API implementation
|
|
13
|
+
- **Event-Driven** - Built on Node.js EventEmitter
|
|
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
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install teh-bot
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Quick Start
|
|
28
|
+
|
|
29
|
+
```javascript
|
|
30
|
+
const TelegramBot = require('teh-bot');
|
|
31
|
+
|
|
32
|
+
const bot = new TelegramBot('YOUR_BOT_TOKEN', {
|
|
33
|
+
polling: true
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
bot.command('start', async (ctx) => {
|
|
37
|
+
await ctx.reply('Hello! Welcome to my bot!');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
bot.on('text', async (message, ctx) => {
|
|
41
|
+
await ctx.reply(`You said: ${message.text}`);
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Table of Contents
|
|
46
|
+
|
|
47
|
+
- [Basic Usage](#basic-usage)
|
|
48
|
+
- [Polling vs Webhooks](#polling-vs-webhooks)
|
|
49
|
+
- [Sending Messages](#sending-messages)
|
|
50
|
+
- [Keyboards](#keyboards)
|
|
51
|
+
- [Commands](#commands)
|
|
52
|
+
- [Middleware](#middleware)
|
|
53
|
+
- [Events](#events)
|
|
54
|
+
- [File Handling](#file-handling)
|
|
55
|
+
- [Error Handling](#error-handling)
|
|
56
|
+
- [API Reference](#api-reference)
|
|
57
|
+
|
|
58
|
+
## Basic Usage
|
|
59
|
+
|
|
60
|
+
### Initializing the Bot
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
const TelegramBot = require('teh-bot');
|
|
64
|
+
|
|
65
|
+
const bot = new TelegramBot('YOUR_BOT_TOKEN', {
|
|
66
|
+
polling: true,
|
|
67
|
+
pollingInterval: 1000,
|
|
68
|
+
pollingTimeout: 30
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Options
|
|
73
|
+
|
|
74
|
+
- `polling` (boolean) - Enable long polling (default: false)
|
|
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
|
|
82
|
+
|
|
83
|
+
## Polling vs Webhooks
|
|
84
|
+
|
|
85
|
+
### Polling Mode
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
const bot = new TelegramBot(token, { polling: true });
|
|
89
|
+
|
|
90
|
+
bot.startPolling();
|
|
91
|
+
|
|
92
|
+
bot.on('polling_error', (error) => {
|
|
93
|
+
console.error('Polling error:', error);
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Webhook Mode
|
|
98
|
+
|
|
99
|
+
```javascript
|
|
100
|
+
const bot = new TelegramBot(token, {
|
|
101
|
+
webhook: true,
|
|
102
|
+
webhookPort: 8443,
|
|
103
|
+
webhookPath: '/bot-webhook'
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
await bot.setWebhook('https://yourdomain.com/bot-webhook');
|
|
107
|
+
|
|
108
|
+
bot.on('webhook_start', (port) => {
|
|
109
|
+
console.log(`Webhook server started on port ${port}`);
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Sending Messages
|
|
114
|
+
|
|
115
|
+
### Text Messages
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
await bot.sendMessage(chatId, 'Hello World!');
|
|
119
|
+
|
|
120
|
+
await bot.sendMessage(chatId, '*Bold* and _italic_ text', {
|
|
121
|
+
parse_mode: 'Markdown'
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
await bot.sendMessage(chatId, '<b>Bold</b> and <i>italic</i> text', {
|
|
125
|
+
parse_mode: 'HTML'
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Photos
|
|
130
|
+
|
|
131
|
+
```javascript
|
|
132
|
+
await bot.sendPhoto(chatId, 'https://example.com/image.jpg');
|
|
133
|
+
|
|
134
|
+
await bot.sendPhoto(chatId, '/path/to/local/image.jpg');
|
|
135
|
+
|
|
136
|
+
await bot.sendPhoto(chatId, 'file_id_from_telegram');
|
|
137
|
+
|
|
138
|
+
await bot.sendPhoto(chatId, photoBuffer);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Documents
|
|
142
|
+
|
|
143
|
+
```javascript
|
|
144
|
+
await bot.sendDocument(chatId, '/path/to/document.pdf', {
|
|
145
|
+
caption: 'Here is your document'
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Other Media Types
|
|
150
|
+
|
|
151
|
+
```javascript
|
|
152
|
+
await bot.sendVideo(chatId, videoPath);
|
|
153
|
+
await bot.sendAudio(chatId, audioPath);
|
|
154
|
+
await bot.sendVoice(chatId, voicePath);
|
|
155
|
+
await bot.sendSticker(chatId, stickerId);
|
|
156
|
+
await bot.sendAnimation(chatId, gifPath);
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Location
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
162
|
+
await bot.sendLocation(chatId, latitude, longitude);
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Contact
|
|
166
|
+
|
|
167
|
+
```javascript
|
|
168
|
+
await bot.sendContact(chatId, '+1234567890', 'John Doe');
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Poll
|
|
172
|
+
|
|
173
|
+
```javascript
|
|
174
|
+
await bot.sendPoll(chatId, 'What is your favorite color?', [
|
|
175
|
+
'Red',
|
|
176
|
+
'Blue',
|
|
177
|
+
'Green',
|
|
178
|
+
'Yellow'
|
|
179
|
+
]);
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Keyboards
|
|
183
|
+
|
|
184
|
+
### Inline Keyboards
|
|
185
|
+
|
|
186
|
+
```javascript
|
|
187
|
+
const keyboard = TelegramBot.InlineKeyboard()
|
|
188
|
+
.text('Button 1', 'callback_data_1')
|
|
189
|
+
.text('Button 2', 'callback_data_2')
|
|
190
|
+
.row()
|
|
191
|
+
.url('Visit Website', 'https://example.com')
|
|
192
|
+
.build();
|
|
193
|
+
|
|
194
|
+
await bot.sendMessage(chatId, 'Choose an option:', {
|
|
195
|
+
reply_markup: keyboard
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
bot.on('callback_query', async (query, ctx) => {
|
|
199
|
+
if (query.data === 'callback_data_1') {
|
|
200
|
+
await ctx.answerCallbackQuery({ text: 'You clicked Button 1!' });
|
|
201
|
+
await ctx.editMessageText('You selected Button 1');
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Reply Keyboards
|
|
207
|
+
|
|
208
|
+
```javascript
|
|
209
|
+
const keyboard = TelegramBot.ReplyKeyboard()
|
|
210
|
+
.text('Option 1')
|
|
211
|
+
.text('Option 2')
|
|
212
|
+
.row()
|
|
213
|
+
.text('Option 3')
|
|
214
|
+
.resize()
|
|
215
|
+
.oneTime()
|
|
216
|
+
.build();
|
|
217
|
+
|
|
218
|
+
await bot.sendMessage(chatId, 'Select an option:', {
|
|
219
|
+
reply_markup: keyboard
|
|
220
|
+
});
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Remove Keyboard
|
|
224
|
+
|
|
225
|
+
```javascript
|
|
226
|
+
await bot.sendMessage(chatId, 'Keyboard removed', {
|
|
227
|
+
reply_markup: TelegramBot.RemoveKeyboard()
|
|
228
|
+
});
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Request Contact/Location
|
|
232
|
+
|
|
233
|
+
```javascript
|
|
234
|
+
const keyboard = TelegramBot.ReplyKeyboard()
|
|
235
|
+
.requestContact('Share Contact')
|
|
236
|
+
.row()
|
|
237
|
+
.requestLocation('Share Location')
|
|
238
|
+
.resize()
|
|
239
|
+
.build();
|
|
240
|
+
|
|
241
|
+
await bot.sendMessage(chatId, 'Please share your info:', {
|
|
242
|
+
reply_markup: keyboard
|
|
243
|
+
});
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Commands
|
|
247
|
+
|
|
248
|
+
### Basic Commands
|
|
249
|
+
|
|
250
|
+
```javascript
|
|
251
|
+
bot.command('start', async (ctx) => {
|
|
252
|
+
await ctx.reply('Welcome! Use /help to see available commands.');
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
bot.command('help', async (ctx) => {
|
|
256
|
+
await ctx.reply('Available commands:\n/start - Start the bot\n/help - Show this message');
|
|
257
|
+
});
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Multiple Command Aliases
|
|
261
|
+
|
|
262
|
+
```javascript
|
|
263
|
+
bot.command(['info', 'about'], async (ctx) => {
|
|
264
|
+
await ctx.reply('Bot information...');
|
|
265
|
+
});
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Command with Arguments
|
|
269
|
+
|
|
270
|
+
```javascript
|
|
271
|
+
bot.on('text', async (message, ctx) => {
|
|
272
|
+
if (message.text.startsWith('/greet')) {
|
|
273
|
+
const args = message.text.split(' ').slice(1);
|
|
274
|
+
const name = args.join(' ') || 'stranger';
|
|
275
|
+
await ctx.reply(`Hello, ${name}!`);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Middleware
|
|
281
|
+
|
|
282
|
+
### Basic Middleware
|
|
283
|
+
|
|
284
|
+
```javascript
|
|
285
|
+
bot.use(async (ctx, next) => {
|
|
286
|
+
console.log('Received update:', ctx.update.update_id);
|
|
287
|
+
await next();
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
bot.use(async (ctx, next) => {
|
|
291
|
+
ctx.startTime = Date.now();
|
|
292
|
+
await next();
|
|
293
|
+
const duration = Date.now() - ctx.startTime;
|
|
294
|
+
console.log(`Request took ${duration}ms`);
|
|
295
|
+
});
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Authentication Middleware
|
|
299
|
+
|
|
300
|
+
```javascript
|
|
301
|
+
const AUTHORIZED_USERS = [123456789, 987654321];
|
|
302
|
+
|
|
303
|
+
bot.use(async (ctx, next) => {
|
|
304
|
+
if (ctx.from && AUTHORIZED_USERS.includes(ctx.from.id)) {
|
|
305
|
+
await next();
|
|
306
|
+
} else {
|
|
307
|
+
await ctx.reply('You are not authorized to use this bot.');
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Logging Middleware
|
|
313
|
+
|
|
314
|
+
```javascript
|
|
315
|
+
bot.use(async (ctx, next) => {
|
|
316
|
+
const user = ctx.from?.username || ctx.from?.id || 'unknown';
|
|
317
|
+
const message = ctx.message?.text || 'no text';
|
|
318
|
+
console.log(`[${new Date().toISOString()}] ${user}: ${message}`);
|
|
319
|
+
await next();
|
|
320
|
+
});
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
## Events
|
|
324
|
+
|
|
325
|
+
### Message Events
|
|
326
|
+
|
|
327
|
+
```javascript
|
|
328
|
+
bot.on('message', (message, ctx) => {
|
|
329
|
+
console.log('New message:', message);
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
bot.on('text', async (message, ctx) => {
|
|
333
|
+
console.log('Text message:', message.text);
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
bot.on('photo', async (message, ctx) => {
|
|
337
|
+
console.log('Photo received:', message.photo);
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
bot.on('document', async (message, ctx) => {
|
|
341
|
+
console.log('Document received:', message.document);
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
bot.on('video', async (message, ctx) => {
|
|
345
|
+
console.log('Video received:', message.video);
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
bot.on('sticker', async (message, ctx) => {
|
|
349
|
+
await ctx.reply('Nice sticker!');
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
bot.on('location', async (message, ctx) => {
|
|
353
|
+
const { latitude, longitude } = message.location;
|
|
354
|
+
await ctx.reply(`You are at: ${latitude}, ${longitude}`);
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
bot.on('contact', async (message, ctx) => {
|
|
358
|
+
await ctx.reply(`Contact received: ${message.contact.first_name}`);
|
|
359
|
+
});
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### Update Events
|
|
363
|
+
|
|
364
|
+
```javascript
|
|
365
|
+
bot.on('edited_message', (message, ctx) => {
|
|
366
|
+
console.log('Message edited');
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
bot.on('callback_query', async (query, ctx) => {
|
|
370
|
+
await ctx.answerCallbackQuery();
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
bot.on('inline_query', async (query, ctx) => {
|
|
374
|
+
console.log('Inline query:', query.query);
|
|
375
|
+
});
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### Error Events
|
|
379
|
+
|
|
380
|
+
```javascript
|
|
381
|
+
bot.on('error', (error) => {
|
|
382
|
+
console.error('Bot error:', error);
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
bot.on('polling_error', (error) => {
|
|
386
|
+
console.error('Polling error:', error);
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
bot.on('webhook_error', (error) => {
|
|
390
|
+
console.error('Webhook error:', error);
|
|
391
|
+
});
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
## File Handling
|
|
395
|
+
|
|
396
|
+
### Download Files
|
|
397
|
+
|
|
398
|
+
```javascript
|
|
399
|
+
bot.on('document', async (message, ctx) => {
|
|
400
|
+
const fileId = message.document.file_id;
|
|
401
|
+
|
|
402
|
+
try {
|
|
403
|
+
await bot.downloadFile(fileId, './downloads/document.pdf');
|
|
404
|
+
await ctx.reply('File downloaded successfully!');
|
|
405
|
+
} catch (error) {
|
|
406
|
+
await ctx.reply('Failed to download file.');
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### Get File Info
|
|
412
|
+
|
|
413
|
+
```javascript
|
|
414
|
+
const file = await bot.getFile(fileId);
|
|
415
|
+
console.log('File path:', file.file_path);
|
|
416
|
+
console.log('File size:', file.file_size);
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
## Error Handling
|
|
420
|
+
|
|
421
|
+
### Try-Catch Pattern
|
|
422
|
+
|
|
423
|
+
```javascript
|
|
424
|
+
bot.command('start', async (ctx) => {
|
|
425
|
+
try {
|
|
426
|
+
await ctx.reply('Welcome!');
|
|
427
|
+
} catch (error) {
|
|
428
|
+
console.error('Failed to send message:', error);
|
|
429
|
+
}
|
|
430
|
+
});
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### Global Error Handler
|
|
434
|
+
|
|
435
|
+
```javascript
|
|
436
|
+
bot.on('error', (error) => {
|
|
437
|
+
if (error.code === 403) {
|
|
438
|
+
console.error('Bot was blocked by user');
|
|
439
|
+
} else if (error.code === 429) {
|
|
440
|
+
console.error('Rate limit exceeded');
|
|
441
|
+
} else {
|
|
442
|
+
console.error('Unexpected error:', error);
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
## API Reference
|
|
448
|
+
|
|
449
|
+
### Bot Methods
|
|
450
|
+
|
|
451
|
+
#### Message Methods
|
|
452
|
+
- `sendMessage(chatId, text, options)` - Send text message
|
|
453
|
+
- `sendPhoto(chatId, photo, options)` - Send photo
|
|
454
|
+
- `sendAudio(chatId, audio, options)` - Send audio
|
|
455
|
+
- `sendDocument(chatId, document, options)` - Send document
|
|
456
|
+
- `sendVideo(chatId, video, options)` - Send video
|
|
457
|
+
- `sendAnimation(chatId, animation, options)` - Send animation/GIF
|
|
458
|
+
- `sendVoice(chatId, voice, options)` - Send voice message
|
|
459
|
+
- `sendVideoNote(chatId, videoNote, options)` - Send video note
|
|
460
|
+
- `sendSticker(chatId, sticker, options)` - Send sticker
|
|
461
|
+
- `sendLocation(chatId, latitude, longitude, options)` - Send location
|
|
462
|
+
- `sendVenue(chatId, latitude, longitude, title, address, options)` - Send venue
|
|
463
|
+
- `sendContact(chatId, phoneNumber, firstName, options)` - Send contact
|
|
464
|
+
- `sendPoll(chatId, question, options, params)` - Send poll
|
|
465
|
+
- `sendDice(chatId, options)` - Send dice
|
|
466
|
+
- `sendChatAction(chatId, action)` - Send chat action
|
|
467
|
+
|
|
468
|
+
#### Edit Methods
|
|
469
|
+
- `editMessageText(text, options)` - Edit message text
|
|
470
|
+
- `editMessageCaption(options)` - Edit message caption
|
|
471
|
+
- `editMessageReplyMarkup(options)` - Edit reply markup
|
|
472
|
+
- `deleteMessage(chatId, messageId)` - Delete message
|
|
473
|
+
|
|
474
|
+
#### Forward Methods
|
|
475
|
+
- `forwardMessage(chatId, fromChatId, messageId, options)` - Forward message
|
|
476
|
+
- `copyMessage(chatId, fromChatId, messageId, options)` - Copy message
|
|
477
|
+
|
|
478
|
+
#### Chat Methods
|
|
479
|
+
- `getChat(chatId)` - Get chat info
|
|
480
|
+
- `getChatAdministrators(chatId)` - Get chat administrators
|
|
481
|
+
- `getChatMemberCount(chatId)` - Get member count
|
|
482
|
+
- `getChatMember(chatId, userId)` - Get chat member
|
|
483
|
+
- `setChatTitle(chatId, title)` - Set chat title
|
|
484
|
+
- `setChatDescription(chatId, description)` - Set chat description
|
|
485
|
+
- `pinChatMessage(chatId, messageId, options)` - Pin message
|
|
486
|
+
- `unpinChatMessage(chatId, options)` - Unpin message
|
|
487
|
+
- `unpinAllChatMessages(chatId)` - Unpin all messages
|
|
488
|
+
- `leaveChat(chatId)` - Leave chat
|
|
489
|
+
- `banChatMember(chatId, userId, options)` - Ban member
|
|
490
|
+
- `unbanChatMember(chatId, userId, options)` - Unban member
|
|
491
|
+
- `restrictChatMember(chatId, userId, permissions, options)` - Restrict member
|
|
492
|
+
- `promoteChatMember(chatId, userId, options)` - Promote member
|
|
493
|
+
|
|
494
|
+
#### File Methods
|
|
495
|
+
- `getFile(fileId)` - Get file info
|
|
496
|
+
- `downloadFile(fileId, destination)` - Download file
|
|
497
|
+
|
|
498
|
+
#### Other Methods
|
|
499
|
+
- `getMe()` - Get bot info
|
|
500
|
+
- `answerCallbackQuery(callbackQueryId, options)` - Answer callback query
|
|
501
|
+
- `answerInlineQuery(inlineQueryId, results, options)` - Answer inline query
|
|
502
|
+
|
|
503
|
+
### Context Object
|
|
504
|
+
|
|
505
|
+
The context object (`ctx`) is passed to command handlers and middleware:
|
|
506
|
+
|
|
507
|
+
```javascript
|
|
508
|
+
{
|
|
509
|
+
update, // Original update object
|
|
510
|
+
bot, // Bot instance
|
|
511
|
+
message, // Message object (if available)
|
|
512
|
+
callbackQuery, // Callback query (if available)
|
|
513
|
+
inlineQuery, // Inline query (if available)
|
|
514
|
+
chat, // Chat object
|
|
515
|
+
from, // User object
|
|
516
|
+
chatId, // Chat ID
|
|
517
|
+
reply, // Reply to current chat
|
|
518
|
+
replyWithPhoto, // Reply with photo
|
|
519
|
+
replyWithDocument, // Reply with document
|
|
520
|
+
editMessageText, // Edit message text
|
|
521
|
+
answerCallbackQuery, // Answer callback query
|
|
522
|
+
deleteMessage // Delete message
|
|
523
|
+
}
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
## Performance Tips
|
|
527
|
+
|
|
528
|
+
1. **Use Rate Limiting**: The bot automatically handles rate limits with smart retry logic
|
|
529
|
+
2. **Batch Requests**: When possible, batch multiple operations
|
|
530
|
+
3. **Use Webhooks in Production**: Webhooks are more efficient than polling for production bots
|
|
531
|
+
4. **Enable Compression**: Use reverse proxy (nginx) with gzip for webhook endpoints
|
|
532
|
+
5. **Connection Pooling**: The module uses optimized HTTP connection handling
|
|
533
|
+
|
|
534
|
+
## Best Practices
|
|
535
|
+
|
|
536
|
+
1. **Always Handle Errors**: Use try-catch blocks and error event listeners
|
|
537
|
+
2. **Validate User Input**: Always validate and sanitize user input
|
|
538
|
+
3. **Use Middleware for Common Tasks**: Authentication, logging, etc.
|
|
539
|
+
4. **Set Request Timeouts**: Adjust timeouts based on your needs
|
|
540
|
+
5. **Implement Graceful Shutdown**: Clean up resources on exit
|
|
541
|
+
|
|
542
|
+
```javascript
|
|
543
|
+
process.on('SIGINT', () => {
|
|
544
|
+
bot.stopPolling();
|
|
545
|
+
console.log('Bot stopped gracefully');
|
|
546
|
+
process.exit(0);
|
|
547
|
+
});
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
## License
|
|
551
|
+
|
|
552
|
+
MIT
|
|
553
|
+
|
|
554
|
+
## Contributing
|
|
555
|
+
|
|
556
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
557
|
+
|
|
558
|
+
## Support
|
|
559
|
+
|
|
560
|
+
For issues and questions, please use the [GitHub Issues](https://github.com/kazedevid/teh/issues) page.
|