@xbibzlibrary/telebibz 0.4.4 → 3.0.1

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 (258) hide show
  1. package/CHANGELOG.md +35 -138
  2. package/LICENSE +1 -1
  3. package/NOTICE.md +9 -4
  4. package/README.md +173 -242
  5. package/examples/01-quickstart.js +13 -0
  6. package/examples/02-menu-tombol.js +22 -0
  7. package/examples/03-wizard.js +29 -0
  8. package/examples/04-broadcast.js +25 -0
  9. package/examples/05-kirim-file.js +19 -0
  10. package/examples/06-menu.js +35 -0
  11. package/examples/07-inline-query.js +18 -0
  12. package/index.d.ts +81 -0
  13. package/index.js +42 -0
  14. package/lib/api.js +154 -0
  15. package/lib/broadcast.js +35 -0
  16. package/lib/composer.js +174 -0
  17. package/lib/context.js +190 -0
  18. package/lib/errors.js +35 -0
  19. package/lib/file.js +41 -0
  20. package/lib/inline-query.js +28 -0
  21. package/lib/keyboard.js +83 -0
  22. package/lib/logger.js +38 -0
  23. package/lib/menus.js +90 -0
  24. package/lib/net.js +115 -0
  25. package/lib/ratelimit.js +61 -0
  26. package/lib/runner.js +45 -0
  27. package/lib/session.js +36 -0
  28. package/lib/telebibz.js +190 -0
  29. package/lib/wizard.js +81 -0
  30. package/package.json +35 -97
  31. package/test/all.test.js +334 -0
  32. package/CODE_OF_CONDUCT.md +0 -37
  33. package/CONTRIBUTING.md +0 -59
  34. package/CONTRIBUTION_RULES.md +0 -41
  35. package/GOVERNANCE.md +0 -47
  36. package/README.id.md +0 -292
  37. package/README.zh-CN.md +0 -292
  38. package/RELEASE_AUTOMATION.md +0 -78
  39. package/RELEASE_POLICY.md +0 -32
  40. package/SECURITY.md +0 -47
  41. package/SHOWCASE.md +0 -29
  42. package/SUPPORT.md +0 -30
  43. package/assets/readme-preview.html +0 -75
  44. package/assets/telebibz-logo.png +0 -0
  45. package/assets/telebibz-readme-preview.png +0 -0
  46. package/bin/telebibz.mjs +0 -3
  47. package/dist/generated/api.d.ts +0 -13
  48. package/dist/generated/api.d.ts.map +0 -1
  49. package/dist/generated/api.js +0 -192
  50. package/dist/generated/api.js.map +0 -1
  51. package/dist/src/api/client.d.ts +0 -62
  52. package/dist/src/api/client.d.ts.map +0 -1
  53. package/dist/src/api/client.js +0 -104
  54. package/dist/src/api/client.js.map +0 -1
  55. package/dist/src/api/errors.d.ts +0 -45
  56. package/dist/src/api/errors.d.ts.map +0 -1
  57. package/dist/src/api/errors.js +0 -65
  58. package/dist/src/api/errors.js.map +0 -1
  59. package/dist/src/api/index.d.ts +0 -6
  60. package/dist/src/api/index.d.ts.map +0 -1
  61. package/dist/src/api/index.js +0 -6
  62. package/dist/src/api/index.js.map +0 -1
  63. package/dist/src/api/telegram-types/LICENSE +0 -21
  64. package/dist/src/api/telegram-types/api.d.ts +0 -22
  65. package/dist/src/api/telegram-types/checklist.d.ts +0 -72
  66. package/dist/src/api/telegram-types/inline.d.ts +0 -692
  67. package/dist/src/api/telegram-types/langs.d.ts +0 -193
  68. package/dist/src/api/telegram-types/manage.d.ts +0 -1144
  69. package/dist/src/api/telegram-types/markup.d.ts +0 -268
  70. package/dist/src/api/telegram-types/message.d.ts +0 -1537
  71. package/dist/src/api/telegram-types/methods.d.ts +0 -2870
  72. package/dist/src/api/telegram-types/mod.d.ts +0 -14
  73. package/dist/src/api/telegram-types/passport.d.ts +0 -163
  74. package/dist/src/api/telegram-types/payment.d.ts +0 -570
  75. package/dist/src/api/telegram-types/rich.d.ts +0 -1010
  76. package/dist/src/api/telegram-types/settings.d.ts +0 -120
  77. package/dist/src/api/telegram-types/story.d.ts +0 -89
  78. package/dist/src/api/telegram-types/update.d.ts +0 -84
  79. package/dist/src/api/telegram.d.ts +0 -7
  80. package/dist/src/api/telegram.d.ts.map +0 -1
  81. package/dist/src/api/telegram.js +0 -2
  82. package/dist/src/api/telegram.js.map +0 -1
  83. package/dist/src/api/transport.d.ts +0 -68
  84. package/dist/src/api/transport.d.ts.map +0 -1
  85. package/dist/src/api/transport.js +0 -264
  86. package/dist/src/api/transport.js.map +0 -1
  87. package/dist/src/api/types.d.ts +0 -466
  88. package/dist/src/api/types.d.ts.map +0 -1
  89. package/dist/src/api/types.js +0 -2
  90. package/dist/src/api/types.js.map +0 -1
  91. package/dist/src/branding/terminal.d.ts +0 -77
  92. package/dist/src/branding/terminal.d.ts.map +0 -1
  93. package/dist/src/branding/terminal.js +0 -328
  94. package/dist/src/branding/terminal.js.map +0 -1
  95. package/dist/src/broadcast/broadcast.d.ts +0 -50
  96. package/dist/src/broadcast/broadcast.d.ts.map +0 -1
  97. package/dist/src/broadcast/broadcast.js +0 -56
  98. package/dist/src/broadcast/broadcast.js.map +0 -1
  99. package/dist/src/cache/cache.d.ts +0 -34
  100. package/dist/src/cache/cache.d.ts.map +0 -1
  101. package/dist/src/cache/cache.js +0 -41
  102. package/dist/src/cache/cache.js.map +0 -1
  103. package/dist/src/cli.d.ts +0 -2
  104. package/dist/src/cli.d.ts.map +0 -1
  105. package/dist/src/cli.js +0 -84
  106. package/dist/src/cli.js.map +0 -1
  107. package/dist/src/context/context.d.ts +0 -124
  108. package/dist/src/context/context.d.ts.map +0 -1
  109. package/dist/src/context/context.js +0 -302
  110. package/dist/src/context/context.js.map +0 -1
  111. package/dist/src/core/bot.d.ts +0 -204
  112. package/dist/src/core/bot.d.ts.map +0 -1
  113. package/dist/src/core/bot.js +0 -506
  114. package/dist/src/core/bot.js.map +0 -1
  115. package/dist/src/core/events.d.ts +0 -75
  116. package/dist/src/core/events.d.ts.map +0 -1
  117. package/dist/src/core/events.js +0 -35
  118. package/dist/src/core/events.js.map +0 -1
  119. package/dist/src/core/webhook-reply.d.ts +0 -34
  120. package/dist/src/core/webhook-reply.d.ts.map +0 -1
  121. package/dist/src/core/webhook-reply.js +0 -37
  122. package/dist/src/core/webhook-reply.js.map +0 -1
  123. package/dist/src/index.d.ts +0 -24
  124. package/dist/src/index.d.ts.map +0 -1
  125. package/dist/src/index.js +0 -24
  126. package/dist/src/index.js.map +0 -1
  127. package/dist/src/keyboard/index.d.ts +0 -46
  128. package/dist/src/keyboard/index.d.ts.map +0 -1
  129. package/dist/src/keyboard/index.js +0 -55
  130. package/dist/src/keyboard/index.js.map +0 -1
  131. package/dist/src/middleware/compose.d.ts +0 -5
  132. package/dist/src/middleware/compose.d.ts.map +0 -1
  133. package/dist/src/middleware/compose.js +0 -17
  134. package/dist/src/middleware/compose.js.map +0 -1
  135. package/dist/src/observability/logger.d.ts +0 -78
  136. package/dist/src/observability/logger.d.ts.map +0 -1
  137. package/dist/src/observability/logger.js +0 -285
  138. package/dist/src/observability/logger.js.map +0 -1
  139. package/dist/src/plugins/plugin.d.ts +0 -38
  140. package/dist/src/plugins/plugin.d.ts.map +0 -1
  141. package/dist/src/plugins/plugin.js +0 -59
  142. package/dist/src/plugins/plugin.js.map +0 -1
  143. package/dist/src/queue/queue.d.ts +0 -77
  144. package/dist/src/queue/queue.d.ts.map +0 -1
  145. package/dist/src/queue/queue.js +0 -213
  146. package/dist/src/queue/queue.js.map +0 -1
  147. package/dist/src/router/router.d.ts +0 -61
  148. package/dist/src/router/router.d.ts.map +0 -1
  149. package/dist/src/router/router.js +0 -183
  150. package/dist/src/router/router.js.map +0 -1
  151. package/dist/src/state/conversation.d.ts +0 -56
  152. package/dist/src/state/conversation.d.ts.map +0 -1
  153. package/dist/src/state/conversation.js +0 -133
  154. package/dist/src/state/conversation.js.map +0 -1
  155. package/dist/src/state/forms.d.ts +0 -34
  156. package/dist/src/state/forms.d.ts.map +0 -1
  157. package/dist/src/state/forms.js +0 -44
  158. package/dist/src/state/forms.js.map +0 -1
  159. package/dist/src/state/menu.d.ts +0 -78
  160. package/dist/src/state/menu.d.ts.map +0 -1
  161. package/dist/src/state/menu.js +0 -127
  162. package/dist/src/state/menu.js.map +0 -1
  163. package/dist/src/storage/storage.d.ts +0 -146
  164. package/dist/src/storage/storage.d.ts.map +0 -1
  165. package/dist/src/storage/storage.js +0 -195
  166. package/dist/src/storage/storage.js.map +0 -1
  167. package/dist/src/telegram-features.d.ts +0 -33
  168. package/dist/src/telegram-features.d.ts.map +0 -1
  169. package/dist/src/telegram-features.js +0 -71
  170. package/dist/src/telegram-features.js.map +0 -1
  171. package/dist/src/testing.d.ts +0 -24
  172. package/dist/src/testing.d.ts.map +0 -1
  173. package/dist/src/testing.js +0 -38
  174. package/dist/src/testing.js.map +0 -1
  175. package/dist/src/utils/concurrency.d.ts +0 -25
  176. package/dist/src/utils/concurrency.d.ts.map +0 -1
  177. package/dist/src/utils/concurrency.js +0 -52
  178. package/dist/src/utils/concurrency.js.map +0 -1
  179. package/dist/src/utils/files.d.ts +0 -45
  180. package/dist/src/utils/files.d.ts.map +0 -1
  181. package/dist/src/utils/files.js +0 -53
  182. package/dist/src/utils/files.js.map +0 -1
  183. package/dist/src/utils/text.d.ts +0 -39
  184. package/dist/src/utils/text.d.ts.map +0 -1
  185. package/dist/src/utils/text.js +0 -56
  186. package/dist/src/utils/text.js.map +0 -1
  187. package/dist/src/webhook/handler.d.ts +0 -19
  188. package/dist/src/webhook/handler.d.ts.map +0 -1
  189. package/dist/src/webhook/handler.js +0 -141
  190. package/dist/src/webhook/handler.js.map +0 -1
  191. package/dist-cjs/generated/api.js +0 -194
  192. package/dist-cjs/package.json +0 -3
  193. package/dist-cjs/src/api/client.js +0 -107
  194. package/dist-cjs/src/api/errors.js +0 -74
  195. package/dist-cjs/src/api/index.js +0 -21
  196. package/dist-cjs/src/api/telegram-types/LICENSE +0 -21
  197. package/dist-cjs/src/api/telegram-types/api.d.ts +0 -22
  198. package/dist-cjs/src/api/telegram-types/checklist.d.ts +0 -72
  199. package/dist-cjs/src/api/telegram-types/inline.d.ts +0 -692
  200. package/dist-cjs/src/api/telegram-types/langs.d.ts +0 -193
  201. package/dist-cjs/src/api/telegram-types/manage.d.ts +0 -1144
  202. package/dist-cjs/src/api/telegram-types/markup.d.ts +0 -268
  203. package/dist-cjs/src/api/telegram-types/message.d.ts +0 -1537
  204. package/dist-cjs/src/api/telegram-types/methods.d.ts +0 -2870
  205. package/dist-cjs/src/api/telegram-types/mod.d.ts +0 -14
  206. package/dist-cjs/src/api/telegram-types/passport.d.ts +0 -163
  207. package/dist-cjs/src/api/telegram-types/payment.d.ts +0 -570
  208. package/dist-cjs/src/api/telegram-types/rich.d.ts +0 -1010
  209. package/dist-cjs/src/api/telegram-types/settings.d.ts +0 -120
  210. package/dist-cjs/src/api/telegram-types/story.d.ts +0 -89
  211. package/dist-cjs/src/api/telegram-types/update.d.ts +0 -84
  212. package/dist-cjs/src/api/telegram.js +0 -2
  213. package/dist-cjs/src/api/transport.js +0 -267
  214. package/dist-cjs/src/api/types.js +0 -2
  215. package/dist-cjs/src/branding/terminal.js +0 -338
  216. package/dist-cjs/src/broadcast/broadcast.js +0 -58
  217. package/dist-cjs/src/cache/cache.js +0 -45
  218. package/dist-cjs/src/cli.js +0 -86
  219. package/dist-cjs/src/context/context.js +0 -305
  220. package/dist-cjs/src/core/bot.js +0 -510
  221. package/dist-cjs/src/core/events.js +0 -38
  222. package/dist-cjs/src/core/webhook-reply.js +0 -42
  223. package/dist-cjs/src/index.js +0 -47
  224. package/dist-cjs/src/keyboard/index.js +0 -61
  225. package/dist-cjs/src/middleware/compose.js +0 -20
  226. package/dist-cjs/src/observability/logger.js +0 -293
  227. package/dist-cjs/src/plugins/plugin.js +0 -63
  228. package/dist-cjs/src/queue/queue.js +0 -219
  229. package/dist-cjs/src/router/router.js +0 -186
  230. package/dist-cjs/src/state/conversation.js +0 -139
  231. package/dist-cjs/src/state/forms.js +0 -47
  232. package/dist-cjs/src/state/menu.js +0 -133
  233. package/dist-cjs/src/storage/storage.js +0 -202
  234. package/dist-cjs/src/telegram-features.js +0 -76
  235. package/dist-cjs/src/testing.js +0 -45
  236. package/dist-cjs/src/utils/concurrency.js +0 -57
  237. package/dist-cjs/src/utils/files.js +0 -58
  238. package/dist-cjs/src/utils/text.js +0 -63
  239. package/dist-cjs/src/webhook/handler.js +0 -144
  240. package/docs/API.id.md +0 -1935
  241. package/docs/API.md +0 -1969
  242. package/docs/API.zh-CN.md +0 -1929
  243. package/docs/GETTING_STARTED.id.md +0 -85
  244. package/docs/GETTING_STARTED.md +0 -85
  245. package/docs/GETTING_STARTED.zh-CN.md +0 -85
  246. package/docs/GITHUB_PACKAGES.id.md +0 -82
  247. package/docs/GITHUB_PACKAGES.md +0 -82
  248. package/docs/GITHUB_PACKAGES.zh-CN.md +0 -82
  249. package/docs/README.md +0 -48
  250. package/docs/STORAGE.id.md +0 -105
  251. package/docs/STORAGE.md +0 -105
  252. package/docs/STORAGE.zh-CN.md +0 -105
  253. package/examples/README.md +0 -37
  254. package/examples/files.ts +0 -35
  255. package/examples/minimal.ts +0 -12
  256. package/examples/tsconfig.json +0 -9
  257. package/examples/webhook.ts +0 -42
  258. package/examples/wizard-registration.ts +0 -42
