@rilong/grammyjs-conversations-esm 2.0.2
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.
- package/LICENSE +21 -0
- package/README.md +59 -0
- package/out/conversation.d.ts +885 -0
- package/out/conversation.js +832 -0
- package/out/deps.node.d.ts +2 -0
- package/out/deps.node.js +1 -0
- package/out/engine.d.ts +212 -0
- package/out/engine.js +238 -0
- package/out/form.d.ts +530 -0
- package/out/form.js +598 -0
- package/out/menu.d.ts +593 -0
- package/out/menu.js +698 -0
- package/out/mod.d.ts +8 -0
- package/out/mod.js +8 -0
- package/out/nope.d.ts +16 -0
- package/out/nope.js +35 -0
- package/out/plugin.d.ts +678 -0
- package/out/plugin.js +578 -0
- package/out/resolve.d.ts +43 -0
- package/out/resolve.js +21 -0
- package/out/state.d.ts +147 -0
- package/out/state.js +125 -0
- package/out/storage.d.ts +169 -0
- package/out/storage.js +105 -0
- package/package.json +43 -0
package/out/plugin.d.ts
ADDED
@@ -0,0 +1,678 @@
|
|
1
|
+
import { Conversation } from "./conversation.js";
|
2
|
+
import { type ApiClientOptions, Context, type Middleware, type MiddlewareFn, type Update, type UserFromGetMe } from "./deps.node.js";
|
3
|
+
import { type ReplayState } from "./engine.js";
|
4
|
+
import { type ConversationStorage } from "./storage.js";
|
5
|
+
/**
|
6
|
+
* Base data that is needed to enter or resume a conversation function. Contains
|
7
|
+
* a subset of properties from the current context object of the outside
|
8
|
+
* middleware tree.
|
9
|
+
*
|
10
|
+
* The contained update is supplied as the new update for the most recent wait
|
11
|
+
* call.
|
12
|
+
*/
|
13
|
+
export interface ContextBaseData {
|
14
|
+
/** The new update to supply to the conversation */
|
15
|
+
update: Update;
|
16
|
+
/** Basic information used to construct `Api` instances */
|
17
|
+
api: ApiBaseData;
|
18
|
+
/** Information about the bot itself. */
|
19
|
+
me: UserFromGetMe;
|
20
|
+
}
|
21
|
+
/**
|
22
|
+
* Base data that is needed to construct new `Api` instances from scratch.
|
23
|
+
* Contains a subset of properties from `ctx.api` from the outside middleware
|
24
|
+
* tree.
|
25
|
+
*/
|
26
|
+
export interface ApiBaseData {
|
27
|
+
/** The bot's token obtained from [@BotFather](https://t.me/BotFather) */
|
28
|
+
token: string;
|
29
|
+
/** Optional confiugration options for the underlying API client */
|
30
|
+
options?: ApiClientOptions;
|
31
|
+
}
|
32
|
+
/**
|
33
|
+
* Optional configuration options for the conversations plugin.
|
34
|
+
*
|
35
|
+
* Note that this configuration object takes two different types of custom
|
36
|
+
* context types. The first type parameter should corresopnd with the context
|
37
|
+
* type of the outside middleware tree. It is used to connect to external
|
38
|
+
* storages.
|
39
|
+
*
|
40
|
+
* The second type parameter should correspond with the custom context type used
|
41
|
+
* inside all conversations. It is used if you define a list of default plugins
|
42
|
+
* to be installed in every conversation you use. If the list of plugins differs
|
43
|
+
* between conversations, you may want to use different context types for them.
|
44
|
+
* In that case, you should use a context type for only those plugins that are
|
45
|
+
* shared between all conversations, or avoid a list of default plugins
|
46
|
+
* entirely.
|
47
|
+
*
|
48
|
+
* @typeParam OC Custom context type of the outside middleware
|
49
|
+
* @typeParam C Custom context type used inside conversations
|
50
|
+
*/
|
51
|
+
export interface ConversationOptions<OC extends Context, C extends Context> {
|
52
|
+
/**
|
53
|
+
* Defines how to persist and version conversation data in between replays.
|
54
|
+
* Most likely, you will want to use this option, as your data is lost
|
55
|
+
* otherwise.
|
56
|
+
*
|
57
|
+
* Data can be stored based on a context object, or based on a key derived
|
58
|
+
* from the context object. See {@link ConversationStorage} for more
|
59
|
+
* information.
|
60
|
+
*
|
61
|
+
* Defaults to an in-memory implementation of the storage. This means that
|
62
|
+
* all conversations will be left when your process terminates.
|
63
|
+
*
|
64
|
+
* Defaults to storing data per chat based on `ctx.chatId`.
|
65
|
+
*/
|
66
|
+
storage?: ConversationStorage<OC, ConversationData>;
|
67
|
+
/**
|
68
|
+
* List of default plugins to install for all conversations.
|
69
|
+
*
|
70
|
+
* Each conversation will have these plugins installed first. In addition,
|
71
|
+
* each conversation will have the plugins installed that you specify
|
72
|
+
* explicitly when using {@link enterConversation}.
|
73
|
+
*/
|
74
|
+
plugins?: Middleware<C>[];
|
75
|
+
/**
|
76
|
+
* Called when a conversation is entered via `ctx.conversation.enter`.
|
77
|
+
*
|
78
|
+
* @param id The identifer of the conversation that was entered
|
79
|
+
* @param ctx The current context object
|
80
|
+
*/
|
81
|
+
onEnter?(id: string, ctx: OC): unknown | Promise<unknown>;
|
82
|
+
/**
|
83
|
+
* Called when a conversation is left via `ctx.conversation.exit` or
|
84
|
+
* `conversation.halt`.
|
85
|
+
*
|
86
|
+
* Note that this callback is not called when a conversation exists normally
|
87
|
+
* by returning or by throwing an error. If you wish to execute logic at the
|
88
|
+
* end of a conversation, you can simply call the callback directly.
|
89
|
+
*
|
90
|
+
* @param id The identifer of the conversation that was entered
|
91
|
+
* @param ctx The current context object
|
92
|
+
*/
|
93
|
+
onExit?(id: string, ctx: OC): unknown | Promise<unknown>;
|
94
|
+
}
|
95
|
+
/**
|
96
|
+
* Internal conversation data representation. Holds the state of any number of
|
97
|
+
* conversations for each conversation identifier.
|
98
|
+
*/
|
99
|
+
export interface ConversationData {
|
100
|
+
[id: string]: ConversationState[];
|
101
|
+
}
|
102
|
+
/**
|
103
|
+
* Context flavor for the outside middleware tree. Installs `ctx.conversation`
|
104
|
+
* on the type of a context object so it can be used to enter or exit
|
105
|
+
* conversations as well as inspect active conversations.
|
106
|
+
*
|
107
|
+
* This should only be installed if you install the {@link conversations}
|
108
|
+
* middleware.
|
109
|
+
*
|
110
|
+
* Note that it is not possible to use the conversations plugin recursively
|
111
|
+
* inside conversations. In other words `ctx.conversation` does not exist inside
|
112
|
+
* a conversation. Consequently, it is always incorrect to install this context
|
113
|
+
* flavor for context objects inside conversations.
|
114
|
+
*/
|
115
|
+
export type ConversationFlavor<C extends Context> = C & {
|
116
|
+
/**
|
117
|
+
* Controls for entering or exiting conversations from the outside
|
118
|
+
* middleware. Also provides a way to inspect which conversations are
|
119
|
+
* currently active.
|
120
|
+
*/
|
121
|
+
conversation: ConversationControls;
|
122
|
+
};
|
123
|
+
/**
|
124
|
+
* A control panel for all known conversations. This holds the `enter` method
|
125
|
+
* that is the main entrypoint to a conversation.
|
126
|
+
*
|
127
|
+
* In addition, conversations can be killed from the outside using one of the
|
128
|
+
* exit methods.
|
129
|
+
*
|
130
|
+
* Finally, the control panel can be used to inspect which conversations are
|
131
|
+
* currently active.
|
132
|
+
*/
|
133
|
+
export interface ConversationControls {
|
134
|
+
/**
|
135
|
+
* Enters the conversation with the given identifer. By default, the name of
|
136
|
+
* the function is the identifier of the function. You can override this
|
137
|
+
* value when calling {@link createConversation}.
|
138
|
+
*
|
139
|
+
* ```ts
|
140
|
+
* // Enters a conversation called "convo" upon a start command.
|
141
|
+
* bot.command("start", async ctx => {
|
142
|
+
* await ctx.conversation.enter("convo")
|
143
|
+
* })
|
144
|
+
* ```
|
145
|
+
*
|
146
|
+
* Entering a conversation will make the conversation run partially until
|
147
|
+
* the first wait call is reached. The enter call will therefore return long
|
148
|
+
* before the conversation has returned.
|
149
|
+
*
|
150
|
+
* You can pass any number of arguments when entering a conversation. These
|
151
|
+
* arguments will be serialized to JSON and persisted in the storage as
|
152
|
+
* `string`. Whenever the conversation is replayed, this string is parsed
|
153
|
+
* back to objects and supplied to the conversation. This means that all
|
154
|
+
* arguments must be JSON-serializable.
|
155
|
+
*
|
156
|
+
* ```ts
|
157
|
+
* // Enters a conversation called "convo" upon a start command.
|
158
|
+
* bot.command("start", async ctx => {
|
159
|
+
* await ctx.conversation.enter("convo", 42, "cool", { args: [2, 1, 0] })
|
160
|
+
* })
|
161
|
+
* async function convo(conversation, ctx, num, str, { args }) {
|
162
|
+
* // ...
|
163
|
+
* }
|
164
|
+
* ```
|
165
|
+
*
|
166
|
+
* Be careful: There is no type safety for conversation arguments! You must
|
167
|
+
* annotate the correct types in the function signature of the conversation
|
168
|
+
* builder function, and you also have to make sure that you pass matching
|
169
|
+
* values to `enter`.
|
170
|
+
*
|
171
|
+
* This method will throw an error if the same or a different conversation
|
172
|
+
* has already been entered. If you want to enter a conversations in
|
173
|
+
* parallel to existing active conversations, you can mark it as parallel.
|
174
|
+
* This can be done by passig `{ parallel: true }` to
|
175
|
+
* {@link createConversation}.
|
176
|
+
*
|
177
|
+
* @param name The identifer of the conversation to enter
|
178
|
+
* @param args Optional list of arguments
|
179
|
+
*/
|
180
|
+
enter(name: string, ...args: unknown[]): Promise<void>;
|
181
|
+
/**
|
182
|
+
* Purges all state of the conversation with the given identifer for the
|
183
|
+
* current chat. This means that if the specified conversation had been
|
184
|
+
* active, it is now terminated. If the conversation was marked as parallel,
|
185
|
+
* all conversations with this identifier are left for the current chat.
|
186
|
+
*
|
187
|
+
* Note that if you call this method concurrently to a replay, the replay
|
188
|
+
* will not be interrupted. However, its data will not be saved as soon as
|
189
|
+
* the replay finishes.
|
190
|
+
*
|
191
|
+
* For every exited conversation, `onExit` will be called if specified when
|
192
|
+
* installing the conversations plugin.
|
193
|
+
*
|
194
|
+
* Does nothing if no conversation with the given name is active in the
|
195
|
+
* current chat.
|
196
|
+
*
|
197
|
+
* @param name The identifier of the conversation to exit
|
198
|
+
*/
|
199
|
+
exit(name: string): Promise<void>;
|
200
|
+
/**
|
201
|
+
* Purges all state of all conversations in the current chat, irrespective
|
202
|
+
* of their identifers. This will terminate all conversations.
|
203
|
+
*
|
204
|
+
* Note that if you call this method concurrently to a replay, the replay
|
205
|
+
* will not be interrupted. However, its data will not be saved as soon as
|
206
|
+
* the replay finishes.
|
207
|
+
*
|
208
|
+
* For every exited conversation, `onExit` will be called if specified when
|
209
|
+
* installing the conversations plugin.
|
210
|
+
*
|
211
|
+
* Does nothing if no conversations are running.
|
212
|
+
*/
|
213
|
+
exitAll(): Promise<void>;
|
214
|
+
/**
|
215
|
+
* Purges all state of the conversation with the given identifer at the
|
216
|
+
* given position for the current chat. This means that if the specified
|
217
|
+
* conversation had been active, it is now terminated. The position is
|
218
|
+
* determined chronologically. For example, passing `0` will exit the oldest
|
219
|
+
* parallel conversation with the given identifier that is still active.
|
220
|
+
*
|
221
|
+
* Note that if you call this method concurrently to a replay, the replay
|
222
|
+
* will not be interrupted. However, its data will not be saved as soon as
|
223
|
+
* the replay finishes.
|
224
|
+
*
|
225
|
+
* `onExit` will be called if specified when installing the conversations
|
226
|
+
* plugin.
|
227
|
+
*
|
228
|
+
* Does nothing if no conversation with the given name is active at the
|
229
|
+
* given position in the current chat.
|
230
|
+
*
|
231
|
+
* @param name The identifier of the conversation to exit
|
232
|
+
* @param index The position of the conversation to exit
|
233
|
+
*/
|
234
|
+
exitOne(name: string, index: number): Promise<void>;
|
235
|
+
/**
|
236
|
+
* Returns an object specifying the number of times that each conversation
|
237
|
+
* is currently active. For example, if a parallel conversation called
|
238
|
+
* "captcha" is active 3 times in the current chat, and a conversation
|
239
|
+
* called "settings" is active once in the same chat, the returned object
|
240
|
+
* will look like this.
|
241
|
+
*
|
242
|
+
* ```ts
|
243
|
+
* {
|
244
|
+
* captcha: 3,
|
245
|
+
* settings: 1,
|
246
|
+
* }
|
247
|
+
* ```
|
248
|
+
*/
|
249
|
+
active(): Record<string, number>;
|
250
|
+
/**
|
251
|
+
* Returns the number of times that a given conversation is active in the
|
252
|
+
* current chat. If no conversation was marked as parallel, this value will
|
253
|
+
* always only be either `0` or `1`.
|
254
|
+
*
|
255
|
+
* For example, this is how you can check if a conversation called
|
256
|
+
* "birthday" is currently active.
|
257
|
+
*
|
258
|
+
* ```ts
|
259
|
+
* if (ctx.conversation.active("birthday")) {
|
260
|
+
* // birthday conversation is active
|
261
|
+
* }
|
262
|
+
* // same but more explicit:
|
263
|
+
* if (ctx.conversation.active("birthday") > 0) {
|
264
|
+
* // birthday conversation is active
|
265
|
+
* }
|
266
|
+
* ```
|
267
|
+
*
|
268
|
+
* @param name
|
269
|
+
*/
|
270
|
+
active(name: string): number;
|
271
|
+
}
|
272
|
+
/**
|
273
|
+
* Middleware for the conversations plugin.
|
274
|
+
*
|
275
|
+
* This is the main thing you have to install in order to use this plugin. It
|
276
|
+
* performs various setup tasks for each context object, and it reads and writes
|
277
|
+
* to the data storage if provided. This middleware has to be installed before
|
278
|
+
* you can install `createConversation` with your conversation builder function.
|
279
|
+
*
|
280
|
+
* You can pass {@link ConversationOptions | an options object} to the plugin.
|
281
|
+
* The most important option is called `storage`. It can be used to persist
|
282
|
+
* conversations durably in any storage backend of your choice. That way, the
|
283
|
+
* conversations can survive restarts of your server.
|
284
|
+
*
|
285
|
+
* ```ts
|
286
|
+
* conversations({
|
287
|
+
* storage: {
|
288
|
+
* type: "key",
|
289
|
+
* version: 0, // change the version when you change your code
|
290
|
+
* adapter: new FileAdapter("/home/bot/data"),
|
291
|
+
* },
|
292
|
+
* });
|
293
|
+
* ```
|
294
|
+
*
|
295
|
+
* A list of known storage adapters can be found
|
296
|
+
* [here](https://github.com/grammyjs/storages/tree/main/packages#grammy-storages).
|
297
|
+
*
|
298
|
+
* It is advisable to version your data when you persist it. Every time you
|
299
|
+
* change your conversation function, you can increment the version. That way,
|
300
|
+
* the conversations plugin can make sure to avoid any data corruption caused by
|
301
|
+
* mismatches between state and implementation.
|
302
|
+
*
|
303
|
+
* Note that the plugin takes two different type parameters. The first type
|
304
|
+
* parameter should corresopnd with the context type of the outside middleware
|
305
|
+
* tree. The second type parameter should correspond with the custom context
|
306
|
+
* type used inside all conversations. If you may want to use different context
|
307
|
+
* types for different conversations, you can simply use `Context` here, and
|
308
|
+
* adjust the type for each conversation individually.
|
309
|
+
*
|
310
|
+
* Be sure to read [the documentation about the conversations
|
311
|
+
* plugin](https://grammy.dev/plugins/conversations) to learn more about how to
|
312
|
+
* use it.
|
313
|
+
*
|
314
|
+
* @param options Optional options for the conversations plugin
|
315
|
+
* @typeParam OC Custom context type of the outside middleware
|
316
|
+
* @typeParam C Custom context type used inside conversations
|
317
|
+
*/
|
318
|
+
export declare function conversations<OC extends Context, C extends Context>(options?: ConversationOptions<OC, C>): MiddlewareFn<ConversationFlavor<OC>>;
|
319
|
+
/**
|
320
|
+
* State of a single conversation.
|
321
|
+
*
|
322
|
+
* Objects of this type are persisted when a conversation is interrupted and the
|
323
|
+
* state of execution is stored in the database.
|
324
|
+
*/
|
325
|
+
export interface ConversationState {
|
326
|
+
/** JSON string of the arguments supplied to a conversation */
|
327
|
+
args?: string;
|
328
|
+
/** The replay state containing the state of execution */
|
329
|
+
replay: ReplayState;
|
330
|
+
/** A list of pending interrupts that can be resolved */
|
331
|
+
interrupts: number[];
|
332
|
+
}
|
333
|
+
/**
|
334
|
+
* A result of running a conversation builder function.
|
335
|
+
*
|
336
|
+
* This is a union of four possible outcomes of the replay. The union members
|
337
|
+
* are discriminated by their `status` property. The replay may have completed
|
338
|
+
* normally, thrown an error, or consumed or skipped the update.
|
339
|
+
*/
|
340
|
+
export type ConversationResult = ConversationComplete | ConversationError | ConversationHandled | ConversationSkipped;
|
341
|
+
/**
|
342
|
+
* A conversation result indicating that the conversation has completed normally
|
343
|
+
* by returning.
|
344
|
+
*/
|
345
|
+
export interface ConversationComplete {
|
346
|
+
/** New status of the conversation, always `"complete"` */
|
347
|
+
status: "complete";
|
348
|
+
/** Whether the conversation demands downstream middleware to be called */
|
349
|
+
next: boolean;
|
350
|
+
}
|
351
|
+
/**
|
352
|
+
* A conversation result indicating that the conversation has completed by
|
353
|
+
* throwing an error.
|
354
|
+
*/
|
355
|
+
export interface ConversationError {
|
356
|
+
/** New status of the conversation, always `"error"` */
|
357
|
+
status: "error";
|
358
|
+
/** The thrown error object */
|
359
|
+
error: unknown;
|
360
|
+
}
|
361
|
+
/**
|
362
|
+
* A conversation result indicating that the conversation has handled the
|
363
|
+
* update. This happens when the conversation builder function was
|
364
|
+
* interrupted by calling `wait`.
|
365
|
+
*
|
366
|
+
* Contains the new replay state which can be used to resume the conversation
|
367
|
+
* further. Also contains a list of pending interrupts which identify the
|
368
|
+
* unresolved `wait` calls.
|
369
|
+
*/
|
370
|
+
export interface ConversationHandled {
|
371
|
+
/** New status of the conversation, always `"handled"` */
|
372
|
+
status: "handled";
|
373
|
+
/** The new replay state after handling the update */
|
374
|
+
replay: ReplayState;
|
375
|
+
/** A list of pending interrupts to resume the conversation */
|
376
|
+
interrupts: number[];
|
377
|
+
}
|
378
|
+
/**
|
379
|
+
* A conversation result indicating that the conversation has decided to skip
|
380
|
+
* handling this update. This happens when the conversation builder function
|
381
|
+
* cancels the execution using `skip`.
|
382
|
+
*/
|
383
|
+
export interface ConversationSkipped {
|
384
|
+
/** New status of the conversation, always `"skipped"` */
|
385
|
+
status: "skipped";
|
386
|
+
/** Whether the conversation demands downstream middleware to be called */
|
387
|
+
next: boolean;
|
388
|
+
}
|
389
|
+
/**
|
390
|
+
* A conversation builder function.
|
391
|
+
*
|
392
|
+
* This is the type of function that defines a conversation. Conversation buider
|
393
|
+
* functions receive as their first argument an instance of
|
394
|
+
* {@link Conversation}. This allows them to wait for updates and control the
|
395
|
+
* conversation in various other ways.
|
396
|
+
*
|
397
|
+
* As a second argument, the first context object is received. This context
|
398
|
+
* object contains the update that was used to enter the conversation.
|
399
|
+
*
|
400
|
+
* Any additional arguments are the values provided to the enter call. Note that
|
401
|
+
* there is no type safety for these parameters.
|
402
|
+
*
|
403
|
+
* @param conversation A conversation handle
|
404
|
+
* @param ctx The initial context object
|
405
|
+
* @typeParam OC Custom context type of the outside middleware
|
406
|
+
* @typeParam C Custom context type used inside conversations
|
407
|
+
*/
|
408
|
+
export type ConversationBuilder<OC extends Context, C extends Context> = (conversation: Conversation<OC, C>, ctx: C, ...args: any[]) => Promise<unknown> | unknown;
|
409
|
+
/**
|
410
|
+
* Configuration options for a conversation. These options can be passed to
|
411
|
+
* {@link createConversation} when installing the conversation.
|
412
|
+
*
|
413
|
+
* @typeParam C The type of context object used inside this conversation
|
414
|
+
*/
|
415
|
+
export interface ConversationConfig<C extends Context> {
|
416
|
+
/**
|
417
|
+
* Identifier of the conversation. The identifier can be used to enter or
|
418
|
+
* exit conversations from middleware.
|
419
|
+
*
|
420
|
+
* Defaults to [the JavaScript function
|
421
|
+
* name](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name).
|
422
|
+
*/
|
423
|
+
id?: string;
|
424
|
+
/**
|
425
|
+
* An array of plugins to be installed on every context object created by
|
426
|
+
* the conversation.
|
427
|
+
*
|
428
|
+
* Remember that when a conversation is executed, it creates a number of
|
429
|
+
* context objects from scratch during each replay. If this is not obvious
|
430
|
+
* to you, it means that you probably should read [the documentation of this
|
431
|
+
* plugin](https://grammy.dev/plugins/conversations) in order to avoid
|
432
|
+
* common pitfalls.
|
433
|
+
*
|
434
|
+
* The created context objects did not pass through the middleware tree, so
|
435
|
+
* they will not have any properties installed on them. You can use this
|
436
|
+
* configuration option to specify a number of grammY plugins that should
|
437
|
+
* receive each context object created by the conversation.
|
438
|
+
*
|
439
|
+
* This lets you use many plugins inside the conversation. However, there
|
440
|
+
* are still a few things to be aware of. In a typical middleware pass,
|
441
|
+
* every plugin can process a context object, then call `next` to wait for
|
442
|
+
* downstream middleware to finish, and then get the opportunity to perform
|
443
|
+
* cleanup tasks or execute other code after the update was processed
|
444
|
+
* downstream.
|
445
|
+
*
|
446
|
+
* Passing middleware to the `plugins` array will behave differently in the
|
447
|
+
* sense that a call to `next` will resolve immediately. The context object
|
448
|
+
* is given to the conversation only after all plugins have processed it.
|
449
|
+
* Plugins that depend on executing tasks after calling `next` therefore
|
450
|
+
* will not work correctly.
|
451
|
+
*
|
452
|
+
* If a plugin decides to fully handle an update by not calling `next`, then
|
453
|
+
* this will consume the update. Any pending `wait` calls inside the
|
454
|
+
* conversation will only receive the next incoming update.
|
455
|
+
*
|
456
|
+
* Note that you can install Bot API transformers from inside middleware,
|
457
|
+
* too. This lets you modify the instances of `Api` created by the
|
458
|
+
* conversations plugin.
|
459
|
+
*
|
460
|
+
* ```ts
|
461
|
+
* plugins: [async (ctx, next) => {
|
462
|
+
* ctx.api.config.use(transformer)
|
463
|
+
* await next()
|
464
|
+
* }]
|
465
|
+
* ```
|
466
|
+
*
|
467
|
+
* In some cases, TypeScript is known not to be able to infer the correct
|
468
|
+
* context type for plugins passed to this configuration option. The types
|
469
|
+
* are still checked, though, which leads to compilation errors. They can be
|
470
|
+
* fixed by passing the custom context type to the plugins explicitly. Note
|
471
|
+
* that you need to use the custom context type used inside the
|
472
|
+
* conversation, not the custom context type used in the outside middleware.
|
473
|
+
*/
|
474
|
+
plugins?: Middleware<C>[];
|
475
|
+
/**
|
476
|
+
* Specifies a default timeout for all wait calls inside the conversation.
|
477
|
+
*
|
478
|
+
* This value can be overridden for each wait call by passing a different
|
479
|
+
* timeout value.
|
480
|
+
*/
|
481
|
+
maxMillisecondsToWait?: number;
|
482
|
+
/**
|
483
|
+
* Marks the conversation as parallel.
|
484
|
+
*
|
485
|
+
* By default, only a single conversation can ben active per chat. When this
|
486
|
+
* option is set to `true`, this conversation can be entered when a
|
487
|
+
* different conversation with the same or a different identifier is already
|
488
|
+
* active. For example, in a single group chat, you can have 10 different
|
489
|
+
* active conversations with 10 different users all at the same time.
|
490
|
+
*
|
491
|
+
* Conversations from different chats are always parallel.
|
492
|
+
*
|
493
|
+
* Only a single conversation can handle an update. When multiple
|
494
|
+
* conversations are active at the same time in a chat, only the first
|
495
|
+
* conversation will receive the update. If it decides to skip the update,
|
496
|
+
* the second conversation will receive the update. This order is determined
|
497
|
+
* by the order in which the different conversations are installed in the
|
498
|
+
* middleware tree. If multiple conversations with the same identifer are
|
499
|
+
* active, they will recieve the update in chronological order of the time
|
500
|
+
* that the conversations were entered.
|
501
|
+
*
|
502
|
+
* By default, when a conversation decides to skip an update, the update
|
503
|
+
* will be dropped. When a conversation is marked as parallel, it will
|
504
|
+
* default to returning the update to the middleware system so that other
|
505
|
+
* active conversations can pick up the update and handle it. This also
|
506
|
+
* means that if you mark a conversation as parallel, unrelated downstream
|
507
|
+
* middleware might process the update.
|
508
|
+
*
|
509
|
+
* When an update is skipped, an option `next` can be passed to override the
|
510
|
+
* above behavior. This lets you decide for every call to `skip` whether
|
511
|
+
* parallel conversations as well as other middleware shall receive an
|
512
|
+
* update, or whether the update should be dropped. The same option exists
|
513
|
+
* for filtered wait calls, chained wait calls, and conversational forms.
|
514
|
+
*
|
515
|
+
* Defaults to `false`.
|
516
|
+
*/
|
517
|
+
parallel?: boolean;
|
518
|
+
}
|
519
|
+
/**
|
520
|
+
* Takes a {@link ConversationBuilder | conversation builder function}, and
|
521
|
+
* turns it into middleware that can be installed on your bot. This middleware
|
522
|
+
* registers the conversation on the context object. Downstream handlers can
|
523
|
+
* then enter the conversation using `ctx.conversation.enter`.
|
524
|
+
*
|
525
|
+
* When an update reaches this middleware and the given conversation is
|
526
|
+
* currently active, then it will receive the update and process it. This
|
527
|
+
* advances the conversation.
|
528
|
+
*
|
529
|
+
* If the conversation is marked as parallel, downstream middleware will be
|
530
|
+
* called if this conversation decides to skip the update.
|
531
|
+
*
|
532
|
+
* You can pass a second parameter of type string to this function in order to
|
533
|
+
* give a different identifier to the conversation. By default, [the name of the
|
534
|
+
* function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name)
|
535
|
+
* is used.
|
536
|
+
*
|
537
|
+
* ```ts
|
538
|
+
* bot.use(createConversation(example, "new-name"))
|
539
|
+
* ```
|
540
|
+
*
|
541
|
+
* Optionally, instead of passing an identifier string as a second argument, you
|
542
|
+
* can pass an options object. It lets you configure the conversation. For example, this is how you can mark a conversation as parallel.
|
543
|
+
*
|
544
|
+
* ```ts
|
545
|
+
* bot.use(createConversation(example, {
|
546
|
+
* id: "new-name",
|
547
|
+
* parallel: true,
|
548
|
+
* }))
|
549
|
+
* ```
|
550
|
+
*
|
551
|
+
* Note that this function takes two different type parameters. The first type
|
552
|
+
* parameter should corresopnd with the context type of the outside middleware
|
553
|
+
* tree. The second type parameter should correspond with the custom context
|
554
|
+
* type used inside the given conversation. These two custom context types can
|
555
|
+
* never be identical because the outside middleware must have
|
556
|
+
* {@link ConversationFlavor} installed, but the custom context type used in the
|
557
|
+
* conversation must never have this type installed.
|
558
|
+
*
|
559
|
+
* @param builder A conversation builder function
|
560
|
+
* @param options A different name for the conversation, or an options object
|
561
|
+
* @typeParam OC Custom context type of the outside middleware
|
562
|
+
* @typeParam C Custom context type used inside this conversation
|
563
|
+
*/
|
564
|
+
export declare function createConversation<OC extends Context, C extends Context>(builder: ConversationBuilder<OC, C>, options?: string | ConversationConfig<C>): MiddlewareFn<ConversationFlavor<OC>>;
|
565
|
+
/**
|
566
|
+
* Takes a conversation builder function and some state and runs all parallel
|
567
|
+
* instances of it until a conversation result was produced.
|
568
|
+
*
|
569
|
+
* This is used internally to run a conversation, but bots typically don't have
|
570
|
+
* to call this method.
|
571
|
+
*
|
572
|
+
* @param builder A conversation builder function
|
573
|
+
* @param base Context base data containing the incoming update
|
574
|
+
* @param id The identifier of the conversation
|
575
|
+
* @param data The state of execution of all parallel conversations
|
576
|
+
* @param options Additional configuration options
|
577
|
+
* @typeParam OC Custom context type of the outside middleware
|
578
|
+
* @typeParam C Custom context type used inside this conversation
|
579
|
+
*/
|
580
|
+
export declare function runParallelConversations<OC extends Context, C extends Context>(builder: ConversationBuilder<OC, C>, base: ContextBaseData, id: string, data: ConversationData, options?: ResumeOptions<OC, C>): Promise<ConversationResult>;
|
581
|
+
/**
|
582
|
+
* A result of entering a conversation builder function.
|
583
|
+
*
|
584
|
+
* This is a union of four possible outcomes of the initial execution. The union
|
585
|
+
* members are discriminated by their `status` property. The execution may have
|
586
|
+
* completed normally, thrown an error, or consumed or skipped the update.
|
587
|
+
*/
|
588
|
+
export type EnterResult = EnterComplete | EnterError | EnterHandled | EnterSkipped;
|
589
|
+
/**
|
590
|
+
* An enter result indicating that the conversation has immediately completed
|
591
|
+
* normally by returning.
|
592
|
+
*/
|
593
|
+
export type EnterComplete = ConversationComplete;
|
594
|
+
/**
|
595
|
+
* An enter result indicating that the conversation has completed by throwing an
|
596
|
+
* error.
|
597
|
+
*/
|
598
|
+
export type EnterError = ConversationError;
|
599
|
+
/**
|
600
|
+
* An enter result indicating that the conversation has handled the update. This
|
601
|
+
* happens when the conversation builder function was interrupted by calling
|
602
|
+
* `wait`.
|
603
|
+
*
|
604
|
+
* Contains the created replay state which can be used to resume the
|
605
|
+
* conversation further. Also contains a list of pending interrupts which
|
606
|
+
* identify the unresolved `wait` calls.
|
607
|
+
*/
|
608
|
+
export interface EnterHandled extends ConversationHandled {
|
609
|
+
/**
|
610
|
+
* A JSON string containing the arguments of the enter call. May be absent
|
611
|
+
* if no arguments were provided.
|
612
|
+
*/
|
613
|
+
args?: string;
|
614
|
+
}
|
615
|
+
/**
|
616
|
+
* An enter result indicating that the conversation has decided to skip handling
|
617
|
+
* this update. This happens when the conversation builder function cancels the
|
618
|
+
* execution using `skip` immediately after being entered. The conversation will
|
619
|
+
* remain active and can handle the next update.
|
620
|
+
*/
|
621
|
+
export interface EnterSkipped extends ConversationSkipped {
|
622
|
+
/**
|
623
|
+
* A JSON string containing the arguments of the enter call. May be absent
|
624
|
+
* if no arguments were provided.
|
625
|
+
*/
|
626
|
+
args?: string;
|
627
|
+
/** The created replay state after handling the update */
|
628
|
+
replay: ReplayState;
|
629
|
+
/** A list of pending interrupts to resume the conversation */
|
630
|
+
interrupts: number[];
|
631
|
+
}
|
632
|
+
/** Options to pass when manually running a conversation from scratch */
|
633
|
+
export interface EnterOptions<OC extends Context, C extends Context> extends ResumeOptions<OC, C> {
|
634
|
+
/** A list of arguments to pass to the conversation */
|
635
|
+
args?: unknown[];
|
636
|
+
}
|
637
|
+
/**
|
638
|
+
* Begins a new execution of a conversation builder function from scratch until
|
639
|
+
* a result was produced.
|
640
|
+
*
|
641
|
+
* This is used internally to enter a conversation, but bots typically don't have
|
642
|
+
* to call this method.
|
643
|
+
*
|
644
|
+
* @param conversation A conversation builder function
|
645
|
+
* @param base Context base data containing the incoming update
|
646
|
+
* @param options Additional configuration options
|
647
|
+
* @typeParam OC Custom context type of the outside middleware
|
648
|
+
* @typeParam C Custom context type used inside this conversation
|
649
|
+
*/
|
650
|
+
export declare function enterConversation<OC extends Context, C extends Context>(conversation: ConversationBuilder<OC, C>, base: ContextBaseData, options?: EnterOptions<OC, C>): Promise<EnterResult>;
|
651
|
+
/** Options to pass when manually resuming a conversation */
|
652
|
+
export interface ResumeOptions<OC extends Context, C extends Context> {
|
653
|
+
/** A context object from the outside middleware to use in `external` */
|
654
|
+
ctx?: OC;
|
655
|
+
/** An array of plugins to run for newly created context objects */
|
656
|
+
plugins?: Middleware<C>[];
|
657
|
+
/** A callback function to run if `conversation.halt` is called */
|
658
|
+
onHalt?(): void | Promise<void>;
|
659
|
+
/** A default wait timeout */
|
660
|
+
maxMillisecondsToWait?: number;
|
661
|
+
/** Whether this conversation is parallel */
|
662
|
+
parallel?: boolean;
|
663
|
+
}
|
664
|
+
/**
|
665
|
+
* Resumes an execution of a conversation builder function until a result was
|
666
|
+
* produced.
|
667
|
+
*
|
668
|
+
* This is used internally to resume a conversation, but bots typically don't
|
669
|
+
* have to call this method.
|
670
|
+
*
|
671
|
+
* @param conversation A conversation builder function
|
672
|
+
* @param base Context base data containing the incoming update
|
673
|
+
* @param state Previous state of the conversation
|
674
|
+
* @param options Additional configuration options
|
675
|
+
* @typeParam OC Custom context type of the outside middleware
|
676
|
+
* @typeParam C Custom context type used inside this conversation
|
677
|
+
*/
|
678
|
+
export declare function resumeConversation<OC extends Context, C extends Context>(conversation: ConversationBuilder<OC, C>, base: ContextBaseData, state: ConversationState, options?: ResumeOptions<OC, C>): Promise<ConversationResult>;
|