Fix the docs of dispatching::dialogue

This commit is contained in:
Temirkhan Myrzamadi 2020-07-25 00:42:53 +06:00
parent a79bb7ba4f
commit bdab7afe64
8 changed files with 110 additions and 32 deletions

View file

@ -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.

View file

@ -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

View file

@ -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<D>`], which encapsulates all the dialogues.
//! 3. Your handler, which receives an update and turns your dialogue into the
//! next state ([`DialogueDispatcherHandlerCx<YourUpdate, D>`] ->
//! [`DialogueStage<D>`]).
//! 4. [`DialogueDispatcher`], which encapsulates your handler, [`Storage<D>`],
//!
//! 3. [`DialogueDispatcher`], which encapsulates your handler, [`Storage<D>`],
//! 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<D>;
//!
//! 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<Message, D, Infallible>| 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<D>`]: crate::dispatching::dialogue::Storage
//!
//! [`DialogueStage<D>`]: 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<YourUpdate, D>`]:
//! crate::dispatching::dialogue::DialogueWithCx
//!
//! [examples/dialogue_bot]: https://github.com/teloxide/teloxide/tree/master/examples/dialogue_bot
#![allow(clippy::type_complexity)]

View file

@ -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.

View file

@ -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,

View file

@ -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<Upd> {

View file

@ -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.

View file

@ -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)]