mirror of
https://github.com/teloxide/teloxide.git
synced 2025-01-03 17:52:12 +01:00
parent
7a3257a5f4
commit
599d4dea25
6 changed files with 185 additions and 86 deletions
|
@ -1,4 +1,11 @@
|
|||
//! REPLs for dispatching updates.
|
||||
//! [REPL]s for dispatching updates.
|
||||
//!
|
||||
//! This module provides functions for easy update handling, that accept a
|
||||
//! single "handler" function that processes all updates of a certain kind. Note
|
||||
//! that REPLs are meant to be used as a prototyping tool and lack configuration
|
||||
//! and some advanced features.
|
||||
//!
|
||||
//! [REPL]: https://en.wikipedia.org/wiki/Read-eval-print_loop
|
||||
|
||||
mod commands_repl;
|
||||
mod repl;
|
||||
|
|
2
src/dispatching/repls/caution.md
Normal file
2
src/dispatching/repls/caution.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
**DO NOT** use this function together with [`Dispatcher`] and other REPLs,
|
||||
because Telegram disallow multiple requests at the same time from the same bot.
|
|
@ -11,36 +11,57 @@ use std::{fmt::Debug, marker::PhantomData};
|
|||
use teloxide_core::requests::Requester;
|
||||
|
||||
/// A [REPL] for commands.
|
||||
///
|
||||
/// All errors from an update listener and handler will be logged.
|
||||
///
|
||||
/// REPLs are meant only for simple bots and rapid prototyping. If you need to
|
||||
/// supply dependencies or describe more complex dispatch logic, please use
|
||||
/// [`Dispatcher`].
|
||||
///
|
||||
/// See also: ["Dispatching or
|
||||
/// REPLs?"](dispatching/index.html#dispatching-or-repls)
|
||||
///
|
||||
/// ## Caution
|
||||
///
|
||||
/// **DO NOT** use this function together with [`Dispatcher`] and other REPLs,
|
||||
/// because Telegram disallow multiple requests at the same time from the same
|
||||
/// bot.
|
||||
///
|
||||
/// ## Dependency requirements
|
||||
///
|
||||
/// - Those of [`HandlerExt::filter_command`]
|
||||
//
|
||||
#[doc = include_str!("preamble.md")]
|
||||
///
|
||||
/// [REPL]: https://en.wikipedia.org/wiki/Read-eval-print_loop
|
||||
/// [`Dispatcher`]: crate::dispatching::Dispatcher
|
||||
///
|
||||
/// ## Signature
|
||||
///
|
||||
/// Don't be scared by many trait bounds in the signature, in essence they
|
||||
/// require:
|
||||
///
|
||||
/// 1. `bot` is a bot, client for the Telegram bot API
|
||||
/// - in teloxide this is represented via a [`Requester`] trait
|
||||
/// 2. `handler` is an async function that returns `Result<(), E>`
|
||||
/// - Such that `E` can be printed with [`Debug`] formatting
|
||||
/// - And all arguments can be extracted from [`DependencyMap`]
|
||||
/// - Which is the same, as all arguments implementing `Send + Sync +
|
||||
/// 'static`
|
||||
/// 3. `cmd` is a type of the command that will be parsed,
|
||||
/// - The command type must implement [`BotCommands`] trait
|
||||
/// - It can be acquired by writing `TheCommandType::ty()`
|
||||
///
|
||||
/// All other requirements are about thread safety and data validity and can be
|
||||
/// ignored for most of the time.
|
||||
///
|
||||
/// ## Handler arguments
|
||||
///
|
||||
/// Teloxide provides the following types to the `handler`:
|
||||
/// - [`Message`]
|
||||
/// - `R` (type of the `bot`)
|
||||
/// - `Cmd` (type of the parsed command)
|
||||
/// - [`Me`]
|
||||
///
|
||||
/// [`Me`]: crate::types::Me
|
||||
/// [`Message`]: crate::types::Message
|
||||
///
|
||||
/// ## Stopping
|
||||
//
|
||||
#[doc = include_str!("stopping.md")]
|
||||
///
|
||||
/// ## Caution
|
||||
//
|
||||
#[doc = include_str!("caution.md")]
|
||||
///
|
||||
#[cfg(feature = "ctrlc_handler")]
|
||||
pub async fn commands_repl<'a, R, Cmd, H, E, Args>(bot: R, handler: H, cmd: PhantomData<Cmd>)
|
||||
where
|
||||
Cmd: BotCommands + Send + Sync + 'static,
|
||||
H: Injectable<DependencyMap, Result<(), E>, Args> + Send + Sync + 'static,
|
||||
R: Requester + Clone + Send + Sync + 'static,
|
||||
<R as Requester>::GetUpdates: Send,
|
||||
H: Injectable<DependencyMap, Result<(), E>, Args> + Send + Sync + 'static,
|
||||
E: Debug + Send + Sync + 'static,
|
||||
Cmd: BotCommands + Send + Sync + 'static,
|
||||
{
|
||||
let cloned_bot = bot.clone();
|
||||
|
||||
|
@ -53,36 +74,57 @@ where
|
|||
.await;
|
||||
}
|
||||
|
||||
/// Like [`commands_repl`], but with a custom [`UpdateListener`].
|
||||
/// A [REPL] for commands, with a custom [`UpdateListener`].
|
||||
//
|
||||
#[doc = include_str!("preamble.md")]
|
||||
///
|
||||
/// All errors from an update listener and handler will be logged.
|
||||
/// [REPL]: https://en.wikipedia.org/wiki/Read-eval-print_loop
|
||||
///
|
||||
/// REPLs are meant only for simple bots and rapid prototyping. If you need to
|
||||
/// supply dependencies or describe more complex dispatch logic, please use
|
||||
/// [`Dispatcher`].
|
||||
/// ## Signature
|
||||
///
|
||||
/// See also: ["Dispatching or
|
||||
/// REPLs?"](dispatching/index.html#dispatching-or-repls)
|
||||
/// Don't be scared by many trait bounds in the signature, in essence they
|
||||
/// require:
|
||||
///
|
||||
/// 1. `bot` is a bot, client for the Telegram bot API
|
||||
/// - in teloxide this is represented via a [`Requester`] trait
|
||||
/// 2. `handler` is an async function that returns `Result<(), E>`
|
||||
/// - Such that `E` can be printed with [`Debug`] formatting
|
||||
/// - And all arguments can be extracted from [`DependencyMap`]
|
||||
/// - Which is the same, as all arguments implementing `Send + Sync +
|
||||
/// 'static`
|
||||
/// 3. `listener` is an [`UpdateListener`]
|
||||
/// 4. `cmd` is a type of the command that will be parsed,
|
||||
/// - The command type must implement [`BotCommands`] trait
|
||||
/// - It can be acquired by writing `TheCommandType::ty()`
|
||||
///
|
||||
/// All other requirements are about thread safety and data validity and can be
|
||||
/// ignored for most of the time.
|
||||
///
|
||||
/// ## Handler arguments
|
||||
///
|
||||
/// Teloxide provides the following types to the `handler`:
|
||||
/// - [`Message`]
|
||||
/// - `R` (type of the `bot`)
|
||||
/// - `Cmd` (type of the parsed command)
|
||||
/// - [`Me`]
|
||||
///
|
||||
/// [`Me`]: crate::types::Me
|
||||
/// [`Message`]: crate::types::Message
|
||||
///
|
||||
/// ## Stopping
|
||||
//
|
||||
#[doc = include_str!("stopping.md")]
|
||||
///
|
||||
/// ## Caution
|
||||
//
|
||||
#[doc = include_str!("caution.md")]
|
||||
///
|
||||
/// **DO NOT** use this function together with [`Dispatcher`] and other REPLs,
|
||||
/// because Telegram disallow multiple requests at the same time from the same
|
||||
/// bot.
|
||||
///
|
||||
/// ## Dependency requirements
|
||||
///
|
||||
/// - Those of [`HandlerExt::filter_command`]
|
||||
///
|
||||
/// [`Dispatcher`]: crate::dispatching::Dispatcher
|
||||
/// [`commands_repl`]: crate::dispatching::repls::commands_repl()
|
||||
/// [`UpdateListener`]: crate::dispatching::update_listeners::UpdateListener
|
||||
#[cfg(feature = "ctrlc_handler")]
|
||||
pub async fn commands_repl_with_listener<'a, R, Cmd, H, L, E, Args>(
|
||||
bot: R,
|
||||
handler: H,
|
||||
listener: L,
|
||||
_cmd: PhantomData<Cmd>,
|
||||
cmd: PhantomData<Cmd>,
|
||||
) where
|
||||
Cmd: BotCommands + Send + Sync + 'static,
|
||||
H: Injectable<DependencyMap, Result<(), E>, Args> + Send + Sync + 'static,
|
||||
|
@ -93,6 +135,8 @@ pub async fn commands_repl_with_listener<'a, R, Cmd, H, L, E, Args>(
|
|||
{
|
||||
use crate::dispatching::Dispatcher;
|
||||
|
||||
let _ = cmd;
|
||||
|
||||
// Other update types are of no interest to use since this REPL is only for
|
||||
// commands. See <https://github.com/teloxide/teloxide/issues/557>.
|
||||
let ignore_update = |_upd| Box::pin(async {});
|
||||
|
|
7
src/dispatching/repls/preamble.md
Normal file
7
src/dispatching/repls/preamble.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
REPLs are meant only for simple bots and rapid prototyping.
|
||||
If you need to supply dependencies or describe more complex dispatch logic, please use [`Dispatcher`].
|
||||
See also: ["Dispatching or REPLs?"](dispatching/index.html#dispatching-or-repls).
|
||||
|
||||
[`Dispatcher`]: crate::dispatching::Dispatcher
|
||||
|
||||
All errors from a the handler and will be logged.
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
dispatching::{update_listeners, update_listeners::UpdateListener, UpdateFilterExt},
|
||||
error_handlers::{LoggingErrorHandler, OnError},
|
||||
error_handlers::LoggingErrorHandler,
|
||||
types::Update,
|
||||
};
|
||||
use dptree::di::{DependencyMap, Injectable};
|
||||
|
@ -8,66 +8,101 @@ use std::fmt::Debug;
|
|||
use teloxide_core::requests::Requester;
|
||||
|
||||
/// A [REPL] for messages.
|
||||
///
|
||||
/// All errors from an update listener and a handler will be logged.
|
||||
///
|
||||
/// REPLs are meant only for simple bots and rapid prototyping. If you need to
|
||||
/// supply dependencies or describe more complex dispatch logic, please use
|
||||
/// [`Dispatcher`].
|
||||
///
|
||||
/// See also: ["Dispatching or
|
||||
/// REPLs?"](dispatching/index.html#dispatching-or-repls)
|
||||
///
|
||||
/// ## Caution
|
||||
///
|
||||
/// **DO NOT** use this function together with [`Dispatcher`] and other REPLs,
|
||||
/// because Telegram disallow multiple requests at the same time from the same
|
||||
/// bot.
|
||||
//
|
||||
#[doc = include_str!("preamble.md")]
|
||||
///
|
||||
/// [REPL]: https://en.wikipedia.org/wiki/Read-eval-print_loop
|
||||
/// [`Dispatcher`]: crate::dispatching::Dispatcher
|
||||
///
|
||||
/// ## Signature
|
||||
///
|
||||
/// Don't be scared by many trait bounds in the signature, in essence they
|
||||
/// require:
|
||||
///
|
||||
/// 1. `bot` is a bot, client for the Telegram bot API
|
||||
/// - in teloxide this is represented via a [`Requester`] trait
|
||||
/// 2. `handler` is an async function that returns `Result<(), E>`
|
||||
/// - Such that `E` can be printed with [`Debug`] formatting
|
||||
/// - And all arguments can be extracted from [`DependencyMap`]
|
||||
/// - Which is the same, as all arguments implementing `Send + Sync +
|
||||
/// 'static`
|
||||
///
|
||||
/// ## Handler arguments
|
||||
///
|
||||
/// Teloxide provides the following types to the `handler`:
|
||||
/// - [`Message`]
|
||||
/// - `R` (type of the `bot`)
|
||||
/// - [`Me`]
|
||||
///
|
||||
/// [`Me`]: crate::types::Me
|
||||
/// [`Message`]: crate::types::Message
|
||||
///
|
||||
/// ## Stopping
|
||||
//
|
||||
#[doc = include_str!("stopping.md")]
|
||||
///
|
||||
/// ## Caution
|
||||
//
|
||||
#[doc = include_str!("caution.md")]
|
||||
///
|
||||
#[cfg(feature = "ctrlc_handler")]
|
||||
pub async fn repl<R, H, E, Args>(bot: R, handler: H)
|
||||
where
|
||||
H: Injectable<DependencyMap, Result<(), E>, Args> + Send + Sync + 'static,
|
||||
Result<(), E>: OnError<E>,
|
||||
E: Debug + Send + Sync + 'static,
|
||||
R: Requester + Send + Sync + Clone + 'static,
|
||||
<R as Requester>::GetUpdates: Send,
|
||||
H: Injectable<DependencyMap, Result<(), E>, Args> + Send + Sync + 'static,
|
||||
E: Debug + Send + Sync + 'static,
|
||||
{
|
||||
let cloned_bot = bot.clone();
|
||||
repl_with_listener(bot, handler, update_listeners::polling_default(cloned_bot).await).await;
|
||||
}
|
||||
|
||||
/// Like [`repl`], but with a custom [`UpdateListener`].
|
||||
/// A [REPL] for messages, with a custom [`UpdateListener`].
|
||||
//
|
||||
#[doc = include_str!("preamble.md")]
|
||||
///
|
||||
/// All errors from an update listener and handler will be logged.
|
||||
///
|
||||
/// REPLs are meant only for simple bots and rapid prototyping. If you need to
|
||||
/// supply dependencies or describe more complex dispatch logic, please use
|
||||
/// [`Dispatcher`].
|
||||
///
|
||||
/// See also: ["Dispatching or
|
||||
/// REPLs?"](dispatching/index.html#dispatching-or-repls)
|
||||
///
|
||||
/// # Caution
|
||||
///
|
||||
/// **DO NOT** use this function together with [`Dispatcher`] and other REPLs,
|
||||
/// because Telegram disallow multiple requests at the same time from the same
|
||||
/// bot.
|
||||
///
|
||||
/// [`Dispatcher`]: crate::dispatching::Dispatcher
|
||||
/// [`repl`]: crate::dispatching::repls::repl()
|
||||
/// [REPL]: https://en.wikipedia.org/wiki/Read-eval-print_loop
|
||||
/// [`UpdateListener`]: crate::dispatching::update_listeners::UpdateListener
|
||||
///
|
||||
/// ## Signature
|
||||
///
|
||||
/// Don't be scared by many trait bounds in the signature, in essence they
|
||||
/// require:
|
||||
///
|
||||
/// 1. `bot` is a bot, client for the Telegram bot API
|
||||
/// - in teloxide this is represented via a [`Requester`] trait
|
||||
/// 2. `handler` is an async function that returns `Result<(), E>`
|
||||
/// - Such that `E` can be printed with [`Debug`] formatting
|
||||
/// - And all arguments can be extracted from [`DependencyMap`]
|
||||
/// - Which is the same, as all arguments implementing `Send + Sync +
|
||||
/// 'static`
|
||||
/// 3. `listener` is an [`UpdateListener`]
|
||||
///
|
||||
/// ## Handler arguments
|
||||
///
|
||||
/// Teloxide provides the following types to the `handler`:
|
||||
/// - [`Message`]
|
||||
/// - `R` (type of the `bot`)
|
||||
/// - [`Me`]
|
||||
///
|
||||
/// [`Me`]: crate::types::Me
|
||||
/// [`Message`]: crate::types::Message
|
||||
///
|
||||
/// ## Stopping
|
||||
//
|
||||
#[doc = include_str!("stopping.md")]
|
||||
///
|
||||
/// ## Caution
|
||||
//
|
||||
#[doc = include_str!("caution.md")]
|
||||
///
|
||||
#[cfg(feature = "ctrlc_handler")]
|
||||
pub async fn repl_with_listener<'a, R, H, E, L, Args>(bot: R, handler: H, listener: L)
|
||||
pub async fn repl_with_listener<R, H, E, L, Args>(bot: R, handler: H, listener: L)
|
||||
where
|
||||
H: Injectable<DependencyMap, Result<(), E>, Args> + Send + Sync + 'static,
|
||||
L: UpdateListener + Send + 'a,
|
||||
L::Err: Debug,
|
||||
Result<(), E>: OnError<E>,
|
||||
E: Debug + Send + Sync + 'static,
|
||||
R: Requester + Clone + Send + Sync + 'static,
|
||||
H: Injectable<DependencyMap, Result<(), E>, Args> + Send + Sync + 'static,
|
||||
E: Debug + Send + Sync + 'static,
|
||||
L: UpdateListener + Send,
|
||||
L::Err: Debug,
|
||||
{
|
||||
use crate::dispatching::Dispatcher;
|
||||
|
||||
|
|
4
src/dispatching/repls/stopping.md
Normal file
4
src/dispatching/repls/stopping.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
To stop repl, simply press `Ctrl`+`C` in the terminal where you run the program.
|
||||
Note that gracefully stopping can take some time (we plan to improve this, see [#711]).
|
||||
|
||||
[#711]: https://github.com/teloxide/teloxide/issues/711
|
Loading…
Reference in a new issue