@mtcute/dispatcher 0.16.0 → 0.16.7

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 (162) hide show
  1. package/README.md +2 -2
  2. package/cjs/callback-data-builder.d.ts +2 -2
  3. package/cjs/callback-data-builder.js +8 -6
  4. package/cjs/callback-data-builder.js.map +1 -1
  5. package/cjs/context/base.d.ts +2 -2
  6. package/cjs/context/base.js.map +1 -1
  7. package/cjs/context/business-message.d.ts +20 -19
  8. package/cjs/context/business-message.js +3 -3
  9. package/cjs/context/business-message.js.map +1 -1
  10. package/cjs/context/callback-query.d.ts +4 -3
  11. package/cjs/context/callback-query.js.map +1 -1
  12. package/cjs/context/chat-join-request.d.ts +2 -2
  13. package/cjs/context/chat-join-request.js.map +1 -1
  14. package/cjs/context/chosen-inline-result.d.ts +2 -2
  15. package/cjs/context/chosen-inline-result.js.map +1 -1
  16. package/cjs/context/inline-query.d.ts +4 -3
  17. package/cjs/context/inline-query.js.map +1 -1
  18. package/cjs/context/message.d.ts +6 -5
  19. package/cjs/context/message.js +3 -3
  20. package/cjs/context/message.js.map +1 -1
  21. package/cjs/context/parse.d.ts +5 -5
  22. package/cjs/context/parse.js +1 -2
  23. package/cjs/context/parse.js.map +1 -1
  24. package/cjs/context/pre-checkout-query.d.ts +2 -2
  25. package/cjs/context/pre-checkout-query.js.map +1 -1
  26. package/cjs/context/scene-transition.d.ts +1 -1
  27. package/cjs/context/scene-transition.js.map +1 -1
  28. package/cjs/dispatcher.d.ts +10 -9
  29. package/cjs/dispatcher.js +34 -31
  30. package/cjs/dispatcher.js.map +1 -1
  31. package/cjs/filters/bots.d.ts +15 -25
  32. package/cjs/filters/bots.js +36 -34
  33. package/cjs/filters/bots.js.map +1 -1
  34. package/cjs/filters/chat.d.ts +5 -5
  35. package/cjs/filters/chat.js +10 -9
  36. package/cjs/filters/chat.js.map +1 -1
  37. package/cjs/filters/group.d.ts +4 -4
  38. package/cjs/filters/group.js +3 -6
  39. package/cjs/filters/group.js.map +1 -1
  40. package/cjs/filters/index.js.map +1 -1
  41. package/cjs/filters/logic.d.ts +1 -1
  42. package/cjs/filters/logic.js +5 -7
  43. package/cjs/filters/logic.js.map +1 -1
  44. package/cjs/filters/message.d.ts +29 -146
  45. package/cjs/filters/message.js +84 -72
  46. package/cjs/filters/message.js.map +1 -1
  47. package/cjs/filters/state.d.ts +3 -3
  48. package/cjs/filters/state.js +5 -4
  49. package/cjs/filters/state.js.map +1 -1
  50. package/cjs/filters/text.d.ts +8 -8
  51. package/cjs/filters/text.js +27 -26
  52. package/cjs/filters/text.js.map +1 -1
  53. package/cjs/filters/types.d.ts +2 -2
  54. package/cjs/filters/types.js +0 -3
  55. package/cjs/filters/types.js.map +1 -1
  56. package/cjs/filters/updates.d.ts +2 -2
  57. package/cjs/filters/updates.js +7 -7
  58. package/cjs/filters/updates.js.map +1 -1
  59. package/cjs/filters/user.d.ts +4 -3
  60. package/cjs/filters/user.js +15 -16
  61. package/cjs/filters/user.js.map +1 -1
  62. package/cjs/handler.d.ts +5 -5
  63. package/cjs/handler.js.map +1 -1
  64. package/cjs/state/key.d.ts +3 -3
  65. package/cjs/state/key.js.map +1 -1
  66. package/cjs/state/provider.d.ts +2 -2
  67. package/cjs/state/provider.js.map +1 -1
  68. package/cjs/state/providers/memory.d.ts +4 -3
  69. package/cjs/state/providers/memory.js.map +1 -1
  70. package/cjs/state/providers/sqlite.d.ts +3 -3
  71. package/cjs/state/providers/sqlite.js.map +1 -1
  72. package/cjs/state/repository.d.ts +7 -7
  73. package/cjs/state/repository.js.map +1 -1
  74. package/cjs/state/service.d.ts +4 -3
  75. package/cjs/state/service.js.map +1 -1
  76. package/cjs/state/update-state.d.ts +1 -1
  77. package/cjs/state/update-state.js +3 -4
  78. package/cjs/state/update-state.js.map +1 -1
  79. package/cjs/wizard.d.ts +8 -7
  80. package/cjs/wizard.js +3 -1
  81. package/cjs/wizard.js.map +1 -1
  82. package/esm/callback-data-builder.d.ts +2 -2
  83. package/esm/callback-data-builder.js +8 -6
  84. package/esm/callback-data-builder.js.map +1 -1
  85. package/esm/context/base.d.ts +2 -2
  86. package/esm/context/base.js.map +1 -1
  87. package/esm/context/business-message.d.ts +20 -19
  88. package/esm/context/business-message.js +3 -3
  89. package/esm/context/business-message.js.map +1 -1
  90. package/esm/context/callback-query.d.ts +4 -3
  91. package/esm/context/callback-query.js.map +1 -1
  92. package/esm/context/chat-join-request.d.ts +2 -2
  93. package/esm/context/chat-join-request.js.map +1 -1
  94. package/esm/context/chosen-inline-result.d.ts +2 -2
  95. package/esm/context/chosen-inline-result.js.map +1 -1
  96. package/esm/context/inline-query.d.ts +4 -3
  97. package/esm/context/inline-query.js.map +1 -1
  98. package/esm/context/message.d.ts +6 -5
  99. package/esm/context/message.js +3 -3
  100. package/esm/context/message.js.map +1 -1
  101. package/esm/context/parse.d.ts +5 -5
  102. package/esm/context/parse.js.map +1 -1
  103. package/esm/context/pre-checkout-query.d.ts +2 -2
  104. package/esm/context/pre-checkout-query.js.map +1 -1
  105. package/esm/context/scene-transition.d.ts +1 -1
  106. package/esm/context/scene-transition.js.map +1 -1
  107. package/esm/dispatcher.d.ts +10 -9
  108. package/esm/dispatcher.js +35 -32
  109. package/esm/dispatcher.js.map +1 -1
  110. package/esm/filters/bots.d.ts +15 -25
  111. package/esm/filters/bots.js +32 -30
  112. package/esm/filters/bots.js.map +1 -1
  113. package/esm/filters/chat.d.ts +5 -5
  114. package/esm/filters/chat.js +8 -7
  115. package/esm/filters/chat.js.map +1 -1
  116. package/esm/filters/group.d.ts +4 -4
  117. package/esm/filters/group.js +1 -3
  118. package/esm/filters/group.js.map +1 -1
  119. package/esm/filters/index.js.map +1 -1
  120. package/esm/filters/logic.d.ts +1 -1
  121. package/esm/filters/logic.js +1 -3
  122. package/esm/filters/logic.js.map +1 -1
  123. package/esm/filters/message.d.ts +29 -146
  124. package/esm/filters/message.js +60 -48
  125. package/esm/filters/message.js.map +1 -1
  126. package/esm/filters/state.d.ts +3 -3
  127. package/esm/filters/state.js +3 -2
  128. package/esm/filters/state.js.map +1 -1
  129. package/esm/filters/text.d.ts +8 -8
  130. package/esm/filters/text.js +22 -20
  131. package/esm/filters/text.js.map +1 -1
  132. package/esm/filters/types.d.ts +2 -2
  133. package/esm/filters/types.js +0 -3
  134. package/esm/filters/types.js.map +1 -1
  135. package/esm/filters/updates.d.ts +2 -2
  136. package/esm/filters/updates.js +7 -7
  137. package/esm/filters/updates.js.map +1 -1
  138. package/esm/filters/user.d.ts +4 -3
  139. package/esm/filters/user.js +15 -16
  140. package/esm/filters/user.js.map +1 -1
  141. package/esm/handler.d.ts +5 -5
  142. package/esm/handler.js.map +1 -1
  143. package/esm/state/key.d.ts +3 -3
  144. package/esm/state/key.js.map +1 -1
  145. package/esm/state/provider.d.ts +2 -2
  146. package/esm/state/provider.js.map +1 -1
  147. package/esm/state/providers/memory.d.ts +4 -3
  148. package/esm/state/providers/memory.js.map +1 -1
  149. package/esm/state/providers/sqlite.d.ts +3 -3
  150. package/esm/state/providers/sqlite.js.map +1 -1
  151. package/esm/state/repository.d.ts +7 -7
  152. package/esm/state/repository.js.map +1 -1
  153. package/esm/state/service.d.ts +4 -3
  154. package/esm/state/service.js +1 -1
  155. package/esm/state/service.js.map +1 -1
  156. package/esm/state/update-state.d.ts +1 -1
  157. package/esm/state/update-state.js +3 -4
  158. package/esm/state/update-state.js.map +1 -1
  159. package/esm/wizard.d.ts +8 -7
  160. package/esm/wizard.js +3 -1
  161. package/esm/wizard.js.map +1 -1
  162. package/package.json +3 -3
@@ -1,38 +1,40 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- // ^^ will be looked into in MTQ-29
3
1
  import { RawDocument, RawLocation, } from '@mtcute/core';
4
2
  /**
5
3
  * Filter incoming messages.
6
4
  *
7
5
  * Messages sent to yourself (i.e. Saved Messages) are also "incoming"
8
6
  */
9
- export const incoming = (msg) => !msg.isOutgoing;
7
+ export const incoming = msg => !msg.isOutgoing;
10
8
  /**
11
9
  * Filter outgoing messages.
12
10
  *
13
11
  * Messages sent to yourself (i.e. Saved Messages) are **not** "outgoing"
14
12
  */
