Module tbot::compositors
source · Expand description
Useful compositors for update handlers.
Let’s start with a simple example. You’re writing a bot, and its main
functionality is searching through something. In private chats, it’s enough
to send a text message to start searching; but in groups, it’s better to
search only when someone sent the /search
command. Since you already
expected to have the same logic in different handlers, you wrote a generic
handler, search
, and then registered it like this:
use std::sync::Arc;
use tbot::{Bot, contexts::fields::Text, prelude::*};
async fn search(context: Arc<impl Text>) {
// ..
}
let mut bot = Bot::from_env("BOT_TOKEN").event_loop();
bot.text(|context| async move {
if context.chat.kind.is_private() {
search(context).await;
}
});
bot.command("search", search);
The text
handler seems a bit too long just to filter out messages from
channels and groups. That’s where we can make use of our first compositor,
filter
! It takes a predicate and a handler and returns its own handler.
If the predicate returns true
, filter
’s handler executes yours.
Here’s an example:
use tbot::{contexts::Text, compositors::filter};
bot.text(filter(
|context: Arc<Text>| async move { context.chat.kind.is_private() },
search,
));
That looks better! But tbot
already provides the predicate we just wrote
ourselves, so let’s use that:
use tbot::{compositors::filter, predicates::chat::is_private};
bot.text(filter(is_private, search));
Great! Now you see how compositors make registering handlers easier.
filter
isn’t the only compositor, you’ll find all of them in this
module.
Remember one thing though. Compositors add layers between the handler
and handler registers. If you’re going to use a closure for your handler,
type inference will fail and you’ll have to explicitly define context
’s
type, as seen in the example with an inlined predicate above. That only
affects closures: using plain functions is fine even with generics, as seen
in the last example.
Modules
StatefulEventLoop
.Functions
handler
only if predicate
returns true
.predicate
, and if it returned Some
,
calls handler
with that value.mapper
, and then passes its return value to handler
.