@dementevdev/maxbot-ts 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (429) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +21 -0
  3. package/README.md +1176 -0
  4. package/dist/cjs/api/BotsApi.d.ts +17 -0
  5. package/dist/cjs/api/BotsApi.d.ts.map +1 -0
  6. package/dist/cjs/api/BotsApi.js +22 -0
  7. package/dist/cjs/api/ChatsApi.d.ts +87 -0
  8. package/dist/cjs/api/ChatsApi.d.ts.map +1 -0
  9. package/dist/cjs/api/ChatsApi.js +144 -0
  10. package/dist/cjs/api/MessagesApi.d.ts +41 -0
  11. package/dist/cjs/api/MessagesApi.d.ts.map +1 -0
  12. package/dist/cjs/api/MessagesApi.js +66 -0
  13. package/dist/cjs/api/SubscriptionsApi.d.ts +45 -0
  14. package/dist/cjs/api/SubscriptionsApi.d.ts.map +1 -0
  15. package/dist/cjs/api/SubscriptionsApi.js +69 -0
  16. package/dist/cjs/api/UploadsApi.d.ts +45 -0
  17. package/dist/cjs/api/UploadsApi.d.ts.map +1 -0
  18. package/dist/cjs/api/UploadsApi.js +113 -0
  19. package/dist/cjs/api/index.d.ts +7 -0
  20. package/dist/cjs/api/index.d.ts.map +1 -0
  21. package/dist/cjs/api/index.js +14 -0
  22. package/dist/cjs/api/interfaces.d.ts +108 -0
  23. package/dist/cjs/api/interfaces.d.ts.map +1 -0
  24. package/dist/cjs/api/interfaces.js +3 -0
  25. package/dist/cjs/bot/Bot.d.ts +380 -0
  26. package/dist/cjs/bot/Bot.d.ts.map +1 -0
  27. package/dist/cjs/bot/Bot.js +624 -0
  28. package/dist/cjs/bot/Composer.d.ts +131 -0
  29. package/dist/cjs/bot/Composer.d.ts.map +1 -0
  30. package/dist/cjs/bot/Composer.js +218 -0
  31. package/dist/cjs/bot/context/BotStartedContext.d.ts +83 -0
  32. package/dist/cjs/bot/context/BotStartedContext.d.ts.map +1 -0
  33. package/dist/cjs/bot/context/BotStartedContext.js +113 -0
  34. package/dist/cjs/bot/context/CallbackContext.d.ts +107 -0
  35. package/dist/cjs/bot/context/CallbackContext.d.ts.map +1 -0
  36. package/dist/cjs/bot/context/CallbackContext.js +158 -0
  37. package/dist/cjs/bot/context/ChatContext.d.ts +35 -0
  38. package/dist/cjs/bot/context/ChatContext.d.ts.map +1 -0
  39. package/dist/cjs/bot/context/ChatContext.js +52 -0
  40. package/dist/cjs/bot/context/MessageContext.d.ts +149 -0
  41. package/dist/cjs/bot/context/MessageContext.d.ts.map +1 -0
  42. package/dist/cjs/bot/context/MessageContext.js +228 -0
  43. package/dist/cjs/bot/context/guards.d.ts +69 -0
  44. package/dist/cjs/bot/context/guards.d.ts.map +1 -0
  45. package/dist/cjs/bot/context/guards.js +85 -0
  46. package/dist/cjs/bot/context/index.d.ts +6 -0
  47. package/dist/cjs/bot/context/index.d.ts.map +1 -0
  48. package/dist/cjs/bot/context/index.js +18 -0
  49. package/dist/cjs/bot/dispatch.d.ts +51 -0
  50. package/dist/cjs/bot/dispatch.d.ts.map +1 -0
  51. package/dist/cjs/bot/dispatch.js +201 -0
  52. package/dist/cjs/bot/index.d.ts +10 -0
  53. package/dist/cjs/bot/index.d.ts.map +1 -0
  54. package/dist/cjs/bot/index.js +24 -0
  55. package/dist/cjs/bot/lifecycle.d.ts +85 -0
  56. package/dist/cjs/bot/lifecycle.d.ts.map +1 -0
  57. package/dist/cjs/bot/lifecycle.js +167 -0
  58. package/dist/cjs/bot/metrics.d.ts +18 -0
  59. package/dist/cjs/bot/metrics.d.ts.map +1 -0
  60. package/dist/cjs/bot/metrics.js +3 -0
  61. package/dist/cjs/bot/routing.d.ts +131 -0
  62. package/dist/cjs/bot/routing.d.ts.map +1 -0
  63. package/dist/cjs/bot/routing.js +198 -0
  64. package/dist/cjs/bot/triggers.d.ts +61 -0
  65. package/dist/cjs/bot/triggers.d.ts.map +1 -0
  66. package/dist/cjs/bot/triggers.js +84 -0
  67. package/dist/cjs/core/errors/MaxError.d.ts +11 -0
  68. package/dist/cjs/core/errors/MaxError.d.ts.map +1 -0
  69. package/dist/cjs/core/errors/MaxError.js +19 -0
  70. package/dist/cjs/core/errors/errors.d.ts +59 -0
  71. package/dist/cjs/core/errors/errors.d.ts.map +1 -0
  72. package/dist/cjs/core/errors/errors.js +84 -0
  73. package/dist/cjs/core/errors/index.d.ts +3 -0
  74. package/dist/cjs/core/errors/index.d.ts.map +1 -0
  75. package/dist/cjs/core/errors/index.js +13 -0
  76. package/dist/cjs/core/http/HttpClient.d.ts +28 -0
  77. package/dist/cjs/core/http/HttpClient.d.ts.map +1 -0
  78. package/dist/cjs/core/http/HttpClient.js +148 -0
  79. package/dist/cjs/core/http/index.d.ts +3 -0
  80. package/dist/cjs/core/http/index.d.ts.map +1 -0
  81. package/dist/cjs/core/http/index.js +6 -0
  82. package/dist/cjs/core/http/interfaces.d.ts +42 -0
  83. package/dist/cjs/core/http/interfaces.d.ts.map +1 -0
  84. package/dist/cjs/core/http/interfaces.js +3 -0
  85. package/dist/cjs/core/rate-limiter/RateLimiter.d.ts +46 -0
  86. package/dist/cjs/core/rate-limiter/RateLimiter.d.ts.map +1 -0
  87. package/dist/cjs/core/rate-limiter/RateLimiter.js +110 -0
  88. package/dist/cjs/core/rate-limiter/index.d.ts +3 -0
  89. package/dist/cjs/core/rate-limiter/index.d.ts.map +1 -0
  90. package/dist/cjs/core/rate-limiter/index.js +6 -0
  91. package/dist/cjs/filters/index.d.ts +2 -0
  92. package/dist/cjs/filters/index.d.ts.map +1 -0
  93. package/dist/cjs/filters/index.js +10 -0
  94. package/dist/cjs/filters/predicates.d.ts +85 -0
  95. package/dist/cjs/filters/predicates.d.ts.map +1 -0
  96. package/dist/cjs/filters/predicates.js +111 -0
  97. package/dist/cjs/index.d.ts +11 -0
  98. package/dist/cjs/index.d.ts.map +1 -0
  99. package/dist/cjs/index.js +27 -0
  100. package/dist/cjs/middleware/compose.d.ts +28 -0
  101. package/dist/cjs/middleware/compose.d.ts.map +1 -0
  102. package/dist/cjs/middleware/compose.js +89 -0
  103. package/dist/cjs/middleware/index.d.ts +3 -0
  104. package/dist/cjs/middleware/index.d.ts.map +1 -0
  105. package/dist/cjs/middleware/index.js +7 -0
  106. package/dist/cjs/middleware/types.d.ts +17 -0
  107. package/dist/cjs/middleware/types.d.ts.map +1 -0
  108. package/dist/cjs/middleware/types.js +3 -0
  109. package/dist/cjs/package.json +3 -0
  110. package/dist/cjs/transport/LongPollingTransport.d.ts +33 -0
  111. package/dist/cjs/transport/LongPollingTransport.d.ts.map +1 -0
  112. package/dist/cjs/transport/LongPollingTransport.js +153 -0
  113. package/dist/cjs/transport/WebhookTransport.d.ts +40 -0
  114. package/dist/cjs/transport/WebhookTransport.d.ts.map +1 -0
  115. package/dist/cjs/transport/WebhookTransport.js +229 -0
  116. package/dist/cjs/transport/index.d.ts +4 -0
  117. package/dist/cjs/transport/index.d.ts.map +1 -0
  118. package/dist/cjs/transport/index.js +8 -0
  119. package/dist/cjs/transport/interfaces.d.ts +74 -0
  120. package/dist/cjs/transport/interfaces.d.ts.map +1 -0
  121. package/dist/cjs/transport/interfaces.js +3 -0
  122. package/dist/cjs/types/bot.d.ts +19 -0
  123. package/dist/cjs/types/bot.d.ts.map +1 -0
  124. package/dist/cjs/types/bot.js +3 -0
  125. package/dist/cjs/types/chat.d.ts +94 -0
  126. package/dist/cjs/types/chat.d.ts.map +1 -0
  127. package/dist/cjs/types/chat.js +3 -0
  128. package/dist/cjs/types/common.d.ts +38 -0
  129. package/dist/cjs/types/common.d.ts.map +1 -0
  130. package/dist/cjs/types/common.js +6 -0
  131. package/dist/cjs/types/index.d.ts +9 -0
  132. package/dist/cjs/types/index.d.ts.map +1 -0
  133. package/dist/cjs/types/index.js +26 -0
  134. package/dist/cjs/types/keyboard.d.ts +97 -0
  135. package/dist/cjs/types/keyboard.d.ts.map +1 -0
  136. package/dist/cjs/types/keyboard.js +3 -0
  137. package/dist/cjs/types/message.d.ts +162 -0
  138. package/dist/cjs/types/message.d.ts.map +1 -0
  139. package/dist/cjs/types/message.js +3 -0
  140. package/dist/cjs/types/subscription.d.ts +23 -0
  141. package/dist/cjs/types/subscription.d.ts.map +1 -0
  142. package/dist/cjs/types/subscription.js +3 -0
  143. package/dist/cjs/types/update.d.ts +99 -0
  144. package/dist/cjs/types/update.d.ts.map +1 -0
  145. package/dist/cjs/types/update.js +3 -0
  146. package/dist/cjs/types/upload.d.ts +29 -0
  147. package/dist/cjs/types/upload.d.ts.map +1 -0
  148. package/dist/cjs/types/upload.js +3 -0
  149. package/dist/cjs/utils/Histogram.d.ts +93 -0
  150. package/dist/cjs/utils/Histogram.d.ts.map +1 -0
  151. package/dist/cjs/utils/Histogram.js +103 -0
  152. package/dist/cjs/utils/assertNever.d.ts +19 -0
  153. package/dist/cjs/utils/assertNever.d.ts.map +1 -0
  154. package/dist/cjs/utils/assertNever.js +24 -0
  155. package/dist/cjs/utils/format.d.ts +22 -0
  156. package/dist/cjs/utils/format.d.ts.map +1 -0
  157. package/dist/cjs/utils/format.js +25 -0
  158. package/dist/cjs/utils/index.d.ts +6 -0
  159. package/dist/cjs/utils/index.d.ts.map +1 -0
  160. package/dist/cjs/utils/index.js +14 -0
  161. package/dist/cjs/utils/keyboard.d.ts +70 -0
  162. package/dist/cjs/utils/keyboard.d.ts.map +1 -0
  163. package/dist/cjs/utils/keyboard.js +166 -0
  164. package/dist/esm/api/BotsApi.d.ts +17 -0
  165. package/dist/esm/api/BotsApi.d.ts.map +1 -0
  166. package/dist/esm/api/BotsApi.js +18 -0
  167. package/dist/esm/api/ChatsApi.d.ts +87 -0
  168. package/dist/esm/api/ChatsApi.d.ts.map +1 -0
  169. package/dist/esm/api/ChatsApi.js +140 -0
  170. package/dist/esm/api/MessagesApi.d.ts +41 -0
  171. package/dist/esm/api/MessagesApi.d.ts.map +1 -0
  172. package/dist/esm/api/MessagesApi.js +62 -0
  173. package/dist/esm/api/SubscriptionsApi.d.ts +45 -0
  174. package/dist/esm/api/SubscriptionsApi.d.ts.map +1 -0
  175. package/dist/esm/api/SubscriptionsApi.js +65 -0
  176. package/dist/esm/api/UploadsApi.d.ts +45 -0
  177. package/dist/esm/api/UploadsApi.d.ts.map +1 -0
  178. package/dist/esm/api/UploadsApi.js +109 -0
  179. package/dist/esm/api/index.d.ts +7 -0
  180. package/dist/esm/api/index.d.ts.map +1 -0
  181. package/dist/esm/api/index.js +6 -0
  182. package/dist/esm/api/interfaces.d.ts +108 -0
  183. package/dist/esm/api/interfaces.d.ts.map +1 -0
  184. package/dist/esm/api/interfaces.js +2 -0
  185. package/dist/esm/bot/Bot.d.ts +380 -0
  186. package/dist/esm/bot/Bot.d.ts.map +1 -0
  187. package/dist/esm/bot/Bot.js +620 -0
  188. package/dist/esm/bot/Composer.d.ts +131 -0
  189. package/dist/esm/bot/Composer.d.ts.map +1 -0
  190. package/dist/esm/bot/Composer.js +214 -0
  191. package/dist/esm/bot/context/BotStartedContext.d.ts +83 -0
  192. package/dist/esm/bot/context/BotStartedContext.d.ts.map +1 -0
  193. package/dist/esm/bot/context/BotStartedContext.js +109 -0
  194. package/dist/esm/bot/context/CallbackContext.d.ts +107 -0
  195. package/dist/esm/bot/context/CallbackContext.d.ts.map +1 -0
  196. package/dist/esm/bot/context/CallbackContext.js +154 -0
  197. package/dist/esm/bot/context/ChatContext.d.ts +35 -0
  198. package/dist/esm/bot/context/ChatContext.d.ts.map +1 -0
  199. package/dist/esm/bot/context/ChatContext.js +48 -0
  200. package/dist/esm/bot/context/MessageContext.d.ts +149 -0
  201. package/dist/esm/bot/context/MessageContext.d.ts.map +1 -0
  202. package/dist/esm/bot/context/MessageContext.js +224 -0
  203. package/dist/esm/bot/context/guards.d.ts +69 -0
  204. package/dist/esm/bot/context/guards.d.ts.map +1 -0
  205. package/dist/esm/bot/context/guards.js +78 -0
  206. package/dist/esm/bot/context/index.d.ts +6 -0
  207. package/dist/esm/bot/context/index.d.ts.map +1 -0
  208. package/dist/esm/bot/context/index.js +6 -0
  209. package/dist/esm/bot/dispatch.d.ts +51 -0
  210. package/dist/esm/bot/dispatch.d.ts.map +1 -0
  211. package/dist/esm/bot/dispatch.js +197 -0
  212. package/dist/esm/bot/index.d.ts +10 -0
  213. package/dist/esm/bot/index.d.ts.map +1 -0
  214. package/dist/esm/bot/index.js +9 -0
  215. package/dist/esm/bot/lifecycle.d.ts +85 -0
  216. package/dist/esm/bot/lifecycle.d.ts.map +1 -0
  217. package/dist/esm/bot/lifecycle.js +163 -0
  218. package/dist/esm/bot/metrics.d.ts +18 -0
  219. package/dist/esm/bot/metrics.d.ts.map +1 -0
  220. package/dist/esm/bot/metrics.js +2 -0
  221. package/dist/esm/bot/routing.d.ts +131 -0
  222. package/dist/esm/bot/routing.d.ts.map +1 -0
  223. package/dist/esm/bot/routing.js +194 -0
  224. package/dist/esm/bot/triggers.d.ts +61 -0
  225. package/dist/esm/bot/triggers.d.ts.map +1 -0
  226. package/dist/esm/bot/triggers.js +80 -0
  227. package/dist/esm/core/errors/MaxError.d.ts +11 -0
  228. package/dist/esm/core/errors/MaxError.d.ts.map +1 -0
  229. package/dist/esm/core/errors/MaxError.js +15 -0
  230. package/dist/esm/core/errors/errors.d.ts +59 -0
  231. package/dist/esm/core/errors/errors.d.ts.map +1 -0
  232. package/dist/esm/core/errors/errors.js +75 -0
  233. package/dist/esm/core/errors/index.d.ts +3 -0
  234. package/dist/esm/core/errors/index.d.ts.map +1 -0
  235. package/dist/esm/core/errors/index.js +3 -0
  236. package/dist/esm/core/http/HttpClient.d.ts +28 -0
  237. package/dist/esm/core/http/HttpClient.d.ts.map +1 -0
  238. package/dist/esm/core/http/HttpClient.js +144 -0
  239. package/dist/esm/core/http/index.d.ts +3 -0
  240. package/dist/esm/core/http/index.d.ts.map +1 -0
  241. package/dist/esm/core/http/index.js +2 -0
  242. package/dist/esm/core/http/interfaces.d.ts +42 -0
  243. package/dist/esm/core/http/interfaces.d.ts.map +1 -0
  244. package/dist/esm/core/http/interfaces.js +2 -0
  245. package/dist/esm/core/rate-limiter/RateLimiter.d.ts +46 -0
  246. package/dist/esm/core/rate-limiter/RateLimiter.d.ts.map +1 -0
  247. package/dist/esm/core/rate-limiter/RateLimiter.js +106 -0
  248. package/dist/esm/core/rate-limiter/index.d.ts +3 -0
  249. package/dist/esm/core/rate-limiter/index.d.ts.map +1 -0
  250. package/dist/esm/core/rate-limiter/index.js +2 -0
  251. package/dist/esm/filters/index.d.ts +2 -0
  252. package/dist/esm/filters/index.d.ts.map +1 -0
  253. package/dist/esm/filters/index.js +2 -0
  254. package/dist/esm/filters/predicates.d.ts +85 -0
  255. package/dist/esm/filters/predicates.d.ts.map +1 -0
  256. package/dist/esm/filters/predicates.js +104 -0
  257. package/dist/esm/index.d.ts +11 -0
  258. package/dist/esm/index.d.ts.map +1 -0
  259. package/dist/esm/index.js +11 -0
  260. package/dist/esm/middleware/compose.d.ts +28 -0
  261. package/dist/esm/middleware/compose.d.ts.map +1 -0
  262. package/dist/esm/middleware/compose.js +85 -0
  263. package/dist/esm/middleware/index.d.ts +3 -0
  264. package/dist/esm/middleware/index.d.ts.map +1 -0
  265. package/dist/esm/middleware/index.js +2 -0
  266. package/dist/esm/middleware/types.d.ts +17 -0
  267. package/dist/esm/middleware/types.d.ts.map +1 -0
  268. package/dist/esm/middleware/types.js +2 -0
  269. package/dist/esm/transport/LongPollingTransport.d.ts +33 -0
  270. package/dist/esm/transport/LongPollingTransport.d.ts.map +1 -0
  271. package/dist/esm/transport/LongPollingTransport.js +149 -0
  272. package/dist/esm/transport/WebhookTransport.d.ts +40 -0
  273. package/dist/esm/transport/WebhookTransport.d.ts.map +1 -0
  274. package/dist/esm/transport/WebhookTransport.js +225 -0
  275. package/dist/esm/transport/index.d.ts +4 -0
  276. package/dist/esm/transport/index.d.ts.map +1 -0
  277. package/dist/esm/transport/index.js +3 -0
  278. package/dist/esm/transport/interfaces.d.ts +74 -0
  279. package/dist/esm/transport/interfaces.d.ts.map +1 -0
  280. package/dist/esm/transport/interfaces.js +2 -0
  281. package/dist/esm/types/bot.d.ts +19 -0
  282. package/dist/esm/types/bot.d.ts.map +1 -0
  283. package/dist/esm/types/bot.js +2 -0
  284. package/dist/esm/types/chat.d.ts +94 -0
  285. package/dist/esm/types/chat.d.ts.map +1 -0
  286. package/dist/esm/types/chat.js +2 -0
  287. package/dist/esm/types/common.d.ts +38 -0
  288. package/dist/esm/types/common.d.ts.map +1 -0
  289. package/dist/esm/types/common.js +5 -0
  290. package/dist/esm/types/index.d.ts +9 -0
  291. package/dist/esm/types/index.d.ts.map +1 -0
  292. package/dist/esm/types/index.js +10 -0
  293. package/dist/esm/types/keyboard.d.ts +97 -0
  294. package/dist/esm/types/keyboard.d.ts.map +1 -0
  295. package/dist/esm/types/keyboard.js +2 -0
  296. package/dist/esm/types/message.d.ts +162 -0
  297. package/dist/esm/types/message.d.ts.map +1 -0
  298. package/dist/esm/types/message.js +2 -0
  299. package/dist/esm/types/subscription.d.ts +23 -0
  300. package/dist/esm/types/subscription.d.ts.map +1 -0
  301. package/dist/esm/types/subscription.js +2 -0
  302. package/dist/esm/types/update.d.ts +99 -0
  303. package/dist/esm/types/update.d.ts.map +1 -0
  304. package/dist/esm/types/update.js +2 -0
  305. package/dist/esm/types/upload.d.ts +29 -0
  306. package/dist/esm/types/upload.d.ts.map +1 -0
  307. package/dist/esm/types/upload.js +2 -0
  308. package/dist/esm/utils/Histogram.d.ts +93 -0
  309. package/dist/esm/utils/Histogram.d.ts.map +1 -0
  310. package/dist/esm/utils/Histogram.js +99 -0
  311. package/dist/esm/utils/assertNever.d.ts +19 -0
  312. package/dist/esm/utils/assertNever.d.ts.map +1 -0
  313. package/dist/esm/utils/assertNever.js +21 -0
  314. package/dist/esm/utils/format.d.ts +22 -0
  315. package/dist/esm/utils/format.d.ts.map +1 -0
  316. package/dist/esm/utils/format.js +22 -0
  317. package/dist/esm/utils/index.d.ts +6 -0
  318. package/dist/esm/utils/index.d.ts.map +1 -0
  319. package/dist/esm/utils/index.js +5 -0
  320. package/dist/esm/utils/keyboard.d.ts +70 -0
  321. package/dist/esm/utils/keyboard.d.ts.map +1 -0
  322. package/dist/esm/utils/keyboard.js +162 -0
  323. package/dist/types/api/BotsApi.d.ts +17 -0
  324. package/dist/types/api/BotsApi.d.ts.map +1 -0
  325. package/dist/types/api/ChatsApi.d.ts +87 -0
  326. package/dist/types/api/ChatsApi.d.ts.map +1 -0
  327. package/dist/types/api/MessagesApi.d.ts +41 -0
  328. package/dist/types/api/MessagesApi.d.ts.map +1 -0
  329. package/dist/types/api/SubscriptionsApi.d.ts +45 -0
  330. package/dist/types/api/SubscriptionsApi.d.ts.map +1 -0
  331. package/dist/types/api/UploadsApi.d.ts +45 -0
  332. package/dist/types/api/UploadsApi.d.ts.map +1 -0
  333. package/dist/types/api/index.d.ts +7 -0
  334. package/dist/types/api/index.d.ts.map +1 -0
  335. package/dist/types/api/interfaces.d.ts +108 -0
  336. package/dist/types/api/interfaces.d.ts.map +1 -0
  337. package/dist/types/bot/Bot.d.ts +380 -0
  338. package/dist/types/bot/Bot.d.ts.map +1 -0
  339. package/dist/types/bot/Composer.d.ts +131 -0
  340. package/dist/types/bot/Composer.d.ts.map +1 -0
  341. package/dist/types/bot/context/BotStartedContext.d.ts +83 -0
  342. package/dist/types/bot/context/BotStartedContext.d.ts.map +1 -0
  343. package/dist/types/bot/context/CallbackContext.d.ts +107 -0
  344. package/dist/types/bot/context/CallbackContext.d.ts.map +1 -0
  345. package/dist/types/bot/context/ChatContext.d.ts +35 -0
  346. package/dist/types/bot/context/ChatContext.d.ts.map +1 -0
  347. package/dist/types/bot/context/MessageContext.d.ts +149 -0
  348. package/dist/types/bot/context/MessageContext.d.ts.map +1 -0
  349. package/dist/types/bot/context/guards.d.ts +69 -0
  350. package/dist/types/bot/context/guards.d.ts.map +1 -0
  351. package/dist/types/bot/context/index.d.ts +6 -0
  352. package/dist/types/bot/context/index.d.ts.map +1 -0
  353. package/dist/types/bot/dispatch.d.ts +51 -0
  354. package/dist/types/bot/dispatch.d.ts.map +1 -0
  355. package/dist/types/bot/index.d.ts +10 -0
  356. package/dist/types/bot/index.d.ts.map +1 -0
  357. package/dist/types/bot/lifecycle.d.ts +85 -0
  358. package/dist/types/bot/lifecycle.d.ts.map +1 -0
  359. package/dist/types/bot/metrics.d.ts +18 -0
  360. package/dist/types/bot/metrics.d.ts.map +1 -0
  361. package/dist/types/bot/routing.d.ts +131 -0
  362. package/dist/types/bot/routing.d.ts.map +1 -0
  363. package/dist/types/bot/triggers.d.ts +61 -0
  364. package/dist/types/bot/triggers.d.ts.map +1 -0
  365. package/dist/types/core/errors/MaxError.d.ts +11 -0
  366. package/dist/types/core/errors/MaxError.d.ts.map +1 -0
  367. package/dist/types/core/errors/errors.d.ts +59 -0
  368. package/dist/types/core/errors/errors.d.ts.map +1 -0
  369. package/dist/types/core/errors/index.d.ts +3 -0
  370. package/dist/types/core/errors/index.d.ts.map +1 -0
  371. package/dist/types/core/http/HttpClient.d.ts +28 -0
  372. package/dist/types/core/http/HttpClient.d.ts.map +1 -0
  373. package/dist/types/core/http/index.d.ts +3 -0
  374. package/dist/types/core/http/index.d.ts.map +1 -0
  375. package/dist/types/core/http/interfaces.d.ts +42 -0
  376. package/dist/types/core/http/interfaces.d.ts.map +1 -0
  377. package/dist/types/core/rate-limiter/RateLimiter.d.ts +46 -0
  378. package/dist/types/core/rate-limiter/RateLimiter.d.ts.map +1 -0
  379. package/dist/types/core/rate-limiter/index.d.ts +3 -0
  380. package/dist/types/core/rate-limiter/index.d.ts.map +1 -0
  381. package/dist/types/filters/index.d.ts +2 -0
  382. package/dist/types/filters/index.d.ts.map +1 -0
  383. package/dist/types/filters/predicates.d.ts +85 -0
  384. package/dist/types/filters/predicates.d.ts.map +1 -0
  385. package/dist/types/index.d.ts +11 -0
  386. package/dist/types/index.d.ts.map +1 -0
  387. package/dist/types/middleware/compose.d.ts +28 -0
  388. package/dist/types/middleware/compose.d.ts.map +1 -0
  389. package/dist/types/middleware/index.d.ts +3 -0
  390. package/dist/types/middleware/index.d.ts.map +1 -0
  391. package/dist/types/middleware/types.d.ts +17 -0
  392. package/dist/types/middleware/types.d.ts.map +1 -0
  393. package/dist/types/transport/LongPollingTransport.d.ts +33 -0
  394. package/dist/types/transport/LongPollingTransport.d.ts.map +1 -0
  395. package/dist/types/transport/WebhookTransport.d.ts +40 -0
  396. package/dist/types/transport/WebhookTransport.d.ts.map +1 -0
  397. package/dist/types/transport/index.d.ts +4 -0
  398. package/dist/types/transport/index.d.ts.map +1 -0
  399. package/dist/types/transport/interfaces.d.ts +74 -0
  400. package/dist/types/transport/interfaces.d.ts.map +1 -0
  401. package/dist/types/types/bot.d.ts +19 -0
  402. package/dist/types/types/bot.d.ts.map +1 -0
  403. package/dist/types/types/chat.d.ts +94 -0
  404. package/dist/types/types/chat.d.ts.map +1 -0
  405. package/dist/types/types/common.d.ts +38 -0
  406. package/dist/types/types/common.d.ts.map +1 -0
  407. package/dist/types/types/index.d.ts +9 -0
  408. package/dist/types/types/index.d.ts.map +1 -0
  409. package/dist/types/types/keyboard.d.ts +97 -0
  410. package/dist/types/types/keyboard.d.ts.map +1 -0
  411. package/dist/types/types/message.d.ts +162 -0
  412. package/dist/types/types/message.d.ts.map +1 -0
  413. package/dist/types/types/subscription.d.ts +23 -0
  414. package/dist/types/types/subscription.d.ts.map +1 -0
  415. package/dist/types/types/update.d.ts +99 -0
  416. package/dist/types/types/update.d.ts.map +1 -0
  417. package/dist/types/types/upload.d.ts +29 -0
  418. package/dist/types/types/upload.d.ts.map +1 -0
  419. package/dist/types/utils/Histogram.d.ts +93 -0
  420. package/dist/types/utils/Histogram.d.ts.map +1 -0
  421. package/dist/types/utils/assertNever.d.ts +19 -0
  422. package/dist/types/utils/assertNever.d.ts.map +1 -0
  423. package/dist/types/utils/format.d.ts +22 -0
  424. package/dist/types/utils/format.d.ts.map +1 -0
  425. package/dist/types/utils/index.d.ts +6 -0
  426. package/dist/types/utils/index.d.ts.map +1 -0
  427. package/dist/types/utils/keyboard.d.ts +70 -0
  428. package/dist/types/utils/keyboard.d.ts.map +1 -0
  429. package/package.json +84 -0