15
- export const outgoing = (msg) => msg.isOutgoing;
13
+ export const outgoing = msg => msg.isOutgoing;
16
14
  /**
17
15
  * Filter for scheduled messages
18
16
  */
19
- export const scheduled = (msg) => msg.isScheduled;
17
+ export const scheduled = msg => msg.isScheduled;
20
18
  /**
21
19
  * Filter messages that are replies to some other message
22
20
  */
23
- export const reply = (msg) => msg.replyToMessage !== null;
21
+ export const reply = msg => msg.replyToMessage !== null;
24
22
  /**
25
23
  * Filter messages that are replies with the given origin type
26
24
  */
27
- export const replyOrigin = (origin) => (msg) => msg.replyToMessage?.originIs(origin) ?? false; // originIs does additional checks
25
+ export function replyOrigin(origin) {
26
+ return msg => msg.replyToMessage?.originIs(origin) ?? false;
27
+ } // originIs does additional checks
28
28
  /**
29
29
  * Filter messages containing some media
30
30
  */
31
- export const media = (msg) => msg.media !== null;
31
+ export const media = msg => msg.media !== null;
32
32
  /**
33
33
  * Filter messages containing media of given type
34
34
  */
35
- export const mediaOf = (type) => (msg) => msg.media?.type === type;
35
+ export function mediaOf(type) {
36
+ return msg => msg.media?.type === type;
37
+ }
36
38
  /** Filter messages containing a photo */
37
39
  export const photo = mediaOf('photo');
38
40
  /** Filter messages containing a dice */
@@ -66,91 +68,101 @@ export const invoice = mediaOf('invoice');
66
68
  /**
67
69
  * Filter messages containing any location (live or static).
68
70
  */
69
- export const anyLocation = (msg) => msg.media instanceof RawLocation;
71
+ export const anyLocation = msg => msg.media instanceof RawLocation;
70
72
  /**
71
73
  * Filter messages containing a document
72
74
  *
73
75
  * This will also match media like audio, video, voice
74
76
  * that also use Documents
75
77
  */
76
- export const anyDocument = (msg) => msg.media instanceof RawDocument;
78
+ export const anyDocument = msg => msg.media instanceof RawDocument;
77
79
  /**
78
80
  * Filter messages containing a simple video.
79
81
  *
80
82
  * This does not include round messages and animations
81
83
  */
82
- export const video = (msg) => msg.media?.type === 'video' && !msg.media.isAnimation && !msg.media.isRound;
84
+ export const video = msg => msg.media?.type === 'video' && !msg.media.isAnimation && !msg.media.isRound;
83
85
  /**
84
86
  * Filter messages containing an animation.
85
87
  *
86
88
  * > **Note**: Legacy GIFs (i.e. documents with `image/gif` MIME)
87
89
  * > are also considered animations.
88
90
  */
89
- export const animation = (msg) => msg.media?.type === 'video' && msg.media.isAnimation && !msg.media.isRound;
91
+ export const animation = msg => msg.media?.type === 'video' && msg.media.isAnimation && !msg.media.isRound;
90
92
  /**
91
93
  * Filter messages containing a round message (aka video note).
92
94
  */
93
- export const roundMessage = (msg) => msg.media?.type === 'video' && !msg.media.isAnimation && msg.media.isRound;
95
+ export const roundMessage = msg => msg.media?.type === 'video' && !msg.media.isAnimation && msg.media.isRound;
94
96
  /**
95
97
  * Filter messages containing a sticker by its type
96
98
  */
97
- export const stickerByType = (type) => (msg) => msg.media?.type === 'sticker' && msg.media.stickerType === type;
99
+ export function stickerByType(type) {
100
+ return msg => msg.media?.type === 'sticker' && msg.media.stickerType === type;
101
+ }
98
102
  /**
99
103
  * Filter messages containing a sticker by its source file type
100
104
  */
101
- export const stickerBySourceType = (type) => (msg) => msg.media?.type === 'sticker' && msg.media.sourceType === type;
105
+ export function stickerBySourceType(type) {
106
+ return msg => msg.media?.type === 'sticker' && msg.media.sourceType === type;
107
+ }
102
108
  /**
103
109
  * Filter text-only messages non-service messages
104
110
  */
105
- export const text = (msg) => msg.media === null && !msg.isService;
111
+ export const text = msg => msg.media === null && !msg.isService;
106
112
  /**
107
113
  * Filter service messages
108
114
  */
109
- export const service = (msg) => msg.isService;
115
+ export const service = msg => msg.isService;
110
116
  /**
111
117
  * Filter service messages by action type
112
118
  */
113
- export const action = (type) => {
119
+ export function action(type) {
114
120
  if (Array.isArray(type)) {
115
121
  const index = {};
116
- type.forEach((it) => (index[it] = true));
117
- return (msg) => msg.action?.type in index;
122
+ type.forEach(it => (index[it] = true));
123
+ return msg => msg.action?.type in index;
118
124
  }
119
- return (msg) => msg.action?.type === type;
120
- };
121
- export const sender = (type) => (msg) => msg.sender.type === type;
125
+ return msg => msg.action?.type === type;
126
+ }
127
+ export function sender(type) {
128
+ return msg => msg.sender.type === type;
129
+ }
122
130
  /**
123
131
  * Filter that matches messages that are replies to some other message that can be fetched
124
132
  * (i.e. not `private` origin, and has not been deleted)
125
133
  *
126
134
  * Optionally, you can pass a filter that will be applied to the replied message.
127
135
  */
128
- export const replyTo = (filter) => async (msg, state) => {
129
- if (!msg.replyToMessage?.id)
130
- return false;
131
- const reply = msg._name === 'new_message' ? await msg.getReplyTo() : msg.replyTo;
132
- if (!reply)
133
- return false;
134
- if (msg._name === 'new_message') {
135
- msg.getReplyTo = () => Promise.resolve(reply);
136
- }
137
- if (!filter)
138
- return true;
139
- return filter(reply, state);
140
- };
136
+ export function replyTo(filter) {
137
+ return async (msg, state) => {
138
+ if (!msg.replyToMessage?.id)
139
+ return false;
140
+ const reply = msg._name === 'new_message' ? await msg.getReplyTo() : msg.replyTo;
141
+ if (!reply)
142
+ return false;
143
+ if (msg._name === 'new_message') {
144
+ msg.getReplyTo = () => Promise.resolve(reply);
145
+ }
146
+ if (!filter)
147
+ return true;
148
+ return filter(reply, state);
149
+ };
150
+ }
141
151
  /**
142
152
  * Middleware-like filter that will fetch the sender of the message
143
153
  * and make it available to further filters, as well as the handler itself.
144
154
  */
