feat: add support for unstable-msc3931/3932 style push conditions parsing
This commit is contained in:
		
							parent
							
								
									89e06adecf
								
							
						
					
					
						commit
						9460702b00
					
				| @ -43,6 +43,8 @@ unstable-msc3552 = ["unstable-msc3551"] | ||||
| unstable-msc3553 = ["unstable-msc3552"] | ||||
| unstable-msc3554 = ["unstable-msc1767"] | ||||
| unstable-msc3783 = [] | ||||
| unstable-msc3931 = [] | ||||
| unstable-msc3932 = ["unstable-msc3931"] | ||||
| unstable-pdu = [] | ||||
| unstable-sanitize = ["dep:html5ever", "dep:phf"] | ||||
| unstable-unspecified = [] | ||||
|  | ||||
| @ -33,6 +33,8 @@ mod condition; | ||||
| mod iter; | ||||
| mod predefined; | ||||
| 
 | ||||
| #[cfg(feature = "unstable-msc3932")] | ||||
| pub use self::condition::RoomVersionFeature; | ||||
| pub use self::{ | ||||
|     action::{Action, Tweak}, | ||||
|     condition::{ | ||||
| @ -433,7 +435,33 @@ impl ConditionalPushRule { | ||||
|     /// * `event` - The flattened JSON representation of a room message event.
 | ||||
|     /// * `context` - The context of the room at the time of the event.
 | ||||
|     pub fn applies(&self, event: &FlattenedJson, context: &PushConditionRoomCtx) -> bool { | ||||
|         self.enabled && self.conditions.iter().all(|cond| cond.applies(event, context)) | ||||
|         if !self.enabled { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         #[cfg(feature = "unstable-msc3932")] | ||||
|         { | ||||
|             // These 3 rules always apply.
 | ||||
|             if self.rule_id != PredefinedOverrideRuleId::Master.as_ref() | ||||
|                 && self.rule_id != PredefinedOverrideRuleId::RoomNotif.as_ref() | ||||
|                 && self.rule_id != PredefinedOverrideRuleId::ContainsDisplayName.as_ref() | ||||
|             { | ||||
|                 // Push rules which don't specify a `room_version_supports` condition are assumed
 | ||||
|                 // to not support extensible events and are therefore expected to be treated as
 | ||||
|                 // disabled when a room version does support extensible events.
 | ||||
|                 let room_supports_ext_ev = | ||||
|                     context.supported_features.contains(&RoomVersionFeature::ExtensibleEvents); | ||||
|                 let rule_has_room_version_supports = self.conditions.iter().any(|condition| { | ||||
|                     matches!(condition, PushCondition::RoomVersionSupports { .. }) | ||||
|                 }); | ||||
| 
 | ||||
|                 if room_supports_ext_ev && !rule_has_room_version_supports { | ||||
|                     return false; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         self.conditions.iter().all(|cond| cond.applies(event, context)) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -1337,6 +1365,8 @@ mod tests { | ||||
|             users_power_levels: BTreeMap::new(), | ||||
|             default_power_level: int!(50), | ||||
|             notification_power_levels: NotificationPowerLevels { room: int!(50) }, | ||||
|             #[cfg(feature = "unstable-msc3931")] | ||||
|             supported_features: Default::default(), | ||||
|         }; | ||||
| 
 | ||||
|         let context_public_room = &PushConditionRoomCtx { | ||||
| @ -1347,6 +1377,8 @@ mod tests { | ||||
|             users_power_levels: BTreeMap::new(), | ||||
|             default_power_level: int!(50), | ||||
|             notification_power_levels: NotificationPowerLevels { room: int!(50) }, | ||||
|             #[cfg(feature = "unstable-msc3931")] | ||||
|             supported_features: Default::default(), | ||||
|         }; | ||||
| 
 | ||||
|         let message = serde_json::from_str::<Raw<JsonValue>>( | ||||
| @ -1438,6 +1470,8 @@ mod tests { | ||||
|             users_power_levels: BTreeMap::new(), | ||||
|             default_power_level: int!(50), | ||||
|             notification_power_levels: NotificationPowerLevels { room: int!(50) }, | ||||
|             #[cfg(feature = "unstable-msc3931")] | ||||
|             supported_features: Default::default(), | ||||
|         }; | ||||
| 
 | ||||
|         let message = serde_json::from_str::<Raw<JsonValue>>( | ||||
|  | ||||
| @ -2,17 +2,60 @@ use std::{collections::BTreeMap, ops::RangeBounds, str::FromStr}; | ||||
| 
 | ||||
| use js_int::{Int, UInt}; | ||||
| use regex::Regex; | ||||
| #[cfg(feature = "unstable-msc3931")] | ||||
| use ruma_macros::StringEnum; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| use serde_json::{to_value as to_json_value, value::Value as JsonValue}; | ||||
| use tracing::{instrument, warn}; | ||||
| use wildmatch::WildMatch; | ||||
| 
 | ||||
| use crate::{power_levels::NotificationPowerLevels, serde::Raw, OwnedRoomId, OwnedUserId, UserId}; | ||||
| #[cfg(feature = "unstable-msc3931")] | ||||
| use crate::{PrivOwnedStr, RoomVersionId}; | ||||
| 
 | ||||
| mod room_member_count_is; | ||||
| 
 | ||||
| pub use room_member_count_is::{ComparisonOperator, RoomMemberCountIs}; | ||||
| 
 | ||||
| /// Features supported by room versions.
 | ||||
| #[cfg(feature = "unstable-msc3931")] | ||||
| #[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/doc/string_enum.md"))] | ||||
| #[derive(Clone, Debug, PartialEq, Eq, StringEnum)] | ||||
| #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] | ||||
| pub enum RoomVersionFeature { | ||||
|     /// m.extensible_events
 | ||||
|     ///
 | ||||
|     /// The room supports [extensible events].
 | ||||
|     ///
 | ||||
|     /// [extensible events]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767
 | ||||
|     #[cfg(feature = "unstable-msc3932")] | ||||
|     #[ruma_enum(rename = "org.matrix.msc3932.extensible_events")] | ||||
|     ExtensibleEvents, | ||||
| 
 | ||||
|     #[doc(hidden)] | ||||
|     _Custom(PrivOwnedStr), | ||||
| } | ||||
| 
 | ||||
| #[cfg(feature = "unstable-msc3931")] | ||||
| impl RoomVersionFeature { | ||||
|     /// Get the default features for the given room version.
 | ||||
|     pub fn list_for_room_version(version: &RoomVersionId) -> Vec<Self> { | ||||
|         match version { | ||||
|             RoomVersionId::V1 | ||||
|             | RoomVersionId::V2 | ||||
|             | RoomVersionId::V3 | ||||
|             | RoomVersionId::V4 | ||||
|             | RoomVersionId::V5 | ||||
|             | RoomVersionId::V6 | ||||
|             | RoomVersionId::V7 | ||||
|             | RoomVersionId::V8 | ||||
|             | RoomVersionId::V9 | ||||
|             | RoomVersionId::V10 | ||||
|             | RoomVersionId::_Custom(_) => vec![], | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// A condition that must apply for an associated push rule's action to be taken.
 | ||||
| #[derive(Clone, Debug, Deserialize, Serialize)] | ||||
| #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] | ||||
| @ -49,6 +92,14 @@ pub enum PushCondition { | ||||
|         /// `content`.
 | ||||
|         key: String, | ||||
|     }, | ||||
| 
 | ||||
|     /// Apply the rule only to rooms that support a given feature.
 | ||||
|     #[cfg(feature = "unstable-msc3931")] | ||||
|     #[serde(rename = "org.matrix.msc3931.room_version_supports")] | ||||
|     RoomVersionSupports { | ||||
|         /// The feature the room must support for the push rule to apply.
 | ||||
|         feature: RoomVersionFeature, | ||||
|     }, | ||||
| } | ||||
| 
 | ||||
| pub(super) fn check_event_match( | ||||
| @ -110,6 +161,13 @@ impl PushCondition { | ||||
|                     None => false, | ||||
|                 } | ||||
|             } | ||||
|             #[cfg(feature = "unstable-msc3931")] | ||||
|             Self::RoomVersionSupports { feature } => match feature { | ||||
|                 RoomVersionFeature::ExtensibleEvents => { | ||||
|                     context.supported_features.contains(&RoomVersionFeature::ExtensibleEvents) | ||||
|                 } | ||||
|                 RoomVersionFeature::_Custom(_) => false, | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -138,6 +196,10 @@ pub struct PushConditionRoomCtx { | ||||
| 
 | ||||
|     /// The notification power levels of the room.
 | ||||
|     pub notification_power_levels: NotificationPowerLevels, | ||||
| 
 | ||||
|     #[cfg(feature = "unstable-msc3931")] | ||||
|     /// The list of features this room's version or the room itself supports.
 | ||||
|     pub supported_features: Vec<RoomVersionFeature>, | ||||
| } | ||||
| 
 | ||||
| /// Additional functions for character matching.
 | ||||
| @ -585,6 +647,8 @@ mod tests { | ||||
|             users_power_levels, | ||||
|             default_power_level: int!(50), | ||||
|             notification_power_levels: NotificationPowerLevels { room: int!(50) }, | ||||
|             #[cfg(feature = "unstable-msc3931")] | ||||
|             supported_features: Default::default(), | ||||
|         }; | ||||
| 
 | ||||
|         let first_event_raw = serde_json::from_str::<Raw<JsonValue>>( | ||||
| @ -658,6 +722,56 @@ mod tests { | ||||
|         assert!(sender_notification_permission.applies(&second_event, &context)); | ||||
|     } | ||||
| 
 | ||||
|     #[cfg(feature = "unstable-msc3932")] | ||||
|     #[test] | ||||
|     fn conditions_apply_to_events_in_room_with_feature() { | ||||
|         let first_sender = user_id!("@worthy_whale:server.name").to_owned(); | ||||
| 
 | ||||
|         let mut users_power_levels = BTreeMap::new(); | ||||
|         users_power_levels.insert(first_sender, int!(25)); | ||||
| 
 | ||||
|         let context_matching = PushConditionRoomCtx { | ||||
|             room_id: room_id!("!room:server.name").to_owned(), | ||||
|             member_count: uint!(3), | ||||
|             user_id: user_id!("@gorilla:server.name").to_owned(), | ||||
|             user_display_name: "Groovy Gorilla".into(), | ||||
|             users_power_levels: users_power_levels.clone(), | ||||
|             default_power_level: int!(50), | ||||
|             notification_power_levels: NotificationPowerLevels { room: int!(50) }, | ||||
|             supported_features: vec![super::RoomVersionFeature::ExtensibleEvents], | ||||
|         }; | ||||
| 
 | ||||
|         let context_not_matching = PushConditionRoomCtx { | ||||
|             room_id: room_id!("!room:server.name").to_owned(), | ||||
|             member_count: uint!(3), | ||||
|             user_id: user_id!("@gorilla:server.name").to_owned(), | ||||
|             user_display_name: "Groovy Gorilla".into(), | ||||
|             users_power_levels, | ||||
|             default_power_level: int!(50), | ||||
|             notification_power_levels: NotificationPowerLevels { room: int!(50) }, | ||||
|             supported_features: vec![], | ||||
|         }; | ||||
| 
 | ||||
|         let simple_event_raw = serde_json::from_str::<Raw<JsonValue>>( | ||||
|             r#"{
 | ||||
|                 "sender": "@worthy_whale:server.name", | ||||
|                 "content": { | ||||
|                     "msgtype": "org.matrix.msc3932.extensible_events", | ||||
|                     "body": "@room Give a warm welcome to Groovy Gorilla" | ||||
|                 } | ||||
|             }"#,
 | ||||
|         ) | ||||
|         .unwrap(); | ||||
|         let simple_event = FlattenedJson::from_raw(&simple_event_raw); | ||||
| 
 | ||||
|         let room_version_condition = PushCondition::RoomVersionSupports { | ||||
|             feature: super::RoomVersionFeature::ExtensibleEvents, | ||||
|         }; | ||||
| 
 | ||||
|         assert!(room_version_condition.applies(&simple_event, &context_matching)); | ||||
|         assert!(!room_version_condition.applies(&simple_event, &context_not_matching)); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn flattened_json_values() { | ||||
|         let raw = serde_json::from_str::<Raw<JsonValue>>( | ||||
|  | ||||
| @ -155,6 +155,8 @@ unstable-msc3575 = ["ruma-client-api?/unstable-msc3575"] | ||||
| unstable-msc3618 = ["ruma-federation-api?/unstable-msc3618"] | ||||
| unstable-msc3723 = ["ruma-federation-api?/unstable-msc3723"] | ||||
| unstable-msc3783 = ["ruma-common/unstable-msc3783"] | ||||
| unstable-msc3931 = ["ruma-common/unstable-msc3931"] | ||||
| unstable-msc3932 = ["ruma-common/unstable-msc3932"] | ||||
| unstable-pdu = ["ruma-common/unstable-pdu"] | ||||
| unstable-sanitize = ["ruma-common/unstable-sanitize"] | ||||
| unstable-unspecified = [ | ||||
| @ -193,6 +195,7 @@ __ci = [ | ||||
|     "unstable-msc3618", | ||||
|     "unstable-msc3723", | ||||
|     "unstable-msc3783", | ||||
|     "unstable-msc3932", | ||||
| ] | ||||
| 
 | ||||
| [dependencies] | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user