package/README.md ADDED
@@ -0,0 +1,1176 @@
1
+ # @dementevdev/maxbot-ts
2
+
3
+ TypeScript SDK для MAX Bot API.
4
+
5
+ - Базовый URL: <https://platform-api.max.ru>
6
+ - Node.js >= 18 (встроенный fetch)
7
+
8
+ ## Содержание
9
+
10
+ **Начало работы**
11
+
12
+ - [Установка](#установка)
13
+ - [Быстрый старт](#быстрый-старт)
14
+ - [Стабильность API](#стабильность-api)
15
+
16
+ **Конфигурация**
17
+
18
+ - [Ограничение параллелизма](#ограничение-параллелизма-обновлений)
19
+ - [Webhook](#webhook)
20
+ - [allowedUpdates — фильтрация типов обновлений](#allowedupdates--фильтрация-типов-обновлений)
21
+
22
+ **Возможности**
23
+
24
+ - [Inline‑клавиатура](#inline-клавиатура)
25
+ - [Загрузка файлов](#загрузка-файлов)
26
+ - [Работа с ошибками](#работа-с-ошибками)
27
+ - [Метрики и наблюдаемость](#метрики-и-наблюдаемость)
28
+ - [Рекомендации по concurrency](#рекомендации-по-параметру-concurrency)
29
+
30
+ **Маршрутизация**
31
+
32
+ - [Middleware-пайплайн](#bot-use--глобальные-middleware)
33
+ - [Filter DSL](#filter-dsl)
34
+ - [Composer — суб-роутер](#composer--суб-роутер)
35
+ - [bot.filter() / ctx.has()](#botfilter--ctxhas)
36
+
37
+ **Продвинутое использование**
38
+
39
+ - [Расширение контекста](#расширение-контекста-custom-context)
40
+ - [Паттерны](#паттерны-patterns)
41
+ - [Migration Guide](#migration-guide-от-handlers-к-middleware)
42
+
43
+ **Справочник**
44
+
45
+ - [Локальные примеры](#локальные-примеры)
46
+ - [API](#api)
47
+ - [Форматы вложений](#формат-contact-вложения-request_contact)
48
+ - [Sub-entry points](#sub-entry-points-tree-shaking)
49
+ - [Versioning](#versioning-semver-policy)
50
+
51
+ ---
52
+
53
+ ## Установка
54
+
55
+ ```bash
56
+ npm i @dementevdev/maxbot-ts
57
+ ```
58
+
59
+ ## Быстрый старт
60
+
61
+ ```ts
62
+ import { Bot } from "@dementevdev/maxbot-ts";
63
+
64
+ const bot = new Bot({
65
+ token: process.env.MAX_BOT_TOKEN!,
66
+ transport: "polling",
67
+ });
68
+
69
+ bot.onMessage(async (ctx) => {
70
+ await ctx.reply("Привет!");
71
+ });
72
+
73
+ // Graceful shutdown: дожидаемся завершения текущих обработчиков
74
+ process.once("SIGINT", async () => {
75
+ await bot.stop();
76
+ process.exit(0);
77
+ });
78
+
79
+ await bot.start();
80
+ ```
81
+
82
+ > **Webhook:** замените `transport: "polling"` на `transport: "webhook"` и добавьте секцию `webhook: { port, url }` — см. [раздел Webhook](#webhook) ниже.
83
+
84
+ ## Стабильность API
85
+
86
+ Пакет следует [SemVer](https://semver.org/). Список **стабильных** экспортов с v1.0.0:
87
+
88
+ | Категория | Символы |
89
+ | ---------------- | --------------------------------------------------------------------------------------------------------- |
90
+ | Бот | `Bot`, `BotConfig`, `Context`, `EventHandler` |
91
+ | Контексты | `MessageContext`, `CallbackContext`, `ChatContext`, `BotStartedContext` |
92
+ | Маршрутизация | `bot.command()`, `bot.hears()`, `bot.action()`, `bot.on()`, `bot.use()`, `bot.filter()` |
93
+ | Триггеры | `HearsTrigger`, `CommandTrigger`, `matchCommand` |
94
+ | Жизненный цикл | `bot.start()`, `bot.stop()`, `bot.getMe()`, `bot.sendMessage()`, `bot.sendPrivateMessage()` |
95
+ | Утилиты | `InlineKeyboard`, `md`, `html`, `Histogram`, `DEFAULT_BUCKETS` |
96
+ | Ошибки | `MaxError`, `RateLimitError`, `AuthError`, `NetworkError`, `ApiError`, `ValidationError`, `NotFoundError` |
97
+ | Composer | `Composer`, `Filter` |
98
+ | Фильтры | `hasText`, `isPrivateChat`, `commandIs`, `hasCallbackPayload`, `payloadIs` |
99
+ | Sub-entry points | `@dementevdev/maxbot-ts/middleware`, `@dementevdev/maxbot-ts/filters` |
100
+
101
+ **Experimental** (сигнатуры стабильны, могут расширяться до v2.0.0): `BotMetrics`, `onMetrics`, `HistogramSnapshot`.
102
+
103
+ Полная semver-политика → [раздел Versioning](#versioning-semver-policy) в конце документа.
104
+
105
+ ---
106
+
107
+ ## Ограничение параллелизма обновлений
108
+
109
+ По умолчанию бот обрабатывает не более 10 обновлений одновременно (`concurrency: 10`).
110
+ Это защищает от burst-нагрузки: новые обновления ждут в очереди, а не запускают
111
+ неограниченное число параллельных промисов.
112
+
113
+ ```ts
114
+ import { Bot } from "@dementevdev/maxbot-ts";
115
+
116
+ const bot = new Bot({
117
+ token: process.env.MAX_BOT_TOKEN!,
118
+ transport: "polling",
119
+ concurrency: 20, // максимум 20 одновременно обрабатываемых update
120
+ });
121
+ ```
122
+
123
+ - Ограничение применяется на уровне одного update.
124
+ - Все хендлеры внутри одного update выполняются параллельно.
125
+ - `Infinity` отключает ограничение и возвращает прежнее поведение.
126
+
127
+ ## Webhook
128
+
129
+ ```ts
130
+ import { Bot } from "@dementevdev/maxbot-ts";
131
+
132
+ const bot = new Bot({
133
+ token: process.env.MAX_BOT_TOKEN!,
134
+ transport: "webhook",
135
+ webhook: {
136
+ port: 3000,
137
+ url: "https://mybot.example.com/webhook",
138
+ autoRegister: true,
139
+ secretToken: process.env.WEBHOOK_SECRET,
140
+ },
141
+ });
142
+
143
+ bot.onMessage(async (ctx) => {
144
+ await ctx.reply("Привет!");
145
+ });
146
+
147
+ bot.start();
148
+ ```
149
+
150
+ ## allowedUpdates — фильтрация типов обновлений
151
+
152
+ По умолчанию бот получает все типы обновлений. Опция `allowedUpdates` в `polling` позволяет
153
+ указать только нужные — сервер не будет отправлять остальные, снижая трафик.
154
+
155
+ ```ts
156
+ const bot = new Bot({
157
+ token: process.env.MAX_BOT_TOKEN!,
158
+ transport: "polling",
159
+ polling: {
160
+ allowedUpdates: ["message_created", "message_callback"],
161
+ },
162
+ });
163
+ ```
164
+
165
+ Доступные типы (`UpdateType`):
166
+
167
+ | Тип | Когда приходит |
168
+ | -------------------- | -------------------------------------- |
169
+ | `message_created` | Новое сообщение в чате или диалоге |
170
+ | `message_edited` | Редактирование сообщения |
171
+ | `message_removed` | Удаление сообщения |
172
+ | `message_callback` | Нажатие inline-кнопки |
173
+ | `bot_started` | Нажатие Start / переход по deep link |
174
+ | `bot_added` | Бот добавлен в чат |
175
+ | `bot_removed` | Бот удалён из чата |
176
+ | `user_added` | Пользователь добавлен в чат через бота |
177
+ | `user_removed` | Пользователь удалён из чата через бота |
178
+ | `chat_title_changed` | Изменение названия чата |
179
+
180
+ > Если не указать `allowedUpdates` — приходят все типы (поведение по умолчанию).
181
+
182
+ ## Inline‑клавиатура
183
+
184
+ ```ts
185
+ import { Bot, InlineKeyboard, md } from "@dementevdev/maxbot-ts";
186
+
187
+ const bot = new Bot({
188
+ token: process.env.MAX_BOT_TOKEN!,
189
+ transport: "polling",
190
+ });
191
+
192
+ bot.onMessage(async (ctx) => {
193
+ const keyboard = new InlineKeyboard()
194
+ .button("Да", "yes")
195
+ .row()
196
+ .button("Нет", "no")
197
+ .build();
198
+
199
+ await ctx.reply(md.bold("Выберите вариант:"), {
200
+ format: "markdown",
201
+ attachments: [keyboard],
202
+ });
203
+ });
204
+
205
+ bot.onCallback(async (ctx) => {
206
+ await ctx.answer({ notification: `Вы нажали: ${ctx.data}` });
207
+ });
208
+
209
+ bot.start();
210
+ ```
211
+
212
+ ## Загрузка файлов
213
+
214
+ Ограничения multipart upload:
215
+
216
+ - Максимальный размер файла: 4 ГБ
217
+ - Можно загружать только один файл за раз
218
+
219
+ ```ts
220
+ import { Bot } from "@dementevdev/maxbot-ts";
221
+ import { readFile } from "node:fs/promises";
222
+
223
+ const bot = new Bot({
224
+ token: process.env.MAX_BOT_TOKEN!,
225
+ transport: "polling",
226
+ });
227
+
228
+ async function uploadImage() {
229
+ const { url } = await bot.api.uploads.getUploadUrl("image");
230
+ const buffer = await readFile("./image.png");
231
+ const blob = new Blob([buffer]);
232
+
233
+ const payload = await bot.api.uploads.uploadFile(url, blob, "image.png");
234
+ return payload;
235
+ }
236
+ ```
237
+
238
+ ## Работа с ошибками
239
+
240
+ Все ошибки SDK наследуют `MaxError`. Иерархия:
241
+
242
+ | Класс | HTTP | Поля | Когда возникает |
243
+ | ----------------- | ------- | ------------------------- | ---------------------------------- |
244
+ | `RateLimitError` | 429 | `retryAfter: number` (мс) | Превышен лимит запросов к API |
245
+ | `AuthError` | 401 | — | Невалидный или отсутствующий токен |
246
+ | `ApiError` | 4xx/5xx | `statusCode`, `apiCode?` | Ошибка на стороне сервера MAX |
247
+ | `NotFoundError` | 404 | — | Чат / сообщение / ресурс не найден |
248
+ | `ValidationError` | — | — | Некорректные параметры вызова |
249
+ | `NetworkError` | — | `cause?: Error` | Таймаут, обрыв сети |
250
+ | `MaxError` | — | `message` | Базовый класс всех ошибок SDK |
251
+
252
+ ```ts
253
+ import {
254
+ Bot,
255
+ MaxError,
256
+ RateLimitError,
257
+ AuthError,
258
+ ApiError,
259
+ NetworkError,
260
+ } from "@dementevdev/maxbot-ts";
261
+
262
+ const bot = new Bot({
263
+ token: process.env.MAX_BOT_TOKEN!,
264
+ transport: "polling",
265
+ });
266
+
267
+ bot.onError((error) => {
268
+ if (error instanceof RateLimitError) {
269
+ // retryAfter — мс до следующего окна.
270
+ // Polling-транспорт сам делает паузу; здесь можно залогировать.
271
+ console.warn(`Rate limit, retry через ${error.retryAfter}мс`);
272
+ return;
273
+ }
274
+
275
+ if (error instanceof AuthError) {
276
+ console.error("Неверный токен — бот не может работать");
277
+ process.exit(1);
278
+ }
279
+
280
+ if (error instanceof NetworkError) {
281
+ // Временная ошибка сети — транспорт восстановится сам
282
+ console.warn("Сеть недоступна:", error.message);
283
+ return;
284
+ }
285
+
286
+ if (error instanceof MaxError) {
287
+ console.error("Ошибка SDK:", error.message);
288
+ return;
289
+ }
290
+
291
+ console.error("Неизвестная ошибка:", error);
292
+ });
293
+ ```
294
+
295
+ > **Retry-поведение**: polling-транспорт при `RateLimitError` автоматически выдерживает паузу `retryAfter` мс перед следующим запросом. При `NetworkError` — экспоненциальный backoff. Приложению не нужно реализовывать retry вручную.
296
+
297
+ ## Метрики и наблюдаемость
298
+
299
+ ### onMetrics — per-update метрики
300
+
301
+ ```ts
302
+ import { Bot } from "@dementevdev/maxbot-ts";
303
+ import type { BotMetrics } from "@dementevdev/maxbot-ts";
304
+
305
+ const bot = new Bot({
306
+ token: process.env.MAX_BOT_TOKEN!,
307
+ transport: "polling",
308
+ onMetrics: (m: BotMetrics) => {
309
+ // m.totalMs — общее время обработки update (middleware + handlers)
310
+ // m.middlewareTimes — массив ms по каждому middleware в порядке регистрации
311
+ // m.queueSizeAtStart — размер очереди ДО захвата слота (backpressure индикатор)
312
+ // m.handlerErrors — число ошибок в handlers для этого update
313
+ // m.updateType — тип update ('message_created', 'message_callback', ...)
314
+
315
+ if (m.totalMs > 500) {
316
+ console.warn(`Slow update: ${m.updateType} — ${m.totalMs}ms`);
317
+ }
318
+ if (m.queueSizeAtStart > 5) {
319
+ console.warn(`Queue pressure: ${m.queueSizeAtStart} waiting`);
320
+ }
321
+ if (m.handlerErrors > 0) {
322
+ console.error(`Handler errors: ${m.handlerErrors} in ${m.updateType}`);
323
+ }
324
+ },
325
+ });
326
+ ```
327
+
328
+ `onMetrics` не влияет на производительность если не задан — замер включается только при его наличии.
329
+
330
+ ### onSlowHandler — порог по времени
331
+
332
+ ```ts
333
+ // Срабатывает только если total time >= 200ms
334
+ bot.onSlowHandler(200, (ms, updateType) => {
335
+ console.warn(`Slow: ${updateType} — ${ms}ms`);
336
+ });
337
+ ```
338
+
339
+ Разница с `onMetrics`: `onSlowHandler` — простой threshold-алерт без детализации по middleware.
340
+
341
+ ### Histogram — гистограмма задержек
342
+
343
+ `Histogram` накапливает измерения `totalMs` по корзинам (buckets) в формате, совместимом с Prometheus.
344
+ Удобен для экспорта p50/p95/p99 в любую систему мониторинга.
345
+
346
+ ```ts
347
+ import { Bot, Histogram } from "@dementevdev/maxbot-ts";
348
+
349
+ const histogram = new Histogram(); // дефолтные корзины: 5, 10, 25, 50, 100, 250, 500, 1000 мс
350
+
351
+ const bot = new Bot({
352
+ token: process.env.MAX_BOT_TOKEN!,
353
+ transport: "polling",
354
+ onMetrics: (m) => histogram.observe(m.totalMs),
355
+ });
356
+
357
+ // Публикуем снимок раз в минуту
358
+ setInterval(() => {
359
+ const snap = histogram.snapshot();
360
+ // snap.buckets: { "5": 12, "10": 45, "25": 78, ..., "+Inf": 100 } — кумулятивно
361
+ // snap.count: 100 — общее число обновлений
362
+ // snap.sum: 3 200 — суммарное время в мс (для расчёта среднего: sum / count)
363
+ console.log(snap);
364
+ histogram.reset(); // сброс для следующего окна
365
+ }, 60_000);
366
+ ```
367
+
368
+ **Кастомные корзины** — передайте массив границ в мс:
369
+
370
+ ```ts
371
+ const h = new Histogram([10, 50, 200, 1000, 5000]);
372
+ ```
373
+
374
+ Корзины автоматически сортируются и дедуплицируются.
375
+
376
+ **Структура снимка** `HistogramSnapshot`:
377
+
378
+ | Поле | Тип | Описание |
379
+ | --------- | ------------------------ | ------------------------------------------------------------------------- |
380
+ | `buckets` | `Record<string, number>` | Кумулятивные счётчики: `"50"` = число наблюдений ≤ 50ms, `"+Inf"` = всего |
381
+ | `sum` | `number` | Сумма всех значений в мс |
382
+ | `count` | `number` | Число наблюдений (= `buckets["+Inf"]`) |
383
+
384
+ **Интеграция с Prometheus** через `prom-client`:
385
+
386
+ ```ts
387
+ import { Registry, Histogram as PromHistogram } from "prom-client";
388
+
389
+ const registry = new Registry();
390
+ const promHist = new PromHistogram({
391
+ name: "bot_update_duration_ms",
392
+ help: "Update processing duration",
393
+ buckets: [5, 10, 25, 50, 100, 250, 500, 1000],
394
+ registers: [registry],
395
+ });
396
+
397
+ bot = new Bot({
398
+ token: process.env.MAX_BOT_TOKEN!,
399
+ transport: "polling",
400
+ onMetrics: (m) => promHist.observe(m.totalMs),
401
+ });
402
+ ```
403
+
404
+ ---
405
+
406
+ ## Рекомендации по параметру concurrency
407
+
408
+ | Профиль бота | Рекомендуемое значение | Обоснование |
409
+ | ------------------------------------ | ---------------------- | ---------------------------------- |
410
+ | Приватные диалоги, быстрые ответы | `10` (по умолчанию) | Баланс параллелизма и защиты |
411
+ | Бот в большой группе / публичный | `20–50` | Больше одновременных пользователей |
412
+ | Webhook-бот с тяжёлой бизнес-логикой | `5–10` | Снизить нагрузку на downstream |
413
+ | Бот с медленными API-вызовами (> 1s) | `20–100` | Большинство времени — I/O ожидание |
414
+ | Минимальный сервис / отладка | `1` | Строгая очерёдность |
415
+ | Без ограничений (legacy-режим) | `Infinity` | Не рекомендуется в проде |
416
+
417
+ **Как определить правильное значение:**
418
+
419
+ 1. Запустите с `onMetrics` и наблюдайте `queueSizeAtStart`
420
+ 2. Если очередь стабильно > 0 — увеличьте `concurrency`
421
+ 3. Если растут ошибки downstream API — уменьшите
422
+ 4. Ориентир: `concurrency ≈ (среднее время handler) / (желаемая latency) × throughput`
423
+
424
+ ```ts
425
+ // Диагностика: подбор concurrency по метрикам
426
+ const bot = new Bot({
427
+ token: process.env.MAX_BOT_TOKEN!,
428
+ transport: "polling",
429
+ concurrency: 10, // начните с дефолта
430
+ onMetrics: (m) => {
431
+ // Если queueSizeAtStart регулярно > 3 — увеличьте concurrency
432
+ // Если totalMs растёт — возможно, downstream перегружен
433
+ console.log(
434
+ JSON.stringify({
435
+ type: m.updateType,
436
+ ms: m.totalMs,
437
+ queue: m.queueSizeAtStart,
438
+ errors: m.handlerErrors,
439
+ }),
440
+ );
441
+ },
442
+ });
443
+ ```
444
+
445
+ ---
446
+
447
+ SDK предоставляет полноценный middleware-пайплайн аналогично Koa/Telegraf.
448
+
449
+ ### bot.use() — глобальные middleware
450
+
451
+ ```ts
452
+ import { Bot } from "@dementevdev/maxbot-ts";
453
+
454
+ const bot = new Bot({
455
+ token: process.env.MAX_BOT_TOKEN!,
456
+ transport: "polling",
457
+ });
458
+
459
+ // Логирование каждого update
460
+ bot.use(async (ctx, next) => {
461
+ const start = Date.now();
462
+ await next();
463
+ console.log(`${ctx.raw.update_type} — ${Date.now() - start}ms`);
464
+ });
465
+
466
+ // Ранний выход без вызова next() останавливает пайплайн
467
+ bot.use(async (ctx, next) => {
468
+ if (ctx.raw.update_type === "message_created") {
469
+ const chatType = ctx.raw.message?.recipient?.chat_type;
470
+ if (chatType !== "dialog") return; // игнорируем групповые сообщения
471
+ }
472
+ await next();
473
+ });
474
+
475
+ bot.onMessage(async (ctx) => {
476
+ await ctx.reply("Привет из private chat!");
477
+ });
478
+
479
+ bot.start();
480
+ ```
481
+
482
+ Middleware выполняется **внутри одного слота семафора** — все ограничения
483
+ `concurrency` сохраняются даже при длинных middleware-цепочках.
484
+
485
+ ### bot.command() / bot.hears() / bot.action()
486
+
487
+ ```ts
488
+ // Команды (срабатывает на /start и /start <args>)
489
+ bot.command("start", async (ctx) => {
490
+ await ctx.reply("Добро пожаловать!");
491
+ });
492
+
493
+ // Произвольный текст: строка, RegExp или массив паттернов (HearsTrigger)
494
+ bot.hears(/^ping$/i, async (ctx) => {
495
+ await ctx.reply("pong 🏓");
496
+ });
497
+
498
+ // Массив — срабатывает если ANY из паттернов совпал (первый побеждает)
499
+ bot.hears(["привет", "hello", /^hi$/i], async (ctx) => {
500
+ await ctx.reply("Привет!");
501
+ });
502
+
503
+ // Нажатие inline-кнопки по payload (строка, RegExp или массив)
504
+ bot.action("confirm", async (ctx) => {
505
+ await ctx.answer({ notification: "Подтверждено ✓" });
506
+ });
507
+
508
+ // Несколько строковых payload — одним обработчиком
509
+ bot.action(["yes", "confirm", "ok"], async (ctx) => {
510
+ await ctx.answer({ notification: "Принято!" });
511
+ });
512
+
513
+ // Несколько RegExp-паттернов
514
+ bot.action([/^buy:(\d+)$/, /^sell:(\d+)$/], async (ctx) => {
515
+ if (isCallbackContext(ctx) && ctx.match) {
516
+ const id = ctx.match[1];
517
+ await ctx.answer({ notification: `Позиция #${id}` });
518
+ }
519
+ });
520
+
521
+ // Все методы возвращают this — можно чейнить
522
+ bot
523
+ .command("help", async (ctx) => ctx.reply("/start — начать"))
524
+ .hears("привет", async (ctx) => ctx.reply("Привет!"));
525
+ ```
526
+
527
+ > **`HearsTrigger`** — тип паттерна для `hears()` и `action()`:
528
+ > `string | RegExp | ReadonlyArray<string | RegExp>`.
529
+ > При массиве срабатывает первый совпавший паттерн; `ctx.match` устанавливается
530
+ > только если совпал RegExp.
531
+
532
+ ### Variadic middlewares
533
+
534
+ `command()`, `hears()`, `action()`, `on()`, `onMessage()`, `onCallback()`, `onStart()` принимают
535
+ произвольное число middleware перед финальным обработчиком.
536
+ Промежуточные должны вызвать `next()`, иначе цепочка прерывается.
537
+
538
+ ```ts
539
+ // Guard: блокирует неавторизованных
540
+ const authMw: Middleware<Context> = async (ctx, next) => {
541
+ if (!isAuthorized(ctx)) return; // next() не вызван → handler не выполнится
542
+ await next();
543
+ };
544
+
545
+ // Логирование
546
+ const logMw: Middleware<Context> = async (ctx, next) => {
547
+ console.log("before");
548
+ await next();
549
+ console.log("after");
550
+ };
551
+
552
+ bot.command("pay", authMw, logMw, async (ctx) => {
553
+ /* ... */
554
+ });
555
+ bot.hears(/^\d+/, authMw, async (ctx) => {
556
+ /* ... */
557
+ });
558
+ bot.action(/^buy:/, authMw, logMw, async (ctx) => {
559
+ /* ... */
560
+ });
561
+ bot.on("message_created", logMw, async (ctx) => {
562
+ /* ... */
563
+ });
564
+ ```
565
+
566
+ ### ctx.match — capture-группы RegExp
567
+
568
+ При использовании RegExp-паттерна в `hears()` и `action()` результат `exec()` сохраняется в `ctx.match`.
569
+ Для строкового паттерна `ctx.match` равен `null`.
570
+
571
+ ```ts
572
+ import { isMessageContext, isCallbackContext } from "@dementevdev/maxbot-ts";
573
+
574
+ // hears: извлекаем числа из текста
575
+ bot.hears(/(\d+)\+(\d+)/, async (ctx) => {
576
+ if (isMessageContext(ctx) && ctx.match) {
577
+ const a = Number(ctx.match[1]);
578
+ const b = Number(ctx.match[2]);
579
+ await ctx.reply(`${a} + ${b} = ${a + b}`);
580
+ }
581
+ });
582
+
583
+ // action: извлекаем id из payload кнопки вида "buy:42"
584
+ bot.action(/^buy:(\d+)$/, async (ctx) => {
585
+ if (isCallbackContext(ctx) && ctx.match) {
586
+ const productId = ctx.match[1]; // "42"
587
+ await ctx.answer({ notification: `Заказ #${productId} оформлен` });
588
+ }
589
+ });
590
+ ```
591
+
592
+ | Свойство | Тип | Доступно в | Значение при строковом паттерне |
593
+ | ----------- | ------------------------- | ----------------------------------- | ------------------------------- |
594
+ | `ctx.match` | `RegExpExecArray \| null` | `MessageContext`, `CallbackContext` | `null` |
595
+
596
+ ### bot.onStart() — deep link и старт бота
597
+
598
+ Событие `bot_started` возникает когда пользователь нажимает кнопку **Start** в диалоге
599
+ или переходит по ссылке вида `https://max.ru/...?start=<payload>`.
600
+
601
+ `ctx.startPayload` содержит значение параметра `start` из ссылки — используйте для
602
+ реферальных программ, onboarding-флоу и контекстного запуска.
603
+
604
+ ```ts
605
+ import { Bot, isBotStartedContext } from "@dementevdev/maxbot-ts";
606
+
607
+ const bot = new Bot({
608
+ token: process.env.MAX_BOT_TOKEN!,
609
+ transport: "polling",
610
+ });
611
+
612
+ // Convenience-метод — алиас для bot.on('bot_started', ...)
613
+ bot.onStart(async (ctx) => {
614
+ if (isBotStartedContext(ctx)) {
615
+ if (ctx.startPayload) {
616
+ // Пользователь перешёл по deep link: https://max.ru/...?start=ref_123
617
+ await ctx.reply(`Вы пришли по реферальной ссылке: ${ctx.startPayload}`);
618
+ } else {
619
+ // Обычный запуск без параметра
620
+ await ctx.reply("Добро пожаловать! Введите /help для справки.");
621
+ }
622
+ }
623
+ });
624
+
625
+ bot.start();
626
+ ```
627
+
628
+ | Свойство / метод | Тип | Описание |
629
+ | --------------------- | ----------------------------- | --------------------------------------- |
630
+ | `ctx.startPayload` | `string \| null \| undefined` | Payload из deep link, `null` если нет |
631
+ | `ctx.chatId` | `number` | ID диалога |
632
+ | `ctx.userId` | `number` | ID пользователя, нажавшего Start |
633
+ | `ctx.user` | `User` | Объект пользователя |
634
+ | `isBotStartedContext` | type guard | Сужает `Context` до `BotStartedContext` |
635
+
636
+ ### ctx.editMessage / ctx.deleteMessage / ctx.sendAction
637
+
638
+ Методы доступны в `MessageContext` и `CallbackContext`. `sendAction` также доступен в `BotStartedContext`.
639
+
640
+ ```ts
641
+ // ── MessageContext ──────────────────────────────────────────────────────────
642
+ bot.onMessage(async (ctx) => {
643
+ if (!isMessageContext(ctx)) return;
644
+
645
+ // Редактировать входящее сообщение (требует rights, обычно своё)
646
+ await ctx.editMessage("обновлённый текст");
647
+
648
+ // Удалить сообщение
649
+ await ctx.deleteMessage();
650
+
651
+ // Произвольное действие: 'typing_on', 'sending_photo', 'mark_seen', …
652
+ await ctx.sendAction("sending_file");
653
+
654
+ // sendTyping() — удобный псевдоним для sendAction('typing_on')
655
+ await ctx.sendTyping();
656
+ });
657
+
658
+ // ── CallbackContext ─────────────────────────────────────────────────────────
659
+ bot.onCallback(async (ctx) => {
660
+ if (!isCallbackContext(ctx)) return;
661
+
662
+ // Редактировать сообщение с кнопкой
663
+ await ctx.editMessage("результат обработан", { format: "markdown" });
664
+
665
+ // Удалить сообщение с кнопкой
666
+ await ctx.deleteMessage();
667
+
668
+ // Показать "печатает..." пока обрабатывается запрос
669
+ await ctx.sendAction("typing_on");
670
+ const result = await processRequest();
671
+ await ctx.reply(result);
672
+ });
673
+
674
+ // ── BotStartedContext ───────────────────────────────────────────────────────
675
+ bot.onStart(async (ctx) => {
676
+ if (!isBotStartedContext(ctx)) return;
677
+ await ctx.sendAction("typing_on");
678
+ await ctx.reply("Добро пожаловать!");
679
+ });
680
+ ```
681
+
682
+ | Метод | Доступен в | Бросает если |
683
+ | ------------------------------ | -------------------------------------------------------- | --------------- |
684
+ | `ctx.editMessage(text, opts?)` | `MessageContext`, `CallbackContext` | нет `messageId` |
685
+ | `ctx.deleteMessage()` | `MessageContext`, `CallbackContext` | нет `messageId` |
686
+ | `ctx.sendAction(action)` | `MessageContext`, `CallbackContext`, `BotStartedContext` | нет `chatId` |
687
+ | `ctx.sendTyping()` | `MessageContext` | нет `chatId` |
688
+
689
+ > `onSlowHandler` — см. раздел [Метрики и наблюдаемость](#метрики-и-наблюдаемость) выше.
690
+
691
+ ---
692
+
693
+ ## Filter DSL
694
+
695
+ Набор предикатов для type-safe фильтрации контекста в middleware:
696
+
697
+ ```ts
698
+ import {
699
+ Bot,
700
+ hasText,
701
+ isPrivateChat,
702
+ commandIs,
703
+ hasCallbackPayload,
704
+ payloadIs,
705
+ } from "@dementevdev/maxbot-ts";
706
+
707
+ const bot = new Bot({
708
+ token: process.env.MAX_BOT_TOKEN!,
709
+ transport: "polling",
710
+ });
711
+
712
+ const isStart = commandIs("start");
713
+ const isDeleteAction = payloadIs(/^delete:/);
714
+
715
+ bot.use(async (ctx, next) => {
716
+ if (isStart(ctx)) {
717
+ await ctx.reply("Привет! /help — список команд");
718
+ return;
719
+ }
720
+
721
+ if (isDeleteAction(ctx)) {
722
+ const id = ctx.data.split(":")[1]; // ctx: CallbackContext, ctx.data: string
723
+ await ctx.answer({ notification: `Удаляю ${id}` });
724
+ return;
725
+ }
726
+
727
+ if (hasText(ctx)) {
728
+ // ctx: MessageContext, ctx.text: string — без undefined
729
+ await ctx.reply(`Эхо: ${ctx.text}`);
730
+ return;
731
+ }
732
+
733
+ await next();
734
+ });
735
+ ```
736
+
737
+ | Предикат | Сужает тип | Описание |
738
+ | ------------------------- | ------------------------------------ | ------------------------------------------------- |
739
+ | `hasText(ctx)` | `MessageContext & { text: string }` | Сообщение с непустым текстом |
740
+ | `isPrivateChat(ctx)` | `MessageContext` | Приватный чат (dialog) |
741
+ | `commandIs(name)` | `MessageContext & { text: string }` | Фабрика — совпадение по команде |
742
+ | `hasCallbackPayload(ctx)` | `CallbackContext & { data: string }` | Callback с непустым payload |
743
+ | `payloadIs(pattern)` | `CallbackContext & { data: string }` | Фабрика — совпадение payload по строке или RegExp |
744
+
745
+ ---
746
+
747
+ ## Composer — суб-роутер
748
+
749
+ `Composer` — независимый роутер, который собирается отдельно от бота и подключается через `bot.use(composer.middleware())`. Поддерживает те же методы маршрутизации что и `Bot`: `command`, `hears`, `action`, `on`, `use`, `filter`.
750
+
751
+ ### Базовое использование
752
+
753
+ ```ts
754
+ import { Bot, Composer } from "@dementevdev/maxbot-ts";
755
+
756
+ const bot = new Bot({
757
+ token: process.env.MAX_BOT_TOKEN!,
758
+ transport: "polling",
759
+ });
760
+
761
+ const router = new Composer();
762
+ router.command("start", async (ctx) => ctx.reply("Привет!"));
763
+ router.hears(/(\d+)\+(\d+)/, async (ctx) => {
764
+ const [, a, b] = ctx.match!;
765
+ await ctx.reply(`${a} + ${b} = ${Number(a) + Number(b)}`);
766
+ });
767
+
768
+ bot.use(router.middleware());
769
+ await bot.start();
770
+ ```
771
+
772
+ ### Изоляция модулей
773
+
774
+ Разбивайте большой бот на независимые файлы — каждый экспортирует один `Composer`:
775
+
776
+ ```ts
777
+ // shop.ts
778
+ import { Composer } from "@dementevdev/maxbot-ts";
779
+ export const shopRouter = new Composer();
780
+
781
+ shopRouter.command("catalog", catalogHandler);
782
+ shopRouter.command("cart", cartHandler);
783
+ shopRouter.action(/^add:(\d+)/, addToCartHandler);
784
+
785
+ // admin.ts
786
+ import { Composer } from "@dementevdev/maxbot-ts";
787
+ import { isAdmin } from "./guards.js";
788
+ export const adminRouter = new Composer();
789
+
790
+ adminRouter.use(isAdmin); // middleware только для этого роутера
791
+ adminRouter.command("stats", statsHandler);
792
+ adminRouter.command("ban", banHandler);
793
+
794
+ // bot.ts
795
+ import { Bot } from "@dementevdev/maxbot-ts";
796
+ import { shopRouter } from "./shop.js";
797
+ import { adminRouter } from "./admin.js";
798
+
799
+ const bot = new Bot({
800
+ token: process.env.MAX_BOT_TOKEN!,
801
+ transport: "polling",
802
+ });
803
+ bot.use(shopRouter.middleware());
804
+ bot.use(adminRouter.middleware());
805
+ await bot.start();
806
+ ```
807
+
808
+ ### Вложенные Composer (under-router)
809
+
810
+ ```ts
811
+ const outer = new Composer();
812
+ const inner = new Composer();
813
+
814
+ inner.command("nested", handler);
815
+ outer.use(inner.middleware());
816
+
817
+ bot.use(outer.middleware());
818
+ ```
819
+
820
+ ### API
821
+
822
+ | Метод | Описание |
823
+ | --------------------------- | ----------------------------------------------------------- |
824
+ | `use(middleware)` | Добавить middleware в цепочку |
825
+ | `on(event, ...fns)` | Подписаться на `UpdateType` |
826
+ | `command(name, ...fns)` | Обработать команду `/name` |
827
+ | `hears(pattern, ...fns)` | Обработать текст (строка или RegExp, устанавливает `match`) |
828
+ | `action(pattern, ...fns)` | Обработать callback payload |
829
+ | `filter(predicate, ...fns)` | Запустить `fns` только если `predicate` вернул `true` |
830
+ | `middleware()` | Вернуть `Middleware` для `bot.use()` |
831
+
832
+ ---
833
+
834
+ ## bot.filter() / ctx.has()
835
+
836
+ ### bot.filter()
837
+
838
+ Подключить middleware только для контекстов, удовлетворяющих предикату. Несовпадающие обновления прозрачно перетекают к следующим обработчикам.
839
+
840
+ ```ts
841
+ import { Bot, hasText, isPrivateChat } from "@dementevdev/maxbot-ts";
842
+
843
+ const bot = new Bot({
844
+ token: process.env.MAX_BOT_TOKEN!,
845
+ transport: "polling",
846
+ });
847
+
848
+ // Только приватные чаты с текстом
849
+ bot.filter(isPrivateChat, async (ctx, next) => {
850
+ console.log("приватный чат");
851
+ await next();
852
+ });
853
+
854
+ // Только сообщения с текстом — ctx.text: string (не undefined)
855
+ bot.filter(hasText, async (ctx) => {
856
+ await ctx.reply(`Эхо: ${ctx.text}`);
857
+ });
858
+
859
+ // Комбинация: Composer подключается только для приватных чатов
860
+ const privateRouter = new Composer();
861
+ privateRouter.command("start", startHandler);
862
+
863
+ bot.filter(isPrivateChat, privateRouter.middleware());
864
+ ```
865
+
866
+ ### ctx.has()
867
+
868
+ Проверить тип контекста прямо внутри обработчика с автоматическим сужением типа:
869
+
870
+ ```ts
871
+ bot.use(async (ctx, next) => {
872
+ if (ctx.has(hasText)) {
873
+ // ctx: MessageContext & { text: string }
874
+ console.log(ctx.text.toUpperCase()); // ctx.text — string, не undefined
875
+ await ctx.sendTyping();
876
+ }
877
+
878
+ if (ctx.has(isCallbackContext)) {
879
+ // ctx: CallbackContext
880
+ await ctx.answer();
881
+ }
882
+
883
+ await next();
884
+ });
885
+ ```
886
+
887
+ Доступен на всех контекстах: `MessageContext`, `CallbackContext`, `ChatContext`, `BotStartedContext`.
888
+
889
+ ```ts
890
+ bot.onStart(async (ctx) => {
891
+ if (ctx.has(isPrivateChat)) {
892
+ // обрабатываем только приватный старт
893
+ }
894
+ });
895
+ ```
896
+
897
+ ---
898
+
899
+ ## Расширение контекста (Custom Context)
900
+
901
+ ```ts
902
+ import { Bot } from "@dementevdev/maxbot-ts";
903
+ import type { Context } from "@dementevdev/maxbot-ts";
904
+
905
+ // Тип расширенного контекста — intersection с базовым
906
+ type SessionCtx = Context & { session: { userId: number; count: number } };
907
+
908
+ const sessions = new Map<number, { userId: number; count: number }>();
909
+
910
+ const bot = new Bot<SessionCtx>({
911
+ token: process.env.MAX_BOT_TOKEN!,
912
+ transport: "polling",
913
+ contextFactory: (base): SessionCtx => {
914
+ const userId =
915
+ base.raw.update_type === "message_created"
916
+ ? base.raw.message.sender.user_id
917
+ : 0;
918
+ const session = sessions.get(userId) ?? { userId, count: 0 };
919
+ sessions.set(userId, session);
920
+ return Object.assign(base as SessionCtx, { session });
921
+ },
922
+ });
923
+
924
+ // В middleware ctx.session типизирован без кастов
925
+ bot.use(async (ctx, next) => {
926
+ ctx.session.count += 1;
927
+ await next();
928
+ });
929
+
930
+ bot.command("stats", async (ctx) => {
931
+ await ctx.reply(`Сообщений: ${ctx.session.count}`);
932
+ });
933
+ ```
934
+
935
+ ---
936
+
937
+ ## Паттерны (Patterns)
938
+
939
+ ### Паттерн 1: Слоистая middleware-архитектура
940
+
941
+ ```ts
942
+ // 1. Глобальная инфраструктура (логи, трейсинг)
943
+ bot.use(loggingMiddleware);
944
+ bot.use(tracingMiddleware);
945
+
946
+ // 2. Безопасность (auth, rate-limit)
947
+ bot.use(authMiddleware);
948
+ bot.use(rateLimitMiddleware);
949
+
950
+ // 3. Бизнес-роутинг
951
+ bot.command("start", startHandler);
952
+ bot.action(/^order:/, orderHandler);
953
+ bot.onMessage(fallbackHandler);
954
+ ```
955
+
956
+ ### Паттерн 2: Переиспользуемые предикаты
957
+
958
+ ```ts
959
+ // predicates.ts
960
+ export const isAdminMessage =
961
+ (adminIds: number[]) =>
962
+ (ctx: Context): ctx is MessageContext =>
963
+ ctx instanceof MessageContext &&
964
+ adminIds.includes(ctx.message.sender.user_id);
965
+
966
+ // bot.ts
967
+ const isAdmin = isAdminMessage([123456789]);
968
+
969
+ bot.use(async (ctx, next) => {
970
+ if (!isAdmin(ctx)) {
971
+ await ctx.reply("Нет доступа");
972
+ return;
973
+ }
974
+ await next();
975
+ });
976
+ ```
977
+
978
+ ### Паттерн 3: Корректный graceful shutdown
979
+
980
+ ```ts
981
+ import { Bot } from "@dementevdev/maxbot-ts";
982
+
983
+ const bot = new Bot({
984
+ token: process.env.MAX_BOT_TOKEN!,
985
+ transport: "polling",
986
+ });
987
+
988
+ bot.onMessage(async (ctx) => {
989
+ await ctx.reply("OK");
990
+ });
991
+
992
+ async function main() {
993
+ await bot.start();
994
+ console.log("Бот запущен");
995
+
996
+ // Graceful shutdown: ждём завершения текущих обработчиков
997
+ process.once("SIGINT", async () => {
998
+ console.log("Останавливаем бота...");
999
+ await bot.stop();
1000
+ process.exit(0);
1001
+ });
1002
+ }
1003
+
1004
+ main().catch(console.error);
1005
+ ```
1006
+
1007
+ ---
1008
+
1009
+ ## Migration Guide: от handlers к middleware
1010
+
1011
+ ### Было (handlers-only)
1012
+
1013
+ ```ts
1014
+ const bot = new Bot({ token, transport: "polling" });
1015
+
1016
+ bot.onMessage(async (ctx) => {
1017
+ if (!ctx.text) return;
1018
+ if (ctx.text === "/start") {
1019
+ await ctx.reply("Привет!");
1020
+ return;
1021
+ }
1022
+ await ctx.reply(`Эхо: ${ctx.text}`);
1023
+ });
1024
+
1025
+ bot.onCallback(async (ctx) => {
1026
+ if (ctx.data === "yes") await ctx.answer({ notification: "Да!" });
1027
+ });
1028
+ ```
1029
+
1030
+ ### Стало (middleware/composer — те же гарантии, лучший DX)
1031
+
1032
+ ```ts
1033
+ const bot = new Bot({ token, transport: "polling" });
1034
+
1035
+ // Опциональный глобальный middleware добавляется через use()
1036
+ // Старые onMessage/onCallback продолжают работать без изменений
1037
+
1038
+ bot.command("start", async (ctx) => {
1039
+ await ctx.reply("Привет!");
1040
+ });
1041
+
1042
+ bot.onMessage(async (ctx) => {
1043
+ if (!ctx.text || ctx.text.startsWith("/")) return;
1044
+ await ctx.reply(`Эхо: ${ctx.text}`);
1045
+ });
1046
+
1047
+ bot.action("yes", async (ctx) => {
1048
+ await ctx.answer({ notification: "Да!" });
1049
+ });
1050
+ ```
1051
+
1052
+ **Что изменилось:**
1053
+
1054
+ - `onMessage`/`onCallback` — полная обратная совместимость, работают как раньше
1055
+ - `bot.use()` добавляет middleware **до** всех существующих handlers
1056
+ - `bot.command()`, `bot.hears()`, `bot.action()` — sugar поверх `bot.on()`
1057
+ - Все middleware и handlers выполняются внутри одного semaphore-slot → `concurrency` по-прежнему работает
1058
+
1059
+ ---
1060
+
1061
+ ## Локальные примеры
1062
+
1063
+ В папке `examples/` лежат готовые сценарии:
1064
+
1065
+ | Файл | Описание |
1066
+ | -------------------------- | --------------------------------------------------------- |
1067
+ | `echo-bot.js` | Минимальный эхо-бот |
1068
+ | `keyboard-bot.js` | Inline-клавиатура и callback |
1069
+ | `command-bot.js` | Команды, hears, action |
1070
+ | `middleware-bot.js` | Middleware-пайплайн, логирование, rate-limit, variadic мw |
1071
+ | `custom-context-bot.js` | Расширение контекста через contextFactory |
1072
+ | `filters-bot.js` | Filter DSL (hasText, payloadIs, commandIs) |
1073
+ | `webhook-bot.js` | Webhook-режим |
1074
+ | `send-media-bot.js` | Загрузка и отправка медиа |
1075
+ | `all-buttons-bot.js` | Все типы кнопок: callback/link/contact/geo/openApp |
1076
+ | `graceful-shutdown-bot.js` | onMetrics, onSlowHandler, onUnknownUpdate, SIGTERM |
1077
+ | `broadcast-bot.js` | Рассылка подписчикам, sendPrivateMessage, getMe |
1078
+ | `wizard-bot.js` | Многошаговый диалог (FSM по шагам) |
1079
+ | `group-bot.js` | Группы: bot_added, user_added, chat_title_changed |
1080
+ | `typing-bot.js` | sendTyping() + replyWithQuote() + /typingtest |
1081
+ | `match-bot.js` | ctx.match: capture-группы в hears() и action() |
1082
+ | `start-payload-bot.js` | bot.onStart(), ctx.startPayload, deep link |
1083
+
1084
+ Эта папка не публикуется в npm-пакет (ограничение через поле `files` в package.json).
1085
+
1086
+ Для запуска примеров локально:
1087
+
1088
+ ```bash
1089
+ npm run build
1090
+ node examples/echo-bot.js
1091
+ ```
1092
+
1093
+ ## API
1094
+
1095
+ Доступ к низкоуровневым методам через `bot.api`:
1096
+
1097
+ - `bot.api.bots.getMe()`
1098
+ - `bot.api.chats.*`
1099
+ - `bot.api.messages.*`
1100
+ - `bot.api.subscriptions.*`
1101
+ - `bot.api.uploads.*`
1102
+
1103
+ Полные типы экспортируются из пакета:
1104
+
1105
+ ```ts
1106
+ import type { Message, Update, Chat, BotInfo } from "@dementevdev/maxbot-ts";
1107
+ ```
1108
+
1109
+ ## Формат contact‑вложения (request_contact)
1110
+
1111
+ При нажатии кнопки request_contact бот получает сообщение с вложением типа contact.
1112
+ Полезные поля payload:
1113
+
1114
+ - vcf_info: vCard строка
1115
+ - vcf_phone: телефон
1116
+ - max_info: объект пользователя (User)
1117
+
1118
+ ## Формат location‑вложения (request_geo_location)
1119
+
1120
+ При нажатии кнопки request_geo_location бот получает сообщение с вложением типа location:
1121
+
1122
+ - latitude: число
1123
+ - longitude: число
1124
+
1125
+ ## Sub-entry points (tree-shaking)
1126
+
1127
+ Модули `middleware` и `filters` доступны как отдельные точки входа — они **не попадают в бандл** тех, кто их не импортирует:
1128
+
1129
+ ```ts
1130
+ // Только core SDK — middleware и filters не включаются
1131
+ import { Bot } from "@dementevdev/maxbot-ts";
1132
+
1133
+ // Только middleware-типы — без остального SDK
1134
+ import type { Middleware, NextFn } from "@dementevdev/maxbot-ts/middleware";
1135
+
1136
+ // Только фильтры
1137
+ import { hasText, payloadIs } from "@dementevdev/maxbot-ts/filters";
1138
+ ```
1139
+
1140
+ Декларации типов (`*.d.ts`) включены в каждый sub-entry point.
1141
+
1142
+ ---
1143
+
1144
+ ## Versioning (Semver policy)
1145
+
1146
+ | Тип изменения | Версия | Примеры |
1147
+ | --------------------------------------- | --------- | ------------------------------------------------- |
1148
+ | Новые публичные методы / опции конфига | **minor** | `bot.use()`, `BotConfig.onMetrics`, `commandIs()` |
1149
+ | Изменение поведения без смены сигнатуры | **minor** | новый параметр с дефолтом |
1150
+ | Breaking change типов публичного API | **major** | изменение `Context`, `Middleware<Ctx>` |
1151
+ | Breaking change рантайм-поведения | **major** | изменение семантики `next()`, `concurrency` |
1152
+ | Bugfixes, внутренние рефакторинги | **patch** | — |
1153
+
1154
+ **Стабильный API (c v1.0.0):**
1155
+
1156
+ - `Bot`, `BotConfig`, `Context`, `EventHandler`
1157
+ - `MessageContext`, `CallbackContext`, `ChatContext`, `BotStartedContext`
1158
+ - `ctx.match` — результат RegExp capture-групп из `hears()`/`action()`
1159
+ - `ctx.startPayload` — payload из deep link в `BotStartedContext`
1160
+ - `ctx.editMessage()`, `ctx.deleteMessage()`, `ctx.sendAction()` — редактирование, удаление, действие
1161
+ - `bot.onMessage()`, `bot.onCallback()`, `bot.onStart()`, `bot.on()`, `bot.start()`, `bot.stop()`
1162
+ - `bot.command()`, `bot.hears()`, `bot.action()` — variadic middlewares: `bot.command('x', mw1, mw2, handler)`
1163
+ - `HearsTrigger` — массив паттернов: `bot.hears([/^\d+$/, 'помощь'], handler)` срабатывает на любой из паттернов
1164
+ - `polling.allowedUpdates` — фильтр типов обновлений
1165
+ - `bot.api.*`
1166
+
1167
+ **Experimental (могут поменяться до v2.0.0 minor-версией):**
1168
+
1169
+ - `BotMetrics`, `onMetrics` — если понадобится расширить структуру метрик
1170
+ - Filter predicates — могут добавляться новые, сигнатуры существующих стабильны
1171
+
1172
+ ---
1173
+
1174
+ ## Лицензия
1175
+
1176
+ [MIT](./LICENSE)