mirror of
https://github.com/teloxide/teloxide.git
synced 2025-01-03 17:52:12 +01:00
Add DispatcherHandlerRxExt
This commit is contained in:
parent
9d78b7e0a6
commit
46b20f676e
7 changed files with 101 additions and 55 deletions
16
README.md
16
README.md
|
@ -63,7 +63,6 @@ $ rustup update stable
|
|||
[dependencies]
|
||||
teloxide = "0.1.0"
|
||||
log = "0.4.8"
|
||||
futures = "0.3.4"
|
||||
tokio = "0.2.11"
|
||||
pretty_env_logger = "0.4.0"
|
||||
```
|
||||
|
@ -147,13 +146,12 @@ async fn answer(
|
|||
}
|
||||
|
||||
async fn handle_command(rx: DispatcherHandlerRx<Message>) {
|
||||
rx.filter_map(|cx| {
|
||||
future::ready(cx.update.text_owned().map(|text| (cx, text)))
|
||||
})
|
||||
.filter_map(|(cx, text)| {
|
||||
future::ready(Command::parse(&text).map(|(command, _)| (cx, command)))
|
||||
})
|
||||
.for_each_concurrent(None, |(cx, command)| async move {
|
||||
// Only iterate through text messages:
|
||||
rx.text_messages()
|
||||
// Only iterate through commands in a proper format:
|
||||
.commands::<Command>()
|
||||
// Execute all incoming commands concurrently:
|
||||
.for_each_concurrent(None, |(cx, command, _)| async move {
|
||||
answer(cx, command).await.log_on_error().await;
|
||||
})
|
||||
.await;
|
||||
|
@ -184,7 +182,7 @@ TELOXIDE_TOKEN=<Your token here> cargo run
|
|||
</div>
|
||||
|
||||
|
||||
See? The dispatcher gives us a stream of messages, so we can handle it as we want! Here we use [`.filter_map()`](https://docs.rs/futures/0.3.4/futures/stream/trait.StreamExt.html#method.filter_map) and [`.for_each_concurrent()`](https://docs.rs/futures/0.3.4/futures/stream/trait.StreamExt.html#method.for_each_concurrent), but others are also available:
|
||||
See? The dispatcher gives us a stream of messages, so we can handle it as we want! Here we use our `.text_messages()`, `.commands()`, and [`.for_each_concurrent()`](https://docs.rs/futures/0.3.4/futures/stream/trait.StreamExt.html#method.for_each_concurrent), but others are also available:
|
||||
- [`.flatten()`](https://docs.rs/futures/0.3.4/futures/stream/trait.StreamExt.html#method.flatten)
|
||||
- [`.left_stream()`](https://docs.rs/futures/0.3.4/futures/stream/trait.StreamExt.html#method.left_stream)
|
||||
- [`.scan()`](https://docs.rs/futures/0.3.4/futures/stream/trait.StreamExt.html#method.scan)
|
||||
|
|
|
@ -176,21 +176,13 @@ async fn action(
|
|||
|
||||
// Handle all messages.
|
||||
async fn handle_commands(rx: DispatcherHandlerRx<Message>) {
|
||||
rx.filter(|cx| future::ready(!cx.update.chat.is_group()))
|
||||
.filter_map(|cx| {
|
||||
future::ready(cx.update.text_owned().map(|text| (cx, text)))
|
||||
})
|
||||
.filter_map(|(cx, text)| {
|
||||
future::ready(Command::parse(&text).map(|(command, args)| {
|
||||
(
|
||||
cx,
|
||||
command,
|
||||
args.into_iter()
|
||||
.map(ToOwned::to_owned)
|
||||
.collect::<Vec<String>>(),
|
||||
)
|
||||
}))
|
||||
})
|
||||
// Only iterate through messages from groups:
|
||||
rx.filter(|cx| future::ready(cx.update.chat.is_group()))
|
||||
// Only iterate through text messages:
|
||||
.text_messages()
|
||||
// Only iterate through commands in a proper format:
|
||||
.commands::<Command>()
|
||||
// Execute all incoming commands concurrently:
|
||||
.for_each_concurrent(None, |(cx, command, args)| async move {
|
||||
action(cx, command, &args).await.log_on_error().await;
|
||||
})
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use teloxide::{prelude::*, utils::command::BotCommand};
|
||||
|
||||
use futures::future;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
#[derive(BotCommand)]
|
||||
|
@ -32,13 +31,12 @@ async fn answer(
|
|||
}
|
||||
|
||||
async fn handle_command(rx: DispatcherHandlerRx<Message>) {
|
||||
rx.filter_map(|cx| {
|
||||
future::ready(cx.update.text_owned().map(|text| (cx, text)))
|
||||
})
|
||||
.filter_map(|(cx, text)| {
|
||||
future::ready(Command::parse(&text).map(|(command, _)| (cx, command)))
|
||||
})
|
||||
.for_each_concurrent(None, |(cx, command)| async move {
|
||||
// Only iterate through text messages:
|
||||
rx.text_messages()
|
||||
// Only iterate through commands in a proper format:
|
||||
.commands::<Command>()
|
||||
// Execute all incoming commands concurrently:
|
||||
.for_each_concurrent(None, |(cx, command, _)| async move {
|
||||
answer(cx, command).await.log_on_error().await;
|
||||
})
|
||||
.await;
|
||||
|
|
61
src/dispatching/dispatcher_handler_rx_ext.rs
Normal file
61
src/dispatching/dispatcher_handler_rx_ext.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
use crate::{
|
||||
prelude::DispatcherHandlerCx, types::Message, utils::command::BotCommand,
|
||||
};
|
||||
use futures::{stream::BoxStream, Stream, StreamExt};
|
||||
|
||||
/// An extension trait to be used with [`DispatcherHandlerRx`].
|
||||
///
|
||||
/// [`DispatcherHandlerRx`]: crate:dispatching::DispatcherHandlerRx
|
||||
pub trait DispatcherHandlerRxExt {
|
||||
/// Extracts only text messages from this stream.
|
||||
fn text_messages(
|
||||
self,
|
||||
) -> BoxStream<'static, (DispatcherHandlerCx<Message>, String)>
|
||||
where
|
||||
Self: Stream<Item = DispatcherHandlerCx<Message>>;
|
||||
|
||||
/// Extracts only commands with their arguments from this stream of text
|
||||
/// messages.
|
||||
fn commands<C>(
|
||||
self,
|
||||
) -> BoxStream<'static, (DispatcherHandlerCx<Message>, C, Vec<String>)>
|
||||
where
|
||||
Self: Stream<Item = (DispatcherHandlerCx<Message>, String)>,
|
||||
C: BotCommand;
|
||||
}
|
||||
|
||||
impl<T> DispatcherHandlerRxExt for T
|
||||
where
|
||||
T: Send + 'static,
|
||||
{
|
||||
fn text_messages(
|
||||
self,
|
||||
) -> BoxStream<'static, (DispatcherHandlerCx<Message>, String)>
|
||||
where
|
||||
Self: Stream<Item = DispatcherHandlerCx<Message>>,
|
||||
{
|
||||
Box::pin(self.filter_map(|cx| async move {
|
||||
cx.update.text_owned().map(|text| (cx, text))
|
||||
}))
|
||||
}
|
||||
|
||||
fn commands<C>(
|
||||
self,
|
||||
) -> BoxStream<'static, (DispatcherHandlerCx<Message>, C, Vec<String>)>
|
||||
where
|
||||
Self: Stream<Item = (DispatcherHandlerCx<Message>, String)>,
|
||||
C: BotCommand,
|
||||
{
|
||||
Box::pin(self.filter_map(|(cx, text)| async move {
|
||||
C::parse(&text).map(|(command, args)| {
|
||||
(
|
||||
cx,
|
||||
command,
|
||||
args.into_iter()
|
||||
.map(ToOwned::to_owned)
|
||||
.collect::<Vec<String>>(),
|
||||
)
|
||||
})
|
||||
}))
|
||||
}
|
||||
}
|
|
@ -81,11 +81,13 @@ pub mod dialogue;
|
|||
mod dispatcher;
|
||||
mod dispatcher_handler;
|
||||
mod dispatcher_handler_cx;
|
||||
mod dispatcher_handler_rx_ext;
|
||||
pub mod update_listeners;
|
||||
|
||||
pub use dispatcher::Dispatcher;
|
||||
pub use dispatcher_handler::DispatcherHandler;
|
||||
pub use dispatcher_handler_cx::DispatcherHandlerCx;
|
||||
pub use dispatcher_handler_rx_ext::DispatcherHandlerRxExt;
|
||||
use tokio::sync::mpsc::UnboundedReceiver;
|
||||
|
||||
/// A type of a stream, consumed by [`Dispatcher`]'s handlers.
|
||||
|
|
22
src/lib.rs
22
src/lib.rs
|
@ -42,7 +42,6 @@
|
|||
//! [dependencies]
|
||||
//! teloxide = "0.1.0"
|
||||
//! log = "0.4.8"
|
||||
//! futures = "0.3.4"
|
||||
//! tokio = "0.2.11"
|
||||
//! pretty_env_logger = "0.4.0"
|
||||
//! ```
|
||||
|
@ -99,7 +98,6 @@
|
|||
//! ```no_run
|
||||
//! // Imports are omitted...
|
||||
//! # use teloxide::{prelude::*, utils::command::BotCommand};
|
||||
//! # use futures::future;
|
||||
//! # use rand::{thread_rng, Rng};
|
||||
//!
|
||||
//! #[derive(BotCommand)]
|
||||
|
@ -134,15 +132,12 @@
|
|||
//! }
|
||||
//!
|
||||
//! async fn handle_command(rx: DispatcherHandlerRx<Message>) {
|
||||
//! rx.filter_map(|cx| {
|
||||
//! future::ready(cx.update.text_owned().map(|text| (cx, text)))
|
||||
//! })
|
||||
//! .filter_map(|(cx, text)| {
|
||||
//! future::ready(
|
||||
//! Command::parse(&text).map(|(command, _)| (cx, command)),
|
||||
//! )
|
||||
//! })
|
||||
//! .for_each_concurrent(None, |(cx, command)| async move {
|
||||
//! // Only iterate through text messages:
|
||||
//! rx.text_messages()
|
||||
//! // Only iterate through commands in a proper format:
|
||||
//! .commands::<Command>()
|
||||
//! // Execute all incoming commands concurrently:
|
||||
//! .for_each_concurrent(None, |(cx, command, _)| async move {
|
||||
//! answer(cx, command).await.log_on_error().await;
|
||||
//! })
|
||||
//! .await;
|
||||
|
@ -178,8 +173,8 @@
|
|||
//!
|
||||
//!
|
||||
//! See? The dispatcher gives us a stream of messages, so we can handle it as we
|
||||
//! want! Here we use [`.filter_map()`] and [`.for_each_concurrent()`], but
|
||||
//! others are also available:
|
||||
//! want! Here we use our `.text_messages()`, `.commands()`, and
|
||||
//! [`.for_each_concurrent()`], but others are also available:
|
||||
//! - [`.flatten()`](https://docs.rs/futures/0.3.4/futures/stream/trait.StreamExt.html#method.flatten)
|
||||
//! - [`.left_stream()`](https://docs.rs/futures/0.3.4/futures/stream/trait.StreamExt.html#method.left_stream)
|
||||
//! - [`.scan()`](https://docs.rs/futures/0.3.4/futures/stream/trait.StreamExt.html#method.scan)
|
||||
|
@ -349,7 +344,6 @@
|
|||
//! [@Botfather]: https://t.me/botfather
|
||||
//! [streams]: https://docs.rs/futures/0.3.4/futures/stream/index.html
|
||||
//! [all 30+ patterns]: https://docs.rs/futures/0.3.4/futures/stream/trait.StreamExt.html
|
||||
//! [`.filter_map()`]: https://docs.rs/futures/0.3.4/futures/stream/trait.StreamExt.html#method.filter_map
|
||||
//! [`.for_each_concurrent()`]: https://docs.rs/futures/0.3.4/futures/stream/trait.StreamExt.html#method.for_each_concurrent
|
||||
//! [See more examples]: https://github.com/teloxide/teloxide/tree/master/examples
|
||||
//! [category theory]: https://en.wikipedia.org/wiki/Category_theory
|
||||
|
|
|
@ -7,6 +7,7 @@ pub use crate::{
|
|||
DialogueStage, GetChatId,
|
||||
},
|
||||
Dispatcher, DispatcherHandlerCx, DispatcherHandlerRx,
|
||||
DispatcherHandlerRxExt,
|
||||
},
|
||||
error_handlers::{LoggingErrorHandler, OnError},
|
||||
requests::{Request, ResponseResult},
|
||||
|
|
Loading…
Reference in a new issue