@mtcute/dispatcher 0.17.2 → 0.18.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 (111) hide show
  1. package/callback-data-builder.cjs +126 -0
  2. package/callback-data-builder.d.cts +49 -0
  3. package/callback-data-builder.js +121 -0
  4. package/callback-data-builder.test.d.cts +1 -0
  5. package/context/base.d.cts +9 -0
  6. package/context/business-message.cjs +143 -0
  7. package/context/business-message.d.cts +60 -0
  8. package/context/business-message.js +138 -0
  9. package/context/callback-query.cjs +92 -0
  10. package/context/callback-query.d.cts +62 -0
  11. package/context/callback-query.js +87 -0
  12. package/context/chat-join-request.cjs +32 -0
  13. package/context/chat-join-request.d.cts +17 -0
  14. package/context/chat-join-request.d.ts +1 -1
  15. package/context/chat-join-request.js +27 -0
  16. package/context/chosen-inline-result.cjs +30 -0
  17. package/context/chosen-inline-result.d.cts +22 -0
  18. package/context/chosen-inline-result.d.ts +1 -1
  19. package/context/chosen-inline-result.js +25 -0
  20. package/context/index.d.cts +9 -0
  21. package/context/inline-query.cjs +20 -0
  22. package/context/inline-query.d.cts +15 -0
  23. package/context/inline-query.js +15 -0
  24. package/context/message.cjs +182 -0
  25. package/context/message.d.cts +82 -0
  26. package/context/message.d.ts +2 -2
  27. package/context/message.js +177 -0
  28. package/context/parse.cjs +45 -0
  29. package/context/parse.d.cts +13 -0
  30. package/context/parse.js +40 -0
  31. package/context/pre-checkout-query.cjs +24 -0
  32. package/context/pre-checkout-query.d.cts +17 -0
  33. package/context/pre-checkout-query.d.ts +1 -1
  34. package/context/pre-checkout-query.js +19 -0
  35. package/context/scene-transition.cjs +52 -0
  36. package/context/scene-transition.d.cts +24 -0
  37. package/context/scene-transition.d.ts +1 -1
  38. package/context/scene-transition.js +47 -0
  39. package/dispatcher.cjs +860 -0
  40. package/dispatcher.d.cts +880 -0
  41. package/dispatcher.d.ts +4 -4
  42. package/dispatcher.js +855 -0
  43. package/filters/bots.cjs +94 -0
  44. package/filters/bots.d.cts +62 -0
  45. package/filters/bots.d.ts +2 -4
  46. package/filters/bots.js +89 -0
  47. package/filters/bots.test.d.cts +1 -0
  48. package/filters/bundle.cjs +79 -0
  49. package/filters/bundle.d.cts +10 -0
  50. package/filters/bundle.js +74 -0
  51. package/filters/chat.cjs +43 -0
  52. package/filters/chat.d.cts +29 -0
  53. package/filters/chat.d.ts +8 -6
  54. package/filters/chat.js +38 -0
  55. package/filters/group.cjs +49 -0
  56. package/filters/group.d.cts +26 -0
  57. package/filters/group.js +44 -0
  58. package/filters/index.d.cts +4 -0
  59. package/filters/logic.cjs +57 -0
  60. package/filters/logic.d.cts +29 -0
  61. package/filters/logic.js +52 -0
  62. package/filters/logic.test.d.cts +1 -0
  63. package/filters/message.cjs +130 -0
  64. package/filters/message.d.cts +223 -0
  65. package/filters/message.d.ts +5 -1
  66. package/filters/message.js +125 -0
  67. package/filters/state.cjs +21 -0
  68. package/filters/state.d.cts +15 -0
  69. package/filters/state.js +16 -0
  70. package/filters/text.cjs +87 -0
  71. package/filters/text.d.cts +64 -0
  72. package/filters/text.d.ts +2 -2
  73. package/filters/text.js +82 -0
  74. package/filters/types.d.cts +91 -0
  75. package/filters/updates.cjs +27 -0
  76. package/filters/updates.d.cts +39 -0
  77. package/filters/updates.js +22 -0
  78. package/filters/user.cjs +57 -0
  79. package/filters/user.d.cts +24 -0
  80. package/filters/user.js +52 -0
  81. package/handler.d.cts +41 -0
  82. package/handler.d.ts +1 -1
  83. package/index.cjs +37 -2528
  84. package/index.js +16 -2507
  85. package/package.json +10 -9
  86. package/propagation.cjs +15 -0
  87. package/propagation.d.cts +22 -0
  88. package/propagation.js +10 -0
  89. package/state/index.d.cts +5 -0
  90. package/state/key.cjs +32 -0
  91. package/state/key.d.cts +24 -0
  92. package/state/key.js +27 -0
  93. package/state/provider.d.cts +5 -0
  94. package/state/providers/index.d.cts +2 -0
  95. package/state/providers/memory.cjs +79 -0
  96. package/state/providers/memory.d.cts +29 -0
  97. package/state/providers/memory.js +74 -0
  98. package/state/providers/sqlite.cjs +99 -0
  99. package/state/providers/sqlite.d.cts +28 -0
  100. package/state/providers/sqlite.js +94 -0
  101. package/state/repository.d.cts +62 -0
  102. package/state/service.cjs +69 -0
  103. package/state/service.d.cts +20 -0
  104. package/state/service.js +64 -0
  105. package/state/update-state.cjs +206 -0
  106. package/state/update-state.d.cts +151 -0
  107. package/state/update-state.d.ts +1 -1
  108. package/state/update-state.js +201 -0
  109. package/wizard.cjs +90 -0
  110. package/wizard.d.cts +64 -0
  111. package/wizard.js +85 -0
