@mtcute/dispatcher 0.1.1 → 0.2.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 (71) hide show
  1. package/cjs/callback-data-builder.d.ts +1 -1
  2. package/cjs/callback-data-builder.js +3 -1
  3. package/cjs/callback-data-builder.js.map +1 -1
  4. package/cjs/callback-data-builder.test.d.ts +1 -0
  5. package/cjs/callback-data-builder.test.js +74 -0
  6. package/cjs/callback-data-builder.test.js.map +1 -0
  7. package/cjs/context/callback-query.d.ts +7 -3
  8. package/cjs/context/callback-query.js +12 -0
  9. package/cjs/context/callback-query.js.map +1 -1
  10. package/cjs/context/index.d.ts +1 -1
  11. package/cjs/context/index.js.map +1 -1
  12. package/cjs/context/message.d.ts +7 -1
  13. package/cjs/context/message.js +20 -0
  14. package/cjs/context/message.js.map +1 -1
  15. package/cjs/dispatcher.d.ts +5 -12
  16. package/cjs/dispatcher.js +112 -63
  17. package/cjs/dispatcher.js.map +1 -1
  18. package/cjs/filters/bots.d.ts +4 -1
  19. package/cjs/filters/bots.js +6 -2
  20. package/cjs/filters/bots.js.map +1 -1
  21. package/cjs/filters/bots.test.d.ts +1 -0
  22. package/cjs/filters/bots.test.js +120 -0
  23. package/cjs/filters/bots.test.js.map +1 -0
  24. package/cjs/filters/index.d.ts +2 -1
  25. package/cjs/filters/index.js.map +1 -1
  26. package/cjs/filters/logic.test.d.ts +1 -0
  27. package/cjs/filters/logic.test.js +169 -0
  28. package/cjs/filters/logic.test.js.map +1 -0
  29. package/cjs/filters/message.d.ts +22 -6
  30. package/cjs/filters/message.js +25 -3
  31. package/cjs/filters/message.js.map +1 -1
  32. package/cjs/state/key.d.ts +2 -2
  33. package/cjs/state/key.js.map +1 -1
  34. package/cjs/state/storage.d.ts +21 -0
  35. package/cjs/state/storage.js.map +1 -1
  36. package/esm/callback-data-builder.d.ts +1 -1
  37. package/esm/callback-data-builder.js +3 -1
  38. package/esm/callback-data-builder.js.map +1 -1
  39. package/esm/callback-data-builder.test.d.ts +1 -0
  40. package/esm/callback-data-builder.test.js +72 -0
  41. package/esm/callback-data-builder.test.js.map +1 -0
  42. package/esm/context/callback-query.d.ts +7 -3
  43. package/esm/context/callback-query.js +13 -1
  44. package/esm/context/callback-query.js.map +1 -1
  45. package/esm/context/index.d.ts +1 -1
  46. package/esm/context/index.js.map +1 -1
  47. package/esm/context/message.d.ts +7 -1
  48. package/esm/context/message.js +21 -1
  49. package/esm/context/message.js.map +1 -1
  50. package/esm/dispatcher.d.ts +5 -12
  51. package/esm/dispatcher.js +112 -63
  52. package/esm/dispatcher.js.map +1 -1
  53. package/esm/filters/bots.d.ts +4 -1
  54. package/esm/filters/bots.js +6 -2
  55. package/esm/filters/bots.js.map +1 -1
  56. package/esm/filters/bots.test.d.ts +1 -0
  57. package/esm/filters/bots.test.js +118 -0
  58. package/esm/filters/bots.test.js.map +1 -0
  59. package/esm/filters/index.d.ts +2 -1
  60. package/esm/filters/index.js.map +1 -1
  61. package/esm/filters/logic.test.d.ts +1 -0
  62. package/esm/filters/logic.test.js +167 -0
  63. package/esm/filters/logic.test.js.map +1 -0
  64. package/esm/filters/message.d.ts +22 -6
  65. package/esm/filters/message.js +22 -2
  66. package/esm/filters/message.js.map +1 -1
  67. package/esm/state/key.d.ts +2 -2
  68. package/esm/state/key.js.map +1 -1
  69. package/esm/state/storage.d.ts +21 -0
  70. package/esm/state/storage.js.map +1 -1
  71. package/package.json +3 -2
package/cjs/dispatcher.js CHANGED
@@ -13,11 +13,13 @@ const index_js_1 = require("./state/index.js");
13
13
  */
