teh-bot 1.0.3 → 1.0.5

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 CHANGED
@@ -1,560 +1,782 @@
1
- # teh-bot - Lightweight Telegram Bot API
2
-
3
- [![npm version](https://img.shields.io/npm/v/teh.svg)](https://www.npmjs.com/package/teh-bot)
4
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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
1
+ # 🤖 Teh Bot - Lightweight Telegram Bot API Library
2
+
3
+ ![Version](https://img.shields.io/badge/version-1.0.5-blue)
4
+ ![License](https://img.shields.io/badge/license-MIT-green)
5
+ ![Node.js](https://img.shields.io/badge/node-%3E%3D14.0.0-brightgreen)
6
+ ![npm](https://img.shields.io/badge/npm-teh--bot-red)
7
+
8
+ A lightweight, high-performance, **zero-dependency** Telegram Bot API library for Node.js. Built with modern JavaScript standards supporting both **CommonJS** and **ES Modules (ESM)**, with full **TypeScript** support.
9
+
10
+ ## Features
11
+
12
+ - **Zero Dependencies** - No external packages required
13
+ - **Dual Module Support** - Works with CommonJS (.cjs), ES Modules (.mjs), and TypeScript (.ts)
14
+ - **Type-Safe** - Full TypeScript definitions included
15
+ - **Lightweight** - Ultra-minimal footprint (~50KB)
16
+ - **High-Performance** - Optimized for speed and efficiency
17
+ - **Polling & Webhook** - Support for both update methods
18
+ - **Event-Driven** - Chainable API with EventEmitter
19
+ - **Middleware Support** - Extensible middleware system
20
+ - ✅ **File Handling** - Easy file upload/download
21
+ - ✅ **Media Support** - Photos, videos, audio, documents, stickers, animations, voice messages
22
+ - ✅ **Keyboard Builders** - Fluent API for inline and reply keyboards
23
+ - ✅ **Full Telegram Bot API Support** - All official API methods implemented
24
+ - ✅ **Chat Management** - Ban, restrict, promote members with ease
25
+ - ✅ **Query Handling** - Inline queries, callback queries, poll answers
26
+ - ✅ **Context Helpers** - Simple reply(), send(), and media methods
27
+ - ✅ **Error Handling** - Comprehensive error information
28
+
29
+ ## 📦 Installation
30
+
31
+ ### Using npm
32
+ ```bash
33
+ npm install teh-bot
34
+ ```
20
35
 
21
- ## Installation
36
+ ### Using yarn
37
+ ```bash
38
+ yarn add teh-bot
39
+ ```
22
40
 
41
+ ### Using pnpm
23
42
  ```bash
24
- npm install teh-bot
43
+ pnpm add teh-bot
25
44
  ```
26
45
 
27
- ## Quick Start
46
+ ## 🚀 Quick Start
28
47
 
48
+ ### CommonJS (.js)
29
49
  ```javascript
30
50
  const TelegramBot = require('teh-bot');
31
51
 
32
- const bot = new TelegramBot('YOUR_BOT_TOKEN', {
33
- polling: true
52
+ const bot = new TelegramBot(process.env.TELEGRAM_BOT_TOKEN, {
53
+ polling: true,
34
54
  });
35
55
 
36
- bot.command('start', async (ctx) => {
37
- await ctx.reply('Hello! Welcome to my bot!');
56
+ bot.command('/start', async (ctx) => {
57
+ await ctx.send('👋 Hello! I am Teh Bot!');
38
58
  });
39
59
 
40
60
  bot.on('text', async (message, ctx) => {
41
- await ctx.reply(`You said: ${message.text}`);
61
+ console.log('Message:', message.text);
42
62
  });
43
- ```
44
-
45
- ## Table of Contents
46
63
 
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
64
+ bot.on('polling_start', () => {
65
+ console.log('✅ Bot started polling');
66
+ });
67
+ ```
61
68
 
69
+ ### ES Modules (.mjs)
62
70
  ```javascript
63
- const TelegramBot = require('teh-bot');
71
+ import TelegramBot from 'teh-bot';
64
72
 
65
- const bot = new TelegramBot('YOUR_BOT_TOKEN', {
73
+ const bot = new TelegramBot(process.env.TELEGRAM_BOT_TOKEN, {
66
74
  polling: true,
67
- pollingInterval: 1000,
68
- pollingTimeout: 30
69
75
  });
70
- ```
71
76
 
72
- ### Options
77
+ bot.command('/start', async (ctx) => {
78
+ await ctx.send('👋 Hello! I am Teh Bot!');
79
+ });
73
80
 
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
81
+ bot.on('text', async (message, ctx) => {
82
+ console.log('Message:', message.text);
83
+ });
82
84
 
83
- ## Polling vs Webhooks
85
+ bot.on('polling_start', () => {
86
+ console.log('✅ Bot started polling');
87
+ });
88
+ ```
84
89
 
85
- ### Polling Mode
90
+ ### TypeScript (.ts)
91
+ ```typescript
92
+ import TelegramBot, { Context } from 'teh-bot';
86
93
 
87
- ```javascript
88
- const bot = new TelegramBot(token, { polling: true });
94
+ const bot = new TelegramBot(process.env.TELEGRAM_BOT_TOKEN || '', {
95
+ polling: true,
96
+ });
89
97
 
90
- bot.startPolling();
98
+ bot.command('/start', async (ctx: Context) => {
99
+ await ctx.send('👋 Hello! I am Teh Bot!');
100
+ });
91
101
 
92
- bot.on('polling_error', (error) => {
93
- console.error('Polling error:', error);
102
+ bot.on('text', async (message, ctx: Context) => {
103
+ console.log('Message:', message.text);
104
+ });
105
+
106
+ bot.on('polling_start', () => {
107
+ console.log('✅ Bot started polling');
94
108
  });
95
109
  ```
96
110
 
97
- ### Webhook Mode
111
+ ## ⚙️ Configuration
98
112
 
113
+ ### BotOptions
99
114
  ```javascript
100
115
  const bot = new TelegramBot(token, {
101
- webhook: true,
102
- webhookPort: 8443,
103
- webhookPath: '/bot-webhook'
116
+ // Polling
117
+ polling: true, // Enable polling (default: false)
118
+ pollingInterval: 1000, // Polling interval in ms (default: 1000)
119
+ pollingTimeout: 30, // Long polling timeout (default: 30)
120
+
121
+ // Webhook
122
+ webhook: false, // Enable webhook (default: false)
123
+ webhookPort: 3000, // Webhook server port (default: 3000)
124
+ webhookPath: '/webhook', // Webhook path (default: '/webhook')
125
+
126
+ // General
127
+ requestTimeout: 30000, // Request timeout in ms (default: 30000)
128
+ maxConnections: 40, // Max concurrent connections (default: 40)
129
+ allowedUpdates: [], // Array of allowed update types (default: [])
130
+ baseApiUrl: 'https://api.telegram.org', // Custom API URL (default)
104
131
  });
132
+ ```
105
133
 
106
- await bot.setWebhook('https://yourdomain.com/bot-webhook');
134
+ ## 📚 API Reference
107
135
 
108
- bot.on('webhook_start', (port) => {
109
- console.log(`Webhook server started on port ${port}`);
136
+ ### Core Methods
137
+
138
+ #### Sending Messages
139
+
140
+ ```javascript
141
+ // Send text message
142
+ await bot.sendMessage(chatId, 'Hello!');
143
+
144
+ // Send text with options
145
+ await bot.sendMessage(chatId, 'Hello!', {
146
+ parse_mode: 'HTML',
147
+ reply_markup: keyboard,
110
148
  });
111
- ```
112
149
 
113
- ## Sending Messages
150
+ // Send media
151
+ await bot.sendPhoto(chatId, photoBuffer, { caption: 'Photo!' });
152
+ await bot.sendVideo(chatId, videoPath);
153
+ await bot.sendAudio(chatId, audioBuffer);
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);
159
+
160
+ // Send location
161
+ await bot.sendLocation(chatId, latitude, longitude);
162
+
163
+ // Send venue
164
+ await bot.sendVenue(chatId, lat, lon, 'Title', 'Address');
114
165
 
115
- ### Text Messages
166
+ // Send contact
167
+ await bot.sendContact(chatId, '+1234567890', 'John');
168
+
169
+ // Send poll
170
+ await bot.sendPoll(chatId, 'Question?', ['Option 1', 'Option 2', 'Option 3']);
171
+
172
+ // Send dice/game
173
+ await bot.sendDice(chatId);
174
+
175
+ // Send chat action (e.g., typing)
176
+ await bot.sendChatAction(chatId, 'typing');
177
+ ```
178
+
179
+ #### Message Management
116
180
 
117
181
  ```javascript
118
- await bot.sendMessage(chatId, 'Hello World!');
182
+ // Edit message
183
+ await bot.editMessageText('New text', {
184
+ chat_id: chatId,
185
+ message_id: messageId,
186
+ parse_mode: 'HTML',
187
+ });
119
188
 
120
- await bot.sendMessage(chatId, '*Bold* and _italic_ text', {
121
- parse_mode: 'Markdown'
189
+ // Edit caption
190
+ await bot.editMessageCaption({
191
+ chat_id: chatId,
192
+ message_id: messageId,
193
+ caption: 'New caption',
122
194
  });
123
195
 
124
- await bot.sendMessage(chatId, '<b>Bold</b> and <i>italic</i> text', {
125
- parse_mode: 'HTML'
196
+ // Edit reply markup
197
+ await bot.editMessageReplyMarkup({
198
+ chat_id: chatId,
199
+ message_id: messageId,
200
+ reply_markup: newKeyboard,
126
201
  });
202
+
203
+ // Delete message
204
+ await bot.deleteMessage(chatId, messageId);
205
+
206
+ // Forward message
207
+ await bot.forwardMessage(chatId, fromChatId, messageId);
208
+
209
+ // Copy message
210
+ await bot.copyMessage(chatId, fromChatId, messageId);
127
211
  ```
128
212
 
129
- ### Photos
213
+ #### Chat Management
130
214
 
131
215
  ```javascript
132
- await bot.sendPhoto(chatId, 'https://example.com/image.jpg');
216
+ // Get chat info
217
+ const chat = await bot.getChat(chatId);
218
+
219
+ // Get chat administrators
220
+ const admins = await bot.getChatAdministrators(chatId);
221
+
222
+ // Get chat member count
223
+ const count = await bot.getChatMemberCount(chatId);
224
+
225
+ // Get specific chat member
226
+ const member = await bot.getChatMember(chatId, userId);
227
+
228
+ // Set chat title
229
+ await bot.setChatTitle(chatId, 'New Title');
133
230
 
134
- await bot.sendPhoto(chatId, '/path/to/local/image.jpg');
231
+ // Set chat description
232
+ await bot.setChatDescription(chatId, 'New Description');
135
233
 
136
- await bot.sendPhoto(chatId, 'file_id_from_telegram');
234
+ // Pin message
235
+ await bot.pinChatMessage(chatId, messageId);
137
236
 
138
- await bot.sendPhoto(chatId, photoBuffer);
237
+ // Unpin message
238
+ await bot.unpinChatMessage(chatId);
239
+
240
+ // Unpin all messages
241
+ await bot.unpinAllChatMessages(chatId);
242
+
243
+ // Leave chat
244
+ await bot.leaveChat(chatId);
139
245
  ```
140
246
 
141
- ### Documents
247
+ #### Member Management
142
248
 
143
249
  ```javascript
144
- await bot.sendDocument(chatId, '/path/to/document.pdf', {
145
- caption: 'Here is your document'
250
+ // Ban member
251
+ await bot.banChatMember(chatId, userId);
252
+
253
+ // Unban member
254
+ await bot.unbanChatMember(chatId, userId);
255
+
256
+ // Restrict member
257
+ await bot.restrictChatMember(chatId, userId, {
258
+ can_send_messages: false,
259
+ can_send_media_messages: false,
260
+ });
261
+
262
+ // Promote member
263
+ await bot.promoteChatMember(chatId, userId, {
264
+ can_manage_chat: true,
265
+ can_delete_messages: true,
146
266
  });
147
267
  ```
148
268
 
149
- ### Other Media Types
269
+ #### File Management
150
270
 
151
271
  ```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);
272
+ // Get file info
273
+ const file = await bot.getFile(fileId);
274
+
275
+ // Download file
276
+ await bot.downloadFile(fileId, '/path/to/save/file.jpg');
157
277
  ```
158
278
 
159
- ### Location
279
+ #### Query Handling
160
280
 
161
281
  ```javascript
162
- await bot.sendLocation(chatId, latitude, longitude);
282
+ // Answer callback query
283
+ await bot.answerCallbackQuery(callbackQueryId, {
284
+ text: 'Button clicked!',
285
+ show_alert: false,
286
+ });
287
+
288
+ // Answer inline query
289
+ await bot.answerInlineQuery(inlineQueryId, [
290
+ {
291
+ type: 'article',
292
+ id: '1',
293
+ title: 'Result',
294
+ input_message_content: { message_text: 'Text' },
295
+ },
296
+ ]);
163
297
  ```
164
298
 
165
- ### Contact
299
+ #### Bot Methods
166
300
 
167
301
  ```javascript
168
- await bot.sendContact(chatId, '+1234567890', 'John Doe');
302
+ // Get bot info
303
+ const me = await bot.getMe();
304
+
305
+ // Get updates
306
+ const updates = await bot.getUpdates();
307
+
308
+ // Set webhook
309
+ await bot.setWebhook('https://example.com/webhook');
310
+
311
+ // Delete webhook
312
+ await bot.deleteWebhook();
313
+
314
+ // Get webhook info
315
+ const info = await bot.getWebhookInfo();
169
316
  ```
170
317
 
171
- ### Poll
318
+ ### Context Methods (Available in Command Handlers & Events)
319
+
320
+ The `ctx` object provides convenient shorthand methods:
172
321
 
173
322
  ```javascript
174
- await bot.sendPoll(chatId, 'What is your favorite color?', [
175
- 'Red',
176
- 'Blue',
177
- 'Green',
178
- 'Yellow'
179
- ]);
323
+ bot.command('/start', async (ctx) => {
324
+ // Send message
325
+ await ctx.send('Hello!');
326
+
327
+ // Reply to message
328
+ await ctx.reply('Reply!');
329
+
330
+ // Reply with media
331
+ await ctx.replyWithPhoto(photoBuffer, { caption: 'Photo!' });
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
+ });
180
350
  ```
181
351
 
182
- ## Keyboards
352
+ ## ⌨️ Keyboard Builders
183
353
 
184
- ### Inline Keyboards
354
+ ### Inline Keyboard
185
355
 
186
356
  ```javascript
187
357
  const keyboard = TelegramBot.InlineKeyboard()
188
- .text('Button 1', 'callback_data_1')
189
- .text('Button 2', 'callback_data_2')
358
+ .text('Button 1', 'btn1')
359
+ .text('Button 2', 'btn2')
190
360
  .row()
191
- .url('Visit Website', 'https://example.com')
361
+ .url('Google', 'https://google.com')
362
+ .url('GitHub', 'https://github.com')
363
+ .row()
364
+ .switchInline('Search', 'query')
192
365
  .build();
193
366
 
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
- });
367
+ await bot.sendMessage(chatId, 'Choose:', { reply_markup: keyboard });
204
368
  ```
205
369
 
206
- ### Reply Keyboards
370
+ ### Reply Keyboard
207
371
 
208
372
  ```javascript
209
373
  const keyboard = TelegramBot.ReplyKeyboard()
210
374
  .text('Option 1')
211
375
  .text('Option 2')
212
376
  .row()
213
- .text('Option 3')
214
- .resize()
215
- .oneTime()
377
+ .requestContact('Share Contact')
378
+ .requestLocation('Share Location')
379
+ .resize(true)
380
+ .oneTime(true)
216
381
  .build();
217
382
 
218
- await bot.sendMessage(chatId, 'Select an option:', {
219
- reply_markup: keyboard
220
- });
383
+ await bot.sendMessage(chatId, 'Choose:', { reply_markup: keyboard });
221
384
  ```
222
385
 
223
386
  ### Remove Keyboard
224
387
 
225
388
  ```javascript
226
389
  await bot.sendMessage(chatId, 'Keyboard removed', {
227
- reply_markup: TelegramBot.RemoveKeyboard()
390
+ reply_markup: TelegramBot.RemoveKeyboard(),
228
391
  });
229
392
  ```
230
393
 
231
- ### Request Contact/Location
394
+ ### Force Reply
232
395
 
233
396
  ```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
397
+ await bot.sendMessage(chatId, 'Reply to me:', {
398
+ reply_markup: TelegramBot.ForceReply(),
243
399
  });
244
400
  ```
245
401
 
246
- ## Commands
402
+ ## 🎯 Event Handling
247
403
 
248
- ### Basic Commands
404
+ ### Message Events
249
405
 
250
406
  ```javascript
251
- bot.command('start', async (ctx) => {
252
- await ctx.reply('Welcome! Use /help to see available commands.');
407
+ // All messages
408
+ bot.on('message', (message, ctx) => {});
409
+
410
+ // Text messages
411
+ bot.on('text', (message, ctx) => {});
412
+
413
+ // Photo messages
414
+ bot.on('photo', (message, ctx) => {});
415
+
416
+ // Video messages
417
+ bot.on('video', (message, ctx) => {});
418
+
419
+ // Audio messages
420
+ bot.on('audio', (message, ctx) => {});
421
+
422
+ // Document messages
423
+ bot.on('document', (message, ctx) => {});
424
+
425
+ // Voice messages
426
+ bot.on('voice', (message, ctx) => {});
427
+
428
+ // Sticker messages
429
+ bot.on('sticker', (message, ctx) => {});
430
+
431
+ // Location messages
432
+ bot.on('location', (message, ctx) => {});
433
+
434
+ // Contact messages
435
+ bot.on('contact', (message, ctx) => {});
436
+
437
+ // Edited messages
438
+ bot.on('edited_message', (message, ctx) => {});
439
+
440
+ // Channel posts
441
+ bot.on('channel_post', (message, ctx) => {});
442
+
443
+ // Edited channel posts
444
+ bot.on('edited_channel_post', (message, ctx) => {});
445
+ ```
446
+
447
+ ### Query Events
448
+
449
+ ```javascript
450
+ // Callback queries (from inline buttons)
451
+ bot.on('callback_query', (query, ctx) => {
452
+ console.log(query.data); // Button callback data
253
453
  });
254
454
 
255
- bot.command('help', async (ctx) => {
256
- await ctx.reply('Available commands:\n/start - Start the bot\n/help - Show this message');
455
+ // Inline queries
456
+ bot.on('inline_query', (query, ctx) => {
457
+ console.log(query.query); // Search query
257
458
  });
459
+
460
+ // Chosen inline result
461
+ bot.on('chosen_inline_result', (result, ctx) => {});
258
462
  ```
259
463
 
260
- ### Multiple Command Aliases
464
+ ### Poll Events
261
465
 
262
466
  ```javascript
263
- bot.command(['info', 'about'], async (ctx) => {
264
- await ctx.reply('Bot information...');
265
- });
467
+ // Poll updates
468
+ bot.on('poll', (poll, ctx) => {});
469
+
470
+ // Poll answers
471
+ bot.on('poll_answer', (answer, ctx) => {});
266
472
  ```
267
473
 
268
- ### Command with Arguments
474
+ ### Chat Member Events
269
475
 
270
476
  ```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
- });
477
+ // Bot added/removed from chat
478
+ bot.on('my_chat_member', (member, ctx) => {});
479
+
480
+ // User added/removed from chat
481
+ bot.on('chat_member', (member, ctx) => {});
278
482
  ```
279
483
 
280
- ## Middleware
484
+ ### System Events
485
+
486
+ ```javascript
487
+ // Update received
488
+ bot.on('update', (update) => {});
489
+
490
+ // Polling started
491
+ bot.on('polling_start', () => {});
492
+
493
+ // Polling stopped
494
+ bot.on('polling_stop', () => {});
495
+
496
+ // Polling error
497
+ bot.on('polling_error', (error) => {});
498
+
499
+ // Webhook started
500
+ bot.on('webhook_start', (port) => {});
501
+
502
+ // Webhook stopped
503
+ bot.on('webhook_stop', () => {});
504
+
505
+ // Webhook error
506
+ bot.on('webhook_error', (error) => {});
507
+
508
+ // General error
509
+ bot.on('error', (error) => {});
510
+ ```
281
511
 
282
- ### Basic Middleware
512
+ ## 🔧 Middleware
283
513
 
284
514
  ```javascript
515
+ // Logging middleware
285
516
  bot.use(async (ctx, next) => {
286
- console.log('Received update:', ctx.update.update_id);
517
+ console.log(`[${new Date().toISOString()}] Message from ${ctx.from?.username}`);
287
518
  await next();
288
519
  });
289
520
 
521
+ // Rate limiting middleware
522
+ const userCalls = new Map();
290
523
  bot.use(async (ctx, next) => {
291
- ctx.startTime = Date.now();
524
+ const userId = ctx.from?.id;
525
+ if (!userId) return;
526
+
527
+ const calls = userCalls.get(userId) || 0;
528
+ if (calls > 5) {
529
+ await ctx.send('Rate limited!');
530
+ return;
531
+ }
532
+
533
+ userCalls.set(userId, calls + 1);
534
+ await next();
535
+ });
536
+
537
+ // Permission checking middleware
538
+ bot.use(async (ctx, next) => {
539
+ const allowedUsers = [123456789, 987654321];
540
+ if (!allowedUsers.includes(ctx.from?.id || 0)) {
541
+ await ctx.send('❌ Not authorized');
542
+ return;
543
+ }
292
544
  await next();
293
- const duration = Date.now() - ctx.startTime;
294
- console.log(`Request took ${duration}ms`);
295
545
  });
296
546
  ```
297
547
 
298
- ### Authentication Middleware
548
+ ## 📋 Command Handling
549
+
550
+ ### Single Command
299
551
 
300
552
  ```javascript
301
- const AUTHORIZED_USERS = [123456789, 987654321];
553
+ bot.command('/start', async (ctx) => {
554
+ await ctx.send('Welcome!');
555
+ });
302
556
 
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
- }
557
+ bot.command('help', async (ctx) => { // With or without /
558
+ await ctx.send('Need help?');
309
559
  });
310
560
  ```
311
561
 
312
- ### Logging Middleware
562
+ ### Multiple Commands
313
563
 
314
564
  ```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();
565
+ bot.command(['/help', '/h', 'help'], async (ctx) => {
566
+ await ctx.send('Here is help');
320
567
  });
321
568
  ```
322
569
 
323
- ## Events
324
-
325
- ### Message Events
570
+ ### Get Command Handler
326
571
 
327
572
  ```javascript
328
- bot.on('message', (message, ctx) => {
329
- console.log('New message:', message);
330
- });
573
+ const handler = bot.command('/start'); // Get without registering
574
+ if (handler) {
575
+ handler(ctx); // Call the handler
576
+ }
577
+ ```
331
578
 
332
- bot.on('text', async (message, ctx) => {
333
- console.log('Text message:', message.text);
334
- });
579
+ ## 🌐 Webhook Mode
335
580
 
336
- bot.on('photo', async (message, ctx) => {
337
- console.log('Photo received:', message.photo);
581
+ ```javascript
582
+ const bot = new TelegramBot(token, {
583
+ webhook: true,
584
+ webhookPort: 3000,
585
+ webhookPath: '/webhook',
338
586
  });
339
587
 
340
- bot.on('document', async (message, ctx) => {
341
- console.log('Document received:', message.document);
588
+ // Webhook events
589
+ bot.on('webhook_start', (port) => {
590
+ console.log(`✅ Webhook listening on port ${port}`);
342
591
  });
343
592
 
344
- bot.on('video', async (message, ctx) => {
345
- console.log('Video received:', message.video);
593
+ bot.on('webhook_stop', () => {
594
+ console.log('Webhook stopped');
346
595
  });
347
596
 
348
- bot.on('sticker', async (message, ctx) => {
349
- await ctx.reply('Nice sticker!');
597
+ bot.on('webhook_error', (error) => {
598
+ console.error('Webhook error:', error);
350
599
  });
351
600
 
352
- bot.on('location', async (message, ctx) => {
353
- const { latitude, longitude } = message.location;
354
- await ctx.reply(`You are at: ${latitude}, ${longitude}`);
355
- });
601
+ // Start webhook
602
+ bot.startWebhook();
356
603
 
357
- bot.on('contact', async (message, ctx) => {
358
- await ctx.reply(`Contact received: ${message.contact.first_name}`);
359
- });
604
+ // Stop webhook
605
+ bot.stopWebhook();
360
606
  ```
361
607
 
362
- ### Update Events
608
+ ## 🔄 Polling Mode
363
609
 
364
610
  ```javascript
365
- bot.on('edited_message', (message, ctx) => {
366
- console.log('Message edited');
611
+ const bot = new TelegramBot(token, {
612
+ polling: true,
613
+ pollingInterval: 1000,
614
+ pollingTimeout: 30,
367
615
  });
368
616
 
369
- bot.on('callback_query', async (query, ctx) => {
370
- await ctx.answerCallbackQuery();
371
- });
617
+ // Start polling
618
+ await bot.startPolling();
372
619
 
373
- bot.on('inline_query', async (query, ctx) => {
374
- console.log('Inline query:', query.query);
375
- });
620
+ // Stop polling
621
+ bot.stopPolling();
376
622
  ```
377
623
 
378
- ### Error Events
624
+ ## 📤 Advanced Examples
379
625
 
380
- ```javascript
381
- bot.on('error', (error) => {
382
- console.error('Bot error:', error);
383
- });
626
+ ### Image Processing Bot
384
627
 
385
- bot.on('polling_error', (error) => {
386
- console.error('Polling error:', error);
387
- });
628
+ ```javascript
629
+ const fs = require('fs');
388
630
 
389
- bot.on('webhook_error', (error) => {
390
- console.error('Webhook error:', error);
631
+ bot.on('photo', async (message, ctx) => {
632
+ const file = await bot.getFile(message.photo[message.photo.length - 1].file_id);
633
+ await bot.downloadFile(file.file_id, './downloaded.jpg');
634
+ await ctx.send('✅ Photo received and saved!');
391
635
  });
392
636
  ```
393
637
 
394
- ## File Handling
395
-
396
- ### Download Files
638
+ ### Interactive Menu
397
639
 
398
640
  ```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.');
641
+ bot.command('/menu', async (ctx) => {
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();
648
+
649
+ await ctx.send('Choose an option:', { reply_markup: keyboard });
650
+ });
651
+
652
+ bot.on('callback_query', async (query, ctx) => {
653
+ switch (query.data) {
654
+ case 'opt_a':
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;
407
665
  }
408
666
  });
409
667
  ```
410
668
 
411
- ### Get File Info
669
+ ### Survey Bot
412
670
 
413
671
  ```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
- ```
672
+ bot.on('poll', async (poll, ctx) => {
673
+ console.log(`Poll: ${poll.question}`);
674
+ console.log(`Total voters: ${poll.total_voter_count}`);
675
+ poll.options.forEach((opt, i) => {
676
+ console.log(` ${i + 1}. ${opt.text}: ${opt.voter_count} votes`);
677
+ });
678
+ });
418
679
 
419
- ## Error Handling
680
+ bot.on('poll_answer', async (answer, ctx) => {
681
+ console.log(`User ${answer.user.id} voted for options: ${answer.option_ids}`);
682
+ });
683
+ ```
420
684
 
421
- ### Try-Catch Pattern
685
+ ### Auto-responder
422
686
 
423
687
  ```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);
688
+ const responses = {
689
+ hello: '👋 Hello! How can I help?',
690
+ hi: '👋 Hi there!',
691
+ bye: '👋 Goodbye!',
692
+ };
693
+
694
+ bot.on('text', async (message, ctx) => {
695
+ const text = message.text?.toLowerCase() || '';
696
+ const response = responses[text];
697
+ if (response) {
698
+ await ctx.send(response);
429
699
  }
430
700
  });
431
701
  ```
432
702
 
433
- ### Global Error Handler
703
+ ## 🐛 Error Handling
434
704
 
435
705
  ```javascript
436
706
  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
- }
707
+ console.error('Bot error:', {
708
+ message: error.message,
709
+ code: error.errorCode,
710
+ response: error.response,
711
+ });
444
712
  });
445
- ```
446
713
 
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:
714
+ bot.on('polling_error', (error) => {
715
+ console.error('Polling error:', error.message);
716
+ // Auto-reconnect happens automatically
717
+ });
506
718
 
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
719
+ try {
720
+ await bot.sendMessage(chatId, 'message');
721
+ } catch (error) {
722
+ console.error('Send failed:', error.message);
523
723
  }
524
724
  ```
525
725
 
526
- ## Performance Tips
726
+ ## 📊 Telegram Bot API Coverage
527
727
 
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
728
+ ### Implemented Features
533
729
 
534
- ## Best Practices
730
+ - **Message Methods** - Send, edit, delete messages and media
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
535
741
 
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
742
+ ## 🔌 Environment Setup
541
743
 
542
- ```javascript
543
- process.on('SIGINT', () => {
544
- bot.stopPolling();
545
- console.log('Bot stopped gracefully');
546
- process.exit(0);
547
- });
744
+ ### Get Your Bot Token
745
+
746
+ 1. Open Telegram and chat with [@BotFather](https://t.me/botfather)
747
+ 2. Send `/newbot` command
748
+ 3. Follow the instructions
749
+ 4. Copy your token
750
+
751
+ ### Set Environment Variable
752
+
753
+ ```bash
754
+ export TELEGRAM_BOT_TOKEN="YOUR_TOKEN_HERE"
548
755
  ```
549
756
 
550
- ## License
757
+ Or in `.env` file:
758
+ ```env
759
+ TELEGRAM_BOT_TOKEN=your_token_here
760
+ ```
761
+
762
+ ## 📝 License
551
763
 
552
- MIT
764
+ MIT License - See LICENSE file for details
553
765
 
554
- ## Contributing
766
+ ## 🤝 Contributing
555
767
 
556
768
  Contributions are welcome! Please feel free to submit a Pull Request.
557
769
 
558
- ## Support
770
+ ## 📞 Support
771
+
772
+ For issues, questions, or suggestions:
773
+ - GitHub Issues: [GitHub Issues](https://github.com/kazedevid/teh/issues)
774
+ - Telegram Bot API Docs: [Official Docs](https://core.telegram.org/bots/api)
775
+
776
+ ## 🙏 Acknowledgments
777
+
778
+ Built with ❤️ for the Telegram Bot API community.
779
+
780
+ ---
559
781
 
560
- For issues and questions, please use the [GitHub Issues](https://github.com/kazedevid/teh/issues) page.
782
+ **Happy botting! 🤖**