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 crate::types::Update;
|
||||||
use std::{future::Future, pin::Pin};
|
use std::{future::Future, pin::Pin};
|
||||||
|
|
||||||
|
/// Continue or terminate a user session.
|
||||||
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
|
||||||
pub enum SessionState<S> {
|
pub enum SessionState<Session> {
|
||||||
Continue(S),
|
Continue(Session),
|
||||||
Terminate,
|
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]
|
#[must_use]
|
||||||
fn handle<'a>(
|
fn handle<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
session: S,
|
session: Session,
|
||||||
update: Update,
|
update: Update,
|
||||||
) -> Pin<Box<dyn Future<Output = SessionState<S>> + 'a>>
|
) -> Pin<Box<dyn Future<Output = SessionState<Session>> + 'a>>
|
||||||
where
|
where
|
||||||
S: 'a;
|
Session: 'a;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The implementation of `Handler` for `Fn(S, Update) -> Future<Output =
|
/// The implementation of `Handler` for `Fn(Session, Update) -> Future<Output =
|
||||||
/// SessionState<S>>`.
|
/// SessionState<Session>>`.
|
||||||
impl<S, F, Fut> Handler<S> for F
|
impl<Session, F, Fut> Handler<Session> for F
|
||||||
where
|
where
|
||||||
F: Fn(S, Update) -> Fut,
|
F: Fn(Session, Update) -> Fut,
|
||||||
Fut: Future<Output = SessionState<S>>,
|
Fut: Future<Output = SessionState<Session>>,
|
||||||
{
|
{
|
||||||
fn handle<'a>(
|
fn handle<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
session: S,
|
session: Session,
|
||||||
update: Update,
|
update: Update,
|
||||||
) -> Pin<Box<dyn Future<Output = Fut::Output> + 'a>>
|
) -> Pin<Box<dyn Future<Output = Fut::Output> + 'a>>
|
||||||
where
|
where
|
||||||
S: 'a,
|
Session: 'a,
|
||||||
{
|
{
|
||||||
Box::pin(async move { self(session, update).await })
|
Box::pin(async move { self(session, update).await })
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
//! Update dispatching.
|
//! 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;
|
pub mod filters;
|
||||||
mod handler;
|
mod handler;
|
||||||
pub mod private;
|
pub mod private;
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
use super::storage::{InMemStorage, Storage};
|
use super::{
|
||||||
|
super::DispatchResult,
|
||||||
|
storage::{InMemStorage, Storage},
|
||||||
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
dispatching::{Handler, SessionState},
|
dispatching::{Handler, SessionState},
|
||||||
types::{ChatKind, Update, UpdateKind},
|
types::{ChatKind, Update, UpdateKind},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A dispatcher that dispatches updates from 1-to-1 chats.
|
||||||
pub struct Dispatcher<'a, Session, H> {
|
pub struct Dispatcher<'a, Session, H> {
|
||||||
storage: Box<dyn Storage<Session> + 'a>,
|
storage: Box<dyn Storage<Session> + 'a>,
|
||||||
handler: H,
|
handler: H,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
|
|
||||||
pub enum DispatchResult {
|
|
||||||
Handled,
|
|
||||||
Unhandled,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros {
|
mod macros {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
@ -33,6 +31,10 @@ where
|
||||||
Session: Default + 'a,
|
Session: Default + 'a,
|
||||||
H: Handler<Session>,
|
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 {
|
pub fn new(handler: H) -> Self {
|
||||||
Self {
|
Self {
|
||||||
storage: Box::new(InMemStorage::default()),
|
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
|
pub fn with_storage<Stg>(handler: H, storage: Stg) -> Self
|
||||||
where
|
where
|
||||||
Stg: Storage<Session> + 'a,
|
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 {
|
pub async fn dispatch(&mut self, update: Update) -> DispatchResult {
|
||||||
let chat_id = match &update.kind {
|
let chat_id = match &update.kind {
|
||||||
UpdateKind::Message(msg) => private_chat_id!(msg),
|
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 dispatcher;
|
||||||
mod storage;
|
mod storage;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,13 @@ use async_trait::async_trait;
|
||||||
use super::Storage;
|
use super::Storage;
|
||||||
use std::collections::HashMap;
|
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)]
|
#[derive(Clone, Debug, Eq, PartialEq, Default)]
|
||||||
pub struct InMemStorage<Session> {
|
pub struct InMemStorage<Session> {
|
||||||
map: HashMap<i64, Session>,
|
map: HashMap<i64, Session>,
|
||||||
|
|
|
@ -3,13 +3,30 @@ mod in_mem_storage;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
pub use in_mem_storage::InMemStorage;
|
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(?Send)]
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait Storage<Session> {
|
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>;
|
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(
|
async fn update_session(
|
||||||
&mut self,
|
&mut self,
|
||||||
chat_id: i64,
|
chat_id: i64,
|
||||||
state: Session,
|
session: Session,
|
||||||
) -> Option<Session>;
|
) -> Option<Session>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
//! - [`polling`], which returns a long/short polling listener with your
|
//! - [`polling`], which returns a long/short polling listener with your
|
||||||
//! configuration.
|
//! configuration.
|
||||||
//!
|
//!
|
||||||
//! And then you can extract updates from it and pass them directly to
|
//! And then you can extract updates from it and pass them directly to a
|
||||||
//! [`Dispatcher::dispatch`].
|
//! dispatcher.
|
||||||
//!
|
//!
|
||||||
//! Telegram supports two ways of [getting updates]: [long]/[short] polling and
|
//! Telegram supports two ways of [getting updates]: [long]/[short] polling and
|
||||||
//! [webhook].
|
//! [webhook].
|
||||||
|
@ -94,7 +94,6 @@
|
||||||
//! [`UpdateListener`]: UpdateListener
|
//! [`UpdateListener`]: UpdateListener
|
||||||
//! [`polling_default`]: polling_default
|
//! [`polling_default`]: polling_default
|
||||||
//! [`polling`]: polling
|
//! [`polling`]: polling
|
||||||
//! [`Dispatcher::dispatch`]: crate::dispatching::Dispatcher::dispatch
|
|
||||||
//! [`Box::get_updates`]: crate::Bot::get_updates
|
//! [`Box::get_updates`]: crate::Bot::get_updates
|
||||||
//! [getting updates]: https://core.telegram.org/bots/api#getting-updates
|
//! [getting updates]: https://core.telegram.org/bots/api#getting-updates
|
||||||
//! [long]: https://en.wikipedia.org/wiki/Push_technology#Long_polling
|
//! [long]: https://en.wikipedia.org/wiki/Push_technology#Long_polling
|
||||||
|
|
Loading…
Reference in a new issue