@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,186 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Router = exports.UPDATE_FILTER_TYPES = void 0;
4
- const compose_js_1 = require("../middleware/compose.js");
5
- function testRegExp(expression, value) {
6
- expression.lastIndex = 0;
7
- return expression.test(value);
8
- }
9
- /** Update types accepted by `on()` filters, mirroring the Telegram `Update` object. */
10
- exports.UPDATE_FILTER_TYPES = [
11
- "message",
12
- "edited_message",
13
- "channel_post",
14
- "edited_channel_post",
15
- "business_connection",
16
- "business_message",
17
- "edited_business_message",
18
- "deleted_business_messages",
19
- "guest_message",
20
- "message_reaction",
21
- "message_reaction_count",
22
- "inline_query",
23
- "chosen_inline_result",
24
- "callback_query",
25
- "shipping_query",
26
- "pre_checkout_query",
27
- "purchased_paid_media",
28
- "poll",
29
- "poll_answer",
30
- "my_chat_member",
31
- "chat_member",
32
- "chat_join_request",
33
- "chat_boost",
34
- "removed_chat_boost",
35
- ];
36
- const updateFilterTypes = new Set(exports.UPDATE_FILTER_TYPES);
37
- function assertValidFilter(filter) {
38
- const type = filter.split(":", 1)[0] ?? "";
39
- if (!updateFilterTypes.has(type))
40
- throw new TypeError(`Unknown update type in filter "${filter}". Expected one of: ${exports.UPDATE_FILTER_TYPES.join(", ")}.`);
41
- }
42
- function matchesFilter(ctx, filter) {
43
- const separator = filter.indexOf(":");
44
- const type = separator < 0 ? filter : filter.slice(0, separator);
45
- const field = separator < 0 ? undefined : filter.slice(separator + 1);
46
- const payload = ctx.update[type];
47
- if (payload === undefined || payload === null)
48
- return false;
49
- if (field === undefined || field === "")
50
- return true;
51
- return typeof payload === "object" && payload[field] !== undefined;
52
- }
53
- class Router {
54
- middlewares = [];
55
- routes = [];
56
- sequence = 0;
57
- matchMode;
58
- constructor(options = {}) {
59
- this.matchMode = options.matchMode ?? "first";
60
- }
61
- use(...middleware) {
62
- if (middleware.length === 0)
63
- return this;
64
- this.middlewares.push(...middleware);
65
- return this;
66
- }
67
- route(matcher, ...middleware) {
68
- if (middleware.length === 0)
69
- throw new Error("A route requires at least one middleware handler.");
70
- this.routes.push({ priority: this.sequence++, matcher, middleware });
71
- return this;
72
- }
73
- command(name, ...middleware) {
74
- return this.route(async (ctx) => {
75
- const text = ctx.message?.text ?? ctx.message?.caption;
76
- if (!text?.startsWith("/"))
77
- return false;
78
- const parts = text.slice(1).split(/\s+/);
79
- const commandWithBot = parts[0] ?? "";
80
- const [command, botUsername] = commandWithBot.split("@");
81
- if (botUsername && ctx.me?.username && botUsername.toLowerCase() !== ctx.me.username.toLowerCase()) {
82
- return false;
83
- }
84
- const matched = typeof name === "string"
85
- ? command === name.replace(/^\//, "")
86
- : testRegExp(name, command ?? "");
87
- if (matched) {
88
- ctx.args = parts.slice(1);
89
- }
90
- return matched;
91
- }, ...middleware);
92
- }
93
- text(value, ...middleware) {
94
- return this.route((ctx) => {
95
- const text = ctx.message?.text ?? ctx.message?.caption;
96
- return text === value;
97
- }, ...middleware);
98
- }
99
- regex(expression, ...middleware) {
100
- return this.route((ctx) => {
101
- const text = ctx.message?.text ?? ctx.message?.caption ?? "";
102
- const match = text.match(expression);
103
- if (match) {
104
- ctx.match = match;
105
- return true;
106
- }
107
- return false;
108
- }, ...middleware);
109
- }
110
- callback(pattern, ...middleware) {
111
- return this.route((ctx) => {
112
- const data = ctx.callbackQuery?.data ?? "";
113
- if (typeof pattern === "string") {
114
- if (pattern.endsWith("*")) {
115
- const prefix = pattern.slice(0, -1);
116
- if (data.startsWith(prefix)) {
117
- ctx.params = { ...ctx.params, wildcard: data.slice(prefix.length) };
118
- return true;
119
- }
120
- return false;
121
- }
122
- return data === pattern;
123
- }
124
- const match = data.match(pattern);
125
- if (match) {
126
- ctx.match = match;
127
- return true;
128
- }
129
- return false;
130
- }, ...middleware);
131
- }
132
- chat(chatId, ...middleware) {
133
- return this.route((ctx) => {
134
- const id = ctx.message?.chat?.id;
135
- return id !== undefined && (id === chatId || String(id) === String(chatId));
136
- }, ...middleware);
137
- }
138
- /**
139
- * Registers handlers for update types, with optional payload narrowing:
140
- * `on("message")`, `on("message:photo")`, `on("callback_query:data")`,
141
- * or an array such as `["message:text", "callback_query:data"]`.
142
- */
143
- on(filter, ...middleware) {
144
- const filters = (Array.isArray(filter) ? filter : [filter]).map((value) => String(value));
145
- if (filters.length === 0)
146
- throw new Error("At least one update filter is required.");
147
- for (const value of filters)
148
- assertValidFilter(value);
149
- return this.route((ctx) => filters.some((value) => matchesFilter(ctx, value)), ...middleware);
150
- }
151
- predicate(matcher, ...middleware) {
152
- return this.route(matcher, ...middleware);
153
- }
154
- nest(child) {
155
- return this.route(() => true, async (ctx, next) => {
156
- await child.handle(ctx, next);
157
- });
158
- }
159
- async handle(ctx, terminal) {
160
- const routeDispatcher = async (currentCtx, next) => {
161
- const ordered = [...this.routes].sort((left, right) => left.priority - right.priority);
162
- let matched = false;
163
- for (const route of ordered) {
164
- if (!(await route.matcher(currentCtx)))
165
- continue;
166
- matched = true;
167
- await (0, compose_js_1.compose)(route.middleware)(currentCtx);
168
- if (this.matchMode === "first")
169
- break;
170
- }
171
- if (!matched) {
172
- if (terminal)
173
- await terminal();
174
- else
175
- await next();
176
- }
177
- };
178
- if (this.middlewares.length === 0) {
179
- await routeDispatcher(ctx, async () => { });
180
- }
181
- else {
182
- await (0, compose_js_1.compose)([...this.middlewares, routeDispatcher])(ctx);
183
- }
184
- }
185
- }
186
- exports.Router = Router;
@@ -1,139 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Wizard = exports.ConversationManager = exports.ConversationFlow = void 0;
4
- exports.conversationKeyFromContext = conversationKeyFromContext;
5
- const storage_js_1 = require("../storage/storage.js");
6
- function conversationKeyFromContext(ctx) {
7
- return ctx.chat?.id !== undefined ? `${ctx.chat.id}:${ctx.from?.id ?? "anonymous"}` : `update:${ctx.update.update_id}`;
8
- }
9
- class ConversationFlow {
10
- ctx;
11
- state;
12
- constructor(ctx, state) {
13
- this.ctx = ctx;
14
- this.state = state;
15
- }
16
- get values() { return this.state.values; }
17
- set(key, value) { this.state.values[key] = value; this.state.updatedAt = Date.now(); return this; }
18
- get(key) { return this.state.values[key]; }
19
- next() { this.state.step += 1; this.state.updatedAt = Date.now(); return this; }
20
- previous() { this.state.step = Math.max(0, this.state.step - 1); this.state.updatedAt = Date.now(); return this; }
21
- complete() { this.state.status = "completed"; this.state.updatedAt = Date.now(); }
22
- cancel() { this.state.status = "cancelled"; this.state.updatedAt = Date.now(); }
23
- }
24
- exports.ConversationFlow = ConversationFlow;
25
- class ConversationManager {
26
- active = new Map();
27
- storage;
28
- constructor(storage = new storage_js_1.MemoryStorage()) {
29
- this.storage = storage;
30
- }
31
- start(key, name, values = {}) {
32
- const state = { name, step: 0, values, status: "active", updatedAt: Date.now() };
33
- this.active.set(key, state);
34
- void this.storage.set(key, state).catch(() => undefined);
35
- return state;
36
- }
37
- async startAsync(key, name, values = {}) {
38
- const state = { name, step: 0, values, status: "active", updatedAt: Date.now() };
39
- this.active.set(key, state);
40
- await this.storage.set(key, state);
41
- return state;
42
- }
43
- get(key) { return this.active.get(key); }
44
- async getAsync(key) {
45
- const cached = this.active.get(key);
46
- if (cached)
47
- return cached;
48
- const stored = await this.storage.get(key);
49
- if (stored)
50
- this.active.set(key, stored);
51
- return stored;
52
- }
53
- cancel(key) {
54
- const state = this.active.get(key);
55
- if (!state)
56
- return false;
57
- state.status = "cancelled";
58
- state.updatedAt = Date.now();
59
- void this.storage.set(key, state).catch(() => undefined);
60
- return true;
61
- }
62
- async cancelAsync(key) {
63
- const state = await this.getAsync(key);
64
- if (!state)
65
- return false;
66
- state.status = "cancelled";
67
- state.updatedAt = Date.now();
68
- await this.storage.set(key, state);
69
- return true;
70
- }
71
- clearExpired(maxAgeMs) {
72
- if (!Number.isFinite(maxAgeMs) || maxAgeMs < 0)
73
- throw new RangeError("maxAgeMs must be non-negative");
74
- const threshold = Date.now() - maxAgeMs;
75
- let removed = 0;
76
- for (const [key, state] of this.active)
77
- if (state.updatedAt < threshold) {
78
- this.active.delete(key);
79
- void this.storage.delete(key);
80
- removed += 1;
81
- }
82
- return removed;
83
- }
84
- async clearExpiredAsync(maxAgeMs) {
85
- if (!Number.isFinite(maxAgeMs) || maxAgeMs < 0)
86
- throw new RangeError("maxAgeMs must be non-negative");
87
- const threshold = Date.now() - maxAgeMs;
88
- let removed = 0;
89
- for await (const [key, state] of this.storage.entries()) {
90
- if (state.updatedAt < threshold) {
91
- await this.storage.delete(key);
92
- this.active.delete(key);
93
- removed += 1;
94
- }
95
- }
96
- return removed;
97
- }
98
- async run(ctx, key, name, steps) {
99
- const existing = await this.getAsync(key);
100
- const state = existing ?? await this.startAsync(key, name);
101
- if (state.name !== name)
102
- throw new Error(`Conversation ${key} belongs to ${state.name}, not ${name}`);
103
- if (state.status !== "active")
104
- return state;
105
- const flow = new ConversationFlow(ctx, state);
106
- const step = steps[state.step];
107
- if (!step)
108
- state.status = "completed";
109
- else {
110
- await step(flow);
111
- if (state.step >= steps.length)
112
- state.status = "completed";
113
- }
114
- state.updatedAt = Date.now();
115
- await this.storage.set(key, state);
116
- this.active.set(key, state);
117
- return state;
118
- }
119
- }
120
- exports.ConversationManager = ConversationManager;
121
- class Wizard {
122
- stepsList = [];
123
- defaultManager;
124
- constructor(manager) {
125
- this.defaultManager = manager ?? new ConversationManager();
126
- }
127
- step(step) { this.stepsList.push(step); return this; }
128
- /**
129
- * Runs the active step for a conversation key. The default manager belongs to
130
- * this Wizard instance and is intentionally reused across updates; passing a
131
- * manager is useful when the application owns persistent storage explicitly.
132
- */
133
- async run(ctx, key = conversationKeyFromContext(ctx), manager) {
134
- return (manager ?? this.defaultManager).run(ctx, key, "wizard", this.stepsList.map((step) => step.run));
135
- }
136
- get steps() { return this.stepsList; }
137
- get manager() { return this.defaultManager; }
138
- }
139
- exports.Wizard = Wizard;
@@ -1,47 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validators = exports.Form = void 0;
4
- class Form {
5
- fields = new Map();
6
- field(definition) { this.fields.set(definition.name, definition); return this; }
7
- async parse(input) {
8
- const issues = [];
9
- const values = {};
10
- for (const [name, field] of this.fields) {
11
- const raw = input[name];
12
- if ((raw === undefined || raw === null || raw === "") && field.required) {
13
- issues.push({ path: name, message: "Field is required", code: "required" });
14
- continue;
15
- }
16
- if (raw === undefined || raw === null || raw === "")
17
- continue;
18
- try {
19
- let value = field.parse(raw);
20
- if (field.transform)
21
- value = await field.transform(value);
22
- const error = await field.validate?.(value);
23
- if (error)
24
- issues.push({ path: name, message: error, code: "invalid" });
25
- else
26
- values[name] = value;
27
- }
28
- catch (error) {
29
- issues.push({ path: name, message: error instanceof Error ? error.message : "Invalid value", code: "parse" });
30
- }
31
- }
32
- return issues.length ? { success: false, issues } : { success: true, data: values };
33
- }
34
- reset() { }
35
- }
36
- exports.Form = Form;
37
- exports.validators = { string: (value) => { if (typeof value !== "string")
38
- throw new TypeError("Expected string"); return value; }, number: (value) => { const number = typeof value === "number" ? value : Number(value); if (!Number.isFinite(number))
39
- throw new TypeError("Expected number"); return number; }, integer: (value) => { const number = exports.validators.number(value); if (!Number.isInteger(number))
40
- throw new TypeError("Expected integer"); return number; }, email: (value) => { const email = exports.validators.string(value); if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email))
41
- throw new TypeError("Expected email"); return email; }, url: (value) => { const url = exports.validators.string(value); try {
42
- new URL(url);
43
- return url;
44
- }
45
- catch {
46
- throw new TypeError("Expected URL");
47
- } } };
@@ -1,133 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MenuController = exports.Menu = void 0;
4
- exports.paginate = paginate;
5
- exports.paginationButtons = paginationButtons;
6
- const index_js_1 = require("../keyboard/index.js");
7
- function paginate(items, page, pageSize) {
8
- if (!Number.isInteger(page) || page < 0)
9
- throw new RangeError("page must be a non-negative integer");
10
- if (!Number.isInteger(pageSize) || pageSize < 1)
11
- throw new RangeError("pageSize must be a positive integer");
12
- const pageCount = Math.max(1, Math.ceil(items.length / pageSize));
13
- const safePage = Math.min(page, pageCount - 1);
14
- const start = safePage * pageSize;
15
- return { items: items.slice(start, start + pageSize), page: safePage, pageCount, hasPrevious: safePage > 0, hasNext: safePage < pageCount - 1 };
16
- }
17
- function paginationButtons(page, prefix, labels = {}) {
18
- const buttons = [];
19
- if (page.hasPrevious)
20
- buttons.push({ text: labels.previous ?? "Previous", callback_data: `${prefix}:page:${page.page - 1}` });
21
- buttons.push({ text: `${page.page + 1}/${page.pageCount}`, callback_data: `${prefix}:noop` });
22
- if (page.hasNext)
23
- buttons.push({ text: labels.next ?? "Next", callback_data: `${prefix}:page:${page.page + 1}` });
24
- return buttons;
25
- }
26
- class Menu {
27
- id;
28
- itemsList = [];
29
- parents = [];
30
- constructor(id) {
31
- this.id = id;
32
- }
33
- item(item) {
34
- if (!item.id || !item.label)
35
- throw new Error("Menu item id and label are required.");
36
- if (item.url !== undefined && item.callbackData !== undefined)
37
- throw new Error("A menu item cannot have both url and callbackData.");
38
- this.itemsList.push(item);
39
- return this;
40
- }
41
- breadcrumb(label) { if (label)
42
- this.parents.push(label); return this; }
43
- get items() { return this.itemsList; }
44
- get breadcrumbs() { return this.parents; }
45
- async visibleItems(context = {}) {
46
- const permissions = context.permissions ? new Set(context.permissions) : undefined;
47
- const result = [];
48
- for (const item of this.itemsList) {
49
- const visible = typeof item.visible === "function" ? await item.visible(context, item) : item.visible ?? true;
50
- if (!visible)
51
- continue;
52
- const allowed = typeof item.permission === "function"
53
- ? await item.permission(context, item)
54
- : item.permission === undefined
55
- ? true
56
- : permissions?.has(item.permission) ?? false;
57
- if (allowed)
58
- result.push(item);
59
- }
60
- return result;
61
- }
62
- async build(context = {}, options = {}) {
63
- const columns = options.columns ?? 1;
64
- if (!Number.isInteger(columns) || columns < 1)
65
- throw new RangeError("columns must be a positive integer");
66
- const keyboard = new index_js_1.InlineKeyboard();
67
- if (options.includeBreadcrumbs && this.parents.length)
68
- keyboard.text(this.parents.join(" / "), `${this.id}:breadcrumb`);
69
- const buttons = (await this.visibleItems(context)).map((item) => item.url
70
- ? { text: item.label, url: item.url }
71
- : { text: item.label, callback_data: item.callbackData ?? `${this.id}:${item.id}` });
72
- keyboard.grid(buttons, columns);
73
- return keyboard;
74
- }
75
- }
76
- exports.Menu = Menu;
77
- class MenuController {
78
- currentPage = 0;
79
- options;
80
- constructor(options) {
81
- if (!options.id || !options.id.trim())
82
- throw new Error("MenuController id is required.");
83
- if (!Number.isInteger(options.pageSize) || options.pageSize < 1)
84
- throw new RangeError("pageSize must be a positive integer");
85
- this.options = options;
86
- }
87
- get page() { return this.currentPage; }
88
- async allItems() { return typeof this.options.items === "function" ? await this.options.items() : this.options.items; }
89
- async render(context = this.options.context ?? {}) {
90
- const items = await this.allItems();
91
- const page = paginate(items, this.currentPage, this.options.pageSize);
92
- this.currentPage = page.page;
93
- const keyboard = new index_js_1.InlineKeyboard();
94
- for (let index = 0; index < page.items.length; index += 1) {
95
- const absoluteIndex = page.page * this.options.pageSize + index;
96
- keyboard.text(this.options.label(page.items[index], absoluteIndex), `${this.options.id}:select:${absoluteIndex}`);
97
- }
98
- const navigation = paginationButtons(page, this.options.id, this.options.labels);
99
- if (navigation.length)
100
- keyboard.row(...navigation);
101
- void context;
102
- return keyboard.build();
103
- }
104
- async handle(data, context = this.options.context ?? {}) {
105
- const prefix = `${this.options.id}:`;
106
- if (!data.startsWith(prefix))
107
- return undefined;
108
- const action = data.slice(prefix.length);
109
- if (action === "noop" || action === "breadcrumb")
110
- return { type: "noop" };
111
- if (action.startsWith("page:")) {
112
- const page = Number(action.slice("page:".length));
113
- if (!Number.isInteger(page) || page < 0)
114
- return undefined;
115
- this.currentPage = page;
116
- const items = await this.allItems();
117
- const pageData = paginate(items, this.currentPage, this.options.pageSize);
118
- this.currentPage = pageData.page;
119
- return { type: "page", page: pageData, keyboard: await this.render(context) };
120
- }
121
- if (action.startsWith("select:")) {
122
- const index = Number(action.slice("select:".length));
123
- const items = await this.allItems();
124
- const item = items[index];
125
- if (item === undefined || !Number.isInteger(index) || index < 0)
126
- return undefined;
127
- await this.options.callback?.(item, context);
128
- return { type: "select", item, index };
129
- }
130
- return undefined;
131
- }
132
- }
133
- exports.MenuController = MenuController;