14
14
  class Dispatcher {
15
15
  constructor(client, params) {
16
- this._groups = {};
16
+ this._groups = new Map();
17
17
  this._groupsOrder = [];
18
18
  this._children = [];
19
19
  this.dispatchRawUpdate = this.dispatchRawUpdate.bind(this);
20
20
  this.dispatchUpdate = this.dispatchUpdate.bind(this);
21
+ this._onClientBeforeConnect = this._onClientBeforeConnect.bind(this);
22
+ this._onClientBeforeClose = this._onClientBeforeClose.bind(this);
21
23
  // eslint-disable-next-line prefer-const
22
24
  let { storage, key, sceneName } = params ?? {};
23
25
  if (client) {
@@ -72,34 +74,75 @@ class Dispatcher {
72
74
  get sceneName() {
73
75
  return this._scene;
74
76
  }
77
+ _onClientBeforeConnect() {
78
+ (async () => {
79
+ if (!this._parent &&
80
+ this._storage &&
81
+ this._storage !== this._client.storage) {
82
+ // this is a root dispatcher with custom storage
83
+ await this._storage.load?.();
84
+ }
85
+ if (this._parent && this._customStorage) {
86
+ // this is a child dispatcher with custom storage
87
+ await this._customStorage.load?.();
88
+ }
89
+ for (const child of this._children) {
90
+ child._onClientBeforeConnect();
91
+ }
92
+ if (this._scenes) {
93
+ for (const scene of this._scenes.values()) {
94
+ scene._onClientBeforeConnect();
95
+ }
96
+ }
97
+ })().catch((err) => this._client._emitError(err));
98
+ }
99
+ _onClientBeforeClose() {
100
+ (async () => {
101
+ if (!this._parent &&
102
+ this._storage &&
103
+ this._storage !== this._client.storage) {
104
+ // this is a root dispatcher with custom storage
105
+ await this._storage.save?.();
106
+ await this._storage.destroy?.();
107
+ }
108
+ if (this._parent && this._customStorage) {
109
+ // this is a child dispatcher with custom storage
110
+ await this._customStorage.save?.();
111
+ await this._customStorage.destroy?.();
112
+ }
113
+ for (const child of this._children) {
114
+ child._onClientBeforeClose();
115
+ }
116
+ if (this._scenes) {
117
+ for (const scene of this._scenes.values()) {
118
+ scene._onClientBeforeClose();
119
+ }
120
+ }
121
+ })().catch((err) => this._client._emitError(err));
122
+ }
75
123
  /**
76
124
  * Bind the dispatcher to the client.
77
125
  * Called by the constructor automatically if
78
126
  * `client` was passed.
79
127
  *
80
- * Under the hood, this replaces client's `dispatchUpdate`
81
- * function, meaning you can't bind two different
82
- * dispatchers to the same client at the same time.
83
- * Instead, use {@link extend}, {@link addChild}
84
- * or {@link addScene} on the existing, already bound dispatcher.
85
- *
86
128
  * Dispatcher also uses bound client to throw errors
87
129
  */
88
130
  bindToClient(client) {
89
131
  client.on('update', this.dispatchUpdate);
90
132
  client.on('raw_update', this.dispatchRawUpdate);
133
+ client.on('before_connect', this._onClientBeforeConnect);
134
+ client.on('before_close', this._onClientBeforeClose);
91
135
  this._client = client;
92
136
  }
93
137
  /**
94
138
  * Unbind a dispatcher from the client.
95
- *
96
- * This will replace client's dispatchUpdate with a no-op.
97
- * If this dispatcher is not bound, nothing will happen.
98
139
  */
99
140
  unbind() {
100
141
  if (this._client) {
101
142
  this._client.off('update', this.dispatchUpdate);
102
143
  this._client.off('raw_update', this.dispatchRawUpdate);
144
+ this._client.off('before_connect', this._onClientBeforeConnect);
145
+ this._client.off('before_close', this._onClientBeforeClose);
103
146
  this._client = undefined;
104
147
  }
105
148
  }
@@ -137,9 +180,9 @@ class Dispatcher {
137
180
  return false;
138
181
  let handled = false;
139
182
  outer: for (const grp of this._groupsOrder) {
140
- const group = this._groups[grp];
141
- if ('raw' in group) {
142
- const handlers = group.raw;
183
+ const group = this._groups.get(grp);
184
+ if (group.has('raw')) {
185
+ const handlers = group.get('raw');
143
186
  for (const h of handlers) {
144
187
  let result;
145
188
  if (!h.check || (await h.check(this._client, update, peers))) {
@@ -231,11 +274,11 @@ class Dispatcher {
231
274
  }
232
275
  }
233
276
  else {
234
- if (!this._scenes || !(parsedScene in this._scenes)) {
277
+ if (!this._scenes || !this._scenes.has(parsedScene)) {
235
278
  // not registered scene
236
279
  return false;
237
280
  }
238
- return this._scenes[parsedScene]._dispatchUpdateNowImpl(update, parsedState, parsedScene, true);
281
+ return this._scenes.get(parsedScene)._dispatchUpdateNowImpl(update, parsedState, parsedScene, true);
239
282
  }
240
283
  }
241
284
  if (parsedState === undefined) {
@@ -274,10 +317,10 @@ class Dispatcher {
274
317
  }
275
318
  if (shouldDispatch) {
276
319
  outer: for (const grp of this._groupsOrder) {
277
- const group = this._groups[grp];
278
- if (update.name in group) {
320
+ const group = this._groups.get(grp);
321
+ if (group.has(update.name)) {
279
322
  // raw is not handled here, so we can safely assume this
280
- const handlers = group[update.name];
323
+ const handlers = group.get(update.name);
281
324
  try {
282
325
  for (const h of handlers) {
283
326
  let result;
@@ -305,7 +348,7 @@ class Dispatcher {
305
348
  if (!scene) {
306
349
  throw new client_1.MtArgumentError('Cannot use ToScene without entering a scene');
307
350
  }
308
- return this._scenes[scene]._dispatchUpdateNowImpl(update, undefined, scene, true);
351
+ return this._scenes.get(scene)._dispatchUpdateNowImpl(update, undefined, scene, true);
309
352
  }
310
353
  }
311
354
  break;
@@ -340,47 +383,49 @@ class Dispatcher {
340
383
  * @param group Handler group index
341
384
  */
342
385
  addUpdateHandler(handler, group = 0) {
343
- if (!(group in this._groups)) {
344
- this._groups[group] = {};
386
+ if (!this._groups.has(group)) {
387
+ this._groups.set(group, new Map());
345
388
  this._groupsOrder.push(group);
346
389
  this._groupsOrder.sort((a, b) => a - b);
347
390
  }
348
- if (!(handler.name in this._groups[group])) {
349
- this._groups[group][handler.name] = [];
391
+ if (!this._groups.get(group).has(handler.name)) {
392
+ this._groups.get(group).set(handler.name, []);
350
393
  }
351
- this._groups[group][handler.name].push(handler);
394
+ this._groups.get(group).get(handler.name).push(handler);
352
395
  }
353
396
  /**
354
397
  * Remove an update handler (or handlers) from a given
355
398
  * handler group.
356
399
  *
357
400
  * @param handler Update handler to remove, its name or `'all'` to remove all
358
- * @param group Handler group index (-1 to affect all groups)
401
+ * @param group Handler group index (null to affect all groups)
359
402
  */
360
403
  removeUpdateHandler(handler, group = 0) {
361
- if (group !== -1 && !(group in this._groups)) {
404
+ if (group !== null && !this._groups.has(group)) {
362
405
  return;
363
406
  }
364
407
  if (typeof handler === 'string') {
365
408
  if (handler === 'all') {
366
- if (group === -1) {
367
- this._groups = {};
409
+ if (group === null) {
410
+ this._groups = new Map();
368
411
  }
369
412
  else {
370
- delete this._groups[group];
413
+ this._groups.delete(group);
371
414
  }
372
415
  }
373
- else {
374
- delete this._groups[group][handler];
416
+ else if (group !== null) {
417
+ this._groups.get(group).delete(handler);
375
418
  }
376
419
  return;
377
420
  }
378
- if (!(handler.name in this._groups[group])) {
421
+ if (group === null)
422
+ return;
423
+ if (!this._groups.get(group).has(handler.name)) {
379
424
  return;
380
425
  }
381
- const idx = this._groups[group][handler.name].indexOf(handler);
426
+ const idx = this._groups.get(group).get(handler.name).indexOf(handler);
382
427
  if (idx > -1) {
383
- this._groups[group][handler.name].splice(idx, 1);
428
+ this._groups.get(group).get(handler.name).splice(idx, 1);
384
429
  }
385
430
  }
386
431
  /**
@@ -473,6 +518,8 @@ class Dispatcher {
473
518
  child._client = this._client;
474
519
  child._storage = this._storage;
475
520
  child._stateKeyDelegate = this._stateKeyDelegate;
521
+ child._customStorage ?? (child._customStorage = this._customStorage);
522
+ child._customStateKeyDelegate ?? (child._customStateKeyDelegate = this._customStateKeyDelegate);
476
523
  }
477
524
  /**
478
525
  * Add a child dispatcher.
@@ -497,16 +544,16 @@ class Dispatcher {
497
544
  }
498
545
  addScene(scene, scoped = true) {
499
546
  if (!this._scenes)
500
- this._scenes = {};
547
+ this._scenes = new Map();
501
548
  if (!scene._scene) {
502
549
  throw new client_1.MtArgumentError('Non-scene dispatcher passed to addScene. Use `Dispatcher.scene()` to create one.');
503
550
  }
504
- if (scene._scene in this._scenes) {
551
+ if (this._scenes.has(scene._scene)) {
505
552
  throw new client_1.MtArgumentError(`Scene with name ${scene._scene} is already registered!`);
506
553
  }
507
554
  this._prepareChild(scene);
508
555
  scene._sceneScoped = scoped;
509
- this._scenes[scene._scene] = scene;
556
+ this._scenes.set(scene._scene, scene);
510
557
  }
511
558
  /**
512
559
  * Remove a child dispatcher.
@@ -548,21 +595,22 @@ class Dispatcher {
548
595
  throw new client_1.MtArgumentError('Provided dispatcher has custom storage and cannot be extended from.');
549
596
  }
550
597
  other._groupsOrder.forEach((group) => {
551
- if (!(group in this._groups)) {
552
- this._groups[group] = other._groups[group];
598
+ if (!this._groups.has(group)) {
599
+ this._groups.set(group, other._groups.get(group));
553
600
  this._groupsOrder.push(group);
554
601
  }
555
602
  else {
556
- const otherGrp = other._groups[group];
557
- const selfGrp = this._groups[group];
558
- Object.keys(otherGrp).forEach((typ) => {
559
- if (!(typ in selfGrp)) {
560
- selfGrp[typ] = otherGrp[typ];
603
+ const otherGrp = other._groups.get(group);
604
+ const selfGrp = this._groups.get(group);
605
+ for (const typ of otherGrp.keys()) {
606
+ if (!selfGrp.has(typ)) {
607
+ selfGrp.set(typ, otherGrp.get(typ));
561
608
  }
562
609
  else {
563
- selfGrp[typ].push(...otherGrp[typ]);
610
+ // selfGrp[typ].push(...otherGrp[typ])
611
+ selfGrp.get(typ).push(...otherGrp.get(typ));
564
612
  }
565
- });
613
+ }
566
614
  }
567
615
  });
568
616
  other._children.forEach((it) => {
@@ -572,16 +620,16 @@ class Dispatcher {
572
620
  if (other._scenes) {
573
621
  const otherScenes = other._scenes;
574
622
  if (!this._scenes)
575
- this._scenes = {};
623
+ this._scenes = new Map();
576
624
  const myScenes = this._scenes;
577
- Object.keys(otherScenes).forEach((key) => {
578
- otherScenes[key]._unparent();
579
- if (key in myScenes) {
625
+ for (const key of otherScenes.keys()) {
626
+ otherScenes.get(key)._unparent();
627
+ if (myScenes.has(key)) {
580
628
  // will be overwritten
581
- delete myScenes[key];
629
+ myScenes.delete(key);
582
630
  }
583
- this.addScene(myScenes[key], myScenes[key]._sceneScoped);
584
- });
631
+ this.addScene(otherScenes.get(key), otherScenes.get(key)._sceneScoped);
632
+ }
585
633
  }
586
634
  this._groupsOrder.sort((a, b) => a - b);
587
635
  }
@@ -600,13 +648,14 @@ class Dispatcher {
600
648
  clone(children = false) {
601
649
  const dp = new Dispatcher();
602
650
  // copy handlers.
603
- Object.keys(this._groups).forEach((key) => {
651
+ for (const key of this._groups.keys()) {
604
652
  const idx = key;
605
- dp._groups[idx] = {};
606
- Object.keys(this._groups[idx]).forEach((type) => {
607
- dp._groups[idx][type] = [...this._groups[idx][type]];
608
- });
609
- });
653
+ dp._groups.set(idx, new Map());
654
+ for (const type of this._groups.get(idx).keys()) {
655
+ // dp._groups.get(idx)!.set(type, [...this._groups.get(idx)!].get(type)!])
656
+ dp._groups.get(idx).set(type, [...this._groups.get(idx).get(type)]);
657
+ }
658
+ }
610
659
  dp._groupsOrder = [...this._groupsOrder];
611
660
  dp._errorHandler = this._errorHandler;
612
661
  dp._customStateKeyDelegate = this._customStateKeyDelegate;
@@ -617,10 +666,10 @@ class Dispatcher {
617
666
  dp.addChild(child);
618
667
  });
619
668
  if (this._scenes) {
620
- Object.keys(this._scenes).forEach((key) => {
621
- const scene = this._scenes[key].clone(true);
622
- dp.addScene(scene, this._scenes[key]._sceneScoped);
623
- });
669
+ for (const key of this._scenes.keys()) {
670
+ const scene = this._scenes.get(key).clone(true);
671
+ dp.addScene(scene, this._scenes.get(key)._sceneScoped);
672
+ }
624
673
  }
625
674
  }
626
675
  return dp;