145
- export const withCompleteSender = (filter) => async (msg, state) => {
146
- try {
147
- await msg.getCompleteSender();
148
- }
149
- catch (e) {
150
- return false;
151
- }
152
- if (!filter)
153
- return true;
154
- return filter(msg, state);
155
- };
155
+ export function withCompleteSender(filter) {
156
+ return async (msg, state) => {
157
+ try {
158
+ await msg.getCompleteSender();
159
+ }
160
+ catch {
161
+ return false;
162
+ }
163
+ if (!filter)
164
+ return true;
165
+ return filter(msg, state);
166
+ };
167
+ }
156
168
  //# sourceMappingURL=message.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"message.js","sourceRoot":"","sources":["../../../src/filters/message.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,mCAAmC;AACnC,OAAO,EAOH,WAAW,EACX,WAAW,GAQd,MAAM,cAAc,CAAA;AAMrB;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAiD,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAA;AAE9F;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAgD,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAA;AAE5F;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAiD,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,CAAA;AAE/F;;GAEG;AACH,MAAM,CAAC,MAAM,KAAK,GAAkE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,cAAc,KAAK,IAAI,CAAA;AAExH;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GACpB,CACI,MAAS,EAMX,EAAE,CACA,CAAC,GAAG,EAAE,EAAE,CACJ,GAAG,CAAC,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAA,CAAC,kCAAkC;AAE5F;;GAEG;AACH,MAAM,CAAC,MAAM,KAAK,GAAsE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,KAAK,IAAI,CAAA;AAEnH;;GAEG;AACH,MAAM,CAAC,MAAM,OAAO,GAChB,CAA6B,IAAO,EAA4E,EAAE,CAC9G,CAAC,GAAG,EAAE,EAAE,CACJ,GAAG,CAAC,KAAK,EAAE,IAAI,KAAK,IAAI,CAAA;AAEpC,yCAAyC;AACzC,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;AACrC,wCAAwC;AACxC,MAAM,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;AACnC,2CAA2C;AAC3C,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA;AACzC,+CAA+C;AAC/C,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;AACrC,8DAA8D;AAC9D,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;AACrC,2CAA2C;AAC3C,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA;AACzC,qDAAqD;AACrD,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;AAC3C,mFAAmF;AACnF,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;AACxC,mDAAmD;AACnD,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;AAC3C,iDAAiD;AACjD,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;AACpD,wCAAwC;AACxC,MAAM,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;AACnC,4CAA4C;AAC5C,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA;AACzC,yCAAyC;AACzC,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;AACrC,wCAAwC;AACxC,MAAM,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;AACnC,4CAA4C;AAC5C,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA;AAEzC;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAA+C,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,YAAY,WAAW,CAAA;AAEhH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAkD,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,YAAY,WAAW,CAAA;AAEnH;;;;GAIG;AACH,MAAM,CAAC,MAAM,KAAK,GAWd,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,KAAK,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAA;AAExF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAWlB,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,KAAK,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAA;AAEvF;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAWrB,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,KAAK,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAA;AAEvF;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GACtB,CAAC,IAAiB,EAA6C,EAAE,CAC7D,CAAC,GAAG,EAAE,EAAE,CACJ,GAAG,CAAC,KAAK,EAAE,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,KAAK,CAAC,WAAW,KAAK,IAAI,CAAA;AAE3E;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAC5B,CAAC,IAAuB,EAA6C,EAAE,CACnE,CAAC,GAAG,EAAE,EAAE,CACJ,GAAG,CAAC,KAAK,EAAE,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,IAAI,CAAA;AAE1E;;GAEG;AACH,MAAM,CAAC,MAAM,IAAI,GAMb,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAA;AAEjD;;GAEG;AACH,MAAM,CAAC,MAAM,OAAO,GAA+C,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,CAAA;AAEzF;;GAEG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CAClB,IAAmB,EASrB,EAAE;IACA,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,KAAK,GAA6B,EAAE,CAAA;QAC1C,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAA;QAExC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAE,GAAG,CAAC,MAAM,EAAE,IAAY,IAAI,KAAK,CAAA;IACtD,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,KAAK,IAAI,CAAA;AAC7C,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,MAAM,GACf,CACI,IAAO,EACmE,EAAE,CAC5E,CAAC,GAAG,EAAE,EAAE,CACJ,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAA;AAEpC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,OAAO,GAChB,CACI,MAA0C,EACgE,EAAE,CAC5G,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;IACjB,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,EAAE;QAAE,OAAO,KAAK,CAAA;IAEzC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,KAAK,aAAa,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAA;IAChF,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAA;IAExB,IAAI,GAAG,CAAC,KAAK,KAAK,aAAa,EAAE,CAAC;QAC9B,GAAG,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IACjD,CAAC;IAED,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAA;IAExB,OAAO,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;AAC/B,CAAC,CAAA;AAET;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAC3B,CACI,MAAiD,EACT,EAAE,CAC1C,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;IACjB,IAAI,CAAC;QACD,MAAM,GAAG,CAAC,iBAAiB,EAAE,CAAA;IACjC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACT,OAAO,KAAK,CAAA;IAChB,CAAC;IAED,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAA;IAExB,OAAO,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;AAC7B,CAAC,CAAA","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n// ^^ will be looked into in MTQ-29\nimport {\n _RepliedMessageAssertionsByOrigin,\n MaybeArray,\n Message,\n MessageAction,\n MessageMediaType,\n Peer,\n RawDocument,\n RawLocation,\n RepliedMessageInfo,\n RepliedMessageOrigin,\n Sticker,\n StickerSourceType,\n StickerType,\n User,\n Video,\n} from '@mtcute/core'\n\nimport { BusinessMessageContext } from '../context/business-message.js'\nimport { MessageContext } from '../index.js'\nimport { Modify, UpdateFilter } from './types.js'\n\n/**\n * Filter incoming messages.\n *\n * Messages sent to yourself (i.e. Saved Messages) are also \"incoming\"\n */\nexport const incoming: UpdateFilter<Message, { isOutgoing: false }> = (msg) => !msg.isOutgoing\n\n/**\n * Filter outgoing messages.\n *\n * Messages sent to yourself (i.e. Saved Messages) are **not** \"outgoing\"\n */\nexport const outgoing: UpdateFilter<Message, { isOutgoing: true }> = (msg) => msg.isOutgoing\n\n/**\n * Filter for scheduled messages\n */\nexport const scheduled: UpdateFilter<Message, { isScheduled: true }> = (msg) => msg.isScheduled\n\n/**\n * Filter messages that are replies to some other message\n */\nexport const reply: UpdateFilter<Message, { replyToMessage: RepliedMessageInfo }> = (msg) => msg.replyToMessage !== null\n\n/**\n * Filter messages that are replies with the given origin type\n */\nexport const replyOrigin =\n <T extends RepliedMessageOrigin>(\n origin: T,\n ): UpdateFilter<\n Message,\n {\n replyToMessage: Modify<RepliedMessageInfo, _RepliedMessageAssertionsByOrigin[T] & { origin: T }>\n }\n > =>\n (msg) =>\n msg.replyToMessage?.originIs(origin) ?? false // originIs does additional checks\n\n/**\n * Filter messages containing some media\n */\nexport const media: UpdateFilter<Message, { media: Exclude<Message['media'], null> }> = (msg) => msg.media !== null\n\n/**\n * Filter messages containing media of given type\n */\nexport const mediaOf =\n <T extends MessageMediaType>(type: T): UpdateFilter<Message, { media: Extract<Message['media'], { type: T }> }> =>\n (msg) =>\n msg.media?.type === type\n\n/** Filter messages containing a photo */\nexport const photo = mediaOf('photo')\n/** Filter messages containing a dice */\nexport const dice = mediaOf('dice')\n/** Filter messages containing a contact */\nexport const contact = mediaOf('contact')\n/** Filter messages containing an audio file */\nexport const audio = mediaOf('audio')\n/** Filter messages containing a voice message (audio-only) */\nexport const voice = mediaOf('voice')\n/** Filter messages containing a sticker */\nexport const sticker = mediaOf('sticker')\n/** Filter messages containing a document (a file) */\nexport const document = mediaOf('document')\n/** Filter messages containing any video (videos, round messages and animations) */\nexport const anyVideo = mediaOf('video')\n/** Filter messages containing a static location */\nexport const location = mediaOf('location')\n/** Filter messages containing a live location */\nexport const liveLocation = mediaOf('live_location')\n/** Filter messages containing a game */\nexport const game = mediaOf('game')\n/** Filter messages containing a web page */\nexport const webpage = mediaOf('webpage')\n/** Filter messages containing a venue */\nexport const venue = mediaOf('venue')\n/** Filter messages containing a poll */\nexport const poll = mediaOf('poll')\n/** Filter messages containing an invoice */\nexport const invoice = mediaOf('invoice')\n\n/**\n * Filter messages containing any location (live or static).\n */\nexport const anyLocation: UpdateFilter<Message, { media: Location }> = (msg) => msg.media instanceof RawLocation\n\n/**\n * Filter messages containing a document\n *\n * This will also match media like audio, video, voice\n * that also use Documents\n */\nexport const anyDocument: UpdateFilter<Message, { media: RawDocument }> = (msg) => msg.media instanceof RawDocument\n\n/**\n * Filter messages containing a simple video.\n *\n * This does not include round messages and animations\n */\nexport const video: UpdateFilter<\n Message,\n {\n media: Modify<\n Video,\n {\n isRound: false\n isAnimation: false\n }\n >\n }\n> = (msg) => msg.media?.type === 'video' && !msg.media.isAnimation && !msg.media.isRound\n\n/**\n * Filter messages containing an animation.\n *\n * > **Note**: Legacy GIFs (i.e. documents with `image/gif` MIME)\n * > are also considered animations.\n */\nexport const animation: UpdateFilter<\n Message,\n {\n media: Modify<\n Video,\n {\n isRound: false\n isAnimation: true\n }\n >\n }\n> = (msg) => msg.media?.type === 'video' && msg.media.isAnimation && !msg.media.isRound\n\n/**\n * Filter messages containing a round message (aka video note).\n */\nexport const roundMessage: UpdateFilter<\n Message,\n {\n media: Modify<\n Video,\n {\n isRound: true\n isAnimation: false\n }\n >\n }\n> = (msg) => msg.media?.type === 'video' && !msg.media.isAnimation && msg.media.isRound\n\n/**\n * Filter messages containing a sticker by its type\n */\nexport const stickerByType =\n (type: StickerType): UpdateFilter<Message, { media: Sticker }> =>\n (msg) =>\n msg.media?.type === 'sticker' && msg.media.stickerType === type\n\n/**\n * Filter messages containing a sticker by its source file type\n */\nexport const stickerBySourceType =\n (type: StickerSourceType): UpdateFilter<Message, { media: Sticker }> =>\n (msg) =>\n msg.media?.type === 'sticker' && msg.media.sourceType === type\n\n/**\n * Filter text-only messages non-service messages\n */\nexport const text: UpdateFilter<\n Message,\n {\n media: null\n isService: false\n }\n> = (msg) => msg.media === null && !msg.isService\n\n/**\n * Filter service messages\n */\nexport const service: UpdateFilter<Message, { isService: true }> = (msg) => msg.isService\n\n/**\n * Filter service messages by action type\n */\nexport const action = <T extends Exclude<MessageAction, null>['type']>(\n type: MaybeArray<T>,\n): UpdateFilter<\n Message,\n {\n action: Extract<MessageAction, { type: T }>\n sender: T extends 'user_joined_link' | 'user_removed' | 'history_cleared' | 'contact_joined' | 'bot_allowed'\n ? User\n : Peer\n }\n> => {\n if (Array.isArray(type)) {\n const index: Partial<Record<T, true>> = {}\n type.forEach((it) => (index[it] = true))\n\n return (msg) => (msg.action?.type as any) in index\n }\n\n return (msg) => msg.action?.type === type\n}\n\nexport const sender =\n <T extends Message['sender']['type']>(\n type: T,\n ): UpdateFilter<Message, { sender: Extract<Message['sender'], { type: T }> }> =>\n (msg) =>\n msg.sender.type === type\n\n/**\n * Filter that matches messages that are replies to some other message that can be fetched\n * (i.e. not `private` origin, and has not been deleted)\n *\n * Optionally, you can pass a filter that will be applied to the replied message.\n */\nexport const replyTo =\n <Mod, State extends object>(\n filter?: UpdateFilter<Message, Mod, State>,\n ): UpdateFilter<MessageContext | BusinessMessageContext, { getReplyTo: () => Promise<Message & Mod> }, State> =>\n async (msg, state) => {\n if (!msg.replyToMessage?.id) return false\n\n const reply = msg._name === 'new_message' ? await msg.getReplyTo() : msg.replyTo\n if (!reply) return false\n\n if (msg._name === 'new_message') {\n msg.getReplyTo = () => Promise.resolve(reply)\n }\n\n if (!filter) return true\n\n return filter(reply, state)\n }\n\n/**\n * Middleware-like filter that will fetch the sender of the message\n * and make it available to further filters, as well as the handler itself.\n */\nexport const withCompleteSender =\n <Mod, State extends object>(\n filter?: UpdateFilter<MessageContext, Mod, State>,\n ): UpdateFilter<MessageContext, Mod, State> =>\n async (msg, state) => {\n try {\n await msg.getCompleteSender()\n } catch (e) {\n return false\n }\n\n if (!filter) return true\n\n return filter(msg, state)\n }\n"]}
