@vvlad1973/telegram-bot-client 2.0.0 → 2.0.2

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,818 +1,835 @@
1
- # Telegram Bot API Client
2
-
3
- TypeScript library for Telegram Bot API with type-safe methods, automatic validation, high-level bot framework, and Native Fetch HTTP client.
4
-
5
- **Version:** 1.4.0
6
- **Supported Telegram Bot API Version:** 9.2
7
- **Node.js:** >=18.0.0
8
-
9
- ## Features
10
-
11
- ### Core Features
12
-
13
- - Type-safe API methods generated from OpenAPI specification
14
- - Native Fetch API (zero dependencies for HTTP)
15
- - Automatic parameter validation using JSON Schema
16
- - Built-in retry logic with exponential backoff
17
- - Multiple bot token management
18
- - Support for JSON, form-urlencoded, and multipart content types
19
- - Comprehensive error handling with typed errors
20
- - Full TypeScript support
21
-
22
- ### High-Level Bot Framework
23
-
24
- - **TelegramBotClient** - Complete bot framework with transport-based architecture
25
- - **Built-in Long Polling** - Integrated multi-route polling with automatic management
26
- - **Route Configuration** - Multi-token support with per-route settings
27
- - **Event System** - Subscribe to specific update types with flexible filters
28
- - **Filter System** - Advanced filtering with RegExp support for all update fields
29
- - **Middleware** - Chain of responsibility pattern for pre-processing
30
- - **Wrapper Classes** - Enhanced Message and CallbackQuery objects with helper methods
31
- - **Keyboard Builders** - Fluent API for building inline and reply keyboards
32
- - **Bot Commands Builder** - Manage bot commands easily
33
- - **Automatic TRACE Logging** - All API methods logged via decorators
34
-
35
- ### Transport Layer
36
-
37
- - Configurable method priorities for rate limiting
38
- - Logger-aware with flexible integration
39
- - Direct request mode for debugging
40
-
41
- ## Installation
42
-
43
- ```bash
44
- npm install @vvlad1973/telegram-bot-client
45
- ```
46
-
47
- ## Quick Start
48
-
49
- ### Simple Bot Example
50
-
51
- ```typescript
52
- import { TelegramBotClient, TelegramTransport, RouteMode } from '@vvlad1973/telegram-bot-client';
53
-
54
- // Create transport
55
- const transport = new TelegramTransport({
56
- tokens: { default: process.env.BOT_TOKEN }
57
- });
58
-
59
- // Create client with built-in long polling
60
- const bot = new TelegramBotClient({
61
- transport,
62
- routes: [
63
- {
64
- id: 'default',
65
- token: process.env.BOT_TOKEN,
66
- mode: RouteMode.LongPolling,
67
- longPolling: { timeout: 30, limit: 100 }
68
- }
69
- ],
70
- defaultRouteId: 'default'
71
- });
72
-
73
- // Handle messages
74
- bot.on('message', async (message) => {
75
- await bot.sendMessage({
76
- chat_id: message.chat.id,
77
- text: `You said: ${message.text}`
78
- });
79
- });
80
-
81
- // Start long polling
82
- await bot.startLongPolling();
83
- console.log('Bot is running...');
84
- ```
85
-
86
- ### Multi-Token Bot Example
87
-
88
- ```typescript
89
- import { TelegramBotClient, TelegramTransport, RouteMode } from '@vvlad1973/telegram-bot-client';
90
-
91
- const transport = new TelegramTransport({
92
- tokens: {
93
- bot1: process.env.BOT1_TOKEN,
94
- bot2: process.env.BOT2_TOKEN
95
- }
96
- });
97
-
98
- const bot = new TelegramBotClient({
99
- transport,
100
- routes: [
101
- {
102
- id: 'bot1',
103
- token: process.env.BOT1_TOKEN,
104
- mode: RouteMode.LongPolling
105
- },
106
- {
107
- id: 'bot2',
108
- token: process.env.BOT2_TOKEN,
109
- mode: RouteMode.LongPolling
110
- }
111
- ]
112
- });
113
-
114
- // Handle messages from all bots
115
- bot.on('message', async (message) => {
116
- console.log('Message from:', message.chat.id);
117
- });
118
-
119
- // Start polling for all routes
120
- await bot.startLongPolling();
121
- ```
122
-
123
- ## High-Level Features
124
-
125
- ### TelegramBotClient
126
-
127
- Concrete class providing complete bot framework:
128
-
129
- ```typescript
130
- import { TelegramBotClient, TelegramTransport } from '@vvlad1973/telegram-bot-client';
131
-
132
- // Create transport
133
- const transport = new TelegramTransport({
134
- tokens: { default: process.env.BOT_TOKEN }
135
- });
136
-
137
- // Create client
138
- const bot = new TelegramBotClient({ transport });
139
-
140
- // Setup event handlers
141
- bot.on('message.text', (message) => {
142
- console.log('Text message:', message.text);
143
- });
144
-
145
- bot.on('message.photo', (message) => {
146
- console.log('Photo received');
147
- });
148
-
149
- bot.on('callback_query', (query) => {
150
- console.log('Callback query:', query.data);
151
- });
152
-
153
- // Setup middleware
154
- bot.use((update, next) => {
155
- console.log('Processing update:', update.update_id);
156
- next();
157
- });
158
- ```
159
-
160
- ### Event System
161
-
162
- Subscribe to specific update types:
163
-
164
- ```typescript
165
- // Text messages
166
- bot.on('message', (message) => {
167
- console.log('Message:', message.text);
168
- });
169
-
170
- // Callback queries
171
- bot.on('callback_query', (query) => {
172
- console.log('Callback data:', query.data);
173
- });
174
-
175
- // All updates
176
- bot.on('*', (update) => {
177
- console.log('Update:', update.update_id);
178
- });
179
- ```
180
-
181
- ## Built-in Long Polling
182
-
183
- TelegramBotClient has integrated long polling support with multi-route management:
184
-
185
- ```typescript
186
- import { TelegramBotClient, TelegramTransport, RouteMode } from '@vvlad1973/telegram-bot-client';
187
-
188
- const transport = new TelegramTransport({
189
- tokens: {
190
- bot1: process.env.BOT1_TOKEN,
191
- bot2: process.env.BOT2_TOKEN
192
- }
193
- });
194
-
195
- const bot = new TelegramBotClient({
196
- transport,
197
- routes: [
198
- {
199
- id: 'bot1',
200
- token: process.env.BOT1_TOKEN,
201
- mode: RouteMode.LongPolling,
202
- longPolling: {
203
- timeout: 30,
204
- limit: 100,
205
- allowedUpdates: ['message', 'callback_query']
206
- }
207
- },
208
- {
209
- id: 'bot2',
210
- token: process.env.BOT2_TOKEN,
211
- mode: RouteMode.Inactive // Manually controlled
212
- }
213
- ],
214
- defaultRouteId: 'bot1'
215
- });
216
-
217
- // Handle updates
218
- bot.on('message', async (message) => {
219
- console.log('New message:', message.text);
220
- });
221
-
222
- // Start long polling for all active routes
223
- await bot.startLongPolling();
224
-
225
- // Route management
226
- await bot.routeLifecycle.activateRoute('bot2', RouteMode.LongPolling);
227
- await bot.routeLifecycle.deactivateRoute('bot2');
228
-
229
- const status = bot.routeLifecycle.getRouteStatus('bot1');
230
- console.log('Bot1 status:', status);
231
-
232
- // Stop long polling
233
- await bot.stopLongPolling();
234
- ```
235
-
236
- **Key Features:**
237
-
238
- - Integrated into TelegramBotClient
239
- - Multi-route support with independent configurations
240
- - Automatic update processing
241
- - Route lifecycle management (activate/deactivate)
242
- - Per-route polling configuration
243
- - Event-driven architecture
244
-
245
- ### Event Filtering
246
-
247
- Filter events by update types:
248
-
249
- ```typescript
250
- // Listen to specific message types
251
- bot.on('message', (message) => {
252
- if (message.text) {
253
- console.log('Text message:', message.text);
254
- }
255
- if (message.photo) {
256
- console.log('Photo message');
257
- }
258
- });
259
-
260
- // Handle callback queries
261
- bot.on('callback_query', (query) => {
262
- console.log('Callback data:', query.data);
263
- });
264
-
265
- // Handle all update types
266
- bot.on('*', (update) => {
267
- console.log('Any update:', update.update_id);
268
- });
269
- ```
270
-
271
- ### Middleware
272
-
273
- Pre-process updates before handlers:
274
-
275
- ```typescript
276
- // Logging
277
- bot.use((update, next) => {
278
- console.log('Update:', update.update_id);
279
- next();
280
- });
281
-
282
- // Authentication
283
- bot.use((update, next) => {
284
- const userId = update.message?.from?.id;
285
- if (isBlocked(userId)) return; // Stop processing
286
- next();
287
- });
288
-
289
- // Async middleware
290
- bot.use(async (update, next) => {
291
- await trackUser(update);
292
- next();
293
- });
294
- ```
295
-
296
- ### Wrapper Classes
297
-
298
- Enhanced message and callback query objects with helper methods:
299
-
300
- ```typescript
301
- import { MessageWrapper, CallbackQueryWrapper } from '@vvlad1973/telegram-bot-client';
302
-
303
- bot.on('message', async (message) => {
304
- const wrapper = new MessageWrapper(message, bot);
305
-
306
- // Reply to the message
307
- await wrapper.reply('Hello!');
308
-
309
- // Forward the message
310
- await wrapper.forward(targetChatId);
311
-
312
- // Delete the message
313
- await wrapper.delete();
314
-
315
- // Check message type
316
- if (wrapper.isText()) {
317
- console.log('Text:', wrapper.text);
318
- }
319
- if (wrapper.isPhoto()) {
320
- console.log('Photo message');
321
- }
322
- });
323
-
324
- bot.on('callback_query', async (query) => {
325
- const wrapper = new CallbackQueryWrapper(query, bot);
326
-
327
- // Answer the callback query
328
- await wrapper.answer('Processing...');
329
-
330
- // Edit the message text
331
- await wrapper.editText('Updated!');
332
-
333
- // Delete the message
334
- await wrapper.deleteMessage();
335
- });
336
- ```
337
-
338
- ### Keyboard Builders
339
-
340
- Fluent API for building keyboards:
341
-
342
- ```typescript
343
- import { InlineKeyboardBuilder, ReplyKeyboardBuilder } from '@vvlad1973/telegram-bot-client';
344
-
345
- // Inline keyboard
346
- const inline = new InlineKeyboardBuilder()
347
- .appendTextButton('Button 1', 'data1', 0)
348
- .appendTextButton('Button 2', 'data2', 0)
349
- .appendUrlButton('Google', 'https://google.com', 1)
350
- .build();
351
-
352
- // Reply keyboard
353
- const reply = new ReplyKeyboardBuilder()
354
- .appendTextButton('Option 1', 0)
355
- .appendTextButton('Option 2', 0)
356
- .setResizeKeyboard(true)
357
- .setOneTimeKeyboard(true)
358
- .build();
359
-
360
- await bot.sendMessage({
361
- chat_id: 123,
362
- text: 'Choose:',
363
- reply_markup: inline
364
- });
365
- ```
366
-
367
- ### Bot Commands Builder
368
-
369
- Manage bot commands easily:
370
-
371
- ```typescript
372
- import { BotCommandsBuilder } from '@vvlad1973/telegram-bot-client';
373
-
374
- const commands = new BotCommandsBuilder()
375
- .addCommand('start', 'Start the bot')
376
- .addCommand('help', 'Show help')
377
- .addCommand('settings', 'Configure settings')
378
- .build();
379
-
380
- await bot.setMyCommands({ commands });
381
- ```
382
-
383
- ## Documentation
384
-
385
- ### Getting Started
386
-
387
- - [Client Guide](docs/guides/CLIENT-GUIDE.md) - Complete guide for TelegramBotClient
388
- - [Filter System](docs/FILTERS.md) - Advanced filtering with examples
389
- - [Quick Start](docs/guides/QUICK-START.md) - Get started in 5 minutes
390
- - [Examples](examples/) - Working code examples
391
-
392
- ### Guides
393
-
394
- - [Multi-Token Configuration](docs/guides/MULTI-TOKEN-GUIDE.md) - Managing multiple bots
395
- - [Error Handling](docs/guides/ERROR-HANDLING.md) - Handle errors gracefully
396
- - [Validation System](docs/guides/VALIDATION.md) - Parameter validation
397
- - [Logger Integration](docs/guides/LOGGER-INTEGRATION.md) - Logging setup
398
- - [Migration Guide](docs/guides/MIGRATION-GUIDE.md) - Upgrade from older versions
399
-
400
- ### Reference
401
-
402
- - [API Reference](docs/typedoc/index.html) - Full API documentation (TypeDoc)
403
- - [Architecture](docs/ARCHITECTURE.md) - System architecture and design
404
-
405
- ### Core API Classes
406
-
407
- **Transport Layer:**
408
-
409
- - `TelegramTransport` - Universal transport with direct HTTP or queue modes
410
- - `TokensManager` - Multi-token management
411
- - `TelegramHttpClient` - Native Fetch HTTP client with retries
412
-
413
- **High-Level Client:**
414
-
415
- - `TelegramBotClient` - Complete bot framework with transport, events, and middleware
416
- - `MessageWrapper` - Enhanced Message with helper methods
417
- - `CallbackQueryWrapper` - Enhanced CallbackQuery with helper methods
418
-
419
- **Client Managers:**
420
-
421
- - `RouteConfigManager` - Route configuration management
422
- - `RouteLifecycleManager` - Route activation and lifecycle
423
- - `PollingIntegrationManager` - Long polling integration
424
-
425
- **Builders:**
426
-
427
- - `InlineKeyboardBuilder` - Build inline keyboards
428
- - `ReplyKeyboardBuilder` - Build reply keyboards
429
- - `BotCommandsBuilder` - Manage bot commands
430
-
431
- **Helpers:**
432
-
433
- - `parseCommand()` - Parse command from text
434
- - `getMessageType()` - Get message type
435
- - `getFileId()` - Extract file_id from media
436
- - `formatUserUrl()` - Format user as display string
437
- - `formatUserMention()` - Create user mentions with formatting
438
- - `getFileUrl()` - Get Telegram file download URL
439
- - `getTelegramFileBuffer()` - Download Telegram file as Buffer
440
- - `getTelegramFileStream()` - Download Telegram file as Stream
441
- - `downloadFileBuffer()` - Download any file as Buffer
442
- - `downloadFileStream()` - Download any file as Stream
443
-
444
- **Decorators:**
445
-
446
- - `@LogMethod` - Automatic method entry/exit logging with parameter sanitization
447
- - `@LogEntry` - Method entry-only logging
448
-
449
- **Constants:**
450
-
451
- - `DiceEmoji` - Emoji for sendDice method
452
- - `MediaType` - Media type constants
453
- - `ParseMode` - Message formatting modes
454
- - `ChatType` - Chat type constants
455
-
456
- ## Helper Functions
457
-
458
- ### Constants
459
-
460
- Type-safe constants for Telegram Bot API:
461
-
462
- ```typescript
463
- import {
464
- DiceEmoji,
465
- MediaType,
466
- ParseMode,
467
- ChatType
468
- } from '@vvlad1973/telegram-bot-client';
469
-
470
- // Send dice with different emoji
471
- await bot.sendDice({
472
- chat_id: 123,
473
- emoji: DiceEmoji.BASKETBALL // 🏀
474
- });
475
-
476
- // Access media from message
477
- const fileId = message[MediaType.PHOTO]?.[0]?.file_id;
478
-
479
- // Send formatted message
480
- await bot.sendMessage({
481
- chat_id: 123,
482
- text: '<b>Bold text</b>',
483
- parse_mode: ParseMode.HTML
484
- });
485
-
486
- // Check chat type
487
- if (message.chat.type === ChatType.PRIVATE) {
488
- // Handle private chat
489
- }
490
- ```
491
-
492
- **Available constants:**
493
-
494
- - **DiceEmoji**: `DICE`, `DARTS`, `BASKETBALL`, `FOOTBALL`, `SLOT_MACHINE`, `BOWLING`
495
- - **MediaType**: `PHOTO`, `VIDEO`, `AUDIO`, `VOICE`, `DOCUMENT`, `STICKER`, `VIDEO_NOTE`, `ANIMATION`
496
- - **ParseMode**: `HTML`, `MARKDOWN`, `MARKDOWN_V2`
497
- - **ChatType**: `PRIVATE`, `GROUP`, `SUPERGROUP`, `CHANNEL`
498
-
499
- ### User Formatting
500
-
501
- Format users for display and create mentions:
502
-
503
- ```typescript
504
- import {
505
- formatUserUrl,
506
- formatUserMention,
507
- ParseMode
508
- } from '@vvlad1973/telegram-bot-client';
509
-
510
- // Format user for display
511
- const display = formatUserUrl(user);
512
- // "@johndoe" or "John Doe" or "User 123"
513
-
514
- // Plain mention URL (default)
515
- const mention = formatUserMention(user);
516
- // "tg://user?id=123456789"
517
-
518
- // HTML mention
519
- await bot.sendMessage({
520
- chat_id: 123,
521
- text: `Hello ${formatUserMention(user, ParseMode.HTML)}!`,
522
- parse_mode: ParseMode.HTML
523
- });
524
- // "Hello <a href="tg://user?id=123">@johndoe</a>!"
525
-
526
- // Markdown mention
527
- await bot.sendMessage({
528
- chat_id: 456,
529
- text: `Welcome ${formatUserMention(user, ParseMode.MARKDOWN_V2)}!`,
530
- parse_mode: ParseMode.MARKDOWN_V2
531
- });
532
- // "Welcome [@johndoe](tg://user?id=123)!"
533
-
534
- // Custom text
535
- const customMention = formatUserMention(user, ParseMode.HTML, 'Click here');
536
- // "<a href="tg://user?id=123">Click here</a>"
537
- ```
538
-
539
- ### File Operations
540
-
541
- Download files from Telegram or external URLs:
542
-
543
- ```typescript
544
- import {
545
- getFileUrl,
546
- getTelegramFileBuffer,
547
- getTelegramFileStream,
548
- downloadFileBuffer
549
- } from '@vvlad1973/telegram-bot-client';
550
- import { writeFile } from 'fs/promises';
551
- import { pipeline } from 'stream/promises';
552
- import { Readable } from 'stream';
553
-
554
- // Get file URL from Telegram
555
- const url = await getFileUrl(fileId, bot);
556
- console.log('File URL:', url);
557
- // "https://api.telegram.org/file/bot<token>/photos/file_123.jpg"
558
-
559
- // Download Telegram file as Buffer
560
- const buffer = await getTelegramFileBuffer(fileId, bot, undefined, {
561
- timeout: 120000, // 2 minutes
562
- retries: 5
563
- });
564
- await writeFile('photo.jpg', buffer);
565
-
566
- // Download large file as Stream (memory efficient)
567
- const stream = await getTelegramFileStream(fileId, bot);
568
- await pipeline(
569
- Readable.fromWeb(stream),
570
- createWriteStream('video.mp4')
571
- );
572
-
573
- // Download external file
574
- const pdfBuffer = await downloadFileBuffer(
575
- 'https://example.com/report.pdf',
576
- bot,
577
- { timeout: 60000 }
578
- );
579
- await writeFile('report.pdf', pdfBuffer);
580
- ```
581
-
582
- **Multi-token support:**
583
-
584
- ```typescript
585
- // Get file from specific bot
586
- const url = await getFileUrl(fileId, bot, 'bot2');
587
- const buffer = await getTelegramFileBuffer(fileId, bot, 'bot2');
588
- ```
589
-
590
- **Advanced options:**
591
-
592
- ```typescript
593
- // Custom timeout and retries
594
- const buffer = await getTelegramFileBuffer(fileId, bot, undefined, {
595
- timeout: 300000, // 5 minutes
596
- retries: 10,
597
- retryDelay: 2000
598
- });
599
-
600
- // Exponential backoff is enabled by default
601
- // Retries: 2s, 4s, 8s, 16s, ...
602
- ```
603
-
604
- ### Public API Methods
605
-
606
- Access internal components for advanced use cases:
607
-
608
- ```typescript
609
- // Get HTTP client for custom operations
610
- const httpClient = bot.getHttpClient();
611
-
612
- // Download with custom logic
613
- const arrayBuffer = await httpClient.downloadFile(url, {
614
- timeout: 60000,
615
- retries: 5
616
- });
617
-
618
- // Get bot token (useful for file URLs)
619
- const token = bot.getToken();
620
- const fileUrl = `https://api.telegram.org/file/bot${token}/${filePath}`;
621
-
622
- // Multi-token: get specific token
623
- const token2 = bot.getToken('bot2');
624
- ```
625
-
626
- ## Examples
627
-
628
- See [examples/](examples/) directory:
629
-
630
- - **simple-bot.ts** - Basic bot with commands and messages
631
- - **advanced-bot.ts** - Filters, middleware, and advanced features
632
- - **webhook-bot.ts** - Webhook-based bot with Express
633
- - **long-polling-multi-token.ts** - Multi-token long polling with worker threads
634
-
635
- Run examples:
636
-
637
- ```bash
638
- BOT_TOKEN=your_token ts-node examples/simple-bot.ts
639
- ```
640
-
641
- ## Logger Integration
642
-
643
- The library supports comprehensive logging with automatic TRACE logging for all API methods:
644
-
645
- ```typescript
646
- import { TelegramBotClient, TelegramTransport, LoggerTree, LoggerBinder } from '@vvlad1973/telegram-bot-client';
647
-
648
- // Create logger tree
649
- const loggerTree = new LoggerTree({
650
- level: 'debug',
651
- prettyPrint: true
652
- });
653
-
654
- // Create logger binder
655
- const loggerBinder = new LoggerBinder(loggerTree);
656
-
657
- // Create transport with logger
658
- const transport = new TelegramTransport({
659
- tokens: { default: process.env.BOT_TOKEN },
660
- loggerBinder,
661
- loggerName: 'TelegramBot'
662
- });
663
-
664
- // Create client with logger
665
- const bot = new TelegramBotClient({
666
- transport,
667
- loggerBinder,
668
- loggerName: 'TelegramBotClient'
669
- });
670
-
671
- // All API method calls are automatically logged at TRACE level
672
- await bot.sendMessage({
673
- chat_id: 123,
674
- text: 'This will be logged'
675
- });
676
- ```
677
-
678
- **Automatic Method Logging:**
679
-
680
- All API methods are decorated with `@LogMethod` decorator that provides:
681
-
682
- - Method entry logging with sanitized parameters (tokens are masked)
683
- - Method exit logging for sync operations
684
- - Async method completion logging
685
- - Complete visibility at TRACE level
686
-
687
- **Log Levels:**
688
-
689
- - **trace**: Method entry/exit, request/response details
690
- - **debug**: Update processing, middleware execution, event emission
691
- - **info**: Lifecycle events, long polling start/stop, route management
692
- - **warn**: Recoverable issues, rate limiting, missing tokens
693
- - **error**: API errors, failed retries, critical failures
694
-
695
- ## Low-Level Transport Usage
696
-
697
- For custom implementations, you can use TelegramTransport directly:
698
-
699
- ```typescript
700
- import { TelegramTransport, InMemoryQueueProvider } from '@vvlad1973/telegram-bot-client';
701
-
702
- // Create queue provider (optional)
703
- const queueProvider = new InMemoryQueueProvider({
704
- globalLimit: 30,
705
- queueLimit: 1,
706
- concurrency: 1
707
- });
708
-
709
- // Create transport
710
- const transport = new TelegramTransport({
711
- tokens: { default: process.env.BOT_TOKEN },
712
- queueProvider, // Optional
713
- httpClientOptions: {
714
- timeout: 30000,
715
- retries: 3,
716
- exponentialBackoff: true
717
- }
718
- });
719
-
720
- // Call API methods directly
721
- await transport.sendMessage({
722
- chat_id: 123,
723
- text: 'Hello!'
724
- });
725
-
726
- await transport.sendPhoto({
727
- chat_id: 123,
728
- photo: 'https://example.com/photo.jpg',
729
- caption: 'Photo'
730
- });
731
-
732
- const updates = await transport.getUpdates({
733
- offset: 0,
734
- timeout: 30
735
- });
736
- ```
737
-
738
- ## Architecture
739
-
740
- ```text
741
- High-Level Framework:
742
- TelegramBotClient (concrete)
743
- ├── Transport Layer (TelegramTransport)
744
- ├── Route Management
745
- │ ├── RouteConfigManager (Configuration)
746
- │ ├── RouteLifecycleManager (Activation/deactivation)
747
- │ └── PollingIntegrationManager (Long polling)
748
- ├── Event System (EventEmitter-based)
749
- ├── Middleware (Chain of responsibility)
750
- └── Wrappers (MessageWrapper, CallbackQueryWrapper)
751
-
752
- Transport Layer:
753
- TelegramTransport
754
- ├── TelegramHttpClient (Native Fetch)
755
- ├── TokensManager (Multi-token support)
756
- ├── QueueProvider (Optional, for rate limiting)
757
- └── BaseTelegramApi (Generated, 100+ API methods with @LogMethod decorators)
758
-
759
- Logging System:
760
- @LogMethod Decorator
761
- ├── Automatic method entry/exit logging
762
- ├── Parameter sanitization (token masking)
763
- └── TRACE level logging for all API calls
764
- ```
765
-
766
- ## Code Generation
767
-
768
- API types and methods are auto-generated:
769
-
770
- ```bash
771
- npm run generate-api
772
- ```
773
-
774
- Generates:
775
-
776
- - `src/api/BaseTelegramApi.generated.ts` - API methods
777
- - `src/api/BaseApi.generated.ts` - Base class with validation
778
- - `src/api/types/*.generated.ts` - TypeScript types
779
-
780
- **Do not edit generated files directly.**
781
-
782
- ## Development
783
-
784
- ```bash
785
- # Install dependencies
786
- npm install
787
-
788
- # Run tests
789
- npm test
790
-
791
- # Build
792
- npm run build
793
-
794
- # Lint
795
- npm run lint
796
-
797
- # Generate API
798
- npm run generate-api
799
- ```
800
-
801
- ## Requirements
802
-
803
- - Node.js 18.0.0 or higher (Native Fetch support)
804
- - TypeScript 5.0+ (if using TypeScript)
805
-
806
- ## License
807
-
808
- MIT
809
-
810
- ## Support
811
-
812
- - [GitHub Issues](https://github.com/vvlad1973/telegram-bot/issues)
813
- - [Documentation](docs/)
814
- - [Examples](examples/)
815
-
816
- ## Contributing
817
-
818
- Contributions are welcome! Please read the contributing guidelines before submitting PRs.
1
+ # @vvlad1973/telegram-bot-client
2
+
3
+ Мощная и типобезопасная библиотека для создания Telegram ботов на TypeScript с поддержкой нескольких токенов, системой событий и расширенной фильтрацией.
4
+
5
+ ## Основные возможности
6
+
7
+ - **Полная типизация TypeScript** - автоматически сгенерированные типы из OpenAPI спецификации Telegram Bot API 9.2.0
8
+ - **Event-driven архитектура** - гибкая система событий для обработки обновлений
9
+ - **Middleware система** - цепочка обработчиков для pre-processing обновлений
10
+ - **Расширенная фильтрация** - мощная система фильтров с поддержкой RegExp
11
+ - **Поддержка нескольких токенов** - управление несколькими ботами одновременно
12
+ - **Long Polling Manager** - встроенный менеджер с worker threads и автоматическими перезапусками
13
+ - **Обертки (Wrappers)** - удобные методы для работы с сообщениями и callback query
14
+ - **Построители (Builders)** - fluent API для создания клавиатур и команд
15
+ - **Обработка ошибок** - иерархия специализированных классов ошибок
16
+ - **Интеграция с логированием** - поддержка LoggerTree и SimpleLogger
17
+ - **Native Fetch API** - использует встроенный fetch без внешних зависимостей
18
+
19
+ ## Установка
20
+
21
+ ```bash
22
+ npm install @vvlad1973/telegram-bot-client
23
+ ```
24
+
25
+ ## Быстрый старт
26
+
27
+ ### Создание и инициализация бота
28
+
29
+ Библиотека поддерживает три режима работы с Telegram Bot API:
30
+
31
+ 1. **Inactive** - неактивный режим (только для отправки запросов)
32
+ 2. **LongPolling** - получение обновлений через long polling
33
+ 3. **Webhook** - получение обновлений через webhook
34
+
35
+ #### Жизненный цикл маршрута (route)
36
+
37
+ Каждый бот проходит следующие этапы:
38
+
39
+ 1. **Создание** - конфигурация маршрута (route) с токеном и режимом
40
+ 2. **Инициализация** - вызов `getMe` для получения информации о боте
41
+ 3. **Активация** - установка режима работы (webhook/polling)
42
+ 4. **Работа** - обработка обновлений
43
+ 5. **Деактивация** - остановка получения обновлений
44
+ 6. **Завершение** - закрытие всех ресурсов
45
+
46
+ ### Режим 1: Inactive (только отправка)
47
+
48
+ Используйте этот режим, когда нужно только отправлять сообщения без получения обновлений:
49
+
50
+ ```typescript
51
+ import { TelegramBotClient, RouteMode } from '@vvlad1973/telegram-bot-client';
52
+
53
+ // Создание клиента
54
+ const bot = new TelegramBotClient({
55
+ routes: {
56
+ token: 'YOUR_BOT_TOKEN',
57
+ mode: RouteMode.Inactive
58
+ }
59
+ });
60
+
61
+ // Инициализация (получает информацию о боте через getMe)
62
+ await bot.init();
63
+
64
+ // Отправка сообщения без получения обновлений
65
+ await bot.sendMessage({
66
+ chat_id: 123456789,
67
+ text: 'Привет! Это одностороннее сообщение.'
68
+ });
69
+
70
+ // Завершение работы
71
+ await bot.shutdown();
72
+ ```
73
+
74
+ ### Режим 2: Long Polling (получение обновлений)
75
+
76
+ Long polling - рекомендуемый режим для разработки и небольших ботов:
77
+
78
+ ```typescript
79
+ import { TelegramBotClient, RouteMode } from '@vvlad1973/telegram-bot-client';
80
+
81
+ // Шаг 1: Создание клиента с конфигурацией
82
+ const bot = new TelegramBotClient({
83
+ routes: {
84
+ token: 'YOUR_BOT_TOKEN',
85
+ mode: RouteMode.LongPolling,
86
+ longPolling: {
87
+ timeout: 30, // Таймаут long polling запроса (сек)
88
+ limit: 100, // Максимальное количество обновлений
89
+ allowedUpdates: [ // Типы обновлений (опционально)
90
+ 'message',
91
+ 'callback_query'
92
+ ]
93
+ }
94
+ }
95
+ });
96
+
97
+ // Шаг 2: Установка обработчиков событий (до инициализации)
98
+ bot.on('/start', (params, wrapper) => {
99
+ wrapper.replyMessage('Добро пожаловать! Я бот в режиме Long Polling.');
100
+ });
101
+
102
+ bot.on('message.text', (wrapper) => {
103
+ wrapper.replyMessage(`Эхо: ${wrapper.text}`);
104
+ });
105
+
106
+ bot.on('callback_query', (wrapper) => {
107
+ wrapper.answer('Кнопка нажата!');
108
+ });
109
+
110
+ // Шаг 3: Инициализация (вызывает getMe, сохраняет информацию о боте)
111
+ await bot.init();
112
+
113
+ // Шаг 4: Запуск long polling (начинает получать обновления)
114
+ await bot.startPolling();
115
+
116
+ console.log('Бот запущен в режиме Long Polling');
117
+
118
+ // Шаг 5: Graceful shutdown
119
+ process.on('SIGINT', async () => {
120
+ console.log('Остановка бота...');
121
+ await bot.stopPolling();
122
+ await bot.shutdown();
123
+ process.exit(0);
124
+ });
125
+ ```
126
+
127
+ ### Режим 3: Webhook (для продакшена)
128
+
129
+ Webhook режим рекомендуется для продакшен-окружения:
130
+
131
+ ```typescript
132
+ import { TelegramBotClient, RouteMode } from '@vvlad1973/telegram-bot-client';
133
+ import express from 'express';
134
+
135
+ // Шаг 1: Создание клиента с webhook конфигурацией
136
+ const bot = new TelegramBotClient({
137
+ routes: {
138
+ token: 'YOUR_BOT_TOKEN',
139
+ mode: RouteMode.Webhook,
140
+ webhook: {
141
+ path: '/webhook/bot', // Путь для webhook
142
+ secretToken: 'your-secret-123', // Секретный токен для защиты
143
+ maxConnections: 100, // Макс. одновременных соединений
144
+ allowedUpdates: [ // Типы обновлений
145
+ 'message',
146
+ 'callback_query'
147
+ ]
148
+ }
149
+ },
150
+ webhookBaseUrl: 'https://your-domain.com' // Базовый URL (обязательно HTTPS!)
151
+ });
152
+
153
+ // Шаг 2: Установка обработчиков
154
+ bot.on('/start', (params, wrapper) => {
155
+ wrapper.replyMessage('Привет! Я бот в режиме Webhook.');
156
+ });
157
+
158
+ bot.on('message.text', (wrapper) => {
159
+ wrapper.replyMessage(`Получено: ${wrapper.text}`);
160
+ });
161
+
162
+ // Шаг 3: Инициализация
163
+ await bot.init();
164
+
165
+ // Шаг 4: Активация (устанавливает webhook через setWebhook)
166
+ await bot.activate();
167
+
168
+ // Шаг 5: Настройка Express для обработки webhook
169
+ const app = express();
170
+ app.use(express.json());
171
+
172
+ app.post('/webhook/bot', async (req, res) => {
173
+ // Проверка секретного токена (опционально)
174
+ const secretToken = req.headers['x-telegram-bot-api-secret-token'];
175
+ if (secretToken !== 'your-secret-123') {
176
+ return res.status(403).send('Forbidden');
177
+ }
178
+
179
+ // Обработка обновления
180
+ try {
181
+ await bot.processUpdate(req.body);
182
+ res.status(200).send('OK');
183
+ } catch (error) {
184
+ console.error('Error processing update:', error);
185
+ res.status(500).send('Error');
186
+ }
187
+ });
188
+
189
+ // Шаг 6: Запуск сервера
190
+ const PORT = process.env.PORT || 3000;
191
+ app.listen(PORT, () => {
192
+ console.log(`Webhook сервер запущен на порту ${PORT}`);
193
+ });
194
+
195
+ // Graceful shutdown
196
+ process.on('SIGINT', async () => {
197
+ console.log('Остановка сервера...');
198
+ await bot.deactivate(); // Удаляет webhook через deleteWebhook
199
+ await bot.shutdown();
200
+ process.exit(0);
201
+ });
202
+ ```
203
+
204
+ ### Режим 4: Переключение между режимами
205
+
206
+ Вы можете создать бота в одном режиме и переключить его в другой:
207
+
208
+ ```typescript
209
+ import { TelegramBotClient, RouteMode } from '@vvlad1973/telegram-bot-client';
210
+
211
+ // Создание в неактивном режиме
212
+ const bot = new TelegramBotClient({
213
+ routes: {
214
+ token: 'YOUR_BOT_TOKEN',
215
+ mode: RouteMode.Inactive
216
+ }
217
+ });
218
+
219
+ // Инициализация
220
+ await bot.init();
221
+
222
+ // Переключение на Long Polling
223
+ await bot.activate(undefined, RouteMode.LongPolling);
224
+ await bot.startPolling();
225
+
226
+ // Работа в режиме Long Polling...
227
+ console.log('Работаем в Long Polling...');
228
+ await new Promise(resolve => setTimeout(resolve, 10000));
229
+
230
+ // Остановка polling и переключение на Webhook
231
+ await bot.stopPolling();
232
+ await bot.deactivate();
233
+
234
+ // Обновление конфигурации маршрута
235
+ bot.setRoute('default', {
236
+ token: 'YOUR_BOT_TOKEN',
237
+ mode: RouteMode.Webhook,
238
+ webhook: { path: '/webhook' }
239
+ });
240
+
241
+ // Активация в режиме Webhook
242
+ await bot.activate(undefined, RouteMode.Webhook);
243
+
244
+ // Теперь бот работает через webhook
245
+ ```
246
+
247
+ ### Режим 5: Автоматическая активация
248
+
249
+ Для упрощения можно использовать автоматическую активацию:
250
+
251
+ ```typescript
252
+ import { TelegramBotClient, RouteMode } from '@vvlad1973/telegram-bot-client';
253
+
254
+ const bot = new TelegramBotClient({
255
+ routes: {
256
+ token: 'YOUR_BOT_TOKEN',
257
+ mode: RouteMode.LongPolling,
258
+ autoActivate: true // Автоматическая активация при инициализации
259
+ }
260
+ });
261
+
262
+ // Обработчики
263
+ bot.on('message.text', (wrapper) => {
264
+ wrapper.replyMessage(`Эхо: ${wrapper.text}`);
265
+ });
266
+
267
+ // Только инициализация - активация произойдет автоматически
268
+ await bot.init();
269
+
270
+ // Для Long Polling все равно нужно запустить polling
271
+ await bot.startPolling();
272
+ ```
273
+
274
+ ### Работа с клавиатурами
275
+
276
+ ```typescript
277
+ import { InlineKeyboardBuilder } from '@vvlad1973/telegram-bot-client';
278
+
279
+ // Создание inline клавиатуры
280
+ const keyboard = new InlineKeyboardBuilder()
281
+ .appendRows(2)
282
+ .appendTextButton('Помощь', 'help', 0)
283
+ .appendTextButton('Настройки', 'settings', 0)
284
+ .appendUrlButton('Наш сайт', 'https://example.com', 1)
285
+ .build();
286
+
287
+ bot.on('/menu', (params, wrapper) => {
288
+ wrapper.replyMessage('Выберите действие:', {
289
+ reply_markup: keyboard
290
+ });
291
+ });
292
+
293
+ // Обработка callback
294
+ bot.on('callback_query', (wrapper) => {
295
+ if (wrapper.data === 'help') {
296
+ wrapper.editMessageText('Справка по боту...');
297
+ wrapper.answer();
298
+ }
299
+ });
300
+ ```
301
+
302
+ ### Фильтрация обновлений
303
+
304
+ ```typescript
305
+ // Фильтр по приватным чатам
306
+ bot.onFilter({
307
+ type: 'message.text',
308
+ chat: 'private'
309
+ }, (wrapper) => {
310
+ wrapper.replyMessage('Это приватный чат');
311
+ });
312
+
313
+ // Фильтр с RegExp
314
+ bot.onFilter({
315
+ type: 'message.text',
316
+ contents: /^\/admin/,
317
+ user: /^(111111|222222)$/ // Только определенные пользователи
318
+ }, (wrapper) => {
319
+ wrapper.replyMessage('Админ-команда');
320
+ });
321
+
322
+ // Фильтр по типу чата
323
+ bot.onFilter({
324
+ type: 'message.text',
325
+ chat_type: 'group'
326
+ }, (wrapper) => {
327
+ console.log('Сообщение из группы');
328
+ });
329
+ ```
330
+
331
+ ### Middleware
332
+
333
+ ```typescript
334
+ // Логирование всех обновлений
335
+ bot.use((update, next, client) => {
336
+ console.log('Update ID:', update.update_id);
337
+ next();
338
+ });
339
+
340
+ // Аутентификация
341
+ bot.use((update, next, client) => {
342
+ const userId = update.message?.from?.id;
343
+ if (isAuthorized(userId)) {
344
+ next(); // Продолжить обработку
345
+ }
346
+ // Если не вызвать next(), обработка остановится
347
+ });
348
+
349
+ // Обработка ошибок
350
+ bot.use(async (update, next, client) => {
351
+ try {
352
+ next();
353
+ } catch (error) {
354
+ console.error('Error processing update:', error);
355
+ }
356
+ });
357
+ ```
358
+
359
+ ## Документация
360
+
361
+ - [Быстрый старт](docs/QUICK-START.md) - подробное руководство для начинающих
362
+ - [Migration Guide v2.0](docs/MIGRATION-GUIDE-v2.md) - миграция с v1.x на v2.0
363
+ - [Справочник классов](docs/CLASS-REFERENCE.md) - полное описание всех классов
364
+ - API Reference - TypeDoc документация (запустите `npm run docs` для генерации)
365
+
366
+ ## Архитектура
367
+
368
+ ```text
369
+ TelegramBotClient (клиентский слой)
370
+ ↓ наследует
371
+ BaseTelegramApi (сгенерированные методы API)
372
+ использует
373
+ TelegramTransport (транспортный слой)
374
+ использует
375
+ TelegramHttpClient (HTTP-клиент)
376
+ использует
377
+ Native Fetch API
378
+ ```
379
+
380
+ ### Основные компоненты
381
+
382
+ - **TelegramBotClient** - основной клиент с системой событий и фильтрацией
383
+ - **TelegramTransport** - транспортный слой для HTTP-запросов
384
+ - **TelegramHttpClient** - HTTP-клиент с автоматическими повторами
385
+ - **TokensManager** - управление несколькими токенами ботов
386
+ - **LongPollingManager** - менеджер long polling с worker threads
387
+ - **MessageWrapper** - обертка для удобной работы с сообщениями
388
+ - **CallbackQueryWrapper** - обертка для callback query
389
+ - **InlineKeyboardBuilder** - построитель inline-клавиатур
390
+ - **ReplyKeyboardBuilder** - построитель обычных клавиатур
391
+
392
+ ## Примеры использования
393
+
394
+ ### Несколько токенов
395
+
396
+ ```typescript
397
+ import { TelegramBotClient, RouteMode } from '@vvlad1973/telegram-bot-client';
398
+
399
+ // Создание клиента с несколькими маршрутами
400
+ const bot = new TelegramBotClient({
401
+ routes: [
402
+ {
403
+ token: 'TOKEN_1',
404
+ mode: RouteMode.LongPolling
405
+ },
406
+ {
407
+ token: 'TOKEN_2',
408
+ mode: RouteMode.Webhook,
409
+ webhook: { path: '/webhook/support' }
410
+ }
411
+ ],
412
+ defaultRouteId: 'default',
413
+ webhookBaseUrl: 'https://example.com'
414
+ });
415
+
416
+ // Инициализация всех маршрутов
417
+ await bot.init();
418
+
419
+ // Активация конкретного маршрута
420
+ await bot.managers.lifecycle.activateRoute('default', RouteMode.LongPolling);
421
+
422
+ // Отправка от конкретного бота
423
+ await bot.sendMessage(
424
+ { chat_id: 123, text: 'Hello from main bot!' },
425
+ { routeId: 'default' }
426
+ );
427
+
428
+ await bot.sendMessage(
429
+ { chat_id: 456, text: 'Hello from support!' },
430
+ { routeId: 'route_1' }
431
+ );
432
+
433
+ // Запуск polling для всех маршрутов в режиме LongPolling
434
+ await bot.startPolling();
435
+ ```
436
+
437
+ ### Работа с менеджерами (Advanced)
438
+
439
+ `TelegramBotClient` использует три менеджера для управления маршрутами:
440
+
441
+ #### 1. RouteConfigManager - управление конфигурацией
442
+
443
+ ```typescript
444
+ // Доступ к менеджеру
445
+ const configManager = bot.managers.config;
446
+
447
+ // Получение списка всех маршрутов
448
+ const routeIds = configManager.getRouteIds();
449
+ console.log('Доступные маршруты:', routeIds);
450
+
451
+ // Получение конфигурации маршрута
452
+ const config = configManager.getRoute('default');
453
+ console.log('Режим:', config.mode);
454
+ console.log('Токен:', config.token);
455
+
456
+ // Установка/обновление конфигурации маршрута
457
+ bot.setRoute('bot2', {
458
+ token: 'NEW_TOKEN',
459
+ mode: RouteMode.LongPolling,
460
+ longPolling: {
461
+ timeout: 30,
462
+ limit: 100
463
+ }
464
+ });
465
+
466
+ // Получение ID маршрута по умолчанию
467
+ const defaultRouteId = configManager.getDefaultRouteId();
468
+
469
+ // Проверка существования маршрута
470
+ if (configManager.hasRoute('bot2')) {
471
+ console.log('Маршрут bot2 существует');
472
+ }
473
+ ```
474
+
475
+ #### 2. RouteLifecycleManager - управление жизненным циклом
476
+
477
+ ```typescript
478
+ // Доступ к менеджеру
479
+ const lifecycleManager = bot.managers.lifecycle;
480
+
481
+ // Инициализация конкретного маршрута (вызывает getMe)
482
+ await lifecycleManager.initRoute('bot1');
483
+
484
+ // Активация маршрута в указанном режиме
485
+ await lifecycleManager.activateRoute('bot1', RouteMode.LongPolling);
486
+
487
+ // Деактивация маршрута (удаляет webhook, останавливает polling)
488
+ await lifecycleManager.deactivateRoute('bot1');
489
+
490
+ // Получение информации о боте (после init)
491
+ const botInfo = lifecycleManager.getBotInfo('bot1');
492
+ console.log('Имя бота:', botInfo.username);
493
+ console.log('ID бота:', botInfo.id);
494
+
495
+ // Получение статуса маршрута
496
+ const status = lifecycleManager.getRouteStatus('bot1');
497
+ console.log('Статус:', status.state); // 'initialized', 'active', 'inactive'
498
+ console.log('Режим:', status.mode); // RouteMode
499
+ console.log('Последняя ошибка:', status.lastError);
500
+
501
+ // Переключение режима (деактивирует текущий и активирует новый)
502
+ await lifecycleManager.switchMode('bot1', RouteMode.Webhook);
503
+
504
+ // Горячая перезагрузка конфигурации (применяет новые настройки)
505
+ await lifecycleManager.hotReload('bot1');
506
+ ```
507
+
508
+ #### 3. PollingIntegrationManager - управление polling
509
+
510
+ ```typescript
511
+ // Доступ к менеджеру
512
+ const pollingManager = bot.managers.polling;
513
+
514
+ // Запуск polling для конкретного маршрута
515
+ await pollingManager.startPolling();
516
+
517
+ // Остановка polling
518
+ await pollingManager.stopPolling();
519
+
520
+ // Проверка активности polling для маршрута
521
+ const isActive = pollingManager.isPollingActive('bot1');
522
+ console.log('Polling активен:', isActive);
523
+
524
+ // Получение текущего offset для маршрута
525
+ const offset = pollingManager.getOffset('bot1');
526
+ console.log('Текущий offset:', offset);
527
+
528
+ // Получение статистики polling для маршрута
529
+ const stats = pollingManager.getStats('bot1');
530
+ console.log('Всего получено обновлений:', stats.totalUpdates);
531
+ console.log('Последнее обновление:', stats.lastUpdate);
532
+ console.log('Статус worker:', stats.workerStatus);
533
+ ```
534
+
535
+ #### Полный пример с менеджерами
536
+
537
+ ```typescript
538
+ import { TelegramBotClient, RouteMode } from '@vvlad1973/telegram-bot-client';
539
+
540
+ // Создание клиента с несколькими маршрутами
541
+ const bot = new TelegramBotClient({
542
+ routes: new Map([
543
+ ['main', {
544
+ token: 'MAIN_BOT_TOKEN',
545
+ mode: RouteMode.Inactive
546
+ }],
547
+ ['support', {
548
+ token: 'SUPPORT_BOT_TOKEN',
549
+ mode: RouteMode.Inactive
550
+ }]
551
+ ]),
552
+ defaultRouteId: 'main'
553
+ });
554
+
555
+ // 1. Инициализация обоих ботов
556
+ console.log('Инициализация ботов...');
557
+ await bot.managers.lifecycle.initRoute('main');
558
+ await bot.managers.lifecycle.initRoute('support');
559
+
560
+ // Проверка информации о ботах
561
+ const mainInfo = bot.managers.lifecycle.getBotInfo('main');
562
+ const supportInfo = bot.managers.lifecycle.getBotInfo('support');
563
+ console.log('Основной бот:', mainInfo.username);
564
+ console.log('Бот поддержки:', supportInfo.username);
565
+
566
+ // 2. Активация основного бота в Long Polling
567
+ console.log('Активация основного бота...');
568
+ await bot.managers.lifecycle.activateRoute('main', RouteMode.LongPolling);
569
+ await bot.startPolling();
570
+
571
+ // 3. Активация бота поддержки в Webhook
572
+ console.log('Активация бота поддержки...');
573
+ bot.setRoute('support', {
574
+ token: 'SUPPORT_BOT_TOKEN',
575
+ mode: RouteMode.Webhook,
576
+ webhook: { path: '/webhook/support' }
577
+ });
578
+ await bot.managers.lifecycle.activateRoute('support', RouteMode.Webhook);
579
+
580
+ // 4. Мониторинг состояния
581
+ setInterval(() => {
582
+ // Статус маршрутов
583
+ const mainStatus = bot.managers.lifecycle.getRouteStatus('main');
584
+ const supportStatus = bot.managers.lifecycle.getRouteStatus('support');
585
+
586
+ console.log('Основной бот - состояние:', mainStatus.state, 'режим:', mainStatus.mode);
587
+ console.log('Бот поддержки - состояние:', supportStatus.state, 'режим:', supportStatus.mode);
588
+
589
+ // Статистика polling для основного бота
590
+ if (bot.managers.polling.isPollingActive('main')) {
591
+ const stats = bot.managers.polling.getStats('main');
592
+ console.log('Получено обновлений:', stats.totalUpdates);
593
+ }
594
+ }, 30000);
595
+
596
+ // 5. Переключение режима основного бота (с Long Polling на Webhook)
597
+ setTimeout(async () => {
598
+ console.log('Переключение основного бота на Webhook...');
599
+ await bot.stopPolling();
600
+ bot.setRoute('main', {
601
+ token: 'MAIN_BOT_TOKEN',
602
+ mode: RouteMode.Webhook,
603
+ webhook: { path: '/webhook/main' }
604
+ });
605
+ await bot.managers.lifecycle.switchMode('main', RouteMode.Webhook);
606
+ }, 60000);
607
+
608
+ // Graceful shutdown
609
+ process.on('SIGINT', async () => {
610
+ console.log('Остановка всех ботов...');
611
+
612
+ // Деактивация всех маршрутов
613
+ for (const routeId of bot.managers.config.getRouteIds()) {
614
+ await bot.managers.lifecycle.deactivateRoute(routeId);
615
+ }
616
+
617
+ await bot.shutdown();
618
+ process.exit(0);
619
+ });
620
+ ```
621
+
622
+ ### Обработка ошибок
623
+
624
+ ```typescript
625
+ import { TelegramRateLimitError, TelegramBadRequestError } from '@vvlad1973/telegram-bot-client';
626
+
627
+ try {
628
+ await bot.sendMessage({
629
+ chat_id: chatId,
630
+ text: 'Hello!'
631
+ });
632
+ } catch (error) {
633
+ if (error instanceof TelegramRateLimitError) {
634
+ console.log(`Rate limited. Retry after ${error.retryAfter} seconds`);
635
+ // Автоматическая задержка
636
+ await new Promise(resolve => setTimeout(resolve, error.getRetryDelay()));
637
+ } else if (error instanceof TelegramBadRequestError) {
638
+ console.error('Bad request:', error.description);
639
+ }
640
+ }
641
+ ```
642
+
643
+ ### Логирование
644
+
645
+ ```typescript
646
+ import { SimpleLogger } from '@vvlad1973/simple-logger';
647
+
648
+ const logger = new SimpleLogger({
649
+ level: 'info',
650
+ prettyPrint: true
651
+ });
652
+
653
+ const transport = new TelegramTransport({
654
+ tokens: { default: token },
655
+ logger
656
+ });
657
+
658
+ const bot = new TelegramBotClient({
659
+ transport,
660
+ logger
661
+ });
662
+
663
+ // Логи автоматически выводятся на всех уровнях
664
+ ```
665
+
666
+ ### MessageWrapper методы
667
+
668
+ ```typescript
669
+ bot.on('message.text', async (wrapper) => {
670
+ // Ответ на сообщение
671
+ await wrapper.replyMessage('Hello!');
672
+
673
+ // Отправка в тот же чат
674
+ await wrapper.answerMessage('Message sent!');
675
+
676
+ // Редактирование
677
+ await wrapper.editText('Updated text');
678
+
679
+ // Удаление
680
+ await wrapper.delete();
681
+
682
+ // Пересылка
683
+ await wrapper.forward(otherChatId);
684
+
685
+ // Закрепление
686
+ await wrapper.pin();
687
+
688
+ // Chat action
689
+ await wrapper.answerChatAction('typing');
690
+
691
+ // Отправка фото
692
+ await wrapper.replyPhoto('file_id_or_url', {
693
+ caption: 'Photo caption'
694
+ });
695
+ });
696
+ ```
697
+
698
+ ### ReplyKeyboardBuilder
699
+
700
+ ```typescript
701
+ import { ReplyKeyboardBuilder } from '@vvlad1973/telegram-bot-client';
702
+
703
+ const keyboard = new ReplyKeyboardBuilder()
704
+ .appendRows(3)
705
+ .appendTextButton('Начать', 0)
706
+ .appendTextButton('Помощь', 0)
707
+ .appendRequestContactButton('Отправить контакт', 1)
708
+ .appendRequestLocationButton('Отправить локацию', 2)
709
+ .setResizeKeyboard(true)
710
+ .setOneTimeKeyboard(true)
711
+ .build();
712
+
713
+ await bot.sendMessage({
714
+ chat_id: chatId,
715
+ text: 'Выберите действие:',
716
+ reply_markup: keyboard
717
+ });
718
+ ```
719
+
720
+ ## Требования
721
+
722
+ - Node.js >= 18.0.0
723
+ - npm >= 9.0.0
724
+ - TypeScript >= 5.0 (для разработки)
725
+
726
+ ## Зависимости
727
+
728
+ Основные зависимости:
729
+
730
+ - `@vvlad1973/base-api` - базовый API класс
731
+ - `@vvlad1973/data-validator` - валидация данных
732
+ - `@vvlad1973/logger-tree` - система логирования
733
+ - `@vvlad1973/simple-logger` - простой логгер
734
+ - `@vvlad1973/utils` - утилиты
735
+ - `ajv` - JSON Schema валидация
736
+
737
+ ## Скрипты
738
+
739
+ ```bash
740
+ # Сборка проекта
741
+ npm run build
742
+
743
+ # Тестирование
744
+ npm test
745
+ npm run test:coverage
746
+
747
+ # Линтинг
748
+ npm run lint
749
+ npm run lint:fix
750
+ npm run lint:md
751
+ npm run lint:md:fix
752
+
753
+ # Генерация документации
754
+ npm run docs
755
+
756
+ # Обновление API
757
+ npm run fetch-api # Скачать спецификацию Telegram Bot API
758
+ npm run generate-api # Сгенерировать типы и методы
759
+ npm run update-api # Скачать и сгенерировать
760
+ ```
761
+
762
+ ## Разработка
763
+
764
+ ### Генерация API
765
+
766
+ Типы и методы автоматически генерируются из OpenAPI спецификации:
767
+
768
+ ```bash
769
+ # Скачать актуальную спецификацию
770
+ npm run fetch-api
771
+
772
+ # Сгенерировать классы и типы
773
+ npm run generate-api
774
+
775
+ # Или всё вместе
776
+ npm run update-api
777
+ ```
778
+
779
+ ### Структура проекта
780
+
781
+ ```text
782
+ telegram-bot-client/
783
+ ├── src/
784
+ │ ├── api/ # Сгенерированные API классы
785
+ │ │ ├── BaseTelegramApi.generated.ts
786
+ │ │ └── types/ # Сгенерированные типы
787
+ │ ├── client/ # TelegramBotClient
788
+ │ ├── transport/ # Транспортный слой
789
+ │ ├── builders/ # Построители клавиатур
790
+ │ ├── wrappers/ # Обертки для Message и CallbackQuery
791
+ │ ├── agents/ # Long Polling Manager
792
+ │ ├── errors/ # Классы ошибок
793
+ │ ├── helpers/ # Вспомогательные функции
794
+ │ └── types/ # Общие типы
795
+ ├── scripts/ # Скрипты генерации
796
+ ├── docs/ # Документация
797
+ ├── examples/ # Примеры
798
+ └── models/ # OpenAPI спецификация
799
+ ```
800
+
801
+ ## Примеры
802
+
803
+ Все примеры использования представлены в разделах выше с подробными комментариями и пояснениями.
804
+
805
+ ## Changelog
806
+
807
+ См. [CHANGELOG.md](CHANGELOG.md) для полной истории изменений.
808
+
809
+ ## Лицензия
810
+
811
+ MIT with Commercial Use License
812
+
813
+ ## Автор
814
+
815
+ Vladislav Vnukovskiy <vvlad1973@gmail.com>
816
+
817
+ ## Ссылки
818
+
819
+ - [GitHub репозиторий](https://github.com/vvlad1973/telegram-bot-client)
820
+ - [npm пакет](https://www.npmjs.com/package/@vvlad1973/telegram-bot-client)
821
+ - [Telegram Bot API документация](https://core.telegram.org/bots/api)
822
+ - [Создание бота через @BotFather](https://t.me/botfather)
823
+
824
+ ## Поддержка
825
+
826
+ Если у вас возникли проблемы или вопросы:
827
+
828
+ 1. Проверьте [документацию](docs/QUICK-START.md)
829
+ 2. Посмотрите [примеры](examples/README.md)
830
+ 3. Создайте [issue на GitHub](https://github.com/vvlad1973/telegram-bot-client/issues)
831
+
832
+ ## Благодарности
833
+
834
+ - Telegram Team за отличный Bot API
835
+ - Сообщество разработчиков Telegram ботов