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-msc3553 = ["unstable-msc3552"] | ||||||
| unstable-msc3554 = ["unstable-msc1767"] | unstable-msc3554 = ["unstable-msc1767"] | ||||||
| unstable-msc3783 = [] | unstable-msc3783 = [] | ||||||
|  | unstable-msc3931 = [] | ||||||
|  | unstable-msc3932 = ["unstable-msc3931"] | ||||||
| unstable-pdu = [] | unstable-pdu = [] | ||||||
| unstable-sanitize = ["dep:html5ever", "dep:phf"] | unstable-sanitize = ["dep:html5ever", "dep:phf"] | ||||||
| unstable-unspecified = [] | unstable-unspecified = [] | ||||||
|  | |||||||
| @ -33,6 +33,8 @@ mod condition; | |||||||
| mod iter; | mod iter; | ||||||
| mod predefined; | mod predefined; | ||||||
| 
 | 
 | ||||||
|  | #[cfg(feature = "unstable-msc3932")] | ||||||
|  | pub use self::condition::RoomVersionFeature; | ||||||
| pub use self::{ | pub use self::{ | ||||||
|     action::{Action, Tweak}, |     action::{Action, Tweak}, | ||||||
|     condition::{ |     condition::{ | ||||||
| @ -433,7 +435,33 @@ impl ConditionalPushRule { | |||||||
|     /// * `event` - The flattened JSON representation of a room message event.
 |     /// * `event` - The flattened JSON representation of a room message event.
 | ||||||
|     /// * `context` - The context of the room at the time of the event.
 |     /// * `context` - The context of the room at the time of the event.
 | ||||||
|     pub fn applies(&self, event: &FlattenedJson, context: &PushConditionRoomCtx) -> bool { |     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(), |             users_power_levels: BTreeMap::new(), | ||||||
|             default_power_level: int!(50), |             default_power_level: int!(50), | ||||||
|             notification_power_levels: NotificationPowerLevels { room: int!(50) }, |             notification_power_levels: NotificationPowerLevels { room: int!(50) }, | ||||||
|  |             #[cfg(feature = "unstable-msc3931")] | ||||||
|  |             supported_features: Default::default(), | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         let context_public_room = &PushConditionRoomCtx { |         let context_public_room = &PushConditionRoomCtx { | ||||||
| @ -1347,6 +1377,8 @@ mod tests { | |||||||
|             users_power_levels: BTreeMap::new(), |             users_power_levels: BTreeMap::new(), | ||||||
|             default_power_level: int!(50), |             default_power_level: int!(50), | ||||||
|             notification_power_levels: NotificationPowerLevels { room: 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>>( |         let message = serde_json::from_str::<Raw<JsonValue>>( | ||||||
| @ -1438,6 +1470,8 @@ mod tests { | |||||||
|             users_power_levels: BTreeMap::new(), |             users_power_levels: BTreeMap::new(), | ||||||
|             default_power_level: int!(50), |             default_power_level: int!(50), | ||||||
|             notification_power_levels: NotificationPowerLevels { room: 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>>( |         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 js_int::{Int, UInt}; | ||||||
| use regex::Regex; | use regex::Regex; | ||||||
|  | #[cfg(feature = "unstable-msc3931")] | ||||||
|  | use ruma_macros::StringEnum; | ||||||
| use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||||
| use serde_json::{to_value as to_json_value, value::Value as JsonValue}; | use serde_json::{to_value as to_json_value, value::Value as JsonValue}; | ||||||
| use tracing::{instrument, warn}; | use tracing::{instrument, warn}; | ||||||
| use wildmatch::WildMatch; | use wildmatch::WildMatch; | ||||||
| 
 | 
 | ||||||
| use crate::{power_levels::NotificationPowerLevels, serde::Raw, OwnedRoomId, OwnedUserId, UserId}; | use crate::{power_levels::NotificationPowerLevels, serde::Raw, OwnedRoomId, OwnedUserId, UserId}; | ||||||
|  | #[cfg(feature = "unstable-msc3931")] | ||||||
|  | use crate::{PrivOwnedStr, RoomVersionId}; | ||||||
| 
 | 
 | ||||||
| mod room_member_count_is; | mod room_member_count_is; | ||||||
| 
 | 
 | ||||||
| pub use room_member_count_is::{ComparisonOperator, RoomMemberCountIs}; | 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.
 | /// A condition that must apply for an associated push rule's action to be taken.
 | ||||||
| #[derive(Clone, Debug, Deserialize, Serialize)] | #[derive(Clone, Debug, Deserialize, Serialize)] | ||||||
| #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] | #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] | ||||||
| @ -49,6 +92,14 @@ pub enum PushCondition { | |||||||
|         /// `content`.
 |         /// `content`.
 | ||||||
|         key: String, |         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( | pub(super) fn check_event_match( | ||||||
| @ -110,6 +161,13 @@ impl PushCondition { | |||||||
|                     None => false, |                     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.
 |     /// The notification power levels of the room.
 | ||||||
|     pub notification_power_levels: NotificationPowerLevels, |     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.
 | /// Additional functions for character matching.
 | ||||||
| @ -585,6 +647,8 @@ mod tests { | |||||||
|             users_power_levels, |             users_power_levels, | ||||||
|             default_power_level: int!(50), |             default_power_level: int!(50), | ||||||
|             notification_power_levels: NotificationPowerLevels { room: 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>>( |         let first_event_raw = serde_json::from_str::<Raw<JsonValue>>( | ||||||
| @ -658,6 +722,56 @@ mod tests { | |||||||
|         assert!(sender_notification_permission.applies(&second_event, &context)); |         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] |     #[test] | ||||||
|     fn flattened_json_values() { |     fn flattened_json_values() { | ||||||
|         let raw = serde_json::from_str::<Raw<JsonValue>>( |         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-msc3618 = ["ruma-federation-api?/unstable-msc3618"] | ||||||
| unstable-msc3723 = ["ruma-federation-api?/unstable-msc3723"] | unstable-msc3723 = ["ruma-federation-api?/unstable-msc3723"] | ||||||
| unstable-msc3783 = ["ruma-common/unstable-msc3783"] | 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-pdu = ["ruma-common/unstable-pdu"] | ||||||
| unstable-sanitize = ["ruma-common/unstable-sanitize"] | unstable-sanitize = ["ruma-common/unstable-sanitize"] | ||||||
| unstable-unspecified = [ | unstable-unspecified = [ | ||||||
| @ -193,6 +195,7 @@ __ci = [ | |||||||
|     "unstable-msc3618", |     "unstable-msc3618", | ||||||
|     "unstable-msc3723", |     "unstable-msc3723", | ||||||
|     "unstable-msc3783", |     "unstable-msc3783", | ||||||
|  |     "unstable-msc3932", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| [dependencies] | [dependencies] | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user