ConversationHandle
Internally used class which acts as a conversation handle.
Type Parameters
C
C extends Context
Constructors
ConversationHandle(
ctx: C,
data: ActiveConversation,
rsr: Resolver<ResolveOps>,
timeout: number | undefined,
);
Properties
form
form: ConversationForm;
Utilities for building forms. Contains methods that let you wait for messages and automatically perform input validation.
Methods
_deactivate
_deactivate(): void;
Internal method, deactivates the conversation handle. Do not use unless you know exactly what you are doing.
_isReplaying (getter)
get _isReplaying();
Internal flag, true
if the conversation is currently replaying in order to jump back to an old state, and false
otherwise. Do not use unless you know exactly what you are doing.
_replayWait
Internal method, replays a wait operation and advances the replay cursor. Do not use unless you know exactly what you are doing.
_replayApi
_replayApi(method: string): Promise<NonNullable<ApiOp["r"]>>;
Internal method, replays an API call operation and advances the replay cursor. Do not use unless you know exactly what you are doing.
_replayExt
_replayExt(): Promise<NonNullable<ExtOp["r"]>>;
Internal method, replays an external operation and advances the replay cursor. Do not use unless you know exactly what you are doing.
_logWait
_logWait(op: WaitOp): void;
Internal method, logs a wait call. Do not use unless you know exactly what you are doing.
_unlogWait
_unlogWait();
Internal method, unlogs the most recent call. Do not use unless you know exactly what you are doing.
_logApi
_logApi(method: string): ApiOp;
Internal method, logs an API call and returns the assigned slot. Do not use unless you know exactly what you are doing.
_logExt
_logExt(): ExtOp;
Internal method, logs an external operation and returns the assigned slot. Do not use unless you know exactly what you are doing.
_finalize
_finalize(slot: AsyncOrder): void;
Internal method, finalizes a previously generated slot. Do not use unless you know exactly what you are doing.
_resolveAt
_resolveAt<T>(index: number, value?: T): Promise<T>;
Internal method, creates a promise from a given value that will resolve at the given index in order to accurately restore the order in which different operations complete. Do not use unless you know exactly what you are doing.
wait
Waits for a new update (e.g. a message, callback query, etc) from the user. Once received, this method returns the new context object for the incoming update.
waitUntil
// Overload 1
waitUntil<D extends C>(predicate: (ctx: C) => ctx is D, opts?: OtherwiseConfig<C>): Promise<D>;
// Overload 2
waitUntil(predicate: (ctx: C) => boolean | Promise<boolean>, opts?: OtherwiseConfig<C>): Promise<C>;
Waits for a new update (e.g. a message, callback query, etc) that fulfils a certain condition. This condition is specified via the given predicate function. As soon as an update arrives for which the predicate function returns true
, this method will return it.
waitUnless
waitUnless(predicate: (ctx: C) => boolean | Promise<boolean>, opts?: OtherwiseConfig<C>): Promise<C>;
Waits for a new update (e.g. a message, callback query, etc) that does not fulfil a certain condition. This condition is specified via the given predicate function. As soon as an update arrives for which the predicate function returns false
, this method will return it.
waitFor
waitFor<Q extends FilterQuery>(query: Q | Q[], opts?: OtherwiseConfig<C>): Promise<Filter<C, Q>>;
Waits for a new update (e.g. a message, callback query, etc) that matches the given filter query. As soon as an update arrives that matches the filter query, the corresponding context object is returned.
waitForHears
waitForHears(trigger: MaybeArray<string | RegExp>, opts?: OtherwiseConfig<C>): Promise<HearsContext<C>>;
Waits for a new message or channel post that contains the given text, or that contains text which matches the given regular expression. This uses the same logic as bot
.
waitForCommand
waitForCommand<S extends string>(command: MaybeArray<StringWithSuggestions<S | "start" | "help" | "settings">>, opts?: OtherwiseConfig<C>): Promise<CommandContext<C>>;
Waits for the specified command. This uses the same logic as bot
.
waitForReaction
waitForReaction(reaction: MaybeArray<ReactionTypeEmoji["emoji"] | ReactionType>, opts?: OtherwiseConfig<C>): Promise<ReactionContext<C>>;
Waits for the specified reaction. This uses the same logic as bot
.
waitForCallbackQuery
waitForCallbackQuery(trigger: MaybeArray<string | RegExp>, opts?: OtherwiseConfig<C>): Promise<CallbackQueryContext<C>>;
Waits for an update which contains the given callback query, or for the callback query data to match the given regular expression. This uses the same logic as bot
.
waitForGameQuery
waitForGameQuery(trigger: MaybeArray<string | RegExp>, opts?: OtherwiseConfig<C>): Promise<GameQueryContext<C>>;
Waits for an update which contains the given game query, or for the game query data to match the given regular expression. This uses the same logic as bot
.
waitFrom
Waits for a new update (e.g. a message, callback query, etc) from the given user. As soon as an update arrives from this user, the corresponding context object is returned.
waitForReplyTo
waitForReplyTo(message_id: number | { message_id: number }, opts?: OtherwiseConfig<C>): Promise<Filter<C, "message" | "channel_post">>;
Waits for a new message or channel post which replies to the specified message. As soon as an update arrives that contains such a message or channel post, the corresponding context object is returned.
skip
skip(opts: { drop?: boolean });
Skips handling the update that was received in the last wait
call. Once called, the conversation resets to the last wait
call, as if the update had never been received. Unless { drop:
is passed, the control flow is passed on immediately, so that middleware downstream of the conversation can continue handling the update.
Effectively, calling await conversation
behaves as if this conversation had not received the update at all.
While the conversation rewinds its logs internally, it does not unsend messages that you send between the calls to wait
and skip
.
external
external<F extends (...args: any[]) => any, I = any>(op: F | {
task: F; args?: Parameters<F>; beforeStore?: (value: Awaited<ReturnType<F>>) => I | Promise<I>; afterLoad?: (value: I) => ReturnType<F> | Promise<ReturnType<F>>; beforeStoreError?: (value: unknown) => unknown | Promise<unknown>; afterLoadError?: (value: unknown) => unknown
}): Promise<Awaited<ReturnType<F>>>;
Safely performs an operation with side-effects. You must use this to wrap all communication with external systems that does not go through grammY, such as database communication or calls to external APIs.
This function will then make sure the operation is only performed once, and not every time a message is handled by the conversation.
It will need to be able to store the result value of this operation in the session. Hence, it must store and load the result of the operation according to your storage adapter. It is therefore best to only return primitive values or POJOs. If you need to transform your data before it can be stored, you can specify the before
function. If you need to transform your data after it was loaded, you can specify the after
function.
session (getter)
Safe alias for ctx
. Use this instead of ctx
when inside a conversation.
As you call conversation
several times throughout the conversation, your session data may evolve. The conversations plugin makes sure to track these changes so that your conversation can work correctly each time it is run. This means that there are several snapshots of the session throughout time which all co-exist. It can be cumbersome to always make sure to use the correct session so that the code does not alter history (this would lead to data loss). You should use this helper type to make sure you are accessing the correct session object at all times.
sleep
sleep(milliseconds: number): Promise<void>;
This method is rarely useful because it freezes your bot and that’s most likely not actually what you want to do. Consider using one of the variants of
wait
instead.
Freezes your bot for the specified number of milliseconds. The current middleware execution will simply stop for a while. Note that if you’re processing updates concurrently (with grammY runner) then unrelated updates will still be handled in the meantime. Note further that sleeping during webhooks is dangerous because it can lead to duplicate updates.
You should use this instead of your own sleeping function so that you don’t block the conversation while it is restoring a previous position.
random
random();
Safely generates a random number from Math
. You should use this instead of Math
in your conversation because non-deterministic behavior is not allowed.
log
log(...args: Parameters<typeof console.log>): void;
Safely perform console
calls, but only when they should really be logged (so not during replay operations).
error
error(...args: Parameters<typeof console.error>): void;
Safely perform console
calls, but only when they should really be logged (so not during replay operations).
now
now();
Safely gets the value of Date
. You should use this instead of Date
in your conversation because the time value changes continuously, which may lead to unpredictable and non-deterministic behavior.
run
run(...middleware: Middleware<C>[]): Promise<void>;
Runs a piece of middleware for each already received context object every time a context object is received. This can be used to install plugins inside conversations.
For instance, if three context objects arrive, this is what happens:
- the first update is received
- the middleware runs for the first update
- the second update is received
- the middleware runs for the first update
- the middleware runs for the second update
- the third update is received
- the middleware runs for the first update
- the middleware runs for the second update
- the middleware runs for the third update
Note that the middleware is run with first update thrice.