From b7369074d4d9e235c4bb9a7529e98c1aa5a662b1 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Fri, 25 Oct 2024 02:56:24 +0000 Subject: [PATCH] add RoomEventFilter matcher for PduEvent Signed-off-by: Jason Volk --- src/core/pdu/filter.rs | 90 ++++++++++++++++++++++++++++++++++++++++++ src/core/pdu/mod.rs | 1 + 2 files changed, 91 insertions(+) create mode 100644 src/core/pdu/filter.rs diff --git a/src/core/pdu/filter.rs b/src/core/pdu/filter.rs new file mode 100644 index 00000000..bd232ebd --- /dev/null +++ b/src/core/pdu/filter.rs @@ -0,0 +1,90 @@ +use ruma::api::client::filter::{RoomEventFilter, UrlFilter}; +use serde_json::Value; + +use crate::{implement, is_equal_to}; + +#[implement(super::PduEvent)] +#[must_use] +pub fn matches(&self, filter: &RoomEventFilter) -> bool { + if !self.matches_sender(filter) { + return false; + } + + if !self.matches_room(filter) { + return false; + } + + if !self.matches_type(filter) { + return false; + } + + if !self.matches_url(filter) { + return false; + } + + true +} + +#[implement(super::PduEvent)] +fn matches_room(&self, filter: &RoomEventFilter) -> bool { + if filter.not_rooms.contains(&self.room_id) { + return false; + } + + if let Some(rooms) = filter.rooms.as_ref() { + if !rooms.contains(&self.room_id) { + return false; + } + } + + true +} + +#[implement(super::PduEvent)] +fn matches_sender(&self, filter: &RoomEventFilter) -> bool { + if filter.not_senders.contains(&self.sender) { + return false; + } + + if let Some(senders) = filter.senders.as_ref() { + if !senders.contains(&self.sender) { + return false; + } + } + + true +} + +#[implement(super::PduEvent)] +fn matches_type(&self, filter: &RoomEventFilter) -> bool { + let event_type = &self.kind.to_cow_str(); + if filter.not_types.iter().any(is_equal_to!(event_type)) { + return false; + } + + if let Some(types) = filter.types.as_ref() { + if !types.iter().any(is_equal_to!(event_type)) { + return false; + } + } + + true +} + +#[implement(super::PduEvent)] +fn matches_url(&self, filter: &RoomEventFilter) -> bool { + let Some(url_filter) = filter.url_filter.as_ref() else { + return true; + }; + + //TODO: might be better to use Ruma's Raw rather than serde here + let url = serde_json::from_str::(self.content.get()) + .expect("parsing content JSON failed") + .get("url") + .is_some_and(Value::is_string); + + match url_filter { + UrlFilter::EventsWithUrl => url, + UrlFilter::EventsWithoutUrl => !url, + } +} diff --git a/src/core/pdu/mod.rs b/src/core/pdu/mod.rs index 9970c39e..ed11adbb 100644 --- a/src/core/pdu/mod.rs +++ b/src/core/pdu/mod.rs @@ -1,6 +1,7 @@ mod builder; mod content; mod count; +mod filter; mod id; mod redact; mod state_res;