diff --git a/src/dispatching/dialogue/bot_dialogue.rs b/src/dispatching/dialogue/bot_dialogue.rs index 4f3124e9..8f9d4bcf 100644 --- a/src/dispatching/dialogue/bot_dialogue.rs +++ b/src/dispatching/dialogue/bot_dialogue.rs @@ -1,10 +1,4 @@ -use crate::{ - dispatching::{ - dialogue::{TransitionIn, TransitionOut}, - UpdateWithCx, - }, - types::Message, -}; +use crate::dispatching::dialogue::{TransitionIn, TransitionOut}; use futures::future::BoxFuture; /// Represents a dialogue FSM. diff --git a/src/dispatching/dialogue/dialogue_dispatcher.rs b/src/dispatching/dialogue/dialogue_dispatcher.rs index 6df9377b..a9c7e4d1 100644 --- a/src/dispatching/dialogue/dialogue_dispatcher.rs +++ b/src/dispatching/dialogue/dialogue_dispatcher.rs @@ -15,11 +15,11 @@ use std::sync::{Arc, Mutex}; /// A dispatcher of dialogues. /// -/// Note that `DialogueDispatcher` implements [`DispatcherHandler`], so you can -/// just put an instance of this dispatcher into the [`Dispatcher`]'s methods. +/// Note that it implements [`DispatcherHandler`], so you can just put an +/// instance of this dispatcher into the [`Dispatcher`]'s methods. /// -/// See [the module-level documentation for the design -/// overview](crate::dispatching::dialogue). +/// See the [module-level documentation](crate::dispatching::dialogue) for the +/// design overview. /// /// [`Dispatcher`]: crate::dispatching::Dispatcher /// [`DispatcherHandler`]: crate::dispatching::DispatcherHandler diff --git a/src/dispatching/dialogue/mod.rs b/src/dispatching/dialogue/mod.rs index f9185357..06e898ae 100644 --- a/src/dispatching/dialogue/mod.rs +++ b/src/dispatching/dialogue/mod.rs @@ -1,20 +1,19 @@ //! Dealing with dialogues. //! -//! There are four main components: +//! There are three main components: +//! +//! 1. Your type `D` (typically an enumeration), implementing [`BotDialogue`]. +//! It is essentially a [FSM]: its variants are possible dialogue states and +//! [`BotDialogue::dispatch`] is a transition function. //! -//! 1. Your type `D`, which designates a dialogue state at the current -//! moment. //! 2. [`Storage`], which encapsulates all the dialogues. -//! 3. Your handler, which receives an update and turns your dialogue into the -//! next state ([`DialogueDispatcherHandlerCx`] -> -//! [`DialogueStage`]). -//! 4. [`DialogueDispatcher`], which encapsulates your handler, [`Storage`], +//! +//! 3. [`DialogueDispatcher`], which encapsulates your handler, [`Storage`], //! and implements [`DispatcherHandler`]. //! -//! For example, you supply [`DialogueDispatcher`] into -//! [`Dispatcher::messages_handler`]. Every time [`Dispatcher`] sees an incoming -//! [`UpdateKind::Message(message)`], `message` is transferred into -//! [`DialogueDispatcher`]. After this, following steps are executed: +//! You pass [`DialogueDispatcher`] into [`Dispatcher`]. Every time +//! [`Dispatcher`] sees an incoming input, it is transferred into +//! [`DialogueDispatcher`], and the following steps are executed: //! //! 1. If a storage doesn't contain a dialogue from this chat, supply //! `D::default()` into you handler, otherwise, supply the saved dialogue @@ -23,21 +22,102 @@ //! from the storage, otherwise ([`DialogueStage::Next`]) force the storage to //! update the dialogue. //! -//! Please, see [examples/dialogue_bot] as an example. +//! To avoid boilerplate, teloxide exports these convenient things: the [`up!`] +//! macro, the [`next`] and [`exit`] functions, and `#[derive(BotDialogue)]`. +//! Here's how your dialogues management code skeleton should look like: +//! +//! ```no_run +//! use std::convert::Infallible; +//! +//! use teloxide::prelude::*; +//! use teloxide_macros::BotDialogue; +//! +//! struct _1State; +//! struct _2State; +//! struct _3State; +//! +//! pub type Out = TransitionOut; +//! +//! pub async fn _1_transition(cx: TransitionIn, state: _1State) { +//! todo!() +//! } +//! pub async fn _2_transition(cx: TransitionIn, state: _2State) { +//! todo!() +//! } +//! pub async fn _3_transition(cx: TransitionIn, state: _3State) { +//! todo!() +//! } +//! +//! #[derive(BotDialogue)] +//! enum D { +//! #[transition(_1_transition)] +//! _1(_1State), +//! #[transition(_2_transition)] +//! _2(_2State), +//! #[transition(_3_transition)] +//! _3(_3State), +//! } +//! +//! impl Default for D { +//! fn default() -> Self { +//! Self::_1(_1State) +//! } +//! } +//! +//! #[tokio::main] +//! async fn main() { +//! run().await; +//! } +//! +//! async fn run() { +//! teloxide::enable_logging!(); +//! log::info!("Starting dialogue_bot!"); +//! +//! let bot = Bot::from_env(); +//! +//! Dispatcher::new(bot) +//! .messages_handler(DialogueDispatcher::new( +//! |input: DialogueWithCx| async move { +//! // Unwrap without panic because of std::convert::Infallible. +//! input +//! .dialogue +//! .unwrap() +//! .dispatch(input.cx) +//! .await +//! .expect("Something wrong with the bot!") +//! }, +//! )) +//! .dispatch() +//! .await; +//! } +//! ``` +//! +//! See [examples/dialogue_bot] as a real example. +//! +//! [`BotDialogue`]: crate::dispatching::dialogue::BotDialogue +//! [`BotDialogue::dispatch`]: +//! crate::dispatching::dialogue::BotDialogue::dispatch +//! [FSM]: https://en.wikipedia.org/wiki/Finite-state_machine //! //! [`Storage`]: crate::dispatching::dialogue::Storage +//! //! [`DialogueStage`]: crate::dispatching::dialogue::DialogueStage //! [`DialogueDispatcher`]: crate::dispatching::dialogue::DialogueDispatcher +//! //! [`DialogueStage::Exit`]: //! crate::dispatching::dialogue::DialogueStage::Exit //! [`DialogueStage::Next`]: crate::dispatching::dialogue::DialogueStage::Next +//! +//! [`up!`]: crate::up +//! [`next`]: crate::dispatching::dialogue::next +//! [`exit`]: crate::dispatching::dialogue::exit +//! //! [`DispatcherHandler`]: crate::dispatching::DispatcherHandler //! [`Dispatcher`]: crate::dispatching::Dispatcher //! [`Dispatcher::messages_handler`]: //! crate::dispatching::Dispatcher::messages_handler //! [`UpdateKind::Message(message)`]: crate::types::UpdateKind::Message -//! [`DialogueWithCx`]: -//! crate::dispatching::dialogue::DialogueWithCx +//! //! [examples/dialogue_bot]: https://github.com/teloxide/teloxide/tree/master/examples/dialogue_bot #![allow(clippy::type_complexity)] diff --git a/src/dispatching/dialogue/storage/serializer.rs b/src/dispatching/dialogue/storage/serializer.rs index f31724a4..3e32735c 100644 --- a/src/dispatching/dialogue/storage/serializer.rs +++ b/src/dispatching/dialogue/storage/serializer.rs @@ -1,4 +1,5 @@ -/// Various serializers for memory storages. +//! Various serializers for memory storages. + use serde::{de::DeserializeOwned, ser::Serialize}; /// A serializer for memory storages. diff --git a/src/dispatching/dispatcher.rs b/src/dispatching/dispatcher.rs index 505ecb3e..822e9011 100644 --- a/src/dispatching/dispatcher.rs +++ b/src/dispatching/dispatcher.rs @@ -48,8 +48,8 @@ fn send<'a, Upd>( /// One dispatcher to rule them all. /// -/// See [the module-level documentation for the design -/// overview](crate::dispatching). +/// See the [module-level documentation](crate::dispatching) for the design +/// overview. pub struct Dispatcher { bot: Bot, diff --git a/src/dispatching/dispatcher_handler.rs b/src/dispatching/dispatcher_handler.rs index a00f2479..60b3840b 100644 --- a/src/dispatching/dispatcher_handler.rs +++ b/src/dispatching/dispatcher_handler.rs @@ -5,8 +5,8 @@ use futures::future::BoxFuture; /// An asynchronous handler of a stream of updates used in [`Dispatcher`]. /// -/// See [the module-level documentation for the design -/// overview](crate::dispatching). +/// See the [module-level documentation](crate::dispatching) for the design +/// overview. /// /// [`Dispatcher`]: crate::dispatching::Dispatcher pub trait DispatcherHandler { diff --git a/src/dispatching/dispatcher_handler_rx_ext.rs b/src/dispatching/dispatcher_handler_rx_ext.rs index 4af16830..48e37556 100644 --- a/src/dispatching/dispatcher_handler_rx_ext.rs +++ b/src/dispatching/dispatcher_handler_rx_ext.rs @@ -5,6 +5,9 @@ use futures::{stream::BoxStream, Stream, StreamExt}; /// An extension trait to be used with [`DispatcherHandlerRx`]. /// +/// See the [module-level documentation](crate::dispatching) for the design +/// overview. +/// /// [`DispatcherHandlerRx`]: crate::dispatching::DispatcherHandlerRx pub trait DispatcherHandlerRxExt { /// Extracts only text messages from this stream of arbitrary messages. diff --git a/src/dispatching/update_with_cx.rs b/src/dispatching/update_with_cx.rs index ec91a0a7..f095bfda 100644 --- a/src/dispatching/update_with_cx.rs +++ b/src/dispatching/update_with_cx.rs @@ -12,8 +12,8 @@ use crate::{ /// A [`Dispatcher`]'s handler's context of a bot and an update. /// -/// See [the module-level documentation for the design -/// overview](crate::dispatching). +/// See the [module-level documentation](crate::dispatching) for the design +/// overview. /// /// [`Dispatcher`]: crate::dispatching::Dispatcher #[derive(Debug)]