Add dialogue::{next, exit}

This commit is contained in:
Temirkhan Myrzamadi 2020-02-11 02:54:08 +06:00
parent 809aaef9b1
commit bde4d09e5d
8 changed files with 40 additions and 26 deletions

View file

@ -11,6 +11,7 @@ pretty_env_logger = "0.3.1"
log = "0.4.8"
tokio = "0.2.9"
strum = "0.17.1"
smart-default = "0.6.0"
strum_macros = "0.17.1"
teloxide = { path = "../../" }

View file

@ -1,5 +1,7 @@
#[macro_use]
extern crate strum_macros;
#[macro_use]
extern crate smart_default;
use std::fmt::{self, Display, Formatter};
use teloxide::{
@ -57,19 +59,15 @@ impl Display for User {
// [States of a dialogue]
// ============================================================================
#[derive(SmartDefault)]
enum State {
#[default]
Start,
FullName,
Age,
FavouriteMusic,
}
impl Default for State {
fn default() -> Self {
Self::Start
}
}
// ============================================================================
// [Control a dialogue]
// ============================================================================
@ -90,14 +88,14 @@ async fn start(mut ctx: Ctx) -> Res {
ctx.reply("Let's start! First, what's your full name?")
.await?;
ctx.dialogue.state = State::FullName;
Ok(DialogueStage::Next(ctx.dialogue))
next(ctx.dialogue)
}
async fn full_name(mut ctx: Ctx) -> Res {
ctx.reply("What a wonderful name! Your age?").await?;
ctx.dialogue.data.full_name = Some(ctx.update.text().unwrap().to_owned());
ctx.dialogue.state = State::Age;
Ok(DialogueStage::Next(ctx.dialogue))
next(ctx.dialogue)
}
async fn age(mut ctx: Ctx) -> Res {
@ -110,7 +108,7 @@ async fn age(mut ctx: Ctx) -> Res {
Err(_) => ctx.reply("Oh, please, enter a number!").await?,
}
Ok(DialogueStage::Next(ctx.dialogue))
next(ctx.dialogue)
}
async fn favourite_music(mut ctx: Ctx) -> Res {
@ -118,11 +116,11 @@ async fn favourite_music(mut ctx: Ctx) -> Res {
Ok(ok) => {
ctx.dialogue.data.favourite_music = Some(ok);
ctx.reply(format!("Fine. {}", ctx.dialogue.data)).await?;
Ok(DialogueStage::Exit)
exit()
}
Err(_) => {
ctx.reply("Oh, please, enter from the keyboard!").await?;
Ok(DialogueStage::Next(ctx.dialogue))
next(ctx.dialogue)
}
}
}
@ -147,7 +145,7 @@ async fn main() {
log::info!("Starting the simple_dialogue bot!");
Dispatcher::new(Bot::new("YourAwesomeToken"))
.message_handler(DialogueDispatcher::new(|ctx| async move {
.message_handler(&DialogueDispatcher::new(|ctx| async move {
handle_message(ctx)
.await
.expect("Something wrong with the bot!")

View file

@ -0,0 +1,20 @@
use crate::dispatching::dialogue::Dialogue;
/// Continue or terminate a dialogue.
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
pub enum DialogueStage<State, T> {
Next(Dialogue<State, T>),
Exit,
}
/// A shortcut for `Ok(DialogueStage::Next(dialogue))`.
pub fn next<E, State, T>(
dialogue: Dialogue<State, T>,
) -> Result<DialogueStage<State, T>, E> {
Ok(DialogueStage::Next(dialogue))
}
/// A shortcut for `Ok(DialogueStage::Exit)`.
pub fn exit<E, State, T>() -> Result<DialogueStage<State, T>, E> {
Ok(DialogueStage::Exit)
}

View file

@ -1,8 +0,0 @@
use crate::dispatching::dialogue::Dialogue;
/// Continue or terminate a dialogue.
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
pub enum DialogueStage<State, T> {
Next(Dialogue<State, T>),
Exit,
}

View file

@ -37,13 +37,13 @@
mod dialogue;
mod dialogue_dispatcher;
mod dialogue_handler_ctx;
mod dialogue_state;
mod dialogue_stage;
mod get_chat_id;
mod storage;
pub use dialogue::Dialogue;
pub use dialogue_dispatcher::DialogueDispatcher;
pub use dialogue_handler_ctx::DialogueHandlerCtx;
pub use dialogue_state::DialogueStage;
pub use dialogue_stage::{exit, next, DialogueStage};
pub use get_chat_id::GetChatId;
pub use storage::{InMemStorage, Storage};

View file

@ -8,7 +8,7 @@ use crate::{
CallbackQuery, ChosenInlineResult, InlineQuery, Message, Poll,
PollAnswer, PreCheckoutQuery, ShippingQuery, Update, UpdateKind,
},
Bot,
Bot, RequestError,
};
use futures::{stream, StreamExt};
use std::{fmt::Debug, future::Future, sync::Arc};
@ -26,7 +26,9 @@ type Handlers<'a, Upd, HandlerE> = Vec<
///
/// See [the module-level documentation for the design
/// overview](crate::dispatching).
pub struct Dispatcher<'a, HandlerE> {
// HandlerE=RequestError doesn't work now, because of very poor type inference.
// See https://github.com/rust-lang/rust/issues/27336 for more details.
pub struct Dispatcher<'a, HandlerE = RequestError> {
bot: Arc<Bot>,
handlers_error_handler: Box<dyn ErrorHandler<HandlerE> + 'a>,

View file

@ -25,7 +25,7 @@
//!
//! // Setup logging here...
//!
//! Dispatcher::new(Bot::new("MyAwesomeToken"))
//! Dispatcher::<RequestError>::new(Bot::new("MyAwesomeToken"))
//! .message_handler(&|ctx: DispatcherHandlerCtx<Message>| async move {
//! ctx.answer("pong").send().await?;
//! Ok(())

View file

@ -3,7 +3,8 @@
pub use crate::{
dispatching::{
dialogue::{
DialogueDispatcher, DialogueHandlerCtx, DialogueStage, GetChatId,
exit, next, DialogueDispatcher, DialogueHandlerCtx, DialogueStage,
GetChatId,
},
Dispatcher, DispatcherHandlerCtx,
},