@mtcute/dispatcher 0.16.7 → 0.16.13

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 (237) hide show
  1. package/{cjs/callback-data-builder.d.ts → callback-data-builder.d.ts} +2 -2
  2. package/callback-data-builder.test.d.ts +1 -0
  3. package/{esm/context → context}/base.d.ts +2 -2
  4. package/{esm/context → context}/business-message.d.ts +5 -6
  5. package/{esm/context → context}/callback-query.d.ts +6 -7
  6. package/{cjs/context → context}/chat-join-request.d.ts +3 -3
  7. package/{esm/context → context}/chosen-inline-result.d.ts +3 -3
  8. package/{esm/context → context}/inline-query.d.ts +4 -5
  9. package/{cjs/context → context}/message.d.ts +11 -6
  10. package/{cjs/context → context}/parse.d.ts +3 -3
  11. package/{esm/context → context}/pre-checkout-query.d.ts +3 -3
  12. package/{esm/context → context}/scene-transition.d.ts +1 -1
  13. package/{cjs/dispatcher.d.ts → dispatcher.d.ts} +9 -10
  14. package/{cjs/filters → filters}/bots.d.ts +4 -4
  15. package/filters/bots.test.d.ts +1 -0
  16. package/{cjs/filters → filters}/chat.d.ts +3 -3
  17. package/{esm/filters → filters}/group.d.ts +4 -4
  18. package/{cjs/filters → filters}/logic.d.ts +1 -1
  19. package/filters/logic.test.d.ts +1 -0
  20. package/{esm/filters → filters}/message.d.ts +9 -5
  21. package/{cjs/filters → filters}/state.d.ts +2 -2
  22. package/{esm/filters → filters}/text.d.ts +3 -3
  23. package/{cjs/filters → filters}/types.d.ts +2 -2
  24. package/{cjs/filters → filters}/updates.d.ts +2 -2
  25. package/{cjs/filters → filters}/user.d.ts +3 -4
  26. package/{cjs/handler.d.ts → handler.d.ts} +5 -5
  27. package/index.cjs +2534 -0
  28. package/index.d.ts +8 -1
  29. package/index.js +2529 -1
  30. package/package.json +28 -24
  31. package/{cjs/state → state}/key.d.ts +3 -3
  32. package/state/provider.d.ts +5 -0
  33. package/{cjs/state → state}/providers/memory.d.ts +3 -4
  34. package/{esm/state → state}/providers/sqlite.d.ts +3 -3
  35. package/{cjs/state → state}/repository.d.ts +1 -1
  36. package/{esm/state → state}/service.d.ts +2 -2
  37. package/{cjs/state → state}/update-state.d.ts +2 -2
  38. package/{esm/wizard.d.ts → wizard.d.ts} +5 -6
  39. package/cjs/callback-data-builder.js +0 -141
  40. package/cjs/callback-data-builder.js.map +0 -1
  41. package/cjs/context/base.d.ts +0 -9
  42. package/cjs/context/base.js +0 -3
  43. package/cjs/context/base.js.map +0 -1
  44. package/cjs/context/business-message.d.ts +0 -61
  45. package/cjs/context/business-message.js +0 -146
  46. package/cjs/context/business-message.js.map +0 -1
  47. package/cjs/context/callback-query.d.ts +0 -63
  48. package/cjs/context/callback-query.js +0 -109
  49. package/cjs/context/callback-query.js.map +0 -1
  50. package/cjs/context/chat-join-request.js +0 -35
  51. package/cjs/context/chat-join-request.js.map +0 -1
  52. package/cjs/context/chosen-inline-result.d.ts +0 -22
  53. package/cjs/context/chosen-inline-result.js +0 -36
  54. package/cjs/context/chosen-inline-result.js.map +0 -1
  55. package/cjs/context/index.js +0 -25
  56. package/cjs/context/index.js.map +0 -1
  57. package/cjs/context/inline-query.d.ts +0 -16
  58. package/cjs/context/inline-query.js +0 -23
  59. package/cjs/context/inline-query.js.map +0 -1
  60. package/cjs/context/message.js +0 -171
  61. package/cjs/context/message.js.map +0 -1
  62. package/cjs/context/parse.js +0 -42
  63. package/cjs/context/parse.js.map +0 -1
  64. package/cjs/context/pre-checkout-query.d.ts +0 -17
  65. package/cjs/context/pre-checkout-query.js +0 -27
  66. package/cjs/context/pre-checkout-query.js.map +0 -1
  67. package/cjs/context/scene-transition.d.ts +0 -24
  68. package/cjs/context/scene-transition.js +0 -52
  69. package/cjs/context/scene-transition.js.map +0 -1
  70. package/cjs/dispatcher.js +0 -908
  71. package/cjs/dispatcher.js.map +0 -1
  72. package/cjs/filters/bots.js +0 -135
  73. package/cjs/filters/bots.js.map +0 -1
  74. package/cjs/filters/bundle.js +0 -27
  75. package/cjs/filters/bundle.js.map +0 -1
  76. package/cjs/filters/chat.js +0 -56
  77. package/cjs/filters/chat.js.map +0 -1
  78. package/cjs/filters/group.d.ts +0 -26
  79. package/cjs/filters/group.js +0 -69
  80. package/cjs/filters/group.js.map +0 -1
  81. package/cjs/filters/index.js +0 -29
  82. package/cjs/filters/index.js.map +0 -1
  83. package/cjs/filters/logic.js +0 -112
  84. package/cjs/filters/logic.js.map +0 -1
  85. package/cjs/filters/message.d.ts +0 -215
  86. package/cjs/filters/message.js +0 -191
  87. package/cjs/filters/message.js.map +0 -1
  88. package/cjs/filters/state.js +0 -33
  89. package/cjs/filters/state.js.map +0 -1
  90. package/cjs/filters/text.d.ts +0 -64
  91. package/cjs/filters/text.js +0 -136
  92. package/cjs/filters/text.js.map +0 -1
  93. package/cjs/filters/types.js +0 -3
  94. package/cjs/filters/types.js.map +0 -1
  95. package/cjs/filters/updates.js +0 -40
  96. package/cjs/filters/updates.js.map +0 -1
  97. package/cjs/filters/user.js +0 -77
  98. package/cjs/filters/user.js.map +0 -1
  99. package/cjs/handler.js +0 -4
  100. package/cjs/handler.js.map +0 -1
  101. package/cjs/index.js +0 -31
  102. package/cjs/index.js.map +0 -1
  103. package/cjs/package.json +0 -3
  104. package/cjs/propagation.js +0 -27
  105. package/cjs/propagation.js.map +0 -1
  106. package/cjs/state/index.js +0 -22
  107. package/cjs/state/index.js.map +0 -1
  108. package/cjs/state/key.js +0 -43
  109. package/cjs/state/key.js.map +0 -1
  110. package/cjs/state/provider.d.ts +0 -5
  111. package/cjs/state/provider.js +0 -3
  112. package/cjs/state/provider.js.map +0 -1
  113. package/cjs/state/providers/index.js +0 -19
  114. package/cjs/state/providers/index.js.map +0 -1
  115. package/cjs/state/providers/memory.js +0 -81
  116. package/cjs/state/providers/memory.js.map +0 -1
  117. package/cjs/state/providers/sqlite.d.ts +0 -28
  118. package/cjs/state/providers/sqlite.js +0 -100
  119. package/cjs/state/providers/sqlite.js.map +0 -1
  120. package/cjs/state/repository.js +0 -3
  121. package/cjs/state/repository.js.map +0 -1
  122. package/cjs/state/service.d.ts +0 -20
  123. package/cjs/state/service.js +0 -70
  124. package/cjs/state/service.js.map +0 -1
  125. package/cjs/state/update-state.js +0 -219
  126. package/cjs/state/update-state.js.map +0 -1
  127. package/cjs/wizard.d.ts +0 -65
  128. package/cjs/wizard.js +0 -105
  129. package/cjs/wizard.js.map +0 -1
  130. package/esm/callback-data-builder.d.ts +0 -49
  131. package/esm/callback-data-builder.js +0 -137
  132. package/esm/callback-data-builder.js.map +0 -1
  133. package/esm/context/base.js +0 -2
  134. package/esm/context/base.js.map +0 -1
  135. package/esm/context/business-message.js +0 -142
  136. package/esm/context/business-message.js.map +0 -1
  137. package/esm/context/callback-query.js +0 -103
  138. package/esm/context/callback-query.js.map +0 -1
  139. package/esm/context/chat-join-request.d.ts +0 -17
  140. package/esm/context/chat-join-request.js +0 -31
  141. package/esm/context/chat-join-request.js.map +0 -1
  142. package/esm/context/chosen-inline-result.js +0 -32
  143. package/esm/context/chosen-inline-result.js.map +0 -1
  144. package/esm/context/index.d.ts +0 -9
  145. package/esm/context/index.js +0 -9
  146. package/esm/context/index.js.map +0 -1
  147. package/esm/context/inline-query.js +0 -19
  148. package/esm/context/inline-query.js.map +0 -1
  149. package/esm/context/message.d.ts +0 -77
  150. package/esm/context/message.js +0 -167
  151. package/esm/context/message.js.map +0 -1
  152. package/esm/context/parse.d.ts +0 -13
  153. package/esm/context/parse.js +0 -39
  154. package/esm/context/parse.js.map +0 -1
  155. package/esm/context/pre-checkout-query.js +0 -23
  156. package/esm/context/pre-checkout-query.js.map +0 -1
  157. package/esm/context/scene-transition.js +0 -48
  158. package/esm/context/scene-transition.js.map +0 -1
  159. package/esm/dispatcher.d.ts +0 -881
  160. package/esm/dispatcher.js +0 -904
  161. package/esm/dispatcher.js.map +0 -1
  162. package/esm/filters/bots.d.ts +0 -64
  163. package/esm/filters/bots.js +0 -131
  164. package/esm/filters/bots.js.map +0 -1
  165. package/esm/filters/bundle.d.ts +0 -10
  166. package/esm/filters/bundle.js +0 -11
  167. package/esm/filters/bundle.js.map +0 -1
  168. package/esm/filters/chat.d.ts +0 -27
  169. package/esm/filters/chat.js +0 -51
  170. package/esm/filters/chat.js.map +0 -1
  171. package/esm/filters/group.js +0 -65
  172. package/esm/filters/group.js.map +0 -1
  173. package/esm/filters/index.d.ts +0 -4
  174. package/esm/filters/index.js +0 -3
  175. package/esm/filters/index.js.map +0 -1
  176. package/esm/filters/logic.d.ts +0 -29
  177. package/esm/filters/logic.js +0 -105
  178. package/esm/filters/logic.js.map +0 -1
  179. package/esm/filters/message.js +0 -168
  180. package/esm/filters/message.js.map +0 -1
  181. package/esm/filters/state.d.ts +0 -15
  182. package/esm/filters/state.js +0 -28
  183. package/esm/filters/state.js.map +0 -1
  184. package/esm/filters/text.js +0 -129
  185. package/esm/filters/text.js.map +0 -1
  186. package/esm/filters/types.d.ts +0 -91
  187. package/esm/filters/types.js +0 -2
  188. package/esm/filters/types.js.map +0 -1
  189. package/esm/filters/updates.d.ts +0 -39
  190. package/esm/filters/updates.js +0 -34
  191. package/esm/filters/updates.js.map +0 -1
  192. package/esm/filters/user.d.ts +0 -25
  193. package/esm/filters/user.js +0 -71
  194. package/esm/filters/user.js.map +0 -1
  195. package/esm/handler.d.ts +0 -41
  196. package/esm/handler.js +0 -3
  197. package/esm/handler.js.map +0 -1
  198. package/esm/index.d.ts +0 -8
  199. package/esm/index.js +0 -9
  200. package/esm/index.js.map +0 -1
  201. package/esm/propagation.d.ts +0 -22
  202. package/esm/propagation.js +0 -24
  203. package/esm/propagation.js.map +0 -1
  204. package/esm/state/index.d.ts +0 -5
  205. package/esm/state/index.js +0 -6
  206. package/esm/state/index.js.map +0 -1
  207. package/esm/state/key.d.ts +0 -24
  208. package/esm/state/key.js +0 -39
  209. package/esm/state/key.js.map +0 -1
  210. package/esm/state/provider.d.ts +0 -5
  211. package/esm/state/provider.js +0 -2
  212. package/esm/state/provider.js.map +0 -1
  213. package/esm/state/providers/index.d.ts +0 -2
  214. package/esm/state/providers/index.js +0 -3
  215. package/esm/state/providers/index.js.map +0 -1
  216. package/esm/state/providers/memory.d.ts +0 -30
  217. package/esm/state/providers/memory.js +0 -77
  218. package/esm/state/providers/memory.js.map +0 -1
  219. package/esm/state/providers/sqlite.js +0 -96
  220. package/esm/state/providers/sqlite.js.map +0 -1
  221. package/esm/state/repository.d.ts +0 -62
  222. package/esm/state/repository.js +0 -2
  223. package/esm/state/repository.js.map +0 -1
  224. package/esm/state/service.js +0 -66
  225. package/esm/state/service.js.map +0 -1
  226. package/esm/state/update-state.d.ts +0 -151
  227. package/esm/state/update-state.js +0 -214
  228. package/esm/state/update-state.js.map +0 -1
  229. package/esm/wizard.js +0 -101
  230. package/esm/wizard.js.map +0 -1
  231. /package/{cjs/context → context}/index.d.ts +0 -0
  232. /package/{cjs/filters → filters}/bundle.d.ts +0 -0
  233. /package/{cjs/filters → filters}/index.d.ts +0 -0
  234. /package/{cjs/index.d.ts → index.d.cts} +0 -0
  235. /package/{cjs/propagation.d.ts → propagation.d.ts} +0 -0
  236. /package/{cjs/state → state}/index.d.ts +0 -0
  237. /package/{cjs/state → state}/providers/index.d.ts +0 -0
