Merge pull request #602 from teloxide/restrict-commands-by-state-purchase

Restrict all purchase bot's commands by `State::Start`
This commit is contained in:
Hirrolot 2022-04-25 14:56:11 +06:00 committed by GitHub
commit ae480cae23
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 32 deletions

View file

@ -42,6 +42,8 @@ enum Command {
Help,
#[command(description = "start the purchase procedure.")]
Start,
#[command(description = "cancel the purchase procedure.")]
Cancel,
}
#[tokio::main]
@ -51,13 +53,22 @@ async fn main() {
let bot = Bot::from_env().auto_send();
let command_handler = dptree::entry()
.filter_command::<Command>()
.branch(
teloxide::handler![State::Start]
.branch(teloxide::handler![Command::Help].endpoint(help))
.branch(teloxide::handler![Command::Start].endpoint(start)),
)
.branch(teloxide::handler![Command::Cancel].endpoint(cancel));
Dispatcher::builder(
bot,
dialogue::enter::<Update, InMemStorage<State>, State, _>()
.branch(
Update::filter_message()
.branch(command_handler)
.branch(teloxide::handler![State::ReceiveFullName].endpoint(receive_full_name))
.branch(dptree::entry().filter_command::<Command>().endpoint(handle_command))
.branch(dptree::endpoint(invalid_state)),
)
.branch(
@ -74,22 +85,26 @@ async fn main() {
.await;
}
async fn handle_command(
bot: AutoSend<Bot>,
msg: Message,
cmd: Command,
dialogue: MyDialogue,
) -> HandlerResult {
match cmd {
Command::Help => {
bot.send_message(msg.chat.id, Command::descriptions().to_string()).await?;
}
Command::Start => {
bot.send_message(msg.chat.id, "Let's start! What's your full name?").await?;
dialogue.update(State::ReceiveFullName).await?;
}
}
async fn start(bot: AutoSend<Bot>, msg: Message, dialogue: MyDialogue) -> HandlerResult {
bot.send_message(msg.chat.id, "Let's start! What's your full name?").await?;
dialogue.update(State::ReceiveFullName).await?;
Ok(())
}
async fn help(bot: AutoSend<Bot>, msg: Message) -> HandlerResult {
bot.send_message(msg.chat.id, Command::descriptions().to_string()).await?;
Ok(())
}
async fn cancel(bot: AutoSend<Bot>, msg: Message, dialogue: MyDialogue) -> HandlerResult {
bot.send_message(msg.chat.id, "Cancelling the dialogue.").await?;
dialogue.exit().await?;
Ok(())
}
async fn invalid_state(bot: AutoSend<Bot>, msg: Message) -> HandlerResult {
bot.send_message(msg.chat.id, "Unable to handle the message. Type /help to see the usage.")
.await?;
Ok(())
}
@ -100,13 +115,13 @@ async fn receive_full_name(
) -> HandlerResult {
match msg.text().map(ToOwned::to_owned) {
Some(full_name) => {
let products = InlineKeyboardMarkup::default().append_row(
vec!["Apple", "Banana", "Orange", "Potato"].into_iter().map(|product| {
InlineKeyboardButton::callback(product.to_owned(), product.to_owned())
}),
);
let products = ["Apple", "Banana", "Orange", "Potato"].map(|product| {
InlineKeyboardButton::callback(product.to_owned(), product.to_owned())
});
bot.send_message(msg.chat.id, "Select a product:").reply_markup(products).await?;
bot.send_message(msg.chat.id, "Select a product:")
.reply_markup(InlineKeyboardMarkup::new([products]))
.await?;
dialogue.update(State::ReceiveProductChoice { full_name }).await?;
}
None => {
@ -134,9 +149,3 @@ async fn receive_product_selection(
Ok(())
}
async fn invalid_state(bot: AutoSend<Bot>, msg: Message) -> HandlerResult {
bot.send_message(msg.chat.id, "Unable to handle the message. Type /help to see the usage.")
.await?;
Ok(())
}

View file

@ -214,11 +214,13 @@ where
}))
}
/// Perform a dialogue FSM transition.
/// Filters an enumeration, passing its payload forwards.
///
/// This macro expands to a [`dptree::Handler`] that filters your dialogue
/// state: if the state enumeration is of a certain variant, the execution
/// continues; otherwise, `dptree` will try the next branch.
/// This macro expands to a [`dptree::Handler`] that acts on your enumeration
/// type: if the enumeration is of a certain variant, the execution continues;
/// otherwise, `dptree` will try the next branch. This is very useful for
/// dialogue FSM transitions and Telegram command filtering; for a complete
/// example, please see [`examples/purchase.rs`].
///
/// Variants can take the following forms:
///
@ -243,6 +245,8 @@ where
/// ## Dependency requirements
///
/// - Your dialogue state enumeration `State`.
///
/// [`examples/purchase.rs`]: https://github.com/teloxide/teloxide/blob/master/examples/purchase.rs
#[macro_export]
macro_rules! handler {
($($variant:ident)::+) => {