dialogue/
dialogue.rs

1// This is a bot that asks you three questions, e.g. a simple test.
2//
3// # Example
4// ```
5//  - Hey
6//  - Let's start! What's your full name?
7//  - Gandalf the Grey
8//  - How old are you?
9//  - 223
10//  - What's your location?
11//  - Middle-earth
12//  - Full name: Gandalf the Grey
13//    Age: 223
14//    Location: Middle-earth
15// ```
16use teloxide::{dispatching::dialogue::InMemStorage, prelude::*};
17
18type MyDialogue = Dialogue<State, InMemStorage<State>>;
19type HandlerResult = Result<(), Box<dyn std::error::Error + Send + Sync>>;
20
21#[derive(Clone, Default)]
22pub enum State {
23    #[default]
24    Start,
25    ReceiveFullName,
26    ReceiveAge {
27        full_name: String,
28    },
29    ReceiveLocation {
30        full_name: String,
31        age: u8,
32    },
33}
34
35#[tokio::main]
36async fn main() {
37    pretty_env_logger::init();
38    log::info!("Starting dialogue bot...");
39
40    let bot = Bot::from_env();
41
42    Dispatcher::builder(
43        bot,
44        Update::filter_message()
45            .enter_dialogue::<Message, InMemStorage<State>, State>()
46            .branch(dptree::case![State::Start].endpoint(start))
47            .branch(dptree::case![State::ReceiveFullName].endpoint(receive_full_name))
48            .branch(dptree::case![State::ReceiveAge { full_name }].endpoint(receive_age))
49            .branch(
50                dptree::case![State::ReceiveLocation { full_name, age }].endpoint(receive_location),
51            ),
52    )
53    .dependencies(dptree::deps![InMemStorage::<State>::new()])
54    .enable_ctrlc_handler()
55    .build()
56    .dispatch()
57    .await;
58}
59
60async fn start(bot: Bot, dialogue: MyDialogue, msg: Message) -> HandlerResult {
61    bot.send_message(msg.chat.id, "Let's start! What's your full name?").await?;
62    dialogue.update(State::ReceiveFullName).await?;
63    Ok(())
64}
65
66async fn receive_full_name(bot: Bot, dialogue: MyDialogue, msg: Message) -> HandlerResult {
67    match msg.text() {
68        Some(text) => {
69            bot.send_message(msg.chat.id, "How old are you?").await?;
70            dialogue.update(State::ReceiveAge { full_name: text.into() }).await?;
71        }
72        None => {
73            bot.send_message(msg.chat.id, "Send me plain text.").await?;
74        }
75    }
76
77    Ok(())
78}
79
80async fn receive_age(
81    bot: Bot,
82    dialogue: MyDialogue,
83    full_name: String, // Available from `State::ReceiveAge`.
84    msg: Message,
85) -> HandlerResult {
86    match msg.text().map(|text| text.parse::<u8>()) {
87        Some(Ok(age)) => {
88            bot.send_message(msg.chat.id, "What's your location?").await?;
89            dialogue.update(State::ReceiveLocation { full_name, age }).await?;
90        }
91        _ => {
92            bot.send_message(msg.chat.id, "Send me a number.").await?;
93        }
94    }
95
96    Ok(())
97}
98
99async fn receive_location(
100    bot: Bot,
101    dialogue: MyDialogue,
102    (full_name, age): (String, u8), // Available from `State::ReceiveLocation`.
103    msg: Message,
104) -> HandlerResult {
105    match msg.text() {
106        Some(location) => {
107            let report = format!("Full name: {full_name}\nAge: {age}\nLocation: {location}");
108            bot.send_message(msg.chat.id, report).await?;
109            dialogue.exit().await?;
110        }
111        None => {
112            bot.send_message(msg.chat.id, "Send me plain text.").await?;
113        }
114    }
115
116    Ok(())
117}