@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/.claude/settings.local.json +2 -1
- package/README.md +835 -818
- package/dist/agents/workers/WorkerClientFactory.js +11 -12
- package/dist/agents/workers/WorkerClientFactory.js.map +1 -1
- package/dist/agents/workers/long-polling-worker-test.js +23 -8
- package/dist/agents/workers/long-polling-worker-test.js.map +1 -1
- package/dist/api/types/GetFileResponseSuccess.generated.d.ts +2 -1
- package/dist/api/types/GetFileResponseSuccess.generated.js.map +1 -1
- package/dist/client/TelegramBotClient.d.ts +253 -14
- package/dist/client/TelegramBotClient.js +211 -37
- package/dist/client/TelegramBotClient.js.map +1 -1
- package/dist/client/managers/RouteLifecycleManager.js +1 -1
- package/dist/client/managers/RouteLifecycleManager.js.map +1 -1
- package/dist/helpers/file-helpers.js +3 -3
- package/dist/helpers/file-helpers.js.map +1 -1
- package/dist/helpers/logger-helpers.js.map +1 -1
- package/dist/helpers/logging-decorators.d.ts +2 -2
- package/dist/helpers/logging-decorators.js +24 -35
- package/dist/helpers/logging-decorators.js.map +1 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/queue/InMemoryQueueProvider.d.ts +1 -2
- package/dist/queue/index.d.ts +1 -1
- package/dist/queue/index.js.map +1 -1
- package/dist/transport/TelegramTransport.js +12 -1
- package/dist/transport/TelegramTransport.js.map +1 -1
- package/package.json +2 -2
- package/typedoc.json +19 -18
package/README.md
CHANGED
|
@@ -1,818 +1,835 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
**
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
bot
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
//
|
|
154
|
-
bot.
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
//
|
|
166
|
-
bot.
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
//
|
|
223
|
-
await bot.
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
-
|
|
388
|
-
-
|
|
389
|
-
-
|
|
390
|
-
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
//
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
//
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
```
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
console.log('
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
//
|
|
567
|
-
|
|
568
|
-
await
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
);
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
//
|
|
613
|
-
const
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
```
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
```typescript
|
|
646
|
-
import {
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
const
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
const
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
#
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
#
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
#
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
#
|
|
798
|
-
|
|
799
|
-
```
|
|
800
|
-
|
|
801
|
-
##
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
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 ботов
|