use ruma::events::{
AnySyncStateEvent, AnySyncTimelineEvent, SyncStateEvent, TimelineEventType,
room::member::{MembershipChange, MembershipState},
};
#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
pub enum TimelineEventFilter {
Include(Vec<TimelineEventCondition>),
Exclude(Vec<TimelineEventCondition>),
}
impl TimelineEventFilter {
pub fn filter(&self, event: &AnySyncTimelineEvent) -> bool {
match self {
Self::Include(conditions) => conditions.iter().any(|c| c.matches(event)),
Self::Exclude(conditions) => !conditions.iter().any(|c| c.matches(event)),
}
}
}
#[derive(Clone)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
pub enum TimelineEventCondition {
EventType(TimelineEventType),
MembershipChange(MembershipChangeFilter),
ProfileChange,
AnyCustomMessageLikeEvent,
AnyCustomStateEvent,
}
#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
#[derive(Clone)]
pub enum MembershipChangeFilter {
Any,
Join,
Leave,
Invite,
Ban,
Knock,
}
impl TimelineEventCondition {
fn matches(&self, event: &AnySyncTimelineEvent) -> bool {
match self {
Self::EventType(event_type) => event.event_type() == *event_type,
Self::MembershipChange(filter) => match event {
AnySyncTimelineEvent::State(AnySyncStateEvent::RoomMember(
SyncStateEvent::Original(ev),
)) => {
if matches!(ev.membership_change(), MembershipChange::ProfileChanged { .. }) {
return false;
}
match (filter, &ev.content.membership) {
(MembershipChangeFilter::Any, _) => {
!matches!(ev.membership_change(), MembershipChange::None)
}
(MembershipChangeFilter::Join, MembershipState::Join) => true,
(MembershipChangeFilter::Invite, MembershipState::Invite) => true,
(MembershipChangeFilter::Leave, MembershipState::Leave) => true,
(MembershipChangeFilter::Knock, MembershipState::Knock) => true,
(MembershipChangeFilter::Ban, MembershipState::Ban) => true,
_ => false,
}
}
_ => false,
},
Self::ProfileChange => match event {
AnySyncTimelineEvent::State(AnySyncStateEvent::RoomMember(
SyncStateEvent::Original(ev),
)) => {
matches!(ev.membership_change(), MembershipChange::ProfileChanged { .. })
}
_ => false,
},
Self::AnyCustomMessageLikeEvent => match event {
AnySyncTimelineEvent::MessageLike(_) => {
matches!(event.event_type(), TimelineEventType::_Custom(_))
}
AnySyncTimelineEvent::State(_) => false,
},
Self::AnyCustomStateEvent => match event {
AnySyncTimelineEvent::State(_) => {
matches!(event.event_type(), TimelineEventType::_Custom(_))
}
AnySyncTimelineEvent::MessageLike(_) => false,
},
}
}
}