diff --git a/src/dispatching/repls.rs b/src/dispatching/repls.rs index b0f450a3..0d41d7ba 100644 --- a/src/dispatching/repls.rs +++ b/src/dispatching/repls.rs @@ -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; diff --git a/src/dispatching/repls/caution.md b/src/dispatching/repls/caution.md new file mode 100644 index 00000000..a5968cb3 --- /dev/null +++ b/src/dispatching/repls/caution.md @@ -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. diff --git a/src/dispatching/repls/commands_repl.rs b/src/dispatching/repls/commands_repl.rs index ceeeb917..b5dd39e7 100644 --- a/src/dispatching/repls/commands_repl.rs +++ b/src/dispatching/repls/commands_repl.rs @@ -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) where - Cmd: BotCommands + Send + Sync + 'static, - H: Injectable, Args> + Send + Sync + 'static, R: Requester + Clone + Send + Sync + 'static, ::GetUpdates: Send, + H: Injectable, 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: PhantomData, ) where Cmd: BotCommands + Send + Sync + 'static, H: Injectable, 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 . let ignore_update = |_upd| Box::pin(async {}); diff --git a/src/dispatching/repls/preamble.md b/src/dispatching/repls/preamble.md new file mode 100644 index 00000000..5c21f079 --- /dev/null +++ b/src/dispatching/repls/preamble.md @@ -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. diff --git a/src/dispatching/repls/repl.rs b/src/dispatching/repls/repl.rs index 529cc711..a755708f 100644 --- a/src/dispatching/repls/repl.rs +++ b/src/dispatching/repls/repl.rs @@ -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(bot: R, handler: H) where - H: Injectable, Args> + Send + Sync + 'static, - Result<(), E>: OnError, - E: Debug + Send + Sync + 'static, R: Requester + Send + Sync + Clone + 'static, ::GetUpdates: Send, + H: Injectable, 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(bot: R, handler: H, listener: L) where - H: Injectable, Args> + Send + Sync + 'static, - L: UpdateListener + Send + 'a, - L::Err: Debug, - Result<(), E>: OnError, - E: Debug + Send + Sync + 'static, R: Requester + Clone + Send + Sync + 'static, + H: Injectable, Args> + Send + Sync + 'static, + E: Debug + Send + Sync + 'static, + L: UpdateListener + Send, + L::Err: Debug, { use crate::dispatching::Dispatcher; diff --git a/src/dispatching/repls/stopping.md b/src/dispatching/repls/stopping.md new file mode 100644 index 00000000..63c65e28 --- /dev/null +++ b/src/dispatching/repls/stopping.md @@ -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