teloxide/examples/simple_fsm/src/main.rs

145 lines
3.9 KiB
Rust
Raw Normal View History

2020-01-29 23:54:40 +01:00
#[macro_use]
extern crate strum_macros;
use std::fmt::{self, Display, Formatter};
use teloxide::{
prelude::*,
types::{KeyboardButton, ReplyKeyboardMarkup},
};
// ============================================================================
// [Favourite music kinds]
// ============================================================================
#[derive(Copy, Clone, Display, EnumString)]
enum FavouriteMusic {
Rock,
Metal,
Pop,
Other,
}
impl FavouriteMusic {
fn markup() -> ReplyKeyboardMarkup {
2020-02-02 19:54:11 +01:00
ReplyKeyboardMarkup::default().append_row(vec![
KeyboardButton::new("Rock"),
KeyboardButton::new("Metal"),
KeyboardButton::new("Pop"),
KeyboardButton::new("Other"),
])
2020-01-29 23:54:40 +01:00
}
}
// ============================================================================
// [A user's data]
// ============================================================================
#[derive(Default)]
struct User {
full_name: Option<String>,
age: Option<u8>,
favourite_music: Option<FavouriteMusic>,
}
impl Display for User {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
write!(
f,
"Your full name: {}, your age: {}, your favourite music: {}",
self.full_name.as_ref().unwrap(),
self.age.unwrap(),
self.favourite_music.unwrap()
)
}
}
// ============================================================================
// [Control our FSM]
// ============================================================================
2020-02-02 19:54:11 +01:00
type Ctx = SessionHandlerCtx<Message, User>;
type Res = Result<SessionState<User>, RequestError>;
2020-01-29 23:54:40 +01:00
async fn send_favourite_music_types(ctx: &Ctx) -> Result<(), RequestError> {
ctx.bot
.send_message(ctx.chat_id(), "Good. Now choose your favourite music:")
.reply_markup(FavouriteMusic::markup())
.send()
.await?;
Ok(())
}
async fn start(ctx: Ctx) -> Res {
2020-02-02 19:54:11 +01:00
ctx.reply("Let's start! First, what's your full name?")
.await?;
2020-02-02 17:32:27 +01:00
Ok(SessionState::Next(ctx.session))
2020-01-29 23:54:40 +01:00
}
async fn full_name(mut ctx: Ctx) -> Res {
2020-02-02 19:54:11 +01:00
ctx.reply("What a wonderful name! Your age?").await?;
2020-01-29 23:54:40 +01:00
ctx.session.full_name = Some(ctx.update.text().unwrap().to_owned());
2020-02-02 17:32:27 +01:00
Ok(SessionState::Next(ctx.session))
2020-01-29 23:54:40 +01:00
}
async fn age(mut ctx: Ctx) -> Res {
match ctx.update.text().unwrap().parse() {
Ok(ok) => {
send_favourite_music_types(&ctx).await?;
ctx.session.age = Some(ok);
}
2020-02-02 19:54:11 +01:00
Err(_) => ctx.reply("Oh, please, enter a number!").await?,
2020-01-29 23:54:40 +01:00
}
2020-02-02 17:32:27 +01:00
Ok(SessionState::Next(ctx.session))
2020-01-29 23:54:40 +01:00
}
async fn favourite_music(mut ctx: Ctx) -> Res {
match ctx.update.text().unwrap().parse() {
Ok(ok) => {
ctx.session.favourite_music = Some(ok);
2020-02-02 19:54:11 +01:00
ctx.reply(format!("Fine. {}", ctx.session)).await?;
2020-02-02 17:32:27 +01:00
Ok(SessionState::Exit)
2020-01-29 23:54:40 +01:00
}
Err(_) => {
2020-02-02 19:54:11 +01:00
ctx.reply("Oh, please, enter from the keyboard!").await?;
2020-02-02 17:32:27 +01:00
Ok(SessionState::Next(ctx.session))
2020-01-29 23:54:40 +01:00
}
}
}
async fn handle_message(ctx: Ctx) -> Res {
if ctx.session.full_name.is_none() {
return full_name(ctx).await;
}
if ctx.session.age.is_none() {
return age(ctx).await;
}
if ctx.session.favourite_music.is_none() {
return favourite_music(ctx).await;
}
2020-02-02 17:32:27 +01:00
Ok(SessionState::Exit)
2020-01-29 23:54:40 +01:00
}
// ============================================================================
// [Run!]
// ============================================================================
#[tokio::main]
async fn main() {
std::env::set_var("RUST_LOG", "simple_fsm=trace");
pretty_env_logger::init();
log::info!("Starting the simple_fsm bot!");
Dispatcher::new(Bot::new("YourAwesomeToken"))
.message_handler(SessionDispatcher::new(|ctx| async move {
2020-02-01 05:05:18 +01:00
handle_message(ctx)
.await
.expect("Something wrong with the bot!")
2020-01-29 23:54:40 +01:00
}))
.dispatch()
.await;
}