@@ -1,61 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ReplyKeyboard = exports.InlineKeyboard = void 0;
4
- exports.removeKeyboard = removeKeyboard;
5
- exports.forceReply = forceReply;
6
- class InlineKeyboard {
7
- rows = [];
8
- static from(rows) { const keyboard = new InlineKeyboard(); keyboard.rows.push(...rows.map((row) => [...row])); return keyboard; }
9
- text(text, callbackData) { return this.button({ text, callback_data: callbackData }); }
10
- url(text, url) { return this.button({ text, url }); }
11
- webApp(text, url) { return this.button({ text, web_app: { url } }); }
12
- pay(text = "Pay") { return this.button({ text, pay: true }); }
13
- copy(text, copiedText) { return this.button({ text, copy_text: { text: copiedText } }); }
14
- switchInline(text, query = "") { return this.button({ text, switch_inline_query: query }); }
15
- switchInlineCurrent(text, query = "") { return this.button({ text, switch_inline_query_current_chat: query }); }
16
- login(text, url, options = {}) { return this.button({ text, login_url: { url, ...options } }); }
17
- game(text) { return this.button({ text, callback_game: {} }); }
18
- button(button) { this.ensureRow().push(validateInlineButton(button)); return this; }
19
- row(...buttons) { this.rows.push(buttons.map(validateInlineButton)); return this; }
20
- conditional(condition, factory) { return condition ? factory(this) : this; }
21
- grid(buttons, columns) { if (!Number.isInteger(columns) || columns < 1)
22
- throw new RangeError("columns must be a positive integer"); for (let index = 0; index < buttons.length; index += columns)
23
- this.rows.push(buttons.slice(index, index + columns).map(validateInlineButton)); return this; }
24
- build() { return { inline_keyboard: this.rows.map((row) => [...row]) }; }
25
- asReplyMarkup() { return this.build(); }
26
- ensureRow() { const row = this.rows.at(-1); if (row)
27
- return row; const next = []; this.rows.push(next); return next; }
28
- }
29
- exports.InlineKeyboard = InlineKeyboard;
30
- class ReplyKeyboard {
31
- rows = [];
32
- options = {};
33
- text(text) { return this.button({ text }); }
34
- contact(text) { return this.button({ text, request_contact: true }); }
35
- location(text) { return this.button({ text, request_location: true }); }
36
- poll(text, type) { return this.button({ text, request_poll: type ? { type } : {} }); }
37
- webApp(text, url) { return this.button({ text, web_app: { url } }); }
38
- requestUsers(text, options = {}) { return this.button({ text, request_users: options }); }
39
- requestChat(text, options = {}) { return this.button({ text, request_chat: options }); }
40
- resized(resize = true) { this.options.resize_keyboard = resize; return this; }
41
- oneTime(oneTime = true) { this.options.one_time_keyboard = oneTime; return this; }
42
- persistent(persistent = true) { this.options.is_persistent = persistent; return this; }
43
- placeholder(text) { this.options.input_field_placeholder = text; return this; }
44
- selective(selective = true) { this.options.selective = selective; return this; }
45
- button(button) { this.ensureRow().push(button); return this; }
46
- row(...buttons) { this.rows.push([...buttons]); return this; }
47
- grid(buttons, columns) { if (!Number.isInteger(columns) || columns < 1)
48
- throw new RangeError("columns must be a positive integer"); for (let index = 0; index < buttons.length; index += columns)
49
- this.rows.push(buttons.slice(index, index + columns)); return this; }
50
- build(options = {}) { return { keyboard: this.rows.map((row) => [...row]), ...this.options, ...options }; }
51
- asReplyMarkup() { return this.build(); }
52
- ensureRow() { const row = this.rows.at(-1); if (row)
53
- return row; const next = []; this.rows.push(next); return next; }
54
- }
55
- exports.ReplyKeyboard = ReplyKeyboard;
56
- function removeKeyboard(selective = false) { return { remove_keyboard: true, ...(selective ? { selective: true } : {}) }; }
57
- function forceReply(placeholder, selective = false) { return { force_reply: true, ...(placeholder ? { input_field_placeholder: placeholder } : {}), ...(selective ? { selective: true } : {}) }; }
58
- function validateInlineButton(button) { if (!button.text)
59
- throw new Error("Inline keyboard button text is required."); const actions = [button.url, button.callback_data, button.web_app, button.login_url, button.switch_inline_query, button.switch_inline_query_current_chat, button.callback_game, button.pay, button.copy_text].filter((value) => value !== undefined); if (actions.length !== 1)
60
- throw new Error(`Inline button ${button.text} must contain exactly one action.`); if (button.callback_data && new TextEncoder().encode(button.callback_data).length > 64)
61
- throw new RangeError("callback_data must be at most 64 bytes."); return { ...button }; }
@@ -1,20 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.compose = compose;
4
- exports.middleware = middleware;
5
- function compose(middleware) {
6
- return async function run(ctx) {
7
- let index = -1;
8
- const dispatch = async (position) => {
9
- if (position <= index)
10
- throw new Error("next() called multiple times");
11
- index = position;
12
- const handler = middleware[position];
13
- if (!handler)
14
- return;
15
- await handler(ctx, () => dispatch(position + 1));
16
- };
17
- await dispatch(0);
18
- };
19
- }
20
- function middleware(handler) { return handler; }
@@ -1,293 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Logger = exports.INCOMING_TEXT_LIMIT = void 0;
4
- exports.redact = redact;
5
- exports.formatLocalStamp = formatLocalStamp;
6
- exports.describeIncomingUpdate = describeIncomingUpdate;
7
- exports.summarizeUpdate = summarizeUpdate;
8
- exports.createLogger = createLogger;
9
- // Higher number = more verbose. `silent` must sort BELOW `error` so that every
10
- // message level is filtered out (a value above all others would let every
11
- // message through, including errors).
12
- const priorities = { silent: -1, error: 0, warn: 1, info: 2, debug: 3, trace: 4 };
13
- const defaultRedactKeys = ["token", "secret", "password", "authorization", "cookie", "private_key", "api_key", "npm_token", "bot_token"];
14
- const ANSI = {
15
- reset: "\u001b[0m",
16
- dim: "\u001b[2m",
17
- red: "\u001b[31m",
18
- yellow: "\u001b[33m",
19
- green: "\u001b[32m",
20
- cyan: "\u001b[36m",
21
- blue: "\u001b[34m",
22
- magenta: "\u001b[35m",
23
- };
24
- function isObject(value) { return typeof value === "object" && value !== null; }
25
- function shouldRedact(key, keys) { const normalized = key.toLowerCase().replace(/[-_]/g, ""); return keys.some((candidate) => normalized.includes(candidate.toLowerCase().replace(/[-_]/g, ""))); }
26
- function redactString(value) {
27
- return value
28
- .replace(/\b\d{6,12}:[A-Za-z0-9_-]{20,}\b/g, "[REDACTED_TELEGRAM_TOKEN]")
29
- .replace(/\bnpm_[A-Za-z0-9]{20,}\b/g, "[REDACTED_NPM_TOKEN]");
30
- }
31
- function safeValue(value, keys, seen = new WeakSet()) {
32
- if (typeof value === "string")
33
- return redactString(value);
34
- if (typeof value === "bigint")
35
- return `${value}n`;
36
- if (value instanceof Error)
37
- return safeValue({ name: value.name, message: value.message, stack: value.stack }, keys, seen);
38
- if (Array.isArray(value)) {
39
- if (seen.has(value))
40
- return "[Circular]";
41
- seen.add(value);
42
- return value.map((item) => safeValue(item, keys, seen));
43
- }
44
- if (!isObject(value))
45
- return value;
46
- if (seen.has(value))
47
- return "[Circular]";
48
- seen.add(value);
49
- const result = {};
50
- for (const [key, nested] of Object.entries(value))
51
- result[key] = shouldRedact(key, keys) ? "[REDACTED]" : safeValue(nested, keys, seen);
52
- return result;
53
- }
54
- function redact(value, keys = defaultRedactKeys) { return safeValue(value, keys); }
55
- function updateType(update) {
56
- if (update.callback_query)
57
- return "callback_query";
58
- if (update.inline_query)
59
- return "inline_query";
60
- if (update.business_message)
61
- return "business_message";
62
- if (update.edited_business_message)
63
- return "edited_business_message";
64
- if (update.guest_message)
65
- return "guest_message";
66
- if (update.edited_guest_message)
67
- return "edited_guest_message";
68
- if (update.message_reaction)
69
- return "message_reaction";
70
- if (update.message_reaction_count)
71
- return "message_reaction_count";
72
- if (update.chat_boost)
73
- return "chat_boost";
74
- if (update.removed_chat_boost)
75
- return "removed_chat_boost";
76
- if (update.message)
77
- return "message";
78
- if (update.edited_message)
79
- return "edited_message";
80
- if (update.channel_post)
81
- return "channel_post";
82
- if (update.edited_channel_post)
83
- return "edited_channel_post";
84
- if (update.my_chat_member)
85
- return "my_chat_member";
86
- if (update.chat_member)
87
- return "chat_member";
88
- if (update.chat_join_request)
89
- return "chat_join_request";
90
- if (update.poll)
91
- return "poll";
92
- if (update.poll_answer)
93
- return "poll_answer";
94
- return "unknown";
95
- }
96
- exports.INCOMING_TEXT_LIMIT = 50;
97
- function padNumber(value) { return String(value).padStart(2, "0"); }
98
- /** Formats a date as `dd/mm/yyyy hh:mm:ss` in local time. */
99
- function formatLocalStamp(date = new Date()) {
100
- return `${padNumber(date.getDate())}/${padNumber(date.getMonth() + 1)}/${date.getFullYear()} ${padNumber(date.getHours())}:${padNumber(date.getMinutes())}:${padNumber(date.getSeconds())}`;
101
- }
102
- function truncateForDisplay(value, limit = exports.INCOMING_TEXT_LIMIT) {
103
- if (value.length <= limit)
104
- return { text: value, truncated: false };
105
- return { text: `${value.slice(0, limit)}…`, truncated: true };
106
- }
107
- function nicknameFromUser(user) {
108
- if (!user)
109
- return undefined;
110
- const name = [user.first_name, user.last_name].filter(Boolean).join(" ").trim();
111
- return name.length > 0 ? name : user.username ?? String(user.id);
112
- }
113
- function messageMediaType(message) {
114
- for (const key of ["photo", "video", "video_note", "animation", "document", "audio", "voice", "sticker", "location", "venue", "contact", "dice", "poll", "story", "paid_media"]) {
115
- if (message[key] !== undefined)
116
- return key;
117
- }
118
- return undefined;
119
- }
120
- /**
121
- * Builds the human-readable description of an incoming update used for the
122
- * `[ => ] Message From ...` terminal lines. Text messages and commands are
123
- * truncated to 50 characters; callback button data is shown in full.
124
- */
125
- function describeIncomingUpdate(update) {
126
- const callback = update.callback_query;
127
- if (callback) {
128
- const result = { kind: "Callback", fromId: callback.from.id, nickname: nicknameFromUser(callback.from), contentLabel: "Data", content: callback.data };
129
- return result;
130
- }
131
- const message = (update.message ?? update.edited_message ?? update.channel_post ?? update.edited_channel_post ?? update.business_message ?? update.edited_business_message ?? update.guest_message ?? update.edited_guest_message);
132
- if (message) {
133
- const from = message.from;
134
- const nickname = nicknameFromUser(from) ?? (message.chat.title !== undefined ? String(message.chat.title) : message.chat.id !== undefined ? String(message.chat.id) : undefined);
135
- const input = { kind: "Message", fromId: from?.id ?? message.chat.id, nickname };
136
- const text = message.text;
137
- if (text !== undefined) {
138
- const truncated = truncateForDisplay(text);
139
- input.contentLabel = "Text";
140
- input.content = truncated.text;
141
- input.truncated = truncated.truncated;
142
- }
143
- else if (message.caption !== undefined) {
144
- const truncated = truncateForDisplay(message.caption);
145
- input.contentLabel = "Caption";
146
- input.content = truncated.text;
147
- input.truncated = truncated.truncated;
148
- }
149
- else {
150
- const media = messageMediaType(message);
151
- if (media !== undefined)
152
- input.contentLabel = media === "photo" ? "Photo" : media.replace(/_/g, " ").replace(/^./, (character) => character.toUpperCase());
153
- }
154
- return input;
155
- }
156
- const inline = update.inline_query;
157
- if (inline) {
158
- const truncated = truncateForDisplay(inline.query);
159
- return { kind: "Inline Query", fromId: inline.from.id, nickname: nicknameFromUser(inline.from), contentLabel: "Query", content: truncated.text, truncated: truncated.truncated };
160
- }
161
- const chosen = update.chosen_inline_result;
162
- if (chosen)
163
- return { kind: "Inline Result", fromId: chosen.from.id, nickname: nicknameFromUser(chosen.from), contentLabel: "Result", content: chosen.result_id };
164
- const chatScoped = update.chat_member ?? update.my_chat_member ?? update.chat_join_request;
165
- if (chatScoped) {
166
- return { kind: "Update", fromId: chatScoped.from.id, nickname: nicknameFromUser(chatScoped.from), contentLabel: "Chat", content: chatScoped.chat.title ?? String(chatScoped.chat.id) };
167
- }
168
- const reaction = update.message_reaction;
169
- const reactor = nicknameFromUser(reaction?.from);
170
- if (reactor)
171
- return { kind: "Reaction", fromId: reaction?.from?.id, nickname: reactor };
172
- return { kind: "Update", context: { type: updateType(update) } };
173
- }
174
- function summarizeUpdate(update, includeContent = false) {
175
- const callback = update.callback_query;
176
- const message = (update.message ?? update.edited_message ?? update.channel_post ?? update.edited_channel_post ?? update.business_message ?? update.edited_business_message ?? update.guest_message ?? update.edited_guest_message ?? callback?.message);
177
- const summary = { updateId: update.update_id, type: updateType(update) };
178
- if (message?.chat?.id !== undefined)
179
- summary.chatId = message.chat.id;
180
- if (message?.from?.id !== undefined)
181
- summary.fromUserId = message.from.id;
182
- if (message?.message_id !== undefined)
183
- summary.messageId = message.message_id;
184
- if (includeContent) {
185
- const text = message?.text ?? message?.caption;
186
- if (text !== undefined)
187
- summary.text = text;
188
- if (callback?.data !== undefined)
189
- summary.callbackData = callback.data;
190
- }
191
- return summary;
192
- }
193
- function levelColor(level) {
194
- if (level === "error")
195
- return ANSI.red;
196
- if (level === "warn")
197
- return ANSI.yellow;
198
- if (level === "debug")
199
- return ANSI.blue;
200
- if (level === "trace")
201
- return ANSI.magenta;
202
- return ANSI.green;
203
- }
204
- function formatEntry(entry, color, format) {
205
- if (format === "json") {
206
- const line = JSON.stringify(entry);
207
- return color ? `${ANSI.dim}${line}${ANSI.reset}` : line;
208
- }
209
- const time = entry.timestamp.slice(11, 23);
210
- const label = entry.level.toUpperCase().padEnd(5, " ");
211
- const context = entry.context && Object.keys(entry.context).length ? ` ${JSON.stringify(entry.context)}` : "";
212
- const line = `${time} ${label} ${entry.event}${context}`;
213
- return color ? `${levelColor(entry.level)}${line}${ANSI.reset}` : line;
214
- }
215
- function createDefaultSink(options, redactKeys) {
216
- const stream = options.stream ?? process.stdout;
217
- const color = options.color ?? Boolean(stream.isTTY && !process.env.NO_COLOR);
218
- const format = options.format ?? "pretty";
219
- return (entry) => {
220
- if (typeof entry.text === "string") {
221
- stream.write(`${redactString(entry.text)}\n`);
222
- return;
223
- }
224
- const safeEntry = redact(entry, redactKeys);
225
- const line = formatEntry(safeEntry, color, format);
226
- stream.write(`${line}\n`);
227
- };
228
- }
229
- class Logger {
230
- level;
231
- format;
232
- color;
233
- includeUpdateContent;
234
- sink;
235
- redactKeys;
236
- baseContext;
237
- constructor(options = {}) {
238
- this.level = options.level ?? "info";
239
- this.format = options.format ?? "pretty";
240
- const stream = options.stream ?? process.stdout;
241
- this.color = options.color ?? Boolean(stream.isTTY && !process.env.NO_COLOR);
242
- this.includeUpdateContent = options.includeUpdateContent ?? false;
243
- this.redactKeys = options.redactKeys ?? defaultRedactKeys;
244
- this.sink = options.sink ?? createDefaultSink({ color: this.color, format: this.format, stream }, this.redactKeys);
245
- this.baseContext = options.context ?? {};
246
- }
247
- child(context) { return new Logger({ level: this.level, format: this.format, color: this.color, sink: this.sink, includeUpdateContent: this.includeUpdateContent, redactKeys: this.redactKeys, context: { ...this.baseContext, ...context } }); }
248
- trace(event, context) { this.write("trace", event, context); }
249
- debug(event, context) { this.write("debug", event, context); }
250
- info(event, context) { this.write("info", event, context); }
251
- warn(event, context) { this.write("warn", event, context); }
252
- error(event, context) { this.write("error", event, context); }
253
- /**
254
- * Logs an incoming update as the human-readable terminal line:
255
- * `[ => ] Message From {id} {nickname} {dd/mm/yyyy} {hh:mm:ss}` followed by
256
- * an indented content line. In `json` format it emits a structured entry
257
- * with the event name `update.received`.
258
- */
259
- incoming(input) {
260
- if (priorities.info > priorities[this.level])
261
- return;
262
- if (this.format === "json") {
263
- const context = { kind: input.kind, ...(input.fromId !== undefined ? { fromId: input.fromId } : {}), ...(input.nickname !== undefined ? { nickname: input.nickname } : {}), ...(input.content !== undefined ? { content: input.content } : {}), ...(input.truncated ? { truncated: true } : {}), ...input.context };
264
- this.write("info", "update.received", context);
265
- return;
266
- }
267
- const stamp = formatLocalStamp();
268
- const identity = [input.fromId !== undefined ? String(input.fromId) : undefined, input.nickname].filter(Boolean).join(" ");
269
- const arrow = this.color ? `\u001b[36m\u001b[1m[ => ]\u001b[0m` : "[ => ]";
270
- const kind = this.color ? `\u001b[1m${input.kind}\u001b[0m` : input.kind;
271
- const header = `${arrow} ${kind} From ${identity} ${this.color ? `\u001b[2m${stamp}\u001b[0m` : stamp}`;
272
- const lines = [redactString(header)];
273
- if (input.content !== undefined || input.contentLabel !== undefined) {
274
- const label = input.contentLabel ?? "Content";
275
- const value = input.content ?? "";
276
- const contentLine = ` ↳ ${label}: ${value}`;
277
- lines.push(this.color ? `\u001b[2m${redactString(contentLine)}\u001b[0m` : redactString(contentLine));
278
- }
279
- this.sink({ timestamp: new Date().toISOString(), level: "info", event: "update.received", text: lines.join("\n") });
280
- }
281
- write(level, event, context = {}) {
282
- if (priorities[level] > priorities[this.level])
283
- return;
284
- const merged = { ...this.baseContext, ...context };
285
- const safe = redact(merged, this.redactKeys);
286
- const entry = { timestamp: new Date().toISOString(), level, event };
287
- if (Object.keys(safe).length)
288
- entry.context = safe;
289
- this.sink(entry);
290
- }
291
- }
292
- exports.Logger = Logger;
293
- function createLogger(options) { return new Logger(options); }
@@ -1,63 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PluginManager = exports.ServiceContainer = void 0;
4
- class ServiceContainer {
5
- values = new Map();
6
- register(name, value) { this.values.set(name, value); return this; }
7
- get(name) { if (!this.values.has(name))
8
- throw new Error(`Service not registered: ${String(name)}`); return this.values.get(name); }
9
- has(name) { return this.values.has(name); }
10
- delete(name) { return this.values.delete(name); }
11
- }
12
- exports.ServiceContainer = ServiceContainer;
13
- class PluginManager {
14
- plugins = [];
15
- api;
16
- setupComplete = false;
17
- constructor(bot) {
18
- const host = bot;
19
- this.api = {
20
- bot,
21
- services: new ServiceContainer(),
22
- registerMiddleware: (middleware) => {
23
- if (typeof middleware !== "function" || !host.use)
24
- throw new TypeError("Plugin middleware must be a function and the bot must support use().");
25
- host.use(middleware);
26
- },
27
- registerRoute: (route) => {
28
- if (typeof route === "function") {
29
- route(bot);
30
- return;
31
- }
32
- if (!route || typeof route !== "object" || !host.router?.route)
33
- throw new TypeError("Plugin route must be a registration function or route descriptor.");
34
- const descriptor = route;
35
- if (typeof descriptor.matcher !== "function" || !Array.isArray(descriptor.middleware) || descriptor.middleware.some((item) => typeof item !== "function"))
36
- throw new TypeError("Plugin route descriptor is invalid.");
37
- host.router.route(descriptor.matcher, ...descriptor.middleware);
38
- },
39
- };
40
- }
41
- use(plugin) { if (this.plugins.some((existing) => existing.name === plugin.name))
42
- throw new Error(`Plugin already registered: ${plugin.name}`); this.plugins.push(plugin); return this; }
43
- /** Installs plugins once; re-running setup after a restart must not double-register middleware. */
44
- async setup() {
45
- if (this.setupComplete)
46
- return;
47
- for (const plugin of this.plugins) {
48
- await plugin.install?.(this.api);
49
- await plugin.setup?.(this.api);
50
- }
51
- this.setupComplete = true;
52
- }
53
- async start() { for (const plugin of this.plugins)
54
- await plugin.onStart?.(this.api); }
55
- async update(context) { for (const plugin of this.plugins)
56
- await plugin.onUpdate?.(context); }
57
- async stop() { for (const plugin of this.plugins)
58
- await plugin.onStop?.(this.api); }
59
- async dispose() { for (const plugin of [...this.plugins].reverse())
60
- await plugin.dispose?.(this.api); }
61
- list() { return this.plugins; }
62
- }
63
- exports.PluginManager = PluginManager;
@@ -1,219 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Scheduler = exports.TaskQueue = void 0;
4
- exports.parseCronExpression = parseCronExpression;
5
- exports.nextCronOccurrence = nextCronOccurrence;
6
- function sleep(delayMs) { return new Promise((resolve) => setTimeout(resolve, delayMs)); }
7
- class TaskQueue {
8
- worker;
9
- options;
10
- pending = [];
11
- jobs = new Map();
12
- controllers = new Map();
13
- active = 0;
14
- sequence = 0;
15
- draining = false;
16
- closed = false;
17
- constructor(worker, options = {}) {
18
- this.worker = worker;
19
- this.options = options;
20
- if ((options.concurrency ?? 1) < 1 || !Number.isInteger(options.concurrency ?? 1))
21
- throw new RangeError("concurrency must be a positive integer");
22
- if ((options.retries ?? 0) < 0 || !Number.isInteger(options.retries ?? 0))
23
- throw new RangeError("retries must be a non-negative integer");
24
- }
25
- add(data, options = {}) {
26
- if (this.closed)
27
- throw new Error("TaskQueue is closed");
28
- const id = options.id ?? `job_${Date.now()}_${this.sequence++}`;
29
- if (this.jobs.has(id))
30
- throw new Error(`Job already exists: ${id}`);
31
- if (options.delayMs !== undefined && options.delayMs < 0)
32
- throw new RangeError("delayMs must be non-negative");
33
- const job = { id, data, attempts: 0, priority: options.priority ?? 0, runAt: Date.now() + (options.delayMs ?? 0), status: "queued" };
34
- this.jobs.set(id, job);
35
- this.pending.push(job);
36
- this.pending.sort((a, b) => b.priority - a.priority || a.runAt - b.runAt);
37
- void this.drain();
38
- return { ...job };
39
- }
40
- get(id) { const job = this.jobs.get(id); return job ? { ...job } : undefined; }
41
- cancel(id) { const job = this.jobs.get(id); if (!job || ["completed", "failed", "cancelled"].includes(job.status))
42
- return false; job.status = "cancelled"; this.controllers.get(id)?.abort(); return true; }
43
- async onIdle() { while (this.pending.some((job) => job.status === "queued") || this.active)
44
- await sleep(10); }
45
- async close() {
46
- this.closed = true;
47
- this.draining = false;
48
- for (const id of this.controllers.keys())
49
- this.cancel(id);
50
- for (const job of this.pending)
51
- if (job.status === "queued")
52
- job.status = "cancelled";
53
- this.pending.length = 0;
54
- await this.onIdle();
55
- }
56
- async drain() {
57
- if (this.draining || this.closed)
58
- return;
59
- this.draining = true;
60
- try {
61
- while (!this.closed && this.pending.some((job) => job.status === "queued") && this.active < (this.options.concurrency ?? 1)) {
62
- const index = this.pending.findIndex((job) => job.runAt <= Date.now() && job.status === "queued");
63
- if (index < 0) {
64
- const next = Math.min(...this.pending.filter((job) => job.status === "queued").map((job) => job.runAt));
65
- await sleep(Math.max(1, next - Date.now()));
66
- continue;
67
- }
68
- const [job] = this.pending.splice(index, 1);
69
- if (!job)
70
- continue;
71
- this.active += 1;
72
- void this.run(job).finally(() => { this.active -= 1; void this.drain(); });
73
- }
74
- }
75
- finally {
76
- this.draining = false;
77
- }
78
- }
79
- async run(job) {
80
- const maxAttempts = this.options.retries ?? 0;
81
- const controller = new AbortController();
82
- this.controllers.set(job.id, controller);
83
- try {
84
- while (job.attempts <= maxAttempts && job.status !== "cancelled") {
85
- job.status = "running";
86
- job.attempts += 1;
87
- try {
88
- await this.worker(job, controller.signal);
89
- job.status = "completed";
90
- return;
91
- }
92
- catch (error) {
93
- job.error = error;
94
- const wasCancelled = job.status === "cancelled";
95
- if (job.attempts > maxAttempts || wasCancelled) {
96
- job.status = wasCancelled ? "cancelled" : "failed";
97
- await this.options.onError?.(error, { ...job });
98
- return;
99
- }
100
- const delay = Math.min(this.options.maxBackoffMs ?? 30_000, (this.options.backoffMs ?? 250) * 2 ** (job.attempts - 1));
101
- await sleep(delay);
102
- }
103
- }
104
- }
105
- finally {
106
- this.controllers.delete(job.id);
107
- }
108
- }
109
- }
110
- exports.TaskQueue = TaskQueue;
111
- function parseCronField(token, min, max, normalize) {
112
- if (!token)
113
- throw new Error("Cron fields cannot be empty");
114
- const values = new Set();
115
- for (const part of token.split(",")) {
116
- const [rangePart, stepPart] = part.split("/");
117
- const step = stepPart === undefined ? 1 : Number(stepPart);
118
- if (!Number.isInteger(step) || step < 1)
119
- throw new Error(`Invalid cron step: ${part}`);
120
- const bounds = rangePart === "*" ? [min, max] : rangePart?.split("-").map(Number);
121
- if (!bounds || bounds.length < 1 || bounds.some((value) => !Number.isInteger(value)))
122
- throw new Error(`Invalid cron range: ${part}`);
123
- const start = bounds[0];
124
- const end = (bounds[1] ?? start);
125
- if (start < min || end > max || start > end)
126
- throw new Error(`Cron value out of range: ${part}`);
127
- for (let value = start; value <= end; value += step)
128
- values.add(normalize ? normalize(value) : value);
129
- }
130
- return { min, max, values };
131
- }
132
- function parseCronExpression(expression) {
133
- const fields = expression.trim().split(/\s+/);
134
- if (fields.length !== 5)
135
- throw new Error("Cron expression must contain exactly five fields: minute hour day-of-month month day-of-week");
136
- return {
137
- minute: parseCronField(fields[0], 0, 59),
138
- hour: parseCronField(fields[1], 0, 23),
139
- dayOfMonth: parseCronField(fields[2], 1, 31),
140
- month: parseCronField(fields[3], 1, 12),
141
- dayOfWeek: parseCronField(fields[4], 0, 7, (value) => value === 7 ? 0 : value),
142
- };
143
- }
144
- function nextCronOccurrence(expression, from = new Date()) {
145
- const cron = typeof expression === "string" ? parseCronExpression(expression) : expression;
146
- const candidate = new Date(from);
147
- candidate.setSeconds(0, 0);
148
- candidate.setMinutes(candidate.getMinutes() + 1);
149
- const maxMinutes = 366 * 24 * 60 * 5;
150
- for (let index = 0; index < maxMinutes; index += 1) {
151
- const dayOfMonthMatches = cron.dayOfMonth.values.has(candidate.getDate());
152
- const dayOfWeekMatches = cron.dayOfWeek.values.has(candidate.getDay());
153
- const dayMatches = cron.dayOfMonth.values.size === cron.dayOfMonth.max - cron.dayOfMonth.min + 1
154
- || cron.dayOfWeek.values.size === cron.dayOfWeek.max - cron.dayOfWeek.min + 1
155
- ? dayOfMonthMatches && dayOfWeekMatches
156
- : dayOfMonthMatches || dayOfWeekMatches;
157
- if (cron.month.values.has(candidate.getMonth() + 1) && cron.hour.values.has(candidate.getHours()) && cron.minute.values.has(candidate.getMinutes()) && dayMatches)
158
- return new Date(candidate);
159
- candidate.setMinutes(candidate.getMinutes() + 1);
160
- }
161
- throw new Error(`Cron expression has no occurrence within five years: ${typeof expression === "string" ? expression : "[parsed]"}`);
162
- }
163
- class Scheduler {
164
- options;
165
- timers = new Map();
166
- nextRuns = new Map();
167
- constructor(options = {}) {
168
- this.options = options;
169
- }
170
- every(id, intervalMs, task) {
171
- if (!Number.isFinite(intervalMs) || intervalMs <= 0)
172
- throw new RangeError("intervalMs must be positive");
173
- this.cancel(id);
174
- const timer = setInterval(() => { void this.run(id, task); }, intervalMs);
175
- this.timers.set(id, timer);
176
- return { id, cancel: () => this.cancel(id) };
177
- }
178
- after(id, delayMs, task) {
179
- if (!Number.isFinite(delayMs) || delayMs < 0)
180
- throw new RangeError("delayMs must be non-negative");
181
- this.cancel(id);
182
- const timer = setTimeout(() => { this.timers.delete(id); void this.run(id, task); }, delayMs);
183
- this.timers.set(id, timer);
184
- return { id, cancel: () => this.cancel(id) };
185
- }
186
- cron(id, expression, task) {
187
- const parsed = parseCronExpression(expression);
188
- this.cancel(id);
189
- const scheduleNext = () => {
190
- const nextRunAt = nextCronOccurrence(parsed);
191
- this.nextRuns.set(id, nextRunAt);
192
- const timer = setTimeout(() => {
193
- this.timers.delete(id);
194
- void this.run(id, task).finally(() => { if (this.nextRuns.has(id))
195
- scheduleNext(); });
196
- }, Math.max(1, nextRunAt.getTime() - Date.now()));
197
- this.timers.set(id, timer);
198
- };
199
- scheduleNext();
200
- const scheduler = this;
201
- return { id, cancel: () => scheduler.cancel(id), get nextRunAt() { return scheduler.nextRuns.get(id); } };
202
- }
203
- getNextRun(id) { const value = this.nextRuns.get(id); return value ? new Date(value) : undefined; }
204
- cancel(id) { const timer = this.timers.get(id); if (!timer) {
205
- this.nextRuns.delete(id);
206
- return false;
207
- } clearTimeout(timer); clearInterval(timer); this.timers.delete(id); this.nextRuns.delete(id); return true; }
208
- clear() { for (const id of [...this.timers.keys()])
209
- this.cancel(id); }
210
- async run(id, task) {
211
- try {
212
- await task();
213
- }
214
- catch (error) {
215
- await this.options.onError?.(error, id);
216
- }
217
- }
218
- }
219
- exports.Scheduler = Scheduler;