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;
|
|
|
|
}
|