Prompt Plugin
A plugin that provides Prompt and Wait methods
NOTE
We recommend considering scenes
instead. Please see the comparison of prompt
and scenes
Installation
npm install @gramio/prompt
yarn add @gramio/prompt
pnpm add @gramio/prompt
bun install @gramio/prompt
Usage
import { Bot, format, bold } from "gramio";
import { prompt } from "@gramio/prompt";
const bot = new Bot(process.env.BOT_TOKEN as string)
.extend(prompt())
.command("start", async (context) => {
const answer = await context.prompt(
"message",
format`What's your ${bold`name`}?`
);
return context.send(`✨ Your name is ${answer.text}`);
})
.onStart(console.log);
bot.start();
Prompt
Prompt with text + params
const answer = await context.prompt("What's your name?");
// or with SendMessageParams
const answer = await context.prompt("True or false?", {
reply_markup: new Keyboard().text("true").row().text("false"),
});
answer is MessageContext
or CallbackQueryContext
Prompt with text + params and the specified event
const answer = await context.prompt("message", "What's your name?");
const answer = await context.prompt("callback_query", "True or false?", {
reply_markup: new InlineKeyboard()
.text("true", "true")
.row()
.text("false", "false"),
});
answer is CallbackQueryContext
Validation
You can define a handler in params to validate the user's answer. If handler returns false, the message will be repeated.
const answer = await context.prompt(
"message",
"Enter a string that contains russian letter",
{
validate: (context) => /[а-яА-Я]/.test(context.text),
//... and some SendMessageParams
}
);
Transform
const name = await context.prompt(
"message",
format`What's your ${bold`name`}?`,
{
transform: (context) => context.text || context.caption || "",
}
);
name is string
Wait
Wait for the next event from the user
const answer = await context.wait();
answer is MessageContext
or CallbackQueryContext
Wait for the next event from the user ignoring events not listed
const answer = await context.wait("message");
answer is CallbackQueryContext
Wait for the next event from the user ignoring non validated answers
You can define a handler in params to validate the user's answer. If handler return false
, the message will be ignored
const answer = await context.wait((context) => /[а-яА-Я]/.test(context.text));
// or combine with event
const answer = await context.wait("message", (context) =>
/[а-яА-Я]/.test(context.text)
);
Wait for the next event from the user ignoring non validated answers with transformer
You can define a handler in params to transform the user's answer.
const answer = await context.wait((context) => /[а-яА-Я]/.test(context.text));
// or combine with event
const answer = await context.wait("message", {
validate: (context) => /[а-яА-Я]/.test(context.text),
transform: (context) => c.text || "",
});
answer is string
waitWithAction
This function is similar to wait
but allows executing an action while waiting for an event and get both results.
const [answer, sentMessage] = await context.waitWithAction(
"message",
() => context.send("Please enter your name"),
{
validate: (ctx) => !!ctx.text,
transform: (ctx) => ctx.text.toUpperCase(),
onValidateError: "Please enter a valid name!",
}
);
// answer has type `string`
// sentMessage has type `MessageContext`
Timeout
Allows setting a response timeout. After timeout expiration, a PromptCancelError
(timeout) error will be thrown (based on timeoutStrategy
). The timeout
(in milliseconds) can be passed in any method's options.
new Bot()
.extend(
prompt({
timeoutStrategy: "on-timer", // or "on-answer" (default)
})
)
.onError("message", ({ error, kind, context }) => {
if (kind === "prompt-cancel") {
// Currently only contains timeout type of error, but this will change
return context.send("Response time expired :(");
}
console.error(error);
return context.send("An error occurred");
})
.command("start", async (context) => {
const [answer, sentMessage] = await context.waitWithAction(
"message",
() => context.send("Please enter your name"),
{
timeout: 10_000, // 10 seconds
}
);
return Promise.all([
sentMessage.delete(),
context.send(`Thank you, ${answer.text}!`),
]);
});
Configuration
import { prompt, type PromptsType } from "@gramio/prompt";
const mySharedMap: PromptsType = new Map();
new Bot().extend(
prompt({
timeoutStrategy: "on-timer",
defaults: {
timeout: 30_000, // 30 seconds
validate: (ctx) => ctx.hasText(),
transform: (ctx) => ctx.text.toUpperCase(),
onValidateError: "Validation failed. Please try again.",
},
map: mySharedMap,
})
);
timeoutStrategy
Controls how Timeout
error is triggered:
"on-answer"
(default) -Timeout
error occurs if user sends message AFTER timeout expiration"on-timer"
-Timeout
error occurs immediately when timer expires viasetTimeout
defaults
Allows setting default values for methods.
map
Enables providing a custom Map for state storage. This allows modifying it from anywhere.