1
+ {"version":3,"file":"message.js","sourceRoot":"","sources":["../../../src/filters/message.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n Audio,\n Contact,\n Dice,\n Document,\n Game,\n Invoice,\n LiveLocation,\n Location,\n MaybeArray,\n Message,\n MessageAction,\n MessageMediaType,\n Peer,\n Photo,\n Poll,\n RepliedMessageInfo,\n RepliedMessageOrigin,\n Sticker,\n StickerSourceType,\n StickerType,\n User,\n Venue,\n Video,\n Voice,\n WebPage,\n _RepliedMessageAssertionsByOrigin,\n} from '@mtcute/core'\nimport {\n RawDocument,\n RawLocation,\n} from '@mtcute/core'\n\nimport type { BusinessMessageContext } from '../context/business-message.js'\nimport type { MessageContext } from '../index.js'\n\nimport type { Modify, UpdateFilter } from './types.js'\n\n/**\n * Filter incoming messages.\n *\n * Messages sent to yourself (i.e. Saved Messages) are also \"incoming\"\n */\nexport const incoming: UpdateFilter<Message, { isOutgoing: false }> = msg => !msg.isOutgoing\n\n/**\n * Filter outgoing messages.\n *\n * Messages sent to yourself (i.e. Saved Messages) are **not** \"outgoing\"\n */\nexport const outgoing: UpdateFilter<Message, { isOutgoing: true }> = msg => msg.isOutgoing\n\n/**\n * Filter for scheduled messages\n */\nexport const scheduled: UpdateFilter<Message, { isScheduled: true }> = msg => msg.isScheduled\n\n/**\n * Filter messages that are replies to some other message\n */\nexport const reply: UpdateFilter<Message, { replyToMessage: RepliedMessageInfo }> = msg => msg.replyToMessage !== null\n\n/**\n * Filter messages that are replies with the given origin type\n */\nexport function replyOrigin<T extends RepliedMessageOrigin>(origin: T): UpdateFilter<\n Message,\n {\n replyToMessage: Modify<RepliedMessageInfo, _RepliedMessageAssertionsByOrigin[T] & { origin: T }>\n }\n> {\n return msg =>\n msg.replyToMessage?.originIs(origin) ?? false\n} // originIs does additional checks\n\n/**\n * Filter messages containing some media\n */\nexport const media: UpdateFilter<Message, { media: Exclude<Message['media'], null> }> = msg => msg.media !== null\n\n/**\n * Filter messages containing media of given type\n */\nexport function mediaOf<T extends MessageMediaType>(type: T): UpdateFilter<\n Message,\n { media: Extract<Message['media'], { type: T }> }\n> {\n return msg =>\n msg.media?.type === type\n}\n\n/** Filter messages containing a photo */\nexport const photo: UpdateFilter<Message, { media: Photo }> = mediaOf('photo')\n/** Filter messages containing a dice */\nexport const dice: UpdateFilter<Message, { media: Dice }> = mediaOf('dice')\n/** Filter messages containing a contact */\nexport const contact: UpdateFilter<Message, { media: Contact }> = mediaOf('contact')\n/** Filter messages containing an audio file */\nexport const audio: UpdateFilter<Message, { media: Audio }> = mediaOf('audio')\n/** Filter messages containing a voice message (audio-only) */\nexport const voice: UpdateFilter<Message, { media: Voice }> = mediaOf('voice')\n/** Filter messages containing a sticker */\nexport const sticker: UpdateFilter<Message, { media: Sticker }> = mediaOf('sticker')\n/** Filter messages containing a document (a file) */\nexport const document: UpdateFilter<Message, { media: Document }> = mediaOf('document')\n/** Filter messages containing any video (videos, round messages and animations) */\nexport const anyVideo: UpdateFilter<Message, { media: Video }> = mediaOf('video')\n/** Filter messages containing a static location */\nexport const location: UpdateFilter<Message, { media: Location }> = mediaOf('location')\n/** Filter messages containing a live location */\nexport const liveLocation: UpdateFilter<Message, { media: LiveLocation }> = mediaOf('live_location')\n/** Filter messages containing a game */\nexport const game: UpdateFilter<Message, { media: Game }> = mediaOf('game')\n/** Filter messages containing a web page */\nexport const webpage: UpdateFilter<Message, { media: WebPage }> = mediaOf('webpage')\n/** Filter messages containing a venue */\nexport const venue: UpdateFilter<Message, { media: Venue }> = mediaOf('venue')\n/** Filter messages containing a poll */\nexport const poll: UpdateFilter<Message, { media: Poll }> = mediaOf('poll')\n/** Filter messages containing an invoice */\nexport const invoice: UpdateFilter<Message, { media: Invoice }> = mediaOf('invoice')\n\n/**\n * Filter messages containing any location (live or static).\n */\nexport const anyLocation: UpdateFilter<Message, { media: Location }> = msg => msg.media instanceof RawLocation\n\n/**\n * Filter messages containing a document\n *\n * This will also match media like audio, video, voice\n * that also use Documents\n */\nexport const anyDocument: UpdateFilter<Message, { media: RawDocument }> = msg => msg.media instanceof RawDocument\n\n/**\n * Filter messages containing a simple video.\n *\n * This does not include round messages and animations\n */\nexport const video: UpdateFilter<\n Message,\n {\n media: Modify<\n Video,\n {\n isRound: false\n isAnimation: false\n }\n >\n }\n> = msg => msg.media?.type === 'video' && !msg.media.isAnimation && !msg.media.isRound\n\n/**\n * Filter messages containing an animation.\n *\n * > **Note**: Legacy GIFs (i.e. documents with `image/gif` MIME)\n * > are also considered animations.\n */\nexport const animation: UpdateFilter<\n Message,\n {\n media: Modify<\n Video,\n {\n isRound: false\n isAnimation: true\n }\n >\n }\n> = msg => msg.media?.type === 'video' && msg.media.isAnimation && !msg.media.isRound\n\n/**\n * Filter messages containing a round message (aka video note).\n */\nexport const roundMessage: UpdateFilter<\n Message,\n {\n media: Modify<\n Video,\n {\n isRound: true\n isAnimation: false\n }\n >\n }\n> = msg => msg.media?.type === 'video' && !msg.media.isAnimation && msg.media.isRound\n\n/**\n * Filter messages containing a sticker by its type\n */\nexport function stickerByType(type: StickerType): UpdateFilter<Message, { media: Sticker }> {\n return msg =>\n msg.media?.type === 'sticker' && msg.media.stickerType === type\n}\n\n/**\n * Filter messages containing a sticker by its source file type\n */\nexport function stickerBySourceType(type: StickerSourceType): UpdateFilter<Message, { media: Sticker }> {\n return msg =>\n msg.media?.type === 'sticker' && msg.media.sourceType === type\n}\n\n/**\n * Filter text-only messages non-service messages\n */\nexport const text: UpdateFilter<\n Message,\n {\n media: null\n isService: false\n }\n> = msg => msg.media === null && !msg.isService\n\n/**\n * Filter service messages\n */\nexport const service: UpdateFilter<Message, { isService: true }> = msg => msg.isService\n\n/**\n * Filter service messages by action type\n */\nexport function action<T extends Exclude<MessageAction, null>['type']>(type: MaybeArray<T>): UpdateFilter<\n Message,\n {\n action: Extract<MessageAction, { type: T }>\n sender: T extends 'user_joined_link' | 'user_removed' | 'history_cleared' | 'contact_joined' | 'bot_allowed'\n ? User\n : Peer\n }\n> {\n if (Array.isArray(type)) {\n const index: Partial<Record<T, true>> = {}\n type.forEach(it => (index[it] = true))\n\n return msg => (msg.action?.type as any) in index\n }\n\n return msg => msg.action?.type === type\n}\n\nexport function sender<T extends Message['sender']['type']>(type: T): UpdateFilter<\n Message,\n { sender: Extract<Message['sender'], { type: T }> }\n> {\n return msg =>\n msg.sender.type === type\n}\n\n/**\n * Filter that matches messages that are replies to some other message that can be fetched\n * (i.e. not `private` origin, and has not been deleted)\n *\n * Optionally, you can pass a filter that will be applied to the replied message.\n */\nexport function replyTo<Mod, State extends object>(\n filter?: UpdateFilter<Message, Mod, State>,\n): UpdateFilter<\n MessageContext | BusinessMessageContext,\n { getReplyTo: () => Promise<Message & Mod> },\n State\n > {\n return async (msg, state) => {\n if (!msg.replyToMessage?.id) return false\n\n const reply = msg._name === 'new_message' ? await msg.getReplyTo() : msg.replyTo\n if (!reply) return false\n\n if (msg._name === 'new_message') {\n msg.getReplyTo = () => Promise.resolve(reply)\n }\n\n if (!filter) return true\n\n return filter(reply, state)\n }\n}\n\n/**\n * Middleware-like filter that will fetch the sender of the message\n * and make it available to further filters, as well as the handler itself.\n */\nexport function withCompleteSender<Mod, State extends object>(\n filter?: UpdateFilter<MessageContext, Mod, State>,\n): UpdateFilter<MessageContext, Mod, State> {\n return async (msg, state) => {\n try {\n await msg.getCompleteSender()\n } catch {\n return false\n }\n\n if (!filter) return true\n\n return filter(msg, state)\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { MaybePromise } from '@mtcute/core';
2
- import { UpdateFilter } from './types.js';
1
+ import type { MaybePromise } from '@mtcute/core';
2
+ import type { UpdateFilter } from './types.js';
3
3
  /**
4
4
  * Create a filter for the cases when the state is empty
5
5
  */
@@ -12,4 +12,4 @@ export declare const stateEmpty: UpdateFilter<any>;
12
12
  *
13
13
  * @param predicate State predicate
14
14
  */
15
- export declare const state: <T extends object>(predicate: (state: T) => MaybePromise<boolean>) => UpdateFilter<any, {}, T>;
15
+ export declare function state<T extends object>(predicate: (state: T) => MaybePromise<boolean>): UpdateFilter<any, {}, T>;
@@ -14,7 +14,8 @@ export const stateEmpty = async (upd, state) => {
14
14
  *
15
15
  * @param predicate State predicate
16
16
  */
17
- export const state = (predicate) => {
17
+ // eslint-disable-next-line ts/no-empty-object-type
18
+ export function state(predicate) {
18
19
  return async (upd, state) => {
19
20
  if (!state)
20
21
  return false;
@@ -23,5 +24,5 @@ export const state = (predicate) => {
23
24
  return false;
24
25
  return predicate(data);
25
26
  };
26
- };
27
+ }
27
28
  //# sourceMappingURL=state.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/filters/state.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAsB,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;IAC9D,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAA;IAExB,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,EAAE,CAAC,CAAA;AAC/B,CAAC,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CACjB,SAA8C,EAEtB,EAAE;IAC1B,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;QACxB,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAA;QACxB,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,CAAA;QAC9B,IAAI,CAAC,IAAI;YAAE,OAAO,KAAK,CAAA;QAEvB,OAAO,SAAS,CAAC,IAAI,CAAC,CAAA;IAC1B,CAAC,CAAA;AACL,CAAC,CAAA","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { MaybePromise } from '@mtcute/core'\n\nimport { UpdateFilter } from './types.js'\n\n/**\n * Create a filter for the cases when the state is empty\n */\nexport const stateEmpty: UpdateFilter<any> = async (upd, state) => {\n if (!state) return false\n\n return !(await state.get())\n}\n\n/**\n * Create a filter based on state predicate\n *\n * If state exists and matches `predicate`, update passes\n * this filter, otherwise it doesn't\n *\n * @param predicate State predicate\n */\nexport const state = <T extends object>(\n predicate: (state: T) => MaybePromise<boolean>,\n // eslint-disable-next-line @typescript-eslint/ban-types\n): UpdateFilter<any, {}, T> => {\n return async (upd, state) => {\n if (!state) return false\n const data = await state.get()\n if (!data) return false\n\n return predicate(data)\n }\n}\n"]}
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/filters/state.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAsB,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;IAC9D,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAA;IAExB,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,EAAE,CAAC,CAAA;AAC/B,CAAC,CAAA;AAED;;;;;;;GAOG;AACH,mDAAmD;AACnD,MAAM,UAAU,KAAK,CAAmB,SAA8C;IAClF,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;QACxB,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAA;QACxB,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,CAAA;QAC9B,IAAI,CAAC,IAAI;YAAE,OAAO,KAAK,CAAA;QAEvB,OAAO,SAAS,CAAC,IAAI,CAAC,CAAA;IAC1B,CAAC,CAAA;AACL,CAAC","sourcesContent":["import type { MaybePromise } from '@mtcute/core'\n\nimport type { UpdateFilter } from './types.js'\n\n/**\n * Create a filter for the cases when the state is empty\n */\nexport const stateEmpty: UpdateFilter<any> = async (upd, state) => {\n if (!state) return false\n\n return !(await state.get())\n}\n\n/**\n * Create a filter based on state predicate\n *\n * If state exists and matches `predicate`, update passes\n * this filter, otherwise it doesn't\n *\n * @param predicate State predicate\n */\n// eslint-disable-next-line ts/no-empty-object-type\nexport function state<T extends object>(predicate: (state: T) => MaybePromise<boolean>): UpdateFilter<any, {}, T> {\n return async (upd, state) => {\n if (!state) return false\n const data = await state.get()\n if (!data) return false\n\n return predicate(data)\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
- import { BusinessCallbackQuery, BusinessMessage, CallbackQuery, ChosenInlineResult, InlineCallbackQuery, InlineQuery, Message } from '@mtcute/core';
2
- import { UpdateContextDistributed } from '../context/base.js';
3
- import { UpdateFilter } from './types.js';
1
+ import type { BusinessCallbackQuery, BusinessMessage, CallbackQuery, ChosenInlineResult, InlineCallbackQuery, InlineQuery, Message } from '@mtcute/core';
2
+ import type { UpdateContextDistributed } from '../context/base.js';
3
+ import type { UpdateFilter } from './types.js';
4
4
  type UpdatesWithText = UpdateContextDistributed<Message | BusinessMessage | InlineQuery | ChosenInlineResult | CallbackQuery | InlineCallbackQuery | BusinessCallbackQuery>;
5
5
  /**
6
6
  * Filter objects that match a given regular expression
@@ -14,7 +14,7 @@ type UpdatesWithText = UpdateContextDistributed<Message | BusinessMessage | Inli
14
14
  *
15
15
  * @param regex Regex to be matched
16
16
  */
17
- export declare const regex: (regex: RegExp) => UpdateFilter<UpdatesWithText, {
17
+ export declare function regex(regex: RegExp): UpdateFilter<UpdatesWithText, {
18
18
  match: RegExpMatchArray;
19
19
  }>;
20
20
  /**
@@ -27,7 +27,7 @@ export declare const regex: (regex: RegExp) => UpdateFilter<UpdatesWithText, {
27
27
  * @param str String to be matched
28
28
  * @param ignoreCase Whether string case should be ignored
29
29
  */
30
- export declare const equals: (str: string, ignoreCase?: boolean) => UpdateFilter<UpdatesWithText>;
30
+ export declare function equals(str: string, ignoreCase?: boolean): UpdateFilter<UpdatesWithText>;
31
31
  /**
32
32
  * Filter objects which contain the text given (as a substring)
33
33
  * - for `Message`, `Message.text` is used
@@ -38,7 +38,7 @@ export declare const equals: (str: string, ignoreCase?: boolean) => UpdateFilter
38
38
  * @param str Substring to be matched
39
39
  * @param ignoreCase Whether string case should be ignored
40
40
  */
41
- export declare const contains: (str: string, ignoreCase?: boolean) => UpdateFilter<UpdatesWithText>;
41
+ export declare function contains(str: string, ignoreCase?: boolean): UpdateFilter<UpdatesWithText>;
42
42
  /**
43
43
  * Filter objects which contain the text starting with a given string
44
44
  * - for `Message`, `Message.text` is used
@@ -49,7 +49,7 @@ export declare const contains: (str: string, ignoreCase?: boolean) => UpdateFilt
49
49
  * @param str Substring to be matched
50
50
  * @param ignoreCase Whether string case should be ignored
51
51
  */
52
- export declare const startsWith: (str: string, ignoreCase?: boolean) => UpdateFilter<UpdatesWithText>;
52
+ export declare function startsWith(str: string, ignoreCase?: boolean): UpdateFilter<UpdatesWithText>;
53
53
  /**
54
54
  * Filter objects which contain the text ending with a given string
55
55
  * - for `Message`, `Message.text` is used
@@ -60,5 +60,5 @@ export declare const startsWith: (str: string, ignoreCase?: boolean) => UpdateFi
60
60
  * @param str Substring to be matched
61
61
  * @param ignoreCase Whether string case should be ignored
62
62
  */
63
- export declare const endsWith: (str: string, ignoreCase?: boolean) => UpdateFilter<UpdatesWithText>;
63
+ export declare function endsWith(str: string, ignoreCase?: boolean): UpdateFilter<UpdatesWithText>;
64
64
  export {};
@@ -27,17 +27,19 @@ function extractText(obj) {
27
27
  *
28
28
  * @param regex Regex to be matched
29
29
  */
30
- export const regex = (regex) => (obj) => {
31
- const txt = extractText(obj);
32
- if (!txt)
30
+ export function regex(regex) {
31
+ return (obj) => {
32
+ const txt = extractText(obj);
33
+ if (!txt)
34
+ return false;
35
+ const m = txt.match(regex);
36
+ if (m) {
37
+ obj.match = m;
38
+ return true;
39
+ }
33
40
  return false;
34
- const m = txt.match(regex);
35
- if (m) {
36
- obj.match = m;
37
- return true;
38
- }
39
- return false;
40
- };
41
+ };
42
+ }
41
43
  /**
42
44
  * Filter objects which contain the exact text given
43
45
  * - for `Message`, `Message.text` is used
@@ -48,13 +50,13 @@ export const regex = (regex) => (obj) => {
48
50
  * @param str String to be matched
49
51
  * @param ignoreCase Whether string case should be ignored
50
52
  */
51
- export const equals = (str, ignoreCase = false) => {
53
+ export function equals(str, ignoreCase = false) {
52
54
  if (ignoreCase) {
53
55
  str = str.toLowerCase();
54
- return (obj) => extractText(obj)?.toLowerCase() === str;
56
+ return obj => extractText(obj)?.toLowerCase() === str;
55
57
  }
56
- return (obj) => extractText(obj) === str;
57
- };
58
+ return obj => extractText(obj) === str;
59
+ }
58
60
  /**
59
61
  * Filter objects which contain the text given (as a substring)
60
62
  * - for `Message`, `Message.text` is used
@@ -65,7 +67,7 @@ export const equals = (str, ignoreCase = false) => {
65
67
  * @param str Substring to be matched
66
68
  * @param ignoreCase Whether string case should be ignored
67
69
  */
68
- export const contains = (str, ignoreCase = false) => {
70
+ export function contains(str, ignoreCase = false) {
69
71
  if (ignoreCase) {
70
72
  str = str.toLowerCase();
71
73
  return (obj) => {
@@ -77,7 +79,7 @@ export const contains = (str, ignoreCase = false) => {
77
79
  const txt = extractText(obj);
78
80
  return txt != null && txt.includes(str);
79
81
  };
80
- };
82
+ }
81
83
  /**
82
84
  * Filter objects which contain the text starting with a given string
83
85
  * - for `Message`, `Message.text` is used
@@ -88,7 +90,7 @@ export const contains = (str, ignoreCase = false) => {
88
90
  * @param str Substring to be matched
89
91
  * @param ignoreCase Whether string case should be ignored
90
92
  */
91
- export const startsWith = (str, ignoreCase = false) => {
93
+ export function startsWith(str, ignoreCase = false) {
92
94
  if (ignoreCase) {
93
95
  str = str.toLowerCase();
94
96
  return (obj) => {
@@ -100,7 +102,7 @@ export const startsWith = (str, ignoreCase = false) => {
100
102
  const txt = extractText(obj);
101
103
  return txt != null && txt.substring(0, str.length) === str;
102
104
  };
103
- };
105
+ }
104
106
  /**
105
107
  * Filter objects which contain the text ending with a given string
106
108
  * - for `Message`, `Message.text` is used
@@ -111,7 +113,7 @@ export const startsWith = (str, ignoreCase = false) => {
111
113
  * @param str Substring to be matched
112
114
  * @param ignoreCase Whether string case should be ignored
113
115
  */
114
- export const endsWith = (str, ignoreCase = false) => {
116
+ export function endsWith(str, ignoreCase = false) {
115
117
  if (ignoreCase) {
116
118
  str = str.toLowerCase();
117
119
  return (obj) => {
@@ -123,5 +125,5 @@ export const endsWith = (str, ignoreCase = false) => {
123
125
  const txt = extractText(obj);
124
126
  return txt != null && txt.substring(0, str.length) === str;
125
127
  };
126
- };
128
+ }
127
129
  //# sourceMappingURL=text.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"text.js","sourceRoot":"","sources":["../../../src/filters/text.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n BusinessCallbackQuery,\n BusinessMessage,\n CallbackQuery,\n ChosenInlineResult,\n InlineCallbackQuery,\n InlineQuery,\n Message,\n} from '@mtcute/core'\n\nimport { UpdateContextDistributed } from '../context/base.js'\nimport { UpdateFilter } from './types.js'\n\ntype UpdatesWithText = UpdateContextDistributed<\n | Message\n | BusinessMessage\n | InlineQuery\n | ChosenInlineResult\n | CallbackQuery\n | InlineCallbackQuery\n | BusinessCallbackQuery\n>\n\nfunction extractText(obj: UpdatesWithText): string | null {\n switch (obj._name) {\n case 'new_message':\n case 'new_business_message':\n return obj.text\n case 'inline_query':\n return obj.query\n case 'chosen_inline_result':\n return obj.id\n case 'callback_query':\n case 'inline_callback_query':\n case 'business_callback_query':\n if (obj.raw.data) return obj.dataStr\n }\n\n return null\n}\n\n/**\n * Filter objects that match a given regular expression\n * - for `Message`, `Message.text` is used\n * - for `InlineQuery`, `InlineQuery.query` is used\n * - for {@link ChosenInlineResult}, {@link ChosenInlineResult#id} is used\n * - for callback queries, `dataStr` is used\n *\n * When a regex matches, the match array is stored in a\n * type-safe extension field `.match` of the object\n *\n * @param regex Regex to be matched\n */\nexport const regex =\n (regex: RegExp): UpdateFilter<UpdatesWithText, { match: RegExpMatchArray }> =>\n (obj) => {\n const txt = extractText(obj)\n if (!txt) return false\n\n const m = txt.match(regex)\n\n if (m) {\n (obj as typeof obj & { match: RegExpMatchArray }).match = m\n\n return true\n }\n\n return false\n }\n\n/**\n * Filter objects which contain the exact text given\n * - for `Message`, `Message.text` is used\n * - for `InlineQuery`, `InlineQuery.query` is used\n * - for {@link ChosenInlineResult}, {@link ChosenInlineResult.id} is used\n * - for callback queries, `dataStr` is used\n *\n * @param str String to be matched\n * @param ignoreCase Whether string case should be ignored\n */\nexport const equals = (str: string, ignoreCase = false): UpdateFilter<UpdatesWithText> => {\n if (ignoreCase) {\n str = str.toLowerCase()\n\n return (obj) => extractText(obj)?.toLowerCase() === str\n }\n\n return (obj) => extractText(obj) === str\n}\n\n/**\n * Filter objects which contain the text given (as a substring)\n * - for `Message`, `Message.text` is used\n * - for `InlineQuery`, `InlineQuery.query` is used\n * - for {@link ChosenInlineResult}, {@link ChosenInlineResult.id} is used\n * - for callback queries, `dataStr` is used\n *\n * @param str Substring to be matched\n * @param ignoreCase Whether string case should be ignored\n */\nexport const contains = (str: string, ignoreCase = false): UpdateFilter<UpdatesWithText> => {\n if (ignoreCase) {\n str = str.toLowerCase()\n\n return (obj) => {\n const txt = extractText(obj)\n\n return txt != null && txt.toLowerCase().includes(str)\n }\n }\n\n return (obj) => {\n const txt = extractText(obj)\n\n return txt != null && txt.includes(str)\n }\n}\n\n/**\n * Filter objects which contain the text starting with a given string\n * - for `Message`, `Message.text` is used\n * - for `InlineQuery`, `InlineQuery.query` is used\n * - for {@link ChosenInlineResult}, {@link ChosenInlineResult.id} is used\n * - for callback queries, `dataStr` is used\n *\n * @param str Substring to be matched\n * @param ignoreCase Whether string case should be ignored\n */\nexport const startsWith = (str: string, ignoreCase = false): UpdateFilter<UpdatesWithText> => {\n if (ignoreCase) {\n str = str.toLowerCase()\n\n return (obj) => {\n const txt = extractText(obj)\n\n return txt != null && txt.toLowerCase().substring(0, str.length) === str\n }\n }\n\n return (obj) => {\n const txt = extractText(obj)\n\n return txt != null && txt.substring(0, str.length) === str\n }\n}\n\n/**\n * Filter objects which contain the text ending with a given string\n * - for `Message`, `Message.text` is used\n * - for `InlineQuery`, `InlineQuery.query` is used\n * - for {@link ChosenInlineResult}, {@link ChosenInlineResult.id} is used\n * - for callback queries, `dataStr` is used\n *\n * @param str Substring to be matched\n * @param ignoreCase Whether string case should be ignored\n */\nexport const endsWith = (str: string, ignoreCase = false): UpdateFilter<UpdatesWithText> => {\n if (ignoreCase) {\n str = str.toLowerCase()\n\n return (obj) => {\n const txt = extractText(obj)\n\n return txt != null && txt.toLowerCase().substring(0, str.length) === str\n }\n }\n\n return (obj) => {\n const txt = extractText(obj)\n\n return txt != null && txt.substring(0, str.length) === str\n }\n}\n"]}
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../../../src/filters/text.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n BusinessCallbackQuery,\n BusinessMessage,\n CallbackQuery,\n ChosenInlineResult,\n InlineCallbackQuery,\n InlineQuery,\n Message,\n} from '@mtcute/core'\n\nimport type { UpdateContextDistributed } from '../context/base.js'\n\nimport type { UpdateFilter } from './types.js'\n\ntype UpdatesWithText = UpdateContextDistributed<\n | Message\n | BusinessMessage\n | InlineQuery\n | ChosenInlineResult\n | CallbackQuery\n | InlineCallbackQuery\n | BusinessCallbackQuery\n>\n\nfunction extractText(obj: UpdatesWithText): string | null {\n switch (obj._name) {\n case 'new_message':\n case 'new_business_message':\n return obj.text\n case 'inline_query':\n return obj.query\n case 'chosen_inline_result':\n return obj.id\n case 'callback_query':\n case 'inline_callback_query':\n case 'business_callback_query':\n if (obj.raw.data) return obj.dataStr\n }\n\n return null\n}\n\n/**\n * Filter objects that match a given regular expression\n * - for `Message`, `Message.text` is used\n * - for `InlineQuery`, `InlineQuery.query` is used\n * - for {@link ChosenInlineResult}, {@link ChosenInlineResult#id} is used\n * - for callback queries, `dataStr` is used\n *\n * When a regex matches, the match array is stored in a\n * type-safe extension field `.match` of the object\n *\n * @param regex Regex to be matched\n */\nexport function regex(regex: RegExp): UpdateFilter<UpdatesWithText, { match: RegExpMatchArray }> {\n return (obj) => {\n const txt = extractText(obj)\n if (!txt) return false\n\n const m = txt.match(regex)\n\n if (m) {\n (obj as typeof obj & { match: RegExpMatchArray }).match = m\n\n return true\n }\n\n return false\n }\n}\n\n/**\n * Filter objects which contain the exact text given\n * - for `Message`, `Message.text` is used\n * - for `InlineQuery`, `InlineQuery.query` is used\n * - for {@link ChosenInlineResult}, {@link ChosenInlineResult.id} is used\n * - for callback queries, `dataStr` is used\n *\n * @param str String to be matched\n * @param ignoreCase Whether string case should be ignored\n */\nexport function equals(str: string, ignoreCase = false): UpdateFilter<UpdatesWithText> {\n if (ignoreCase) {\n str = str.toLowerCase()\n\n return obj => extractText(obj)?.toLowerCase() === str\n }\n\n return obj => extractText(obj) === str\n}\n\n/**\n * Filter objects which contain the text given (as a substring)\n * - for `Message`, `Message.text` is used\n * - for `InlineQuery`, `InlineQuery.query` is used\n * - for {@link ChosenInlineResult}, {@link ChosenInlineResult.id} is used\n * - for callback queries, `dataStr` is used\n *\n * @param str Substring to be matched\n * @param ignoreCase Whether string case should be ignored\n */\nexport function contains(str: string, ignoreCase = false): UpdateFilter<UpdatesWithText> {\n if (ignoreCase) {\n str = str.toLowerCase()\n\n return (obj) => {\n const txt = extractText(obj)\n\n return txt != null && txt.toLowerCase().includes(str)\n }\n }\n\n return (obj) => {\n const txt = extractText(obj)\n\n return txt != null && txt.includes(str)\n }\n}\n\n/**\n * Filter objects which contain the text starting with a given string\n * - for `Message`, `Message.text` is used\n * - for `InlineQuery`, `InlineQuery.query` is used\n * - for {@link ChosenInlineResult}, {@link ChosenInlineResult.id} is used\n * - for callback queries, `dataStr` is used\n *\n * @param str Substring to be matched\n * @param ignoreCase Whether string case should be ignored\n */\nexport function startsWith(str: string, ignoreCase = false): UpdateFilter<UpdatesWithText> {\n if (ignoreCase) {\n str = str.toLowerCase()\n\n return (obj) => {\n const txt = extractText(obj)\n\n return txt != null && txt.toLowerCase().substring(0, str.length) === str\n }\n }\n\n return (obj) => {\n const txt = extractText(obj)\n\n return txt != null && txt.substring(0, str.length) === str\n }\n}\n\n/**\n * Filter objects which contain the text ending with a given string\n * - for `Message`, `Message.text` is used\n * - for `InlineQuery`, `InlineQuery.query` is used\n * - for {@link ChosenInlineResult}, {@link ChosenInlineResult.id} is used\n * - for callback queries, `dataStr` is used\n *\n * @param str Substring to be matched\n * @param ignoreCase Whether string case should be ignored\n */\nexport function endsWith(str: string, ignoreCase = false): UpdateFilter<UpdatesWithText> {\n if (ignoreCase) {\n str = str.toLowerCase()\n\n return (obj) => {\n const txt = extractText(obj)\n\n return txt != null && txt.toLowerCase().substring(0, str.length) === str\n }\n }\n\n return (obj) => {\n const txt = extractText(obj)\n\n return txt != null && txt.substring(0, str.length) === str\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { MaybePromise } from '@mtcute/core';
2
- import { UpdateState } from '../state/update-state.js';
1
+ import type { MaybePromise } from '@mtcute/core';
2
+ import type { UpdateState } from '../state/update-state.js';
3
3
  /**
4
4
  * Type describing a primitive filter, which is a function taking some `Base`
5
5
  * and a {@link TelegramClient}, checking it against some condition
@@ -1,5 +1,2 @@
1
- /* eslint-disable @typescript-eslint/ban-types */
2
- /* eslint-disable @typescript-eslint/no-explicit-any */
3
- // ^^ will be looked into in MTQ-29
4
1
  export {};
5
2
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/filters/types.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,uDAAuD;AACvD,mCAAmC","sourcesContent":["/* eslint-disable @typescript-eslint/ban-types */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n// ^^ will be looked into in MTQ-29\n\nimport { MaybePromise } from '@mtcute/core'\n\nimport { UpdateState } from '../state/update-state.js'\n/**\n * Type describing a primitive filter, which is a function taking some `Base`\n * and a {@link TelegramClient}, checking it against some condition\n * and returning a boolean.\n *\n * If `true` is returned, the filter is considered\n * to be matched, and the appropriate update handler function is called,\n * otherwise next registered handler is checked.\n *\n * Additionally, filter might contain a type modification\n * to `Base` for better code insights. If it is present,\n * it is used to overwrite types (!) of some of the `Base` fields\n * to given (note that this is entirely compile-time! object is not modified)\n *\n * For parametrized filters (like {@link filters.regex}),\n * type modification can also be used to add additional fields\n * (in case of `regex`, its match array is added to `.match`)\n *\n * Example without type mod:\n * ```typescript\n *\n * const hasPhoto: UpdateFilter<Message> = msg => msg.media?.type === 'photo'\n *\n * // ..later..\n * tg.onNewMessage(hasPhoto, async (msg) => {\n * // `hasPhoto` filter matched, so we can safely assume\n * // that `msg.media` is a Photo.\n * //\n * // but it is very redundant, verbose and error-rome,\n * // wonder if we could make typescript do this automagically and safely...\n * await (msg.media as Photo).downloadToFile(`${msg.id}.jpg`)\n * })\n * ```\n *\n * Example with type mod:\n * ```typescript\n *\n * const hasPhoto: UpdateFilter<Message, { media: Photo }> = msg => msg.media?.type === 'photo'\n *\n * // ..later..\n * tg.onNewMessage(hasPhoto, async (msg) => {\n * // since `hasPhoto` filter matched,\n * // we have applied the modification to `msg`,\n * // and `msg.media` now has type `Photo`\n * //\n * // no more redundancy and type casts!\n * await msg.media.downloadToFile(`${msg.id}.jpg`)\n * })\n * ```\n *\n * > **Note**: Type modification can contain anything, even totally unrelated types\n * > and it is *your* task to keep track that everything is correct.\n * >\n * > Bad example:\n * > ```typescript\n * > // we check for `Photo`, but type contains `Audio`. this will be a problem!\n * > const hasPhoto: UpdateFilter<Message, { media: Audio }> = msg => msg.media?.type === 'photo'\n * >\n * > // ..later..\n * > tg.onNewMessage(hasPhoto, async (msg) => {\n * > // oops! `msg.media` is `Audio` and does not have `.width`!\n * > console.log(msg.media.width)\n * > })\n * > ```\n *\n * > **Warning!** Do not use the generics provided in functions\n * > like `and`, `or`, etc. Those are meant to be inferred by the compiler!\n */\n// we need the second parameter because it carries meta information\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport type UpdateFilter<Base, Mod = {}, State extends object = never> = (\n update: Base,\n state?: UpdateState<State>,\n) => MaybePromise<boolean>\n\nexport type Modify<Base, Mod> = Omit<Base, keyof Mod> & Mod\nexport type Invert<Base, Mod> = {\n [P in keyof Mod & keyof Base]: Exclude<Base[P], Mod[P]>\n}\n\nexport type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never\n\nexport type ExtractBase<Filter> = Filter extends UpdateFilter<infer I, any> ? I : never\n\nexport type ExtractMod<Filter> = Filter extends UpdateFilter<any, infer I> ? I : never\n\nexport type ExtractState<Filter> = Filter extends UpdateFilter<any, any, infer I> ? I : never\n\nexport type TupleKeys<T extends any[]> = Exclude<keyof T, keyof []>\nexport type WrapBase<T extends any[]> = {\n [K in TupleKeys<T>]: { base: ExtractBase<T[K]> }\n}\nexport type Values<T> = T[keyof T]\nexport type UnwrapBase<T> = T extends { base: any } ? T['base'] : never\nexport type ExtractBaseMany<Filters extends any[]> = UnwrapBase<UnionToIntersection<Values<WrapBase<Filters>>>>\n\nexport type EmptyObject = Record<never, never>\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/filters/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { MaybePromise } from '@mtcute/core'\n\nimport type { UpdateState } from '../state/update-state.js'\n/**\n * Type describing a primitive filter, which is a function taking some `Base`\n * and a {@link TelegramClient}, checking it against some condition\n * and returning a boolean.\n *\n * If `true` is returned, the filter is considered\n * to be matched, and the appropriate update handler function is called,\n * otherwise next registered handler is checked.\n *\n * Additionally, filter might contain a type modification\n * to `Base` for better code insights. If it is present,\n * it is used to overwrite types (!) of some of the `Base` fields\n * to given (note that this is entirely compile-time! object is not modified)\n *\n * For parametrized filters (like {@link filters.regex}),\n * type modification can also be used to add additional fields\n * (in case of `regex`, its match array is added to `.match`)\n *\n * Example without type mod:\n * ```typescript\n *\n * const hasPhoto: UpdateFilter<Message> = msg => msg.media?.type === 'photo'\n *\n * // ..later..\n * tg.onNewMessage(hasPhoto, async (msg) => {\n * // `hasPhoto` filter matched, so we can safely assume\n * // that `msg.media` is a Photo.\n * //\n * // but it is very redundant, verbose and error-rome,\n * // wonder if we could make typescript do this automagically and safely...\n * await (msg.media as Photo).downloadToFile(`${msg.id}.jpg`)\n * })\n * ```\n *\n * Example with type mod:\n * ```typescript\n *\n * const hasPhoto: UpdateFilter<Message, { media: Photo }> = msg => msg.media?.type === 'photo'\n *\n * // ..later..\n * tg.onNewMessage(hasPhoto, async (msg) => {\n * // since `hasPhoto` filter matched,\n * // we have applied the modification to `msg`,\n * // and `msg.media` now has type `Photo`\n * //\n * // no more redundancy and type casts!\n * await msg.media.downloadToFile(`${msg.id}.jpg`)\n * })\n * ```\n *\n * > **Note**: Type modification can contain anything, even totally unrelated types\n * > and it is *your* task to keep track that everything is correct.\n * >\n * > Bad example:\n * > ```typescript\n * > // we check for `Photo`, but type contains `Audio`. this will be a problem!\n * > const hasPhoto: UpdateFilter<Message, { media: Audio }> = msg => msg.media?.type === 'photo'\n * >\n * > // ..later..\n * > tg.onNewMessage(hasPhoto, async (msg) => {\n * > // oops! `msg.media` is `Audio` and does not have `.width`!\n * > console.log(msg.media.width)\n * > })\n * > ```\n *\n * > **Warning!** Do not use the generics provided in functions\n * > like `and`, `or`, etc. Those are meant to be inferred by the compiler!\n */\n// we need the second parameter because it carries meta information\n// eslint-disable-next-line unused-imports/no-unused-vars, ts/no-empty-object-type\nexport type UpdateFilter<Base, Mod = {}, State extends object = never> = (\n update: Base,\n state?: UpdateState<State>,\n) => MaybePromise<boolean>\n\nexport type Modify<Base, Mod> = Omit<Base, keyof Mod> & Mod\nexport type Invert<Base, Mod> = {\n [P in keyof Mod & keyof Base]: Exclude<Base[P], Mod[P]>\n}\n\nexport type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never\n\nexport type ExtractBase<Filter> = Filter extends UpdateFilter<infer I, any> ? I : never\n\nexport type ExtractMod<Filter> = Filter extends UpdateFilter<any, infer I> ? I : never\n\nexport type ExtractState<Filter> = Filter extends UpdateFilter<any, any, infer I> ? I : never\n\nexport type TupleKeys<T extends any[]> = Exclude<keyof T, keyof []>\nexport type WrapBase<T extends any[]> = {\n [K in TupleKeys<T>]: { base: ExtractBase<T[K]> }\n}\nexport type Values<T> = T[keyof T]\nexport type UnwrapBase<T> = T extends { base: any } ? T['base'] : never\nexport type ExtractBaseMany<Filters extends any[]> = UnwrapBase<UnionToIntersection<Values<WrapBase<Filters>>>>\n\nexport type EmptyObject = Record<never, never>\n"]}
@@ -1,5 +1,5 @@
1
- import { ChatMemberUpdate, ChatMemberUpdateType, UserStatus, UserStatusUpdate } from '@mtcute/core';
2
- import { UpdateFilter } from './types.js';
1
+ import type { ChatMemberUpdate, ChatMemberUpdateType, UserStatus, UserStatusUpdate } from '@mtcute/core';
2
+ import type { UpdateFilter } from './types.js';
3
3
  /**
4
4
  * Create a filter for {@link ChatMemberUpdate} by update type
5
5
  *
@@ -7,10 +7,10 @@
7
7
  export const chatMember = (types) => {
8
8
  if (Array.isArray(types)) {
9
9
  const index = {};
10
- types.forEach((typ) => (index[typ] = true));
11
- return (upd) => upd.type in index;
10
+ types.forEach(typ => (index[typ] = true));
11
+ return upd => upd.type in index;
12
12
  }
13
- return (upd) => upd.type === types;
13
+ return upd => upd.type === types;
14
14
  };
15
15
  /**
16
16
  * Create a filter for {@link UserStatusUpdate} by new user status
@@ -21,14 +21,14 @@ export const chatMember = (types) => {
21
21
  export const userStatus = (statuses) => {
22
22
  if (Array.isArray(statuses)) {
23
23
  const index = {};
24
- statuses.forEach((typ) => (index[typ] = true));
25
- return (upd) => upd.status in index;
24
+ statuses.forEach(typ => (index[typ] = true));
25
+ return upd => upd.status in index;
26
26
  }
27
- return (upd) => upd.status === statuses;
27
+ return upd => upd.status === statuses;
28
28
  };
29
29
  /**
30
30
  * Create a filter for {@link ChatMemberUpdate} for updates
31
31
  * regarding current user
32
32
  */
33
- export const chatMemberSelf = (upd) => upd.isSelf;
33
+ export const chatMemberSelf = upd => upd.isSelf;
34
34
  //# sourceMappingURL=updates.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"updates.js","sourceRoot":"","sources":["../../../src/filters/updates.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,UAAU,GAGnB,CAAC,KAAuC,EAAkC,EAAE;IAC5E,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,KAAK,GAAgD,EAAE,CAAA;QAC7D,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,CAAA;QAE3C,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,IAAI,KAAK,CAAA;IACrC,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,KAAK,CAAA;AACtC,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,UAAU,GAYnB,CAAC,QAAgC,EAAkC,EAAE;IACrE,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAsC,EAAE,CAAA;QACnD,QAAQ,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,CAAA;QAE9C,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,IAAI,KAAK,CAAA;IACvC,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAA;AAC3C,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAqD,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAA","sourcesContent":["import { ChatMemberUpdate, ChatMemberUpdateType, MaybeArray, UserStatus, UserStatusUpdate } from '@mtcute/core'\n\nimport { UpdateFilter } from './types.js'\n\n/**\n * Create a filter for {@link ChatMemberUpdate} by update type\n *\n * @param types Update type(s)\n * @link ChatMemberUpdate.Type\n */\nexport const chatMember: {\n <T extends ChatMemberUpdateType>(type: T): UpdateFilter<ChatMemberUpdate, { type: T }>\n <T extends ChatMemberUpdateType[]>(types: T): UpdateFilter<ChatMemberUpdate, { type: T[number] }>\n} = (types: MaybeArray<ChatMemberUpdateType>): UpdateFilter<ChatMemberUpdate> => {\n if (Array.isArray(types)) {\n const index: Partial<Record<ChatMemberUpdateType, true>> = {}\n types.forEach((typ) => (index[typ] = true))\n\n return (upd) => upd.type in index\n }\n\n return (upd) => upd.type === types\n}\n\n/**\n * Create a filter for {@link UserStatusUpdate} by new user status\n *\n * @param statuses Update type(s)\n * @link User.Status\n */\nexport const userStatus: {\n <T extends UserStatus>(\n status: T,\n ): UpdateFilter<\n UserStatusUpdate,\n {\n type: T\n lastOnline: T extends 'offline' ? Date : null\n nextOffline: T extends 'online' ? Date : null\n }\n >\n <T extends UserStatus[]>(statuses: T): UpdateFilter<UserStatusUpdate, { type: T[number] }>\n} = (statuses: MaybeArray<UserStatus>): UpdateFilter<UserStatusUpdate> => {\n if (Array.isArray(statuses)) {\n const index: Partial<Record<UserStatus, true>> = {}\n statuses.forEach((typ) => (index[typ] = true))\n\n return (upd) => upd.status in index\n }\n\n return (upd) => upd.status === statuses\n}\n\n/**\n * Create a filter for {@link ChatMemberUpdate} for updates\n * regarding current user\n */\nexport const chatMemberSelf: UpdateFilter<ChatMemberUpdate, { isSelf: true }> = (upd) => upd.isSelf\n"]}
1
+ {"version":3,"file":"updates.js","sourceRoot":"","sources":["../../../src/filters/updates.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,UAAU,GAGnB,CAAC,KAAuC,EAAkC,EAAE;IAC5E,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,KAAK,GAAgD,EAAE,CAAA;QAC7D,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,CAAA;QAEzC,OAAO,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,IAAI,KAAK,CAAA;IACnC,CAAC;IAED,OAAO,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,KAAK,CAAA;AACpC,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,UAAU,GAYnB,CAAC,QAAgC,EAAkC,EAAE;IACrE,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAsC,EAAE,CAAA;QACnD,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,CAAA;QAE5C,OAAO,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,IAAI,KAAK,CAAA;IACrC,CAAC;IAED,OAAO,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAA;AACzC,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAqD,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAA","sourcesContent":["import type { ChatMemberUpdate, ChatMemberUpdateType, MaybeArray, UserStatus, UserStatusUpdate } from '@mtcute/core'\n\nimport type { UpdateFilter } from './types.js'\n\n/**\n * Create a filter for {@link ChatMemberUpdate} by update type\n *\n * @param types Update type(s)\n * @link ChatMemberUpdate.Type\n */\nexport const chatMember: {\n <T extends ChatMemberUpdateType>(type: T): UpdateFilter<ChatMemberUpdate, { type: T }>\n <T extends ChatMemberUpdateType[]>(types: T): UpdateFilter<ChatMemberUpdate, { type: T[number] }>\n} = (types: MaybeArray<ChatMemberUpdateType>): UpdateFilter<ChatMemberUpdate> => {\n if (Array.isArray(types)) {\n const index: Partial<Record<ChatMemberUpdateType, true>> = {}\n types.forEach(typ => (index[typ] = true))\n\n return upd => upd.type in index\n }\n\n return upd => upd.type === types\n}\n\n/**\n * Create a filter for {@link UserStatusUpdate} by new user status\n *\n * @param statuses Update type(s)\n * @link User.Status\n */\nexport const userStatus: {\n <T extends UserStatus>(\n status: T,\n ): UpdateFilter<\n UserStatusUpdate,\n {\n type: T\n lastOnline: T extends 'offline' ? Date : null\n nextOffline: T extends 'online' ? Date : null\n }\n >\n <T extends UserStatus[]>(statuses: T): UpdateFilter<UserStatusUpdate, { type: T[number] }>\n} = (statuses: MaybeArray<UserStatus>): UpdateFilter<UserStatusUpdate> => {\n if (Array.isArray(statuses)) {\n const index: Partial<Record<UserStatus, true>> = {}\n statuses.forEach(typ => (index[typ] = true))\n\n return upd => upd.status in index\n }\n\n return upd => upd.status === statuses\n}\n\n/**\n * Create a filter for {@link ChatMemberUpdate} for updates\n * regarding current user\n */\nexport const chatMemberSelf: UpdateFilter<ChatMemberUpdate, { isSelf: true }> = upd => upd.isSelf\n"]}
@@ -1,6 +1,7 @@
1
- import { BotChatJoinRequestUpdate, BusinessCallbackQuery, BusinessMessage, CallbackQuery, ChatMemberUpdate, ChosenInlineResult, DeleteStoryUpdate, HistoryReadUpdate, InlineCallbackQuery, InlineQuery, MaybeArray, Message, PollVoteUpdate, StoryUpdate, User, UserStatusUpdate, UserTypingUpdate } from '@mtcute/core';
2
- import { UpdateContextDistributed } from '../context/base.js';
3
- import { UpdateFilter } from './types.js';
1
+ import type { BotChatJoinRequestUpdate, BusinessCallbackQuery, BusinessMessage, CallbackQuery, ChatMemberUpdate, ChosenInlineResult, DeleteStoryUpdate, HistoryReadUpdate, InlineCallbackQuery, InlineQuery, MaybeArray, Message, PollVoteUpdate, StoryUpdate, UserStatusUpdate, UserTypingUpdate } from '@mtcute/core';
2
+ import { User } from '@mtcute/core';
3
+ import type { UpdateContextDistributed } from '../context/base.js';
4
+ import type { UpdateFilter } from './types.js';
4
5
  /**
5
6
  * Filter messages generated by yourself (including Saved Messages)
6
7
  */