mirror of
https://github.com/teloxide/teloxide.git
synced 2024-12-22 14:35:36 +01:00
Write the docs
This commit is contained in:
parent
1547034741
commit
3351838a36
7 changed files with 87 additions and 24 deletions
|
@ -1,37 +1,47 @@
|
|||
use crate::types::Update;
|
||||
use std::{future::Future, pin::Pin};
|
||||
|
||||
/// Continue or terminate a user session.
|
||||
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
|
||||
pub enum SessionState<S> {
|
||||
Continue(S),
|
||||
pub enum SessionState<Session> {
|
||||
Continue(Session),
|
||||
Terminate,
|
||||
}
|
||||
|
||||
pub trait Handler<S> {
|
||||
/// A handler of a user session and an update.
|
||||
///
|
||||
/// ## Returns
|
||||
/// Returns [`SessionState::Continue(session)`] if it wants to be called again
|
||||
/// after a new update, or [`SessionState::Terminate`] if not.
|
||||
///
|
||||
/// [`SessionState::Continue(session)`]:
|
||||
/// crate::dispatching::SessionState::Continue
|
||||
/// [`SessionState::Terminate`]: crate::dispatching::SessionState::Terminate
|
||||
pub trait Handler<Session> {
|
||||
#[must_use]
|
||||
fn handle<'a>(
|
||||
&'a self,
|
||||
session: S,
|
||||
session: Session,
|
||||
update: Update,
|
||||
) -> Pin<Box<dyn Future<Output = SessionState<S>> + 'a>>
|
||||
) -> Pin<Box<dyn Future<Output = SessionState<Session>> + 'a>>
|
||||
where
|
||||
S: 'a;
|
||||
Session: 'a;
|
||||
}
|
||||
|
||||
/// The implementation of `Handler` for `Fn(S, Update) -> Future<Output =
|
||||
/// SessionState<S>>`.
|
||||
impl<S, F, Fut> Handler<S> for F
|
||||
/// The implementation of `Handler` for `Fn(Session, Update) -> Future<Output =
|
||||
/// SessionState<Session>>`.
|
||||
impl<Session, F, Fut> Handler<Session> for F
|
||||
where
|
||||
F: Fn(S, Update) -> Fut,
|
||||
Fut: Future<Output = SessionState<S>>,
|
||||
F: Fn(Session, Update) -> Fut,
|
||||
Fut: Future<Output = SessionState<Session>>,
|
||||
{
|
||||
fn handle<'a>(
|
||||
&'a self,
|
||||
session: S,
|
||||
session: Session,
|
||||
update: Update,
|
||||
) -> Pin<Box<dyn Future<Output = Fut::Output> + 'a>>
|
||||
where
|
||||
S: 'a,
|
||||
Session: 'a,
|
||||
{
|
||||
Box::pin(async move { self(session, update).await })
|
||||
}
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
//! Update dispatching.
|
||||
|
||||
/// If an update was handled by a dispatcher or not.
|
||||
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
|
||||
pub enum DispatchResult {
|
||||
Handled,
|
||||
Unhandled,
|
||||
}
|
||||
|
||||
pub mod filters;
|
||||
mod handler;
|
||||
pub mod private;
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
use super::storage::{InMemStorage, Storage};
|
||||
use super::{
|
||||
super::DispatchResult,
|
||||
storage::{InMemStorage, Storage},
|
||||
};
|
||||
use crate::{
|
||||
dispatching::{Handler, SessionState},
|
||||
types::{ChatKind, Update, UpdateKind},
|
||||
};
|
||||
|
||||
/// A dispatcher that dispatches updates from 1-to-1 chats.
|
||||
pub struct Dispatcher<'a, Session, H> {
|
||||
storage: Box<dyn Storage<Session> + 'a>,
|
||||
handler: H,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
|
||||
pub enum DispatchResult {
|
||||
Handled,
|
||||
Unhandled,
|
||||
}
|
||||
|
||||
#[macro_use]
|
||||
mod macros {
|
||||
#[macro_export]
|
||||
|
@ -33,6 +31,10 @@ where
|
|||
Session: Default + 'a,
|
||||
H: Handler<Session>,
|
||||
{
|
||||
/// Creates a dispatcher with the specified `handler` and [`InMemStorage`]
|
||||
/// (a default storage).
|
||||
///
|
||||
/// [`InMemStorage`]: crate::dispatching::private::InMemStorage
|
||||
pub fn new(handler: H) -> Self {
|
||||
Self {
|
||||
storage: Box::new(InMemStorage::default()),
|
||||
|
@ -40,6 +42,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a dispatcher with the specified `handler` and `storage`.
|
||||
pub fn with_storage<Stg>(handler: H, storage: Stg) -> Self
|
||||
where
|
||||
Stg: Storage<Session> + 'a,
|
||||
|
@ -50,6 +53,16 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Dispatches a single `update`.
|
||||
///
|
||||
/// ## Returns
|
||||
/// Returns [`DispatchResult::Handled`] if `update` was supplied to a
|
||||
/// handler, and [`DispatchResult::Unhandled`] if it was an update not
|
||||
/// from a 1-to-1 chat.
|
||||
///
|
||||
/// [`DispatchResult::Handled`]: crate::dispatching::DispatchResult::Handled
|
||||
/// [`DispatchResult::Unhandled`]:
|
||||
/// crate::dispatching::DispatchResult::Unhandled
|
||||
pub async fn dispatch(&mut self, update: Update) -> DispatchResult {
|
||||
let chat_id = match &update.kind {
|
||||
UpdateKind::Message(msg) => private_chat_id!(msg),
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
//! Dispatching updates from 1-to-1 chats.
|
||||
//!
|
||||
//! It's fairly simple: you have a session type and a handler that accepts
|
||||
//! (session, update) and turns a session into the next state. When a new
|
||||
//! user sends a message to your bot, the dispatcher creates a default session
|
||||
//! and supplies it to your handler, but when an old user sends a message, your
|
||||
//! handler gets the saved session with him.
|
||||
|
||||
// TODO: examples
|
||||
|
||||
mod dispatcher;
|
||||
mod storage;
|
||||
|
||||
|
|
|
@ -3,6 +3,13 @@ use async_trait::async_trait;
|
|||
use super::Storage;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// A memory storage based on a hash map. Stores all the sessions directly in
|
||||
/// RAM.
|
||||
///
|
||||
/// ## Note
|
||||
/// All the sessions will be lost after you restart your bot. If you need to
|
||||
/// store them somewhere on a drive, you need to implement a storage
|
||||
/// communicating with a DB.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Default)]
|
||||
pub struct InMemStorage<Session> {
|
||||
map: HashMap<i64, Session>,
|
||||
|
|
|
@ -3,13 +3,30 @@ mod in_mem_storage;
|
|||
use async_trait::async_trait;
|
||||
pub use in_mem_storage::InMemStorage;
|
||||
|
||||
/// A storage of user sessions.
|
||||
///
|
||||
/// You can implement this trait for a structure that communicates with a DB and
|
||||
/// be sure that after you restart your bot, all the sessions won't be lost.
|
||||
///
|
||||
/// For a storage based on a simple hash map, see [`InMemStorage`].
|
||||
///
|
||||
/// [`InMemStorage`]: crate::dispatching::private::InMemStorage
|
||||
#[async_trait(?Send)]
|
||||
#[async_trait]
|
||||
pub trait Storage<Session> {
|
||||
/// Removes a session with the specified `chat_id`.
|
||||
///
|
||||
/// Returns `None` if there wasn't such a session, `Some(session)` if a
|
||||
/// `session` was deleted.
|
||||
async fn remove_session(&mut self, chat_id: i64) -> Option<Session>;
|
||||
|
||||
/// Updates a session with the specified `chat_id`.
|
||||
///
|
||||
/// Returns `None` if there wasn't such a session, `Some(session)` if a
|
||||
/// `session` was updated.
|
||||
async fn update_session(
|
||||
&mut self,
|
||||
chat_id: i64,
|
||||
state: Session,
|
||||
session: Session,
|
||||
) -> Option<Session>;
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
//! - [`polling`], which returns a long/short polling listener with your
|
||||
//! configuration.
|
||||
//!
|
||||
//! And then you can extract updates from it and pass them directly to
|
||||
//! [`Dispatcher::dispatch`].
|
||||
//! And then you can extract updates from it and pass them directly to a
|
||||
//! dispatcher.
|
||||
//!
|
||||
//! Telegram supports two ways of [getting updates]: [long]/[short] polling and
|
||||
//! [webhook].
|
||||
|
@ -94,7 +94,6 @@
|
|||
//! [`UpdateListener`]: UpdateListener
|
||||
//! [`polling_default`]: polling_default
|
||||
//! [`polling`]: polling
|
||||
//! [`Dispatcher::dispatch`]: crate::dispatching::Dispatcher::dispatch
|
||||
//! [`Box::get_updates`]: crate::Bot::get_updates
|
||||
//! [getting updates]: https://core.telegram.org/bots/api#getting-updates
|
||||
//! [long]: https://en.wikipedia.org/wiki/Push_technology#Long_polling
|
||||
|
|
Loading…
Reference in a new issue