diff --git a/examples/simple_dialogue/Cargo.toml b/examples/simple_dialogue/Cargo.toml index 42d2efd7..d9c28590 100644 --- a/examples/simple_dialogue/Cargo.toml +++ b/examples/simple_dialogue/Cargo.toml @@ -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 = "../../" } diff --git a/examples/simple_dialogue/src/main.rs b/examples/simple_dialogue/src/main.rs index a99dfac0..12b6e6d7 100644 --- a/examples/simple_dialogue/src/main.rs +++ b/examples/simple_dialogue/src/main.rs @@ -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!") diff --git a/src/dispatching/dialogue/dialogue_stage.rs b/src/dispatching/dialogue/dialogue_stage.rs new file mode 100644 index 00000000..43ea25cd --- /dev/null +++ b/src/dispatching/dialogue/dialogue_stage.rs @@ -0,0 +1,20 @@ +use crate::dispatching::dialogue::Dialogue; + +/// Continue or terminate a dialogue. +#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)] +pub enum DialogueStage { + Next(Dialogue), + Exit, +} + +/// A shortcut for `Ok(DialogueStage::Next(dialogue))`. +pub fn next( + dialogue: Dialogue, +) -> Result, E> { + Ok(DialogueStage::Next(dialogue)) +} + +/// A shortcut for `Ok(DialogueStage::Exit)`. +pub fn exit() -> Result, E> { + Ok(DialogueStage::Exit) +} diff --git a/src/dispatching/dialogue/dialogue_state.rs b/src/dispatching/dialogue/dialogue_state.rs deleted file mode 100644 index 24a0413e..00000000 --- a/src/dispatching/dialogue/dialogue_state.rs +++ /dev/null @@ -1,8 +0,0 @@ -use crate::dispatching::dialogue::Dialogue; - -/// Continue or terminate a dialogue. -#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)] -pub enum DialogueStage { - Next(Dialogue), - Exit, -} diff --git a/src/dispatching/dialogue/mod.rs b/src/dispatching/dialogue/mod.rs index 7d97a6a8..4294eb5e 100644 --- a/src/dispatching/dialogue/mod.rs +++ b/src/dispatching/dialogue/mod.rs @@ -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}; diff --git a/src/dispatching/dispatcher.rs b/src/dispatching/dispatcher.rs index 61795838..00b62163 100644 --- a/src/dispatching/dispatcher.rs +++ b/src/dispatching/dispatcher.rs @@ -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, handlers_error_handler: Box + 'a>, diff --git a/src/dispatching/mod.rs b/src/dispatching/mod.rs index 35ab0c65..8c158038 100644 --- a/src/dispatching/mod.rs +++ b/src/dispatching/mod.rs @@ -25,7 +25,7 @@ //! //! // Setup logging here... //! -//! Dispatcher::new(Bot::new("MyAwesomeToken")) +//! Dispatcher::::new(Bot::new("MyAwesomeToken")) //! .message_handler(&|ctx: DispatcherHandlerCtx| async move { //! ctx.answer("pong").send().await?; //! Ok(()) diff --git a/src/prelude.rs b/src/prelude.rs index dabc41d7..c70efa5b 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -3,7 +3,8 @@ pub use crate::{ dispatching::{ dialogue::{ - DialogueDispatcher, DialogueHandlerCtx, DialogueStage, GetChatId, + exit, next, DialogueDispatcher, DialogueHandlerCtx, DialogueStage, + GetChatId, }, Dispatcher, DispatcherHandlerCtx, },