From 27906a16841b17aff69fb86d0135d4b249b729e5 Mon Sep 17 00:00:00 2001 From: Pavel Kirilin <win10@list.ru> Date: Fri, 24 Feb 2023 09:27:32 +0000 Subject: [PATCH] Added midlewares. --- Cargo.lock | 1 + Cargo.toml | 1 + src/bot/filters/filtered_handler.rs | 8 +++++- src/bot/handlers/fun/greeter.rs | 10 ++----- src/bot/main.rs | 10 +++++-- src/bot/middlewares/base.rs | 5 ++++ src/bot/middlewares/mark_unread.rs | 43 ++++++++++++++++++++++++++++ src/bot/middlewares/members_count.rs | 36 +++++++++++++++++++++++ src/bot/middlewares/mod.rs | 3 ++ src/bot/mod.rs | 1 + 10 files changed, 106 insertions(+), 12 deletions(-) create mode 100644 src/bot/middlewares/base.rs create mode 100644 src/bot/middlewares/mark_unread.rs create mode 100644 src/bot/middlewares/members_count.rs create mode 100644 src/bot/middlewares/mod.rs diff --git a/Cargo.lock b/Cargo.lock index f7f525a..a5684ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2151,6 +2151,7 @@ dependencies = [ "futures", "grammers-client", "grammers-session", + "grammers-tl-types", "lazy_static", "log", "rand 0.8.5", diff --git a/Cargo.toml b/Cargo.toml index fbc8a78..421376d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ dyn-clone = "1.0.10" fern = { version = "0.6.1", features = ["chrono", "colored"] } futures = "0.3.26" grammers-client = { version = "0.4.0", features = ["markdown", "html"] } +grammers-tl-types = { version = "0.4.0" } grammers-session = "0.4.0" lazy_static = "1.4.0" log = "0.4.17" diff --git a/src/bot/filters/filtered_handler.rs b/src/bot/filters/filtered_handler.rs index 44fd29f..85a59cd 100644 --- a/src/bot/filters/filtered_handler.rs +++ b/src/bot/filters/filtered_handler.rs @@ -1,6 +1,6 @@ use grammers_client::Update; -use crate::bot::handlers::Handler; +use crate::bot::{handlers::Handler, middlewares::base::Middleware}; use super::base::Filter; @@ -28,6 +28,12 @@ impl FilteredHandler { self } + /// Wraps a middleware around a handler. + pub fn add_middleware<M: Middleware + 'static>(mut self) -> Self { + self.handler = Box::new(M::from_handler(self.handler)); + self + } + /// This method performs checks for all filters we have. /// We run it not in parralel for fast fail strategy. pub fn check(&self, update: &Update) -> bool { diff --git a/src/bot/handlers/fun/greeter.rs b/src/bot/handlers/fun/greeter.rs index fc83bd3..f5ae4c8 100644 --- a/src/bot/handlers/fun/greeter.rs +++ b/src/bot/handlers/fun/greeter.rs @@ -20,17 +20,11 @@ pub struct Greeter; #[async_trait] impl Handler for Greeter { - async fn react(&self, client: &Client, update: &Update) -> anyhow::Result<()> { + async fn react(&self, _: &Client, update: &Update) -> anyhow::Result<()> { let Update::NewMessage(message) = update else {return Ok(())}; - // Check if chat has less than 100 participants. - let participants = client.iter_participants(message.chat()).total().await?; - if participants >= 100 { - return Ok(()); - } - // Choose random greeting from the list of greetings. - let reply_text = GREETINGS.iter().choose(&mut rand::thread_rng()).copied(); + let reply_text = GREETINGS.iter().choose(&mut rand::rngs::OsRng).copied(); if let Some(text) = reply_text { message.reply(text).await?; diff --git a/src/bot/main.rs b/src/bot/main.rs index 5241355..1ea8623 100644 --- a/src/bot/main.rs +++ b/src/bot/main.rs @@ -25,6 +25,7 @@ use super::{ fun::{blyaficator::Blyaficator, greeter::Greeter, repeator::Repeator, rotator::Rotator}, Handler, }, + middlewares::members_count::MembersCount, }; /// Authorization function. @@ -103,7 +104,8 @@ async fn run(args: BotConfig, client: Client) -> anyhow::Result<()> { .add_filter(SilentFilter) .add_filter(ExcludedChatsFilter(vec![me.id()])) .add_filter(TextFilter(&["привет"], TextMatchMethod::IStartsWith)) - .add_filter(ExcludedChatsFilter(args.excluded_chats)), + .add_filter(ExcludedChatsFilter(args.excluded_chats)) + .add_middleware::<MembersCount<100>>(), // Getting chat id. FilteredHandler::new(GetChatId) .add_filter(TextFilter(&[".cid"], TextMatchMethod::IMatches)), @@ -117,7 +119,8 @@ async fn run(args: BotConfig, client: Client) -> anyhow::Result<()> { .add_filter(UpdateTypeFilter(&[UpdateType::New])) .add_filter(SilentFilter) .add_filter(ExcludedChatsFilter(args.currency_excluded_chats)) - .add_filter(CurrencyTextFilter), + .add_filter(CurrencyTextFilter) + .add_middleware::<MembersCount<100>>(), // Simlpe rotator. FilteredHandler::new(Rotator) .add_filter(UpdateTypeFilter(&[UpdateType::New])) @@ -134,7 +137,8 @@ async fn run(args: BotConfig, client: Client) -> anyhow::Result<()> { .add_filter(MessageDirectionFilter(MessageDirection::Incoming)) .add_filter(SilentFilter) .add_filter(ExcludedChatsFilter(vec![me.id()])) - .add_filter(RegexFilter(Regex::new("^[)0]+$")?)), + .add_filter(RegexFilter(Regex::new("^[)0]+$")?)) + .add_middleware::<MembersCount<100>>(), ]; let mut errors_count = 0; diff --git a/src/bot/middlewares/base.rs b/src/bot/middlewares/base.rs new file mode 100644 index 0000000..f441fd7 --- /dev/null +++ b/src/bot/middlewares/base.rs @@ -0,0 +1,5 @@ +use crate::bot::handlers::Handler; + +pub trait Middleware: Handler { + fn from_handler(handler: Box<dyn Handler>) -> Self; +} diff --git a/src/bot/middlewares/mark_unread.rs b/src/bot/middlewares/mark_unread.rs new file mode 100644 index 0000000..186983a --- /dev/null +++ b/src/bot/middlewares/mark_unread.rs @@ -0,0 +1,43 @@ +use grammers_client::{Client, Update}; +use grammers_tl_types::types::{InputDialogPeer, InputPeerChat}; + +use crate::{ + bot::{handlers::Handler, middlewares::base::Middleware}, + utils::messages::get_message, +}; + +#[derive(Clone)] +pub struct MarkUnread { + handler: Box<dyn Handler>, +} + +#[async_trait::async_trait] +impl Handler for MarkUnread { + async fn react(&self, client: &Client, update: &Update) -> anyhow::Result<()> { + let res = self.handler.react(client, update).await; + + if let Some(message) = get_message(update) { + let res = client + .invoke(&grammers_tl_types::functions::messages::MarkDialogUnread { + peer: grammers_tl_types::enums::InputDialogPeer::Peer(InputDialogPeer { + peer: grammers_tl_types::enums::InputPeer::Chat(InputPeerChat { + chat_id: message.chat().id(), + }), + }), + unread: true, + }) + .await; + if let Err(err) = res { + log::warn!("Cannot mark dialog unread. Reason: {err}."); + } + } + + res + } +} + +impl Middleware for MarkUnread { + fn from_handler(handler: Box<dyn Handler>) -> Self { + Self { handler } + } +} diff --git a/src/bot/middlewares/members_count.rs b/src/bot/middlewares/members_count.rs new file mode 100644 index 0000000..ef7d8aa --- /dev/null +++ b/src/bot/middlewares/members_count.rs @@ -0,0 +1,36 @@ +use grammers_client::{Client, Update}; + +use crate::{ + bot::{handlers::Handler, middlewares::base::Middleware}, + utils::messages::get_message, +}; + +#[derive(Clone)] +pub struct MembersCount<const MAX_COUNT: usize> { + handler: Box<dyn Handler>, +} + +#[async_trait::async_trait] +impl<const MAX_COUNT: usize> Handler for MembersCount<MAX_COUNT> { + async fn react(&self, client: &Client, update: &Update) -> anyhow::Result<()> { + if let Some(message) = get_message(update) { + let participants = client + .iter_participants(message.chat()) + .total() + .await + .unwrap_or(0); + + if participants > MAX_COUNT { + log::warn!("Too many participants. Skipping."); + return Ok(()); + } + } + self.handler.react(client, update).await + } +} + +impl<const MAX_COUNT: usize> Middleware for MembersCount<MAX_COUNT> { + fn from_handler(handler: Box<dyn Handler>) -> Self { + Self { handler } + } +} diff --git a/src/bot/middlewares/mod.rs b/src/bot/middlewares/mod.rs new file mode 100644 index 0000000..d0ec112 --- /dev/null +++ b/src/bot/middlewares/mod.rs @@ -0,0 +1,3 @@ +pub mod base; +pub mod mark_unread; +pub mod members_count; diff --git a/src/bot/mod.rs b/src/bot/mod.rs index 340c21b..0aeb394 100644 --- a/src/bot/mod.rs +++ b/src/bot/mod.rs @@ -1,6 +1,7 @@ mod filters; mod handlers; mod main; +pub mod middlewares; pub mod utils; pub use main::start; -- GitLab