1414
1515use std:: collections:: { BTreeMap , BTreeSet } ;
1616
17+ use crate :: push:: JsonValue ;
1718use anyhow:: { Context , Error } ;
1819use lazy_static:: lazy_static;
1920use log:: warn;
@@ -63,7 +64,7 @@ impl RoomVersionFeatures {
6364pub struct PushRuleEvaluator {
6465 /// A mapping of "flattened" keys to simple JSON values in the event, e.g.
6566 /// includes things like "type" and "content.msgtype".
66- flattened_keys : BTreeMap < String , SimpleJsonValue > ,
67+ flattened_keys : BTreeMap < String , JsonValue > ,
6768
6869 /// The "content.body", if any.
6970 body : String ,
@@ -87,7 +88,7 @@ pub struct PushRuleEvaluator {
8788
8889 /// The related events, indexed by relation type. Flattened in the same manner as
8990 /// `flattened_keys`.
90- related_events_flattened : BTreeMap < String , BTreeMap < String , SimpleJsonValue > > ,
91+ related_events_flattened : BTreeMap < String , BTreeMap < String , JsonValue > > ,
9192
9293 /// If msc3664, push rules for related events, is enabled.
9394 related_event_match_enabled : bool ,
@@ -101,6 +102,9 @@ pub struct PushRuleEvaluator {
101102
102103 /// If MSC3758 (exact_event_match push rule condition) is enabled.
103104 msc3758_exact_event_match : bool ,
105+
106+ /// If MSC3966 (exact_event_property_contains push rule condition) is enabled.
107+ msc3966_exact_event_property_contains : bool ,
104108}
105109
106110#[ pymethods]
@@ -109,21 +113,22 @@ impl PushRuleEvaluator {
109113 #[ allow( clippy:: too_many_arguments) ]
110114 #[ new]
111115 pub fn py_new (
112- flattened_keys : BTreeMap < String , SimpleJsonValue > ,
116+ flattened_keys : BTreeMap < String , JsonValue > ,
113117 has_mentions : bool ,
114118 user_mentions : BTreeSet < String > ,
115119 room_mention : bool ,
116120 room_member_count : u64 ,
117121 sender_power_level : Option < i64 > ,
118122 notification_power_levels : BTreeMap < String , i64 > ,
119- related_events_flattened : BTreeMap < String , BTreeMap < String , SimpleJsonValue > > ,
123+ related_events_flattened : BTreeMap < String , BTreeMap < String , JsonValue > > ,
120124 related_event_match_enabled : bool ,
121125 room_version_feature_flags : Vec < String > ,
122126 msc3931_enabled : bool ,
123127 msc3758_exact_event_match : bool ,
128+ msc3966_exact_event_property_contains : bool ,
124129 ) -> Result < Self , Error > {
125130 let body = match flattened_keys. get ( "content.body" ) {
126- Some ( SimpleJsonValue :: Str ( s) ) => s. clone ( ) ,
131+ Some ( JsonValue :: Value ( SimpleJsonValue :: Str ( s) ) ) => s. clone ( ) ,
127132 _ => String :: new ( ) ,
128133 } ;
129134
@@ -141,6 +146,7 @@ impl PushRuleEvaluator {
141146 room_version_feature_flags,
142147 msc3931_enabled,
143148 msc3758_exact_event_match,
149+ msc3966_exact_event_property_contains,
144150 } )
145151 }
146152
@@ -263,6 +269,9 @@ impl PushRuleEvaluator {
263269 KnownCondition :: RelatedEventMatch ( event_match) => {
264270 self . match_related_event_match ( event_match, user_id) ?
265271 }
272+ KnownCondition :: ExactEventPropertyContains ( exact_event_match) => {
273+ self . match_exact_event_property_contains ( exact_event_match) ?
274+ }
266275 KnownCondition :: IsUserMention => {
267276 if let Some ( uid) = user_id {
268277 self . user_mentions . contains ( uid)
@@ -345,7 +354,7 @@ impl PushRuleEvaluator {
345354 return Ok ( false ) ;
346355 } ;
347356
348- let haystack = if let Some ( SimpleJsonValue :: Str ( haystack) ) =
357+ let haystack = if let Some ( JsonValue :: Value ( SimpleJsonValue :: Str ( haystack) ) ) =
349358 self . flattened_keys . get ( & * event_match. key )
350359 {
351360 haystack
@@ -377,7 +386,9 @@ impl PushRuleEvaluator {
377386
378387 let value = & exact_event_match. value ;
379388
380- let haystack = if let Some ( haystack) = self . flattened_keys . get ( & * exact_event_match. key ) {
389+ let haystack = if let Some ( JsonValue :: Value ( haystack) ) =
390+ self . flattened_keys . get ( & * exact_event_match. key )
391+ {
381392 haystack
382393 } else {
383394 return Ok ( false ) ;
@@ -441,11 +452,12 @@ impl PushRuleEvaluator {
441452 return Ok ( false ) ;
442453 } ;
443454
444- let haystack = if let Some ( SimpleJsonValue :: Str ( haystack) ) = event. get ( & * * key) {
445- haystack
446- } else {
447- return Ok ( false ) ;
448- } ;
455+ let haystack =
456+ if let Some ( JsonValue :: Value ( SimpleJsonValue :: Str ( haystack) ) ) = event. get ( & * * key) {
457+ haystack
458+ } else {
459+ return Ok ( false ) ;
460+ } ;
449461
450462 // For the content.body we match against "words", but for everything
451463 // else we match against the entire value.
@@ -459,6 +471,29 @@ impl PushRuleEvaluator {
459471 compiled_pattern. is_match ( haystack)
460472 }
461473
474+ /// Evaluates a `exact_event_property_contains` condition. (MSC3758)
475+ fn match_exact_event_property_contains (
476+ & self ,
477+ exact_event_match : & ExactEventMatchCondition ,
478+ ) -> Result < bool , Error > {
479+ // First check if the feature is enabled.
480+ if !self . msc3966_exact_event_property_contains {
481+ return Ok ( false ) ;
482+ }
483+
484+ let value = & exact_event_match. value ;
485+
486+ let haystack = if let Some ( JsonValue :: Array ( haystack) ) =
487+ self . flattened_keys . get ( & * exact_event_match. key )
488+ {
489+ haystack
490+ } else {
491+ return Ok ( false ) ;
492+ } ;
493+
494+ Ok ( haystack. contains ( & * * value) )
495+ }
496+
462497 /// Match the member count against an 'is' condition
463498 /// The `is` condition can be things like '>2', '==3' or even just '4'.
464499 fn match_member_count ( & self , is : & str ) -> Result < bool , Error > {
@@ -488,7 +523,7 @@ fn push_rule_evaluator() {
488523 let mut flattened_keys = BTreeMap :: new ( ) ;
489524 flattened_keys. insert (
490525 "content.body" . to_string ( ) ,
491- SimpleJsonValue :: Str ( "foo bar bob hello" . to_string ( ) ) ,
526+ JsonValue :: Value ( SimpleJsonValue :: Str ( "foo bar bob hello" . to_string ( ) ) ) ,
492527 ) ;
493528 let evaluator = PushRuleEvaluator :: py_new (
494529 flattened_keys,
@@ -503,6 +538,7 @@ fn push_rule_evaluator() {
503538 vec ! [ ] ,
504539 true ,
505540 true ,
541+ true ,
506542 )
507543 . unwrap ( ) ;
508544
@@ -519,7 +555,7 @@ fn test_requires_room_version_supports_condition() {
519555 let mut flattened_keys = BTreeMap :: new ( ) ;
520556 flattened_keys. insert (
521557 "content.body" . to_string ( ) ,
522- SimpleJsonValue :: Str ( "foo bar bob hello" . to_string ( ) ) ,
558+ JsonValue :: Value ( SimpleJsonValue :: Str ( "foo bar bob hello" . to_string ( ) ) ) ,
523559 ) ;
524560 let flags = vec ! [ RoomVersionFeatures :: ExtensibleEvents . as_str( ) . to_string( ) ] ;
525561 let evaluator = PushRuleEvaluator :: py_new (
@@ -535,6 +571,7 @@ fn test_requires_room_version_supports_condition() {
535571 flags,
536572 true ,
537573 true ,
574+ true ,
538575 )
539576 . unwrap ( ) ;
540577
0 commit comments