2020-01-29 23:54:40 +01:00
|
|
|
#[macro_use]
|
|
|
|
extern crate strum_macros;
|
2020-02-10 21:54:08 +01:00
|
|
|
#[macro_use]
|
|
|
|
extern crate smart_default;
|
2020-01-29 23:54:40 +01:00
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ============================================================================
|
2020-02-10 22:51:50 +01:00
|
|
|
// [A UserInfo's data]
|
2020-01-29 23:54:40 +01:00
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
#[derive(Default)]
|
2020-02-10 22:51:50 +01:00
|
|
|
struct UserInfo {
|
2020-01-29 23:54:40 +01:00
|
|
|
full_name: Option<String>,
|
|
|
|
age: Option<u8>,
|
|
|
|
favourite_music: Option<FavouriteMusic>,
|
|
|
|
}
|
|
|
|
|
2020-02-10 22:51:50 +01:00
|
|
|
impl Display for UserInfo {
|
2020-01-29 23:54:40 +01:00
|
|
|
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
|
|
|
// ============================================================================
|
2020-02-04 16:38:25 +01:00
|
|
|
// [States of a dialogue]
|
2020-02-03 15:53:12 +01:00
|
|
|
// ============================================================================
|
|
|
|
|
2020-02-10 21:54:08 +01:00
|
|
|
#[derive(SmartDefault)]
|
2020-02-04 16:38:25 +01:00
|
|
|
enum State {
|
2020-02-10 21:54:08 +01:00
|
|
|
#[default]
|
2020-02-03 15:53:12 +01:00
|
|
|
Start,
|
|
|
|
FullName,
|
|
|
|
Age,
|
|
|
|
FavouriteMusic,
|
|
|
|
}
|
|
|
|
|
|
|
|
// ============================================================================
|
2020-02-04 16:38:25 +01:00
|
|
|
// [Control a dialogue]
|
2020-02-03 15:53:12 +01:00
|
|
|
// ============================================================================
|
|
|
|
|
2020-02-10 22:51:50 +01:00
|
|
|
type Ctx = DialogueHandlerCtx<Message, State, UserInfo>;
|
|
|
|
type Res = Result<DialogueStage<State, UserInfo>, 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> {
|
2020-02-10 22:13:09 +01:00
|
|
|
ctx.answer("Good. Now choose your favourite music:")
|
2020-01-29 23:54:40 +01:00
|
|
|
.reply_markup(FavouriteMusic::markup())
|
|
|
|
.send()
|
|
|
|
.await?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-02-04 16:38:25 +01:00
|
|
|
async fn start(mut ctx: Ctx) -> Res {
|
2020-02-10 22:13:09 +01:00
|
|
|
ctx.answer("Let's start! First, what's your full name?")
|
|
|
|
.send()
|
2020-02-02 19:54:11 +01:00
|
|
|
.await?;
|
2020-02-10 23:04:57 +01:00
|
|
|
state!(ctx, State::FullName);
|
2020-02-10 21:54:08 +01:00
|
|
|
next(ctx.dialogue)
|
2020-01-29 23:54:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
async fn full_name(mut ctx: Ctx) -> Res {
|
2020-02-10 22:13:09 +01:00
|
|
|
ctx.answer("What a wonderful name! Your age?")
|
|
|
|
.send()
|
|
|
|
.await?;
|
2020-02-04 16:38:25 +01:00
|
|
|
ctx.dialogue.data.full_name = Some(ctx.update.text().unwrap().to_owned());
|
2020-02-10 23:04:57 +01:00
|
|
|
state!(ctx, State::Age);
|
2020-02-10 21:54:08 +01:00
|
|
|
next(ctx.dialogue)
|
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-04 16:38:25 +01:00
|
|
|
ctx.dialogue.data.age = Some(ok);
|
2020-02-10 23:04:57 +01:00
|
|
|
state!(ctx, State::FavouriteMusic);
|
2020-01-29 23:54:40 +01:00
|
|
|
}
|
2020-02-10 22:13:09 +01:00
|
|
|
Err(_) => ctx
|
|
|
|
.answer("Oh, please, enter a number!")
|
|
|
|
.send()
|
|
|
|
.await
|
|
|
|
.map(|_| ())?,
|
2020-01-29 23:54:40 +01:00
|
|
|
}
|
|
|
|
|
2020-02-10 21:54:08 +01:00
|
|
|
next(ctx.dialogue)
|
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-04 16:38:25 +01:00
|
|
|
ctx.dialogue.data.favourite_music = Some(ok);
|
2020-02-10 22:13:09 +01:00
|
|
|
ctx.answer(format!("Fine. {}", ctx.dialogue.data))
|
|
|
|
.send()
|
|
|
|
.await?;
|
2020-02-10 21:54:08 +01:00
|
|
|
exit()
|
2020-01-29 23:54:40 +01:00
|
|
|
}
|
|
|
|
Err(_) => {
|
2020-02-10 22:13:09 +01:00
|
|
|
ctx.answer("Oh, please, enter from the keyboard!")
|
|
|
|
.send()
|
|
|
|
.await?;
|
2020-02-10 21:54:08 +01:00
|
|
|
next(ctx.dialogue)
|
2020-01-29 23:54:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn handle_message(ctx: Ctx) -> Res {
|
2020-02-04 16:38:25 +01:00
|
|
|
match ctx.dialogue.state {
|
|
|
|
State::Start => start(ctx).await,
|
|
|
|
State::FullName => full_name(ctx).await,
|
|
|
|
State::Age => age(ctx).await,
|
|
|
|
State::FavouriteMusic => favourite_music(ctx).await,
|
2020-01-29 23:54:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
// [Run!]
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
#[tokio::main]
|
|
|
|
async fn main() {
|
2020-02-04 16:38:25 +01:00
|
|
|
std::env::set_var("RUST_LOG", "simple_dialogue=trace");
|
2020-01-29 23:54:40 +01:00
|
|
|
pretty_env_logger::init();
|
2020-02-04 16:38:25 +01:00
|
|
|
log::info!("Starting the simple_dialogue bot!");
|
2020-01-29 23:54:40 +01:00
|
|
|
|
|
|
|
Dispatcher::new(Bot::new("YourAwesomeToken"))
|
2020-02-10 21:54:08 +01:00
|
|
|
.message_handler(&DialogueDispatcher::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;
|
|
|
|
}
|