@@ -1,77 +0,0 @@
1
- import { MemoryStorageDriver } from '@mtcute/core';
2
- class MemoryStateRepository {
3
- _driver;
4
- state;
5
- rl;
6
- constructor(_driver) {
7
- this._driver = _driver;
8
- this.state = this._driver.getState('dispatcher_fsm', () => new Map());
9
- this.rl = this._driver.getState('rl', () => new Map());
10
- }
11
- setState(key, state, ttl) {
12
- this.state.set(key, {
13
- value: state,
14
- expiresAt: ttl ? Date.now() + ttl * 1000 : undefined,
15
- });
16
- }
17
- getState(key, now) {
18
- const state = this.state.get(key);
19
- if (!state)
20
- return null;
21
- if (state.expiresAt && state.expiresAt < now) {
22
- this.state.delete(key);
23
- return null;
24
- }
25
- return state.value;
26
- }
27
- deleteState(key) {
28
- this.state.delete(key);
29
- }
30
- vacuum(now) {
31
- for (const [key, state] of this.state.entries()) {
32
- if (state.expiresAt && state.expiresAt < now) {
33
- this.state.delete(key);
34
- }
35
- }
36
- for (const [key, state] of this.rl.entries()) {
37
- if (state.reset < now) {
38
- this.rl.delete(key);
39
- }
40
- }
41
- }
42
- getRateLimit(key, now, limit, window) {
43
- // leaky bucket
44
- const item = this.rl.get(key);
45
- if (!item) {
46
- const state = {
47
- reset: now + window * 1000,
48
- remaining: limit,
49
- };
50
- this.rl.set(key, state);
51
- return [state.remaining, state.reset];
52
- }
53
- if (item.reset < now) {
54
- // expired
55
- const state = {
56
- reset: now + window * 1000,
57
- remaining: limit,
58
- };
59
- this.rl.set(key, state);
60
- return [state.remaining, state.reset];
61
- }
62
- item.remaining = item.remaining > 0 ? item.remaining - 1 : 0;
63
- return [item.remaining, item.reset];
64
- }
65
- resetRateLimit(key) {
66
- this.rl.delete(key);
67
- }
68
- }
69
- export class MemoryStateStorage {
70
- driver;
71
- state;
72
- constructor(driver = new MemoryStorageDriver()) {
73
- this.driver = driver;
74
- this.state = new MemoryStateRepository(this.driver);
75
- }
76
- }
77
- //# sourceMappingURL=memory.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../../src/state/providers/memory.ts"],"names":[],"mappings":"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","sourcesContent":["import type { MaybePromise } from '@mtcute/core'\nimport { MemoryStorageDriver } from '@mtcute/core'\n\nimport type { IStateStorageProvider } from '../provider.js'\nimport type { IStateRepository } from '../repository.js'\n\ninterface StateDto {\n value: string\n expiresAt?: number\n}\n\ninterface RateLimitDto {\n reset: number\n remaining: number\n}\n\nclass MemoryStateRepository implements IStateRepository {\n readonly state: Map<string, StateDto>\n readonly rl: Map<string, RateLimitDto>\n constructor(readonly _driver: MemoryStorageDriver) {\n this.state = this._driver.getState<Map<string, StateDto>>('dispatcher_fsm', () => new Map())\n this.rl = this._driver.getState<Map<string, RateLimitDto>>('rl', () => new Map())\n }\n\n setState(key: string, state: string, ttl?: number | undefined): void {\n this.state.set(key, {\n value: state,\n expiresAt: ttl ? Date.now() + ttl * 1000 : undefined,\n })\n }\n\n getState(key: string, now: number): string | null {\n const state = this.state.get(key)\n if (!state) return null\n\n if (state.expiresAt && state.expiresAt < now) {\n this.state.delete(key)\n\n return null\n }\n\n return state.value\n }\n\n deleteState(key: string): void {\n this.state.delete(key)\n }\n\n vacuum(now: number): void {\n for (const [key, state] of this.state.entries()) {\n if (state.expiresAt && state.expiresAt < now) {\n this.state.delete(key)\n }\n }\n\n for (const [key, state] of this.rl.entries()) {\n if (state.reset < now) {\n this.rl.delete(key)\n }\n }\n }\n\n getRateLimit(key: string, now: number, limit: number, window: number): [number, number] {\n // leaky bucket\n const item = this.rl.get(key)\n\n if (!item) {\n const state: RateLimitDto = {\n reset: now + window * 1000,\n remaining: limit,\n }\n\n this.rl.set(key, state)\n\n return [state.remaining, state.reset]\n }\n\n if (item.reset < now) {\n // expired\n\n const state: RateLimitDto = {\n reset: now + window * 1000,\n remaining: limit,\n }\n\n this.rl.set(key, state)\n\n return [state.remaining, state.reset]\n }\n\n item.remaining = item.remaining > 0 ? item.remaining - 1 : 0\n\n return [item.remaining, item.reset]\n }\n\n resetRateLimit(key: string): MaybePromise<void> {\n this.rl.delete(key)\n }\n}\n\nexport class MemoryStateStorage implements IStateStorageProvider {\n readonly state: MemoryStateRepository\n\n constructor(readonly driver: MemoryStorageDriver = new MemoryStorageDriver()) {\n this.state = new MemoryStateRepository(this.driver)\n }\n}\n"]}
@@ -1,96 +0,0 @@
1
- class SqliteStateRepository {
2
- _driver;
3
- constructor(_driver) {
4
- this._driver = _driver;
5
- _driver.registerMigration('state', 1, (db) => {
6
- db.exec(`
7
- create table fsm_state (
8
- key text primary key,
9
- value text not null,
10
- expires_at integer
11
- );
12
- create table rl_state (
13
- key text primary key,
14
- reset integer not null,
15
- remaining integer not null
16
- );
17
- `);
18
- });
19
- _driver.onLoad(() => {
20
- this._setState = _driver.db.prepare('insert or replace into fsm_state (key, value, expires_at) values (?, ?, ?)');
21
- this._getState = _driver.db.prepare('select value, expires_at from fsm_state where key = ?');
22
- this._deleteState = _driver.db.prepare('delete from fsm_state where key = ?');
23
- this._deleteOldState = _driver.db.prepare('delete from fsm_state where expires_at < ?');
24
- this._setRl = _driver.db.prepare('insert or replace into rl_state (key, reset, remaining) values (?, ?, ?)');
25
- this._getRl = _driver.db.prepare('select reset, remaining from rl_state where key = ?');
26
- this._deleteRl = _driver.db.prepare('delete from rl_state where key = ?');
27
- this._deleteOldRl = _driver.db.prepare('delete from rl_state where reset < ?');
28
- });
29
- _driver.registerLegacyMigration('state', (db) => {
30
- // not too important information, just drop the table
31
- db.exec('drop table state');
32
- });
33
- }
34
- _setState;
35
- setState(key, state, ttl) {
36
- this._setState.run(key, state, ttl ? Date.now() + ttl * 1000 : undefined);
37
- }
38
- _getState;
39
- getState(key, now) {
40
- const res_ = this._getState.get(key);
41
- if (!res_)
42
- return null;
43
- const res = res_;
44
- if (res.expires_at && res.expires_at < now) {
45
- this._deleteState.run(key);
46
- return null;
47
- }
48
- return res.value;
49
- }
50
- _deleteState;
51
- deleteState(key) {
52
- this._deleteState.run(key);
53
- }
54
- _deleteOldState;
55
- _deleteOldRl;
56
- vacuum(now) {
57
- this._deleteOldState.run(now);
58
- this._deleteOldRl.run(now);
59
- }
60
- _setRl;
61
- _getRl;
62
- _deleteRl;
63
- getRateLimit(key, now, limit, window) {
64
- const val = this._getRl.get(key);
65
- // hot path. rate limit fsm entries always have an expiration date
66
- if (!val || val.reset < now) {
67
- // expired or does not exist
68
- const item = {
69
- reset: now + window * 1000,
70
- remaining: limit,
71
- };
72
- this._setRl.run(key, item.reset, item.remaining);
73
- return [item.remaining, item.reset];
74
- }
75
- if (val.remaining > 0) {
76
- val.remaining -= 1;
77
- this._setRl.run(key, val.reset, val.remaining);
78
- }
79
- return [val.remaining, val.reset];
80
- }
81
- resetRateLimit(key) {
82
- this._deleteRl.run(key);
83
- }
84
- }
85
- export class SqliteStateStorage {
86
- driver;
87
- state;
88
- constructor(driver) {
89
- this.driver = driver;
90
- this.state = new SqliteStateRepository(driver);
91
- }
92
- static from(provider) {
93
- return new SqliteStateStorage(provider.driver);
94
- }
95
- }
96
- //# sourceMappingURL=sqlite.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../../../src/state/providers/sqlite.ts"],"names":[],"mappings":"AAeA,MAAM,qBAAqB;IACF;IAArB,YAAqB,OAAgC;QAAhC,YAAO,GAAP,OAAO,CAAyB;QACjD,OAAO,CAAC,iBAAiB,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE;YACzC,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;aAWP,CAAC,CAAA;QACN,CAAC,CAAC,CAAA;QACF,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE;YAChB,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC,OAAO,CAC/B,4EAA4E,CAC/E,CAAA;YACD,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,uDAAuD,CAAC,CAAA;YAC5F,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,qCAAqC,CAAC,CAAA;YAC7E,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,4CAA4C,CAAC,CAAA;YAEvF,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,0EAA0E,CAAC,CAAA;YAC5G,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,qDAAqD,CAAC,CAAA;YACvF,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAA;YACzE,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,sCAAsC,CAAC,CAAA;QAClF,CAAC,CAAC,CAAA;QACF,OAAO,CAAC,uBAAuB,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE;YAC5C,qDAAqD;YACrD,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA;QAC/B,CAAC,CAAC,CAAA;IACN,CAAC;IAEO,SAAS,CAAmB;IACpC,QAAQ,CAAC,GAAW,EAAE,KAAa,EAAE,GAAwB;QACzD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IAC7E,CAAC;IAEO,SAAS,CAAmB;IACpC,QAAQ,CAAC,GAAW,EAAE,GAAW;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACpC,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAA;QACtB,MAAM,GAAG,GAAG,IAAgB,CAAA;QAE5B,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC;YACzC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YAE1B,OAAO,IAAI,CAAA;QACf,CAAC;QAED,OAAO,GAAG,CAAC,KAAK,CAAA;IACpB,CAAC;IAEO,YAAY,CAAmB;IACvC,WAAW,CAAC,GAAW;QACnB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC9B,CAAC;IAEO,eAAe,CAAmB;IAClC,YAAY,CAAmB;IACvC,MAAM,CAAC,GAAW;QACd,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC7B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC9B,CAAC;IAEO,MAAM,CAAmB;IACzB,MAAM,CAAmB;IACzB,SAAS,CAAmB;IAEpC,YAAY,CAAC,GAAW,EAAE,GAAW,EAAE,KAAa,EAAE,MAAc;QAChE,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAA6B,CAAA;QAE5D,kEAAkE;QAElE,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,GAAG,GAAG,EAAE,CAAC;YAC1B,4BAA4B;YAC5B,MAAM,IAAI,GAAiB;gBACvB,KAAK,EAAE,GAAG,GAAG,MAAM,GAAG,IAAI;gBAC1B,SAAS,EAAE,KAAK;aACnB,CAAA;YAED,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;YAEhD,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAA;QACvC,CAAC;QAED,IAAI,GAAG,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC;YACpB,GAAG,CAAC,SAAS,IAAI,CAAC,CAAA;YAElB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,SAAS,CAAC,CAAA;QAClD,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,CAAA;IACrC,CAAC;IAED,cAAc,CAAC,GAAW;QACtB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC3B,CAAC;CACJ;AAED,MAAM,OAAO,kBAAkB;IAEN;IADZ,KAAK,CAAuB;IACrC,YAAqB,MAA+B;QAA/B,WAAM,GAAN,MAAM,CAAyB;QAChD,IAAI,CAAC,KAAK,GAAG,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAAA;IAClD,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,QAA2B;QACnC,OAAO,IAAI,kBAAkB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IAClD,CAAC;CACJ","sourcesContent":["import type { BaseSqliteStorage, BaseSqliteStorageDriver, ISqliteStatement, MaybePromise } from '@mtcute/core'\n\nimport type { IStateStorageProvider } from '../provider.js'\nimport type { IStateRepository } from '../repository.js'\n\ninterface StateDto {\n value: string\n expires_at: number | null\n}\n\ninterface RateLimitDto {\n reset: number\n remaining: number\n}\n\nclass SqliteStateRepository implements IStateRepository {\n constructor(readonly _driver: BaseSqliteStorageDriver) {\n _driver.registerMigration('state', 1, (db) => {\n db.exec(`\n create table fsm_state (\n key text primary key,\n value text not null,\n expires_at integer\n );\n create table rl_state (\n key text primary key,\n reset integer not null,\n remaining integer not null\n );\n `)\n })\n _driver.onLoad(() => {\n this._setState = _driver.db.prepare(\n 'insert or replace into fsm_state (key, value, expires_at) values (?, ?, ?)',\n )\n this._getState = _driver.db.prepare('select value, expires_at from fsm_state where key = ?')\n this._deleteState = _driver.db.prepare('delete from fsm_state where key = ?')\n this._deleteOldState = _driver.db.prepare('delete from fsm_state where expires_at < ?')\n\n this._setRl = _driver.db.prepare('insert or replace into rl_state (key, reset, remaining) values (?, ?, ?)')\n this._getRl = _driver.db.prepare('select reset, remaining from rl_state where key = ?')\n this._deleteRl = _driver.db.prepare('delete from rl_state where key = ?')\n this._deleteOldRl = _driver.db.prepare('delete from rl_state where reset < ?')\n })\n _driver.registerLegacyMigration('state', (db) => {\n // not too important information, just drop the table\n db.exec('drop table state')\n })\n }\n\n private _setState!: ISqliteStatement\n setState(key: string, state: string, ttl?: number | undefined): MaybePromise<void> {\n this._setState.run(key, state, ttl ? Date.now() + ttl * 1000 : undefined)\n }\n\n private _getState!: ISqliteStatement\n getState(key: string, now: number): MaybePromise<string | null> {\n const res_ = this._getState.get(key)\n if (!res_) return null\n const res = res_ as StateDto\n\n if (res.expires_at && res.expires_at < now) {\n this._deleteState.run(key)\n\n return null\n }\n\n return res.value\n }\n\n private _deleteState!: ISqliteStatement\n deleteState(key: string): MaybePromise<void> {\n this._deleteState.run(key)\n }\n\n private _deleteOldState!: ISqliteStatement\n private _deleteOldRl!: ISqliteStatement\n vacuum(now: number): MaybePromise<void> {\n this._deleteOldState.run(now)\n this._deleteOldRl.run(now)\n }\n\n private _setRl!: ISqliteStatement\n private _getRl!: ISqliteStatement\n private _deleteRl!: ISqliteStatement\n\n getRateLimit(key: string, now: number, limit: number, window: number): [number, number] {\n const val = this._getRl.get(key) as RateLimitDto | undefined\n\n // hot path. rate limit fsm entries always have an expiration date\n\n if (!val || val.reset < now) {\n // expired or does not exist\n const item: RateLimitDto = {\n reset: now + window * 1000,\n remaining: limit,\n }\n\n this._setRl.run(key, item.reset, item.remaining)\n\n return [item.remaining, item.reset]\n }\n\n if (val.remaining > 0) {\n val.remaining -= 1\n\n this._setRl.run(key, val.reset, val.remaining)\n }\n\n return [val.remaining, val.reset]\n }\n\n resetRateLimit(key: string): MaybePromise<void> {\n this._deleteRl.run(key)\n }\n}\n\nexport class SqliteStateStorage implements IStateStorageProvider {\n readonly state: SqliteStateRepository\n constructor(readonly driver: BaseSqliteStorageDriver) {\n this.state = new SqliteStateRepository(driver)\n }\n\n static from(provider: BaseSqliteStorage): SqliteStateStorage {\n return new SqliteStateStorage(provider.driver)\n }\n}\n"]}
@@ -1,62 +0,0 @@
1
- import type { MaybePromise } from '@mtcute/core';
2
- /**
3
- * Interface for FSM storage for the dispatcher.
4
- *
5
- * All of the officially supported storages already implement
6
- * this interface, so you can just re-use it.
7
- *
8
- * Current scene is a special case of a `string` state,
9
- * Most of the time you can just store it the same way
10
- * as normal state, prefixing with something like `$current_state_`
11
- * (scene name can't start with `$`).
12
- * Alternatively, you can store them as simple strings
13
- */
14
- export interface IStateRepository {
15
- /**
16
- * Retrieve state from the storage
17
- * If state is not found or has expired, return `null`
18
- *
19
- * @param key Key of the state, as defined by {@link StateKeyDelegate}
20
- */
21
- getState: (key: string, now: number) => MaybePromise<string | null>;
22
- /**
23
- * Save state to the storage
24
- *
25
- * @param key Key of the state, as defined by {@link StateKeyDelegate}
26
- * @param state String representing the state
27
- * @param ttl TTL for the state, in seconds
28
- */
29
- setState: (key: string, state: string, ttl?: number) => MaybePromise<void>;
30
- /**
31
- * Delete state from the storage
32
- *
33
- * @param key Key of the state, as defined by {@link StateKeyDelegate}
34
- */
35
- deleteState: (key: string) => MaybePromise<void>;
36
- /**
37
- * Clean up expired states and rate limits.
38
- *
39
- * @param now Current unix time in ms
40
- */
41
- vacuum: (now: number) => MaybePromise<void>;
42
- /**
43
- * Get information about a rate limit.
44
- *
45
- * It is recommended that you use sliding window or leaky bucket
46
- * to implement rate limiting ([learn more](https://konghq.com/blog/how-to-design-a-scalable-rate-limiting-algorithm/)),
47
- *
48
- * @param key Key of the rate limit
49
- * @param now Current unix time in ms
50
- * @param limit Maximum number of requests in `window`
51
- * @param window Window size in seconds
52
- * @returns Tuple containing the number of remaining and
53
- * unix time in ms when the user can try again
54
- */
55
- getRateLimit: (key: string, now: number, limit: number, window: number) => MaybePromise<[number, number]>;
56
- /**
57
- * Reset a rate limit.
58
- *
59
- * @param key Key of the rate limit
60
- */
61
- resetRateLimit: (key: string) => MaybePromise<void>;
62
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=repository.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"repository.js","sourceRoot":"","sources":["../../../src/state/repository.ts"],"names":[],"mappings":"","sourcesContent":["import type { MaybePromise } from '@mtcute/core'\n\n/**\n * Interface for FSM storage for the dispatcher.\n *\n * All of the officially supported storages already implement\n * this interface, so you can just re-use it.\n *\n * Current scene is a special case of a `string` state,\n * Most of the time you can just store it the same way\n * as normal state, prefixing with something like `$current_state_`\n * (scene name can't start with `$`).\n * Alternatively, you can store them as simple strings\n */\nexport interface IStateRepository {\n /**\n * Retrieve state from the storage\n * If state is not found or has expired, return `null`\n *\n * @param key Key of the state, as defined by {@link StateKeyDelegate}\n */\n getState: (key: string, now: number) => MaybePromise<string | null>\n\n /**\n * Save state to the storage\n *\n * @param key Key of the state, as defined by {@link StateKeyDelegate}\n * @param state String representing the state\n * @param ttl TTL for the state, in seconds\n */\n setState: (key: string, state: string, ttl?: number) => MaybePromise<void>\n\n /**\n * Delete state from the storage\n *\n * @param key Key of the state, as defined by {@link StateKeyDelegate}\n */\n deleteState: (key: string) => MaybePromise<void>\n\n /**\n * Clean up expired states and rate limits.\n *\n * @param now Current unix time in ms\n */\n vacuum: (now: number) => MaybePromise<void>\n\n /**\n * Get information about a rate limit.\n *\n * It is recommended that you use sliding window or leaky bucket\n * to implement rate limiting ([learn more](https://konghq.com/blog/how-to-design-a-scalable-rate-limiting-algorithm/)),\n *\n * @param key Key of the rate limit\n * @param now Current unix time in ms\n * @param limit Maximum number of requests in `window`\n * @param window Window size in seconds\n * @returns Tuple containing the number of remaining and\n * unix time in ms when the user can try again\n */\n getRateLimit: (key: string, now: number, limit: number, window: number) => MaybePromise<[number, number]>\n\n /**\n * Reset a rate limit.\n *\n * @param key Key of the rate limit\n */\n resetRateLimit: (key: string) => MaybePromise<void>\n}\n"]}
@@ -1,66 +0,0 @@
1
- import { LruMap, asyncResettable } from '@mtcute/core/utils.js';
2
- const makeCurrentSceneKey = (key) => `$current_scene_${key}`;
3
- export class StateService {
4
- provider;
5
- constructor(provider) {
6
- this.provider = provider;
7
- }
8
- _cache = new LruMap(100);
9
- _vacuumTimer;
10
- _loaded = false;
11
- _load = asyncResettable(async () => {
12
- await this.provider.driver.load?.();
13
- this._loaded = true;
14
- });
15
- async load() {
16
- await this._load.run();
17
- this._vacuumTimer = setInterval(() => {
18
- Promise.resolve(this.provider.state.vacuum(Date.now())).catch(() => { });
19
- }, 300_000);
20
- }
21
- async destroy() {
22
- await this.provider.driver.save?.();
23
- await this.provider.driver.destroy?.();
24
- clearInterval(this._vacuumTimer);
25
- this._loaded = false;
26
- }
27
- async getState(key) {
28
- if (!this._loaded)
29
- await this.load();
30
- const cached = this._cache.get(key);
31
- if (cached)
32
- return cached;
33
- const state = await this.provider.state.getState(key, Date.now());
34
- if (!state)
35
- return null;
36
- return JSON.parse(state);
37
- }
38
- async setState(key, state, ttl) {
39
- if (!this._loaded)
40
- await this.load();
41
- this._cache.set(key, state);
42
- await this.provider.state.setState(key, JSON.stringify(state), ttl);
43
- }
44
- async deleteState(key) {
45
- if (!this._loaded)
46
- await this.load();
47
- this._cache.delete(key);
48
- await this.provider.state.deleteState(key);
49
- }
50
- getCurrentScene(key) {
51
- return this.getState(makeCurrentSceneKey(key));
52
- }
53
- setCurrentScene(key, scene, ttl) {
54
- return this.setState(makeCurrentSceneKey(key), scene, ttl);
55
- }
56
- deleteCurrentScene(key) {
57
- return this.deleteState(makeCurrentSceneKey(key));
58
- }
59
- getRateLimit(key, limit, window) {
60
- return this.provider.state.getRateLimit(key, Date.now(), limit, window);
61
- }
62
- resetRateLimit(key) {
63
- return this.provider.state.resetRateLimit(key);
64
- }
65
- }
66
- //# sourceMappingURL=service.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../../../src/state/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAK/D,MAAM,mBAAmB,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,kBAAkB,GAAG,EAAE,CAAA;AAEpE,MAAM,OAAO,YAAY;IACA;IAArB,YAAqB,QAA+B;QAA/B,aAAQ,GAAR,QAAQ,CAAuB;IAAG,CAAC;IAEhD,MAAM,GAA4B,IAAI,MAAM,CAAC,GAAG,CAAC,CAAA;IACjD,YAAY,CAAiB;IAE7B,OAAO,GAAG,KAAK,CAAA;IACf,KAAK,GAAG,eAAe,CAAC,KAAK,IAAI,EAAE;QACvC,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAA;QACnC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;IACvB,CAAC,CAAC,CAAA;IAEF,KAAK,CAAC,IAAI;QACN,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAA;QACtB,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE;YACjC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAC3E,CAAC,EAAE,OAAO,CAAC,CAAA;IACf,CAAC;IAED,KAAK,CAAC,OAAO;QACT,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAA;QACnC,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAA;QACtC,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;QAChC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;IACxB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAI,GAAW;QACzB,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,CAAC,IAAI,EAAE,CAAA;QAEpC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACnC,IAAI,MAAM;YAAE,OAAO,MAAW,CAAA;QAE9B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;QACjE,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAA;QAEvB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAM,CAAA;IACjC,CAAC;IAED,KAAK,CAAC,QAAQ,CAAI,GAAW,EAAE,KAAQ,EAAE,GAAY;QACjD,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,CAAC,IAAI,EAAE,CAAA;QAEpC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QAC3B,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAA;IACvE,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,GAAW;QACzB,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,CAAC,IAAI,EAAE,CAAA;QAEpC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACvB,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;IAC9C,CAAC;IAED,eAAe,CAAC,GAAW;QACvB,OAAO,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAA;IAClD,CAAC;IAED,eAAe,CAAC,GAAW,EAAE,KAAa,EAAE,GAAY;QACpD,OAAO,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAA;IAC9D,CAAC;IAED,kBAAkB,CAAC,GAAW;QAC1B,OAAO,IAAI,CAAC,WAAW,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAA;IACrD,CAAC;IAED,YAAY,CAAC,GAAW,EAAE,KAAa,EAAE,MAAc;QACnD,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;IAC3E,CAAC;IAED,cAAc,CAAC,GAAW;QACtB,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAA;IAClD,CAAC;CACJ","sourcesContent":["import { LruMap, asyncResettable } from '@mtcute/core/utils.js'\nimport type { MaybePromise } from '@mtcute/core'\n\nimport type { IStateStorageProvider } from './provider.js'\n\nconst makeCurrentSceneKey = (key: string) => `$current_scene_${key}`\n\nexport class StateService {\n constructor(readonly provider: IStateStorageProvider) {}\n\n private _cache: LruMap<string, unknown> = new LruMap(100)\n private _vacuumTimer?: NodeJS.Timeout\n\n private _loaded = false\n private _load = asyncResettable(async () => {\n await this.provider.driver.load?.()\n this._loaded = true\n })\n\n async load(): Promise<void> {\n await this._load.run()\n this._vacuumTimer = setInterval(() => {\n Promise.resolve(this.provider.state.vacuum(Date.now())).catch(() => {})\n }, 300_000)\n }\n\n async destroy(): Promise<void> {\n await this.provider.driver.save?.()\n await this.provider.driver.destroy?.()\n clearInterval(this._vacuumTimer)\n this._loaded = false\n }\n\n async getState<T>(key: string): Promise<T | null> {\n if (!this._loaded) await this.load()\n\n const cached = this._cache.get(key)\n if (cached) return cached as T\n\n const state = await this.provider.state.getState(key, Date.now())\n if (!state) return null\n\n return JSON.parse(state) as T\n }\n\n async setState<T>(key: string, state: T, ttl?: number): Promise<void> {\n if (!this._loaded) await this.load()\n\n this._cache.set(key, state)\n await this.provider.state.setState(key, JSON.stringify(state), ttl)\n }\n\n async deleteState(key: string): Promise<void> {\n if (!this._loaded) await this.load()\n\n this._cache.delete(key)\n await this.provider.state.deleteState(key)\n }\n\n getCurrentScene(key: string): Promise<string | null> {\n return this.getState(makeCurrentSceneKey(key))\n }\n\n setCurrentScene(key: string, scene: string, ttl?: number): Promise<void> {\n return this.setState(makeCurrentSceneKey(key), scene, ttl)\n }\n\n deleteCurrentScene(key: string): Promise<void> {\n return this.deleteState(makeCurrentSceneKey(key))\n }\n\n getRateLimit(key: string, limit: number, window: number): MaybePromise<[number, number]> {\n return this.provider.state.getRateLimit(key, Date.now(), limit, window)\n }\n\n resetRateLimit(key: string): MaybePromise<void> {\n return this.provider.state.resetRateLimit(key)\n }\n}\n"]}
@@ -1,151 +0,0 @@
1
- import { MtcuteError } from '@mtcute/core';
2
- import type { Dispatcher } from '../dispatcher.js';
3
- import type { StateService } from './service.js';
4
- /**
5
- * Error thrown by `.rateLimit()`
6
- */
7
- export declare class RateLimitError extends MtcuteError {
8
- readonly reset: number;
9
- constructor(reset: number);
10
- }
11
- /**
12
- * State of the current update.
13
- *
14
- * @template State Type that represents the state
15
- * @template SceneName Possible scene names
16
- */
17
- export declare class UpdateState<State extends object> {
18
- private _key;
19
- private _localKey;
20
- private _storage;
21
- private _scene;
22
- private _scoped?;
23
- private _cached?;
24
- private _localStorage;
25
- private _localKeyBase;
26
- constructor(storage: StateService, key: string, scene: string | null, scoped?: boolean, customStorage?: StateService, customKey?: string);
27
- /** Name of the current scene */
28
- get scene(): string | null;
29
- private _updateLocalKey;
30
- /**
31
- * Retrieve the state from the storage, falling back to default
32
- * if not found
33
- *
34
- * @param fallback Default state value
35
- * @param force Whether to ignore cached state (def. `false`)
36
- */
37
- get(fallback: State | (() => State), force?: boolean): Promise<State>;
38
- /**
39
- * Retrieve the state from the storage, falling back to default
40
- * if not found
41
- *
42
- * @param fallback Default state value
43
- * @param force Whether to ignore cached state (def. `false`)
44
- */
45
- get(fallback?: State | (() => State), force?: boolean): Promise<State | null>;
46
- /**
47
- * Retrieve the state from the storage
48
- *
49
- * @param force Whether to ignore cached state (def. `false`)
50
- */
51
- get(force?: boolean): Promise<State | null>;
52
- /**
53
- * Set new state to the storage
54
- *
55
- * @param state New state
56
- * @param ttl TTL for the new state (in seconds)
57
- */
58
- set(state: State, ttl?: number): Promise<void>;
59
- /**
60
- * Merge the given object to the current state.
61
- *
62
- * > **Note**: If the storage currently has no state,
63
- * > then `fallback` must be provided.
64
- *
65
- * Basically a shorthand to calling `.get()`,
66
- * modifying and then calling `.set()`
67
- *
68
- * @param state State to be merged
69
- * @param fallback Default state
70
- * @param ttl TTL for the new state (in seconds)
71
- * @param forceLoad Whether to force load the old state from storage
72
- */
73
- merge(state: Partial<State>, params?: {
74
- fallback?: State | (() => State);
75
- ttl?: number;
76
- forceLoad?: boolean;
77
- }): Promise<State>;
78
- /**
79
- * Delete the state from the storage
80
- */
81
- delete(): Promise<void>;
82
- /**
83
- * Enter some scene
84
- */
85
- enter<SceneState extends object, Scene extends Dispatcher<SceneState>>(scene: Scene, params?: {
86
- /**
87
- * Initial state for the scene
88
- *
89
- * Note that this will only work if the scene uses the same key delegate as this state.
90
- */
91
- with?: SceneState;
92
- /** TTL for the scene (in seconds) */
93
- ttl?: number;
94
- /**
95
- * If currently in a scoped scene, whether to reset the state
96
- *
97
- * @default true
98
- */
99
- reset?: boolean;
100
- }): Promise<void>;
101
- /**
102
- * Exit from current scene to the root
103
- *
104
- * @param reset
105
- * Whether to reset scene state (only applicable in case this is a scoped scene)
106
- */
107
- exit(reset?: boolean): Promise<void>;
108
- /**
109
- * Rate limit some handler.
110
- *
111
- * When the rate limit exceeds, {@link RateLimitError} is thrown.
112
- *
113
- * This is a simple rate-limiting solution that uses
114
- * the same key as the state. If you need something more
115
- * sophisticated and/or customizable, you'll have to implement
116
- * your own rate-limiter.
117
- *
118
- * > **Note**: `key` is used to prefix the local key
119
- * > derived using the given key delegate.
120
- *
121
- * @param key Key of the rate limit
122
- * @param limit Maximum number of requests in `window`
123
- * @param window Window size in seconds
124
- * @returns Tuple containing the number of remaining and
125
- * unix time in ms when the user can try again
126
- */
127
- rateLimit(key: string, limit: number, window: number): Promise<[number, number]>;
128
- /**
129
- * Throttle some handler.
130
- *
131
- * When the rate limit exceeds, this function waits for it to reset.
132
- *
133
- * This is a simple wrapper over {@link rateLimit}, and follows the same logic.
134
- *
135
- * > **Note**: `key` is used to prefix the local key
136
- * > derived using the given key delegate.
137
- *
138
- * @param key Key of the rate limit
139
- * @param limit Maximum number of requests in `window`
140
- * @param window Window size in seconds
141
- * @returns Tuple containing the number of remaining and
142
- * unix time in ms when the user can try again
143
- */
144
- throttle(key: string, limit: number, window: number): Promise<[number, number]>;
145
- /**
146
- * Reset the rate limit
147
- *
148
- * @param key Key of the rate limit
149
- */
150
- resetRateLimit(key: string): Promise<void>;
151
- }