diff --git a/README.md b/README.md index 13d56758..eb1abe58 100644 --- a/README.md +++ b/README.md @@ -156,19 +156,15 @@ async fn answer(cx: UpdateWithCx, command: Command) -> ResponseResult<( Ok(()) } -async fn handle_commands(rx: DispatcherHandlerRx) { - rx.commands::(panic!("Insert here your bot's name")) - .for_each_concurrent(None, |(cx, command)| async move { - answer(cx, command).await.log_on_error().await; - }) - .await; -} - #[tokio::main] async fn main() { - // Setup is omitted... -} + teloxide::enable_logging!(); + log::info!("Starting simple_commands_bot..."); + let bot = Bot::from_env(); + + teloxide::commands_repl(bot, panic!("Insert here your bot's name"), answer).await; +} ```
diff --git a/examples/admin_bot/src/main.rs b/examples/admin_bot/src/main.rs index 78c51cb4..76eed1c7 100644 --- a/examples/admin_bot/src/main.rs +++ b/examples/admin_bot/src/main.rs @@ -2,8 +2,6 @@ use std::str::FromStr; use teloxide::{prelude::*, types::ChatPermissions, utils::command::BotCommand}; -use futures::future; - // Derive BotCommand to parse text with a command into this enumeration. // // 1. rename = "lowercase" turns all the commands into lowercase letters. @@ -130,16 +128,6 @@ async fn action(cx: UpdateWithCx, command: Command) -> ResponseResult<( Ok(()) } -async fn handle_commands(rx: DispatcherHandlerRx) { - rx.filter(|cx| future::ready(cx.update.chat.is_group())) - .commands::(panic!("Insert here your bot's name")) - // Execute all incoming commands concurrently: - .for_each_concurrent(None, |(cx, command)| async move { - action(cx, command).await.log_on_error().await; - }) - .await; -} - #[tokio::main] async fn main() { run().await; @@ -151,5 +139,5 @@ async fn run() { let bot = Bot::from_env(); - Dispatcher::new(bot).messages_handler(handle_commands).dispatch().await + teloxide::commands_repl(bot, panic!("Insert here your bot's name"), action).await; } diff --git a/examples/simple_commands_bot/src/main.rs b/examples/simple_commands_bot/src/main.rs index 1bdf7d5e..241ad2c0 100644 --- a/examples/simple_commands_bot/src/main.rs +++ b/examples/simple_commands_bot/src/main.rs @@ -25,14 +25,6 @@ async fn answer(cx: UpdateWithCx, command: Command) -> ResponseResult<( Ok(()) } -async fn handle_commands(rx: DispatcherHandlerRx) { - rx.commands::(panic!("Insert here your bot's name")) - .for_each_concurrent(None, |(cx, command)| async move { - answer(cx, command).await.log_on_error().await; - }) - .await; -} - #[tokio::main] async fn main() { run().await; @@ -44,5 +36,5 @@ async fn run() { let bot = Bot::from_env(); - Dispatcher::new(bot).messages_handler(handle_commands).dispatch().await; + teloxide::commands_repl(bot, panic!("Insert here your bot's name"), answer).await; } diff --git a/src/dispatching/commands_repl.rs b/src/dispatching/commands_repl.rs new file mode 100644 index 00000000..e9587008 --- /dev/null +++ b/src/dispatching/commands_repl.rs @@ -0,0 +1,47 @@ +use crate::{ + dispatching::{Dispatcher, DispatcherHandlerRx, DispatcherHandlerRxExt, UpdateWithCx}, + error_handlers::OnError, + requests::ResponseResult, + types::Message, + utils::command::BotCommand, + Bot, +}; +use futures::StreamExt; +use std::{future::Future, sync::Arc}; + +/// A [REPL] for commands. +/// +/// Used mostly for testing and demonstrative purposes. +/// +/// # Caution +/// **DO NOT** use this function together with [`Dispatcher`] and [`repl`], +/// because Telegram disallow multiple requests at the same time from the same +/// bot. +/// +/// [REPL]: https://en.wikipedia.org/wiki/Read-eval-print_loop +/// [`Dispatcher`]: crate::dispatching::Dispatcher +/// [`repl`]: crate::dispatching::repl +pub async fn commands_repl(bot: Bot, bot_name: &'static str, handler: H) +where + Cmd: BotCommand + Send + 'static, + H: Fn(UpdateWithCx, Cmd) -> Fut + Send + Sync + 'static, + Fut: Future> + Send + 'static, +{ + let handler = Arc::new(handler); + + Dispatcher::new(bot) + .messages_handler(move |rx: DispatcherHandlerRx| { + rx.commands::(bot_name).for_each_concurrent( + None, + move |(cx, cmd)| { + let handler = Arc::clone(&handler); + + async move { + handler(cx, cmd).await.log_on_error().await; + } + }, + ) + }) + .dispatch() + .await; +} diff --git a/src/dispatching/mod.rs b/src/dispatching/mod.rs index 02306349..d137d84c 100644 --- a/src/dispatching/mod.rs +++ b/src/dispatching/mod.rs @@ -43,6 +43,7 @@ //! [`tokio::sync::mpsc::UnboundedReceiver`]: https://docs.rs/tokio/0.2.11/tokio/sync/mpsc/struct.UnboundedReceiver.html //! [examples/dialogue_bot]: https://github.com/teloxide/teloxide/tree/master/examples/dialogue_bot +mod commands_repl; pub mod dialogue; mod dispatcher; mod dispatcher_handler; @@ -51,6 +52,7 @@ mod repl; pub mod update_listeners; mod update_with_cx; +pub use commands_repl::commands_repl; pub use dispatcher::Dispatcher; pub use dispatcher_handler::DispatcherHandler; pub use dispatcher_handler_rx_ext::DispatcherHandlerRxExt; diff --git a/src/dispatching/repl.rs b/src/dispatching/repl.rs index d138f402..3b3b9b2f 100644 --- a/src/dispatching/repl.rs +++ b/src/dispatching/repl.rs @@ -13,11 +13,13 @@ use std::{future::Future, sync::Arc}; /// Used mostly for testing and demonstrative purposes. /// /// # Caution -/// **DO NOT** use this function together with [`Dispatcher`], because Telegram -/// disallow multiple requests at the same time from the same bot. +/// **DO NOT** use this function together with [`Dispatcher`] and +/// [`commands_repl`], because Telegram disallow multiple requests at the same +/// time from the same bot. /// /// [REPL]: https://en.wikipedia.org/wiki/Read-eval-print_loop /// [`Dispatcher`]: crate::dispatching::Dispatcher +/// [`commands_repl`]: crate::dispatching::commands_repl pub async fn repl(bot: Bot, handler: H) where H: Fn(UpdateWithCx) -> Fut + Send + Sync + 'static, diff --git a/src/lib.rs b/src/lib.rs index bb0c071f..07f54b1c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,7 +42,7 @@ #![forbid(unsafe_code)] pub use bot::{Bot, BotBuilder}; -pub use dispatching::repl; +pub use dispatching::{commands_repl, repl}; pub use errors::{ApiErrorKind, DownloadError, KnownApiErrorKind, RequestError}; mod errors;