package/dispatcher.cjs ADDED
@@ -0,0 +1,860 @@
1
+ if (typeof globalThis !== "undefined" && !globalThis._MTCUTE_CJS_DEPRECATION_WARNED) {
2
+ globalThis._MTCUTE_CJS_DEPRECATION_WARNED = true;
3
+ console.warn("[mtcute-workspace] CommonJS support is deprecated and will be removed in 0.20.0. Please consider switching to ESM, it's " + (/* @__PURE__ */ new Date()).getFullYear() + " already.");
4
+ console.warn("[mtcute-workspace] Learn more about switching to ESM: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c");
5
+ }
6
+ "use strict";
7
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
8
+ const utils = require("@fuman/utils");
9
+ const core = require("@mtcute/core");
10
+ const parse = require("./context/parse.cjs");
11
+ const sceneTransition = require("./context/scene-transition.cjs");
12
+ const service = require("./state/service.cjs");
13
+ const key = require("./state/key.cjs");
14
+ const updateState = require("./state/update-state.cjs");
15
+ class Dispatcher {
16
+ _groups = /* @__PURE__ */ new Map();
17
+ _groupsOrder = [];
18
+ _client;
19
+ _parent;
20
+ _children = [];
21
+ _scenes;
22
+ _scene;
23
+ _sceneScoped;
24
+ _storage;
25
+ _stateKeyDelegate;
26
+ _customStateKeyDelegate;
27
+ _customStorage;
28
+ _deps = {};
29
+ _errorHandler;
30
+ _preUpdateHandler;
31
+ _postUpdateHandler;
32
+ _sceneTransitionHandler;
33
+ constructor(client, params) {
34
+ this.dispatchRawUpdate = this.dispatchRawUpdate.bind(this);
35
+ this.dispatchUpdate = this.dispatchUpdate.bind(this);
36
+ let { storage, key: key$1, sceneName } = params ?? {};
37
+ if (client) {
38
+ this.bindToClient(client);
39
+ if (storage) {
40
+ this._storage = new service.StateService(storage);
41
+ this._stateKeyDelegate = key$1 ?? key.defaultStateKeyDelegate;
42
+ }
43
+ } else {
44
+ if (storage) {
45
+ this._customStorage = new service.StateService(storage);
46
+ }
47
+ if (key$1) {
48
+ this._customStateKeyDelegate = key$1;
49
+ }
50
+ if (sceneName) {
51
+ if (sceneName[0] === "$") {
52
+ throw new core.MtArgumentError("Scene name cannot start with $");
53
+ }
54
+ this._scene = sceneName;
55
+ }
56
+ }
57
+ }
58
+ static for(client, params) {
59
+ return new Dispatcher(client, params);
60
+ }
61
+ /**
62
+ * Create a new child dispatcher.
63
+ */
64
+ static child(params) {
65
+ return new Dispatcher(void 0, params);
66
+ }
67
+ /**
68
+ * Create a new scene dispatcher
69
+ */
70
+ static scene(name, params) {
71
+ return new Dispatcher(void 0, { sceneName: name, ...params });
72
+ }
73
+ /** For scene dispatchers, name of the scene */
74
+ get sceneName() {
75
+ return this._scene;
76
+ }
77
+ inject(name, value) {
78
+ if (this._parent) {
79
+ throw new core.MtArgumentError("Cannot inject dependencies to child dispatchers");
80
+ }
81
+ if (typeof name === "object") {
82
+ for (const [k, v] of Object.entries(name)) {
83
+ this._deps[k] = v;
84
+ }
85
+ } else {
86
+ this._deps[name] = value;
87
+ }
88
+ }
89
+ /**
90
+ * Get the dependencies injected into this dispatcher.
91
+ */
92
+ get deps() {
93
+ return this._deps;
94
+ }
95
+ /**
96
+ * Bind the dispatcher to the client.
97
+ * Called by the constructor automatically if
98
+ * `client` was passed.
99
+ *
100
+ * Dispatcher also uses bound client to throw errors
101
+ */
102
+ bindToClient(client) {
103
+ client.onUpdate.add(this.dispatchUpdate);
104
+ client.onRawUpdate.add(this.dispatchRawUpdate);
105
+ this._client = client;
106
+ }
107
+ /**
108
+ * Unbind a dispatcher from the client.
109
+ */
110
+ unbind() {
111
+ if (this._client) {
112
+ this._client.onUpdate.remove(this.dispatchUpdate);
113
+ this._client.onRawUpdate.remove(this.dispatchRawUpdate);
114
+ this._client = void 0;
115
+ }
116
+ }
117
+ /**
118
+ * Destroy the dispatcher and all its children.
119
+ *
120
+ * When destroying, all the registered handlers are removed,
121
+ * and the underlying storage is freed.
122
+ */
123
+ async destroy() {
124
+ if (this._parent && this._customStorage) {
125
+ await this._customStorage.destroy();
126
+ } else if (!this._parent && this._storage) {
127
+ await this._storage.destroy();
128
+ }
129
+ this.removeUpdateHandler("all");
130
+ for (const child of this._children) {
131
+ await child.destroy();
132
+ }
133
+ for (const scene of this._scenes?.values() ?? []) {
134
+ await scene.destroy();
135
+ }
136
+ }
137
+ /**
138
+ * Process a raw update with this dispatcher.
139
+ * Calling this method without bound client will not work.
140
+ *
141
+ * Under the hood asynchronously calls {@link dispatchRawUpdateNow}
142
+ * with error handler set to client's one.
143
+ *
144
+ * @param update Update to process
145
+ * @param peers Peers index
146
+ */
147
+ dispatchRawUpdate({ update, peers }) {
148
+ if (!this._client) return;
149
+ this.dispatchRawUpdateNow(update, peers).catch((err) => this._client.onError.emit(utils.unknownToError(err)));
150
+ }
151
+ /**
152
+ * Process a raw update right now in the current stack.
153
+ *
154
+ * Unlike {@link dispatchRawUpdate}, this does not schedule
155
+ * the update to be dispatched, but dispatches it immediately,
156
+ * and after `await`ing this method you can be certain that the update
157
+ * was fully processed by all the registered handlers, including children.
158
+ *
159
+ * @param update Update to process
160
+ * @param peers Peers map
161
+ * @returns Whether the update was handled
162
+ */
163
+ async dispatchRawUpdateNow(update, peers) {
164
+ if (!this._client) return false;
165
+ let handled = false;
166
+ outer: for (const grp of this._groupsOrder) {
167
+ const group = this._groups.get(grp);
168
+ if (group.has("raw")) {
169
+ const handlers = group.get("raw");
170
+ for (const h of handlers) {
171
+ let result;
172
+ if (!h.check || await h.check(this._client, update, peers)) {
173
+ result = await h.callback(this._client, update, peers);
174
+ handled = true;
175
+ } else {
176
+ continue;
177
+ }
178
+ switch (result) {
179
+ case "continue":
180
+ continue;
181
+ case "stop":
182
+ break outer;
183
+ case "stop-children":
184
+ return handled;
185
+ }
186
+ break;
187
+ }
188
+ }
189
+ }
190
+ for (const child of this._children) {
191
+ const childHandled = await child.dispatchRawUpdateNow(update, peers);
192
+ handled ||= childHandled;
193
+ }
194
+ return handled;
195
+ }
196
+ /**
197
+ * Process an update with this dispatcher.
198
+ * Calling this method without bound client will not work.
199
+ *
200
+ * Under the hood asynchronously calls {@link dispatchUpdateNow}
201
+ * with error handler set to client's one.
202
+ *
203
+ * @param update Update to process
204
+ */
205
+ dispatchUpdate(update) {
206
+ if (!this._client) return;
207
+ this.dispatchUpdateNow(update).catch((err) => this._client.onError.emit(utils.unknownToError(err)));
208
+ }
209
+ /**
210
+ * Process an update right now in the current stack.
211
+ *
212
+ * Unlike {@link dispatchUpdate}, this does not schedule
213
+ * the update to be dispatched, but dispatches it immediately,
214
+ * and after `await`ing this method you can be certain that the update
215
+ * was fully processed by all the registered handlers, including children.
216
+ *
217
+ * @param update Update to process
218
+ * @returns Whether the update was handled
219
+ */
220
+ async dispatchUpdateNow(update) {
221
+ return this._dispatchUpdateNowImpl(update);
222
+ }
223
+ async _dispatchUpdateNowImpl(update, parsedState, parsedScene, forceScene, parsedContext) {
224
+ if (!this._client) return false;
225
+ if (parsedScene === void 0) {
226
+ if (this._storage && this._scenes && (update.name === "new_message" || update.name === "edit_message" || update.name === "callback_query" || update.name === "message_group" || update.name === "new_business_message" || update.name === "edit_business_message" || update.name === "business_message_group")) {
227
+ if (!parsedContext) parsedContext = parse._parsedUpdateToContext(this._client, update);
228
+ const key2 = await this._stateKeyDelegate(parsedContext);
229
+ if (key2) {
230
+ parsedScene = await this._storage.getCurrentScene(key2);
231
+ } else {
232
+ parsedScene = null;
233
+ }
234
+ } else {
235
+ parsedScene = null;
236
+ }
237
+ }
238
+ if (!forceScene && parsedScene !== null) {
239
+ if (this._scene) {
240
+ if (this._scene !== parsedScene) {
241
+ return false;
242
+ }
243
+ } else {
244
+ if (!this._scenes || !this._scenes.has(parsedScene)) {
245
+ return false;
246
+ }
247
+ return this._scenes.get(parsedScene)._dispatchUpdateNowImpl(update, parsedState, parsedScene, true);
248
+ }
249
+ }
250
+ if (parsedState === void 0) {
251
+ if (this._storage && (update.name === "new_message" || update.name === "edit_message" || update.name === "callback_query" || update.name === "message_group" || update.name === "new_business_message" || update.name === "edit_business_message" || update.name === "business_message_group")) {
252
+ if (!parsedContext) parsedContext = parse._parsedUpdateToContext(this._client, update);
253
+ const key2 = await this._stateKeyDelegate(parsedContext);
254
+ if (key2) {
255
+ let customKey;
256
+ if (!this._customStateKeyDelegate || (customKey = await this._customStateKeyDelegate(parsedContext))) {
257
+ parsedState = new updateState.UpdateState(
258
+ this._storage,
259
+ key2,
260
+ this._scene ?? null,
261
+ this._sceneScoped,
262
+ this._customStorage,
263
+ customKey
264
+ );
265
+ }
266
+ } else {
267
+ parsedState = null;
268
+ }
269
+ } else {
270
+ parsedState = null;
271
+ }
272
+ }
273
+ let shouldDispatch = true;
274
+ let shouldDispatchChildren = true;
275
+ let handled = false;
276
+ switch (await this._preUpdateHandler?.(update, parsedState)) {
277
+ case "stop":
278
+ shouldDispatch = false;
279
+ break;
280
+ case "stop-children":
281
+ return false;
282
+ }
283
+ if (shouldDispatch) {
284
+ outer: for (const grp of this._groupsOrder) {
285
+ const group = this._groups.get(grp);
286
+ if (group.has(update.name)) {
287
+ const handlers = group.get(update.name);
288
+ try {
289
+ for (const h of handlers) {
290
+ let result;
291
+ if (!parsedContext) parsedContext = parse._parsedUpdateToContext(this._client, update);
292
+ if (!h.check || await h.check(parsedContext, parsedState)) {
293
+ result = await h.callback(parsedContext, parsedState);
294
+ handled = true;
295
+ } else {
296
+ continue;
297
+ }
298
+ if (parsedState && this._scenes) {
299
+ const newScene = parsedState.scene;
300
+ if (parsedScene !== newScene) {
301
+ const nextDp = newScene ? this._scenes.get(newScene) : this._parent;
302
+ if (!nextDp) {
303
+ throw new core.MtArgumentError(`Scene ${newScene} not found`);
304
+ }
305
+ if (nextDp._sceneTransitionHandler) {
306
+ const transition = new sceneTransition.SceneTransitionContext(parsedScene, parsedContext);
307
+ const transitionResult = await nextDp._sceneTransitionHandler?.(
308
+ transition,
309
+ parsedState
310
+ );
311
+ switch (transitionResult) {
312
+ case "stop":
313
+ return true;
314
+ case "continue":
315
+ continue;
316
+ case "scene": {
317
+ const scene = parsedState.scene;
318
+ const dp = scene ? nextDp._scenes.get(scene) : nextDp._parent;
319
+ return dp._dispatchUpdateNowImpl(update, void 0, scene, true);
320
+ }
321
+ }
322
+ }
323
+ }
324
+ }
325
+ switch (result) {
326
+ case "continue":
327
+ continue;
328
+ case "stop":
329
+ break outer;
330
+ case "stop-children":
331
+ shouldDispatchChildren = false;
332
+ break outer;
333
+ case "scene": {
334
+ if (!parsedState) {
335
+ throw new core.MtArgumentError("Cannot use ToScene without state");
336
+ }
337
+ const scene = parsedState.scene;
338
+ const dp = scene ? this._scenes.get(scene) : this._parent;
339
+ return dp._dispatchUpdateNowImpl(update, void 0, scene, true);
340
+ }
341
+ }
342
+ break;
343
+ }
344
+ } catch (e) {
345
+ if (this._errorHandler) {
346
+ const handled2 = await this._errorHandler(e, update, parsedState);
347
+ if (!handled2) throw e;
348
+ } else {
349
+ throw e;
350
+ }
351
+ }
352
+ }
353
+ }
354
+ }
355
+ if (shouldDispatchChildren) {
356
+ for (const child of this._children) {
357
+ const childHandled = await child._dispatchUpdateNowImpl(update);
358
+ handled ||= childHandled;
359
+ }
360
+ }
361
+ await this._postUpdateHandler?.(handled, update, parsedState);
362
+ return handled;
363
+ }
364
+ /**
365
+ * Add an update handler to a given handlers group
366
+ *
367
+ * @param handler Update handler
368
+ * @param group Handler group index
369
+ */
370
+ addUpdateHandler(handler, group = 0) {
371
+ if (!this._groups.has(group)) {
372
+ this._groups.set(group, /* @__PURE__ */ new Map());
373
+ this._groupsOrder.push(group);
374
+ this._groupsOrder.sort((a, b) => a - b);
375
+ }
376
+ if (!this._groups.get(group).has(handler.name)) {
377
+ this._groups.get(group).set(handler.name, []);
378
+ }
379
+ this._groups.get(group).get(handler.name).push(handler);
380
+ }
381
+ /**
382
+ * Remove an update handler (or handlers) from a given
383
+ * handler group.
384
+ *
385
+ * @param handler Update handler to remove, its name or `'all'` to remove all
386
+ * @param group Handler group index (null to affect all groups)
387
+ */
388
+ removeUpdateHandler(handler, group = 0) {
389
+ if (group !== null && !this._groups.has(group)) {
390
+ return;
391
+ }
392
+ if (typeof handler === "string") {
393
+ if (handler === "all") {
394
+ if (group === null) {
395
+ this._groups = /* @__PURE__ */ new Map();
396
+ } else {
397
+ this._groups.delete(group);
398
+ }
399
+ } else if (group !== null) {
400
+ this._groups.get(group).delete(handler);
401
+ }
402
+ return;
403
+ }
404
+ if (group === null) return;
405
+ if (!this._groups.get(group).has(handler.name)) {
406
+ return;
407
+ }
408
+ const idx = this._groups.get(group).get(handler.name).indexOf(handler);
409
+ if (idx > -1) {
410
+ this._groups.get(group).get(handler.name).splice(idx, 1);
411
+ }
412
+ }
413
+ /**
414
+ * Register an error handler.
415
+ *
416
+ * This is used locally within this dispatcher
417
+ * (does not affect children/parent) whenever
418
+ * an error is thrown inside an update handler.
419
+ * Not used for raw update handlers
420
+ *
421
+ * When an error is thrown, but there is no error
422
+ * handler, it is propagated to `TelegramClient`.
423
+ *
424
+ * There can be at most one error handler.
425
+ * Pass `null` to remove it.
426
+ *
427
+ * @param handler Error handler
428
+ */
429
+ onError(handler) {
430
+ if (handler) this._errorHandler = handler;
431
+ else this._errorHandler = void 0;
432
+ }
433
+ /**
434
+ * Register pre-update middleware.
435
+ *
436
+ * This is used locally within this dispatcher
437
+ * (does not affect children/parent) before processing
438
+ * an update, and can be used to skip this update.
439
+ *
440
+ * There can be at most one pre-update middleware.
441
+ * Pass `null` to remove it.
442
+ *
443
+ * @param handler Pre-update middleware
444
+ */
445
+ onPreUpdate(handler) {
446
+ if (handler) this._preUpdateHandler = handler;
447
+ else this._preUpdateHandler = void 0;
448
+ }
449
+ /**
450
+ * Register post-update middleware.
451
+ *
452
+ * This is used locally within this dispatcher
453
+ * (does not affect children/parent) after successfully
454
+ * processing an update, and can be used for stats.
455
+ *
456
+ * There can be at most one post-update middleware.
457
+ * Pass `null` to remove it.
458
+ *
459
+ * @param handler Pre-update middleware
460
+ */
461
+ onPostUpdate(handler) {
462
+ if (handler) this._postUpdateHandler = handler;
463
+ else this._postUpdateHandler = void 0;
464
+ }
465
+ /**
466
+ * Set error handler that will propagate
467
+ * the error to the parent dispatcher
468
+ */
469
+ propagateErrorToParent(err, update, state) {
470
+ if (!this.parent) {
471
+ throw new core.MtArgumentError("This dispatcher is not a child");
472
+ }
473
+ if (this.parent._errorHandler) {
474
+ return this.parent._errorHandler(err, update, state);
475
+ }
476
+ throw err;
477
+ }
478
+ // children //
479
+ /**
480
+ * Get parent dispatcher if current dispatcher is a child.
481
+ * Otherwise, return `null`
482
+ */
483
+ get parent() {
484
+ return this._parent ?? null;
485
+ }
486
+ _prepareChild(child) {
487
+ if (child._client) {
488
+ throw new core.MtArgumentError(
489
+ `Provided dispatcher is ${child._parent ? "already a child. Use parent.removeChild() before calling addChild()" : "already bound to a client. Use unbind() before calling addChild()"}`
490
+ );
491
+ }
492
+ child._parent = this;
493
+ child._client = this._client;
494
+ child._storage = this._storage;
495
+ child._deps = this._deps;
496
+ child._scenes = this._scenes;
497
+ child._stateKeyDelegate = this._stateKeyDelegate;
498
+ child._customStorage ??= this._customStorage;
499
+ child._customStateKeyDelegate ??= this._customStateKeyDelegate;
500
+ }
501
+ /**
502
+ * Add a child dispatcher.
503
+ *
504
+ * Child dispatchers are called when dispatching updates
505
+ * just like normal, except they can be controlled
506
+ * externally. Additionally, child dispatcher have their own
507
+ * independent handler grouping that does not interfere with parent's,
508
+ * including `StopPropagation` (i.e. returning `StopPropagation` will
509
+ * still call children. To entirely stop, use `StopChildrenPropagation`)
510
+ *
511
+ * Note that child dispatchers share the same TelegramClient and
512
+ * storage binding as the parent, don't bind them manually.
513
+ *
514
+ * @param child Other dispatcher
515
+ */
516
+ addChild(child) {
517
+ if (this._children.includes(child)) return;
518
+ this._prepareChild(child);
519
+ this._children.push(child);
520
+ }
521
+ addScene(scene, scoped = true) {
522
+ if (!this._scenes) this._scenes = /* @__PURE__ */ new Map();
523
+ if (!scene._scene) {
524
+ throw new core.MtArgumentError(
525
+ "Non-scene dispatcher passed to addScene. Use `Dispatcher.scene()` to create one."
526
+ );
527
+ }
528
+ if (this._scenes.has(scene._scene)) {
529
+ throw new core.MtArgumentError(`Scene with name ${scene._scene} is already registered!`);
530
+ }
531
+ this._prepareChild(scene);
532
+ scene._sceneScoped = scoped;
533
+ this._scenes.set(scene._scene, scene);
534
+ }
535
+ /**
536
+ * Remove a child dispatcher.
537
+ *
538
+ * Removing child dispatcher will also remove
539
+ * child dispatcher's client binding.
540
+ *
541
+ * If the provided dispatcher is not a child of current,
542
+ * this function will silently fail.
543
+ *
544
+ * @param child Other dispatcher
545
+ */
546
+ removeChild(child) {
547
+ const idx = this._children.indexOf(child);
548
+ if (idx > -1) {
549
+ child._unparent();
550
+ this._children.splice(idx, 1);
551
+ }
552
+ }
553
+ _unparent() {
554
+ this._parent = this._client = void 0;
555
+ this._deps = {};
556
+ this._stateKeyDelegate = void 0;
557
+ this._storage = void 0;
558
+ }
559
+ /**
560
+ * Extend current dispatcher by copying other dispatcher's
561
+ * handlers and children to the current.
562
+ *
563
+ * This might be more efficient for simple cases, but do note that the handler
564
+ * groups, children and scenes will get merged (unlike {@link addChild},
565
+ * where they are independent). Also note that unlike with children,
566
+ * when adding handlers to `other` *after* you extended
567
+ * the current dispatcher, changes will not be applied.
568
+ *
569
+ * @param other Other dispatcher
570
+ */
571
+ extend(other) {
572
+ if (other._customStorage || other._customStateKeyDelegate) {
573
+ throw new core.MtArgumentError("Provided dispatcher has custom storage and cannot be extended from.");
574
+ }
575
+ other._groupsOrder.forEach((group) => {
576
+ if (!this._groups.has(group)) {
577
+ this._groups.set(group, other._groups.get(group));
578
+ this._groupsOrder.push(group);
579
+ } else {
580
+ const otherGrp = other._groups.get(group);
581
+ const selfGrp = this._groups.get(group);
582
+ for (const typ of otherGrp.keys()) {
583
+ if (!selfGrp.has(typ)) {
584
+ selfGrp.set(typ, otherGrp.get(typ));
585
+ } else {
586
+ selfGrp.get(typ).push(...otherGrp.get(typ));
587
+ }
588
+ }
589
+ }
590
+ });
591
+ other._children.forEach((it) => {
592
+ it._unparent();
593
+ this.addChild(it);
594
+ });
595
+ if (other._scenes) {
596
+ const otherScenes = other._scenes;
597
+ if (!this._scenes) this._scenes = /* @__PURE__ */ new Map();
598
+ const myScenes = this._scenes;
599
+ for (const key2 of otherScenes.keys()) {
600
+ otherScenes.get(key2)._unparent();
601
+ if (myScenes.has(key2)) {
602
+ myScenes.delete(key2);
603
+ }
604
+ this.addScene(otherScenes.get(key2), otherScenes.get(key2)._sceneScoped);
605
+ }
606
+ }
607
+ this._groupsOrder.sort((a, b) => a - b);
608
+ }
609
+ /**
610
+ * Create a clone of this dispatcher, that has the same handlers,
611
+ * but is not bound to a client or to a parent dispatcher.
612
+ *
613
+ * Custom Storage and key delegate are copied too.
614
+ *
615
+ * By default, child dispatchers (and scenes) are ignored, since
616
+ * that requires cloning every single one of them recursively
617
+ * and then binding them back.
618
+ *
619
+ * @param children Whether to also clone children and scenes
620
+ */
621
+ clone(children = false) {
622
+ const dp = new Dispatcher();
623
+ for (const key2 of this._groups.keys()) {
624
+ const idx = key2;
625
+ dp._groups.set(idx, /* @__PURE__ */ new Map());
626
+ for (const type of this._groups.get(idx).keys()) {
627
+ dp._groups.get(idx).set(type, [...this._groups.get(idx).get(type)]);
628
+ }
629
+ }
630
+ dp._groupsOrder = [...this._groupsOrder];
631
+ dp._errorHandler = this._errorHandler;
632
+ dp._customStateKeyDelegate = this._customStateKeyDelegate;
633
+ dp._customStorage = this._customStorage;
634
+ if (children) {
635
+ this._children.forEach((it) => {
636
+ const child = it.clone(true);
637
+ dp.addChild(child);
638
+ });
639
+ if (this._scenes) {
640
+ for (const key2 of this._scenes.keys()) {
641
+ const scene = this._scenes.get(key2).clone(true);
642
+ dp.addScene(scene, this._scenes.get(key2)._sceneScoped);
643
+ }
644
+ }
645
+ }
646
+ return dp;
647
+ }
648
+ getState(object) {
649
+ if (!this._storage) {
650
+ throw new core.MtArgumentError("Cannot use getUpdateState() filter without state storage");
651
+ }
652
+ if (typeof object === "string") {
653
+ return new updateState.UpdateState(this._storage, object, this._scene ?? null, this._sceneScoped, this._customStorage);
654
+ }
655
+ return Promise.resolve(this._stateKeyDelegate(object)).then((key2) => {
656
+ if (!key2) {
657
+ throw new core.MtArgumentError("Cannot derive key from given object");
658
+ }
659
+ if (!this._customStateKeyDelegate) {
660
+ return new updateState.UpdateState(this._storage, key2, this._scene ?? null, this._sceneScoped, this._customStorage);
661
+ }
662
+ return Promise.resolve(this._customStateKeyDelegate(object)).then((customKey) => {
663
+ if (!customKey) {
664
+ throw new core.MtArgumentError("Cannot derive custom key from given object");
665
+ }
666
+ return new updateState.UpdateState(
667
+ this._storage,
668
+ key2,
669
+ this._scene ?? null,
670
+ this._sceneScoped,
671
+ this._customStorage,
672
+ customKey
673
+ );
674
+ });
675
+ });
676
+ }
677
+ /**
678
+ * Get global state.
679
+ *
680
+ * This will load the state for the given object
681
+ * ignoring local custom storage, key delegate and scene scope.
682
+ */
683
+ getGlobalState(object) {
684
+ if (!this._parent) {
685
+ throw new core.MtArgumentError("This dispatcher does not have a parent");
686
+ }
687
+ return Promise.resolve(this._stateKeyDelegate(object)).then((key2) => {
688
+ if (!key2) {
689
+ throw new core.MtArgumentError("Cannot derive key from given object");
690
+ }
691
+ return new updateState.UpdateState(this._storage, key2, this._scene ?? null, false);
692
+ });
693
+ }
694
+ // addUpdateHandler convenience wrappers //
695
+ _addKnownHandler(name, filter, handler, group) {
696
+ if (typeof handler === "number" || typeof handler === "undefined") {
697
+ this.addUpdateHandler(
698
+ {
699
+ name,
700
+ callback: filter
701
+ },
702
+ handler
703
+ );
704
+ } else {
705
+ this.addUpdateHandler(
706
+ {
707
+ name,
708
+ callback: handler,
709
+ check: filter
710
+ },
711
+ group
712
+ );
713
+ }
714
+ }
715
+ /** @internal */
716
+ onRawUpdate(filter, handler, group) {
717
+ this._addKnownHandler("raw", filter, handler, group);
718
+ }
719
+ /**
720
+ * Register a scene transition handler
721
+ *
722
+ * This handler is called whenever a scene transition occurs
723
+ * in the context of the scene that is being entered,
724
+ * and before any of the its own handlers are called,
725
+ * and can be used to customize the transition behavior:
726
+ * - `Stop` to prevent dispatching the update any further **even if ToScene/ToRoot was used**
727
+ * - `Continue` same as Stop, but still dispatch the update to children
728
+ * - `ToScene` to prevent the transition and dispatch the update to the scene entered in the transition handler
729
+ *
730
+ * > **Note**: if multiple `state.enter()` calls were made within the same update,
731
+ * > this handler will only be called for the last one.
732
+ *
733
+ * @param handler Raw update handler
734
+ * @param group Handler group index
735
+ */
736
+ onSceneTransition(handler) {
737
+ if (handler) this._sceneTransitionHandler = handler;
738
+ else this._sceneTransitionHandler = void 0;
739
+ }
740
+ /** @internal */
741
+ onAnyCallbackQuery(filter, handler, group) {
742
+ this._addKnownHandler("callback_query", filter, handler, group);
743
+ this._addKnownHandler("inline_callback_query", filter, handler, group);
744
+ this._addKnownHandler("business_callback_query", filter, handler, group);
745
+ }
746
+ /** @internal */
747
+ onNewMessage(filter, handler, group) {
748
+ this._addKnownHandler("new_message", filter, handler, group);
749
+ }
750
+ /** @internal */
751
+ onEditMessage(filter, handler, group) {
752
+ this._addKnownHandler("edit_message", filter, handler, group);
753
+ }
754
+ /** @internal */
755
+ onMessageGroup(filter, handler, group) {
756
+ this._addKnownHandler("message_group", filter, handler, group);
757
+ }
758
+ /** @internal */
759
+ onDeleteMessage(filter, handler, group) {
760
+ this._addKnownHandler("delete_message", filter, handler, group);
761
+ }
762
+ /** @internal */
763
+ onChatMemberUpdate(filter, handler, group) {
764
+ this._addKnownHandler("chat_member", filter, handler, group);
765
+ }
766
+ /** @internal */
767
+ onInlineQuery(filter, handler, group) {
768
+ this._addKnownHandler("inline_query", filter, handler, group);
769
+ }
770
+ /** @internal */
771
+ onChosenInlineResult(filter, handler, group) {
772
+ this._addKnownHandler("chosen_inline_result", filter, handler, group);
773
+ }
774
+ /** @internal */
775
+ onCallbackQuery(filter, handler, group) {
776
+ this._addKnownHandler("callback_query", filter, handler, group);
777
+ }
778
+ /** @internal */
779
+ onInlineCallbackQuery(filter, handler, group) {
780
+ this._addKnownHandler("inline_callback_query", filter, handler, group);
781
+ }
782
+ /** @internal */
783
+ onBusinessCallbackQuery(filter, handler, group) {
784
+ this._addKnownHandler("business_callback_query", filter, handler, group);
785
+ }
786
+ /** @internal */
787
+ onPollUpdate(filter, handler, group) {
788
+ this._addKnownHandler("poll", filter, handler, group);
789
+ }
790
+ /** @internal */
791
+ onPollVote(filter, handler, group) {
792
+ this._addKnownHandler("poll_vote", filter, handler, group);
793
+ }
794
+ /** @internal */
795
+ onUserStatusUpdate(filter, handler, group) {
796
+ this._addKnownHandler("user_status", filter, handler, group);
797
+ }
798
+ /** @internal */
799
+ onUserTyping(filter, handler, group) {
800
+ this._addKnownHandler("user_typing", filter, handler, group);
801
+ }
802
+ /** @internal */
803
+ onHistoryRead(filter, handler, group) {
804
+ this._addKnownHandler("history_read", filter, handler, group);
805
+ }
806
+ /** @internal */
807
+ onBotStopped(filter, handler, group) {
808
+ this._addKnownHandler("bot_stopped", filter, handler, group);
809
+ }
810
+ /** @internal */
811
+ onBotChatJoinRequest(filter, handler, group) {
812
+ this._addKnownHandler("bot_chat_join_request", filter, handler, group);
813
+ }
814
+ /** @internal */
815
+ onChatJoinRequest(filter, handler, group) {
816
+ this._addKnownHandler("chat_join_request", filter, handler, group);
817
+ }
818
+ /** @internal */
819
+ onPreCheckoutQuery(filter, handler, group) {
820
+ this._addKnownHandler("pre_checkout_query", filter, handler, group);
821
+ }
822
+ /** @internal */
823
+ onStoryUpdate(filter, handler, group) {
824
+ this._addKnownHandler("story", filter, handler, group);
825
+ }
826
+ /** @internal */
827
+ onDeleteStory(filter, handler, group) {
828
+ this._addKnownHandler("delete_story", filter, handler, group);
829
+ }
830
+ /** @internal */
831
+ onBotReactionUpdate(filter, handler, group) {
832
+ this._addKnownHandler("bot_reaction", filter, handler, group);
833
+ }
834
+ /** @internal */
835
+ onBotReactionCountUpdate(filter, handler, group) {
836
+ this._addKnownHandler("bot_reaction_count", filter, handler, group);
837
+ }
838
+ /** @internal */
839
+ onBusinessConnectionUpdate(filter, handler, group) {
840
+ this._addKnownHandler("business_connection", filter, handler, group);
841
+ }
842
+ /** @internal */
843
+ onNewBusinessMessage(filter, handler, group) {
844
+ this._addKnownHandler("new_business_message", filter, handler, group);
845
+ }
846
+ /** @internal */
847
+ onEditBusinessMessage(filter, handler, group) {
848
+ this._addKnownHandler("edit_business_message", filter, handler, group);
849
+ }
850
+ /** @internal */
851
+ onBusinessMessageGroup(filter, handler, group) {
852
+ this._addKnownHandler("business_message_group", filter, handler, group);
853
+ }
854
+ /** @internal */
855
+ onDeleteBusinessMessage(filter, handler, group) {
856
+ this._addKnownHandler("delete_business_message", filter, handler, group);
857
+ }
858
+ // end-codegen
859
+ }
860
+ exports.Dispatcher = Dispatcher;