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()
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-03 15:53:12 +01:00
|
|
|
// ============================================================================
|
|
|
|
// [FSM - Finite-State Machine]
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
enum Fsm {
|
|
|
|
Start,
|
|
|
|
FullName,
|
|
|
|
Age,
|
|
|
|
FavouriteMusic,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for Fsm {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::Start
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
// [Our Session type]
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
struct Session {
|
|
|
|
user: User,
|
|
|
|
fsm: Fsm,
|
|
|
|
}
|
|
|
|
|
2020-01-29 23:54:40 +01:00
|
|
|
// ============================================================================
|
|
|
|
// [Control our FSM]
|
|
|
|
// ============================================================================
|
|
|
|
|
2020-02-03 15:53:12 +01:00
|
|
|
type Ctx = SessionHandlerCtx<Message, Session>;
|
|
|
|
type Res = Result<SessionState<Session>, RequestError>;
|
2020-02-02 19:54:11 +01:00
|
|
|
|
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-03 15:53:12 +01:00
|
|
|
ctx.session.state = Fsm::FullName;
|
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-02-03 15:53:12 +01:00
|
|
|
ctx.session.user.full_name = Some(ctx.update.text().unwrap().to_owned());
|
|
|
|
ctx.session.fsm = Fsm::Age;
|
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?;
|
2020-02-03 15:53:12 +01:00
|
|
|
ctx.session.user.age = Some(ok);
|
|
|
|
ctx.session.fsm = Fsm::FavouriteMusic;
|
2020-01-29 23:54:40 +01:00
|
|
|
}
|
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) => {
|
2020-02-03 15:53:12 +01:00
|
|
|
ctx.session.user.favourite_music = Some(ok);
|
|
|
|
ctx.reply(format!("Fine. {}", ctx.session.user)).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 {
|
2020-02-03 15:53:12 +01:00
|
|
|
match ctx.session.fsm {
|
|
|
|
Fsm::Start => start(ctx).await,
|
|
|
|
Fsm::FullName => full_name(ctx).await,
|
|
|
|
Fsm::Age => age(ctx).await,
|
|
|
|
Fsm::FavouriteMusic => favourite_music(ctx).await,
|
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;
|
|
|
|
}
|