diff --git a/rust/src/push/evaluator.rs b/rust/src/push/evaluator.rs
index ec7a8c4453..dd6b4343ec 100644
--- a/rust/src/push/evaluator.rs
+++ b/rust/src/push/evaluator.rs
@@ -22,8 +22,8 @@ use regex::Regex;
use super::{
utils::{get_glob_matcher, get_localpart_from_id, GlobMatchType},
- Action, Condition, EventMatchCondition, FilteredPushRules, KnownCondition,
- RelatedEventMatchCondition,
+ Action, Condition, EventMatchCondition, ExactEventMatchCondition, FilteredPushRules,
+ KnownCondition, RelatedEventMatchCondition, SimpleJsonValue,
};
lazy_static! {
@@ -61,9 +61,9 @@ impl RoomVersionFeatures {
/// Allows running a set of push rules against a particular event.
#[pyclass]
pub struct PushRuleEvaluator {
- /// A mapping of "flattened" keys to string values in the event, e.g.
+ /// A mapping of "flattened" keys to simple JSON values in the event, e.g.
/// includes things like "type" and "content.msgtype".
- flattened_keys: BTreeMap<String, String>,
+ flattened_keys: BTreeMap<String, SimpleJsonValue>,
/// The "content.body", if any.
body: String,
@@ -87,7 +87,7 @@ pub struct PushRuleEvaluator {
/// The related events, indexed by relation type. Flattened in the same manner as
/// `flattened_keys`.
- related_events_flattened: BTreeMap<String, BTreeMap<String, String>>,
+ related_events_flattened: BTreeMap<String, BTreeMap<String, SimpleJsonValue>>,
/// If msc3664, push rules for related events, is enabled.
related_event_match_enabled: bool,
@@ -98,6 +98,9 @@ pub struct PushRuleEvaluator {
/// If MSC3931 (room version feature flags) is enabled. Usually controlled by the same
/// flag as MSC1767 (extensible events core).
msc3931_enabled: bool,
+
+ /// If MSC3758 (exact_event_match push rule condition) is enabled.
+ msc3758_exact_event_match: bool,
}
#[pymethods]
@@ -106,22 +109,23 @@ impl PushRuleEvaluator {
#[allow(clippy::too_many_arguments)]
#[new]
pub fn py_new(
- flattened_keys: BTreeMap<String, String>,
+ flattened_keys: BTreeMap<String, SimpleJsonValue>,
has_mentions: bool,
user_mentions: BTreeSet<String>,
room_mention: bool,
room_member_count: u64,
sender_power_level: Option<i64>,
notification_power_levels: BTreeMap<String, i64>,
- related_events_flattened: BTreeMap<String, BTreeMap<String, String>>,
+ related_events_flattened: BTreeMap<String, BTreeMap<String, SimpleJsonValue>>,
related_event_match_enabled: bool,
room_version_feature_flags: Vec<String>,
msc3931_enabled: bool,
+ msc3758_exact_event_match: bool,
) -> Result<Self, Error> {
- let body = flattened_keys
- .get("content.body")
- .cloned()
- .unwrap_or_default();
+ let body = match flattened_keys.get("content.body") {
+ Some(SimpleJsonValue::Str(s)) => s.clone(),
+ _ => String::new(),
+ };
Ok(PushRuleEvaluator {
flattened_keys,
@@ -136,6 +140,7 @@ impl PushRuleEvaluator {
related_event_match_enabled,
room_version_feature_flags,
msc3931_enabled,
+ msc3758_exact_event_match,
})
}
@@ -252,6 +257,9 @@ impl PushRuleEvaluator {
KnownCondition::EventMatch(event_match) => {
self.match_event_match(event_match, user_id)?
}
+ KnownCondition::ExactEventMatch(exact_event_match) => {
+ self.match_exact_event_match(exact_event_match)?
+ }
KnownCondition::RelatedEventMatch(event_match) => {
self.match_related_event_match(event_match, user_id)?
}
@@ -337,7 +345,9 @@ impl PushRuleEvaluator {
return Ok(false);
};
- let haystack = if let Some(haystack) = self.flattened_keys.get(&*event_match.key) {
+ let haystack = if let Some(SimpleJsonValue::Str(haystack)) =
+ self.flattened_keys.get(&*event_match.key)
+ {
haystack
} else {
return Ok(false);
@@ -355,6 +365,27 @@ impl PushRuleEvaluator {
compiled_pattern.is_match(haystack)
}
+ /// Evaluates a `exact_event_match` condition. (MSC3758)
+ fn match_exact_event_match(
+ &self,
+ exact_event_match: &ExactEventMatchCondition,
+ ) -> Result<bool, Error> {
+ // First check if the feature is enabled.
+ if !self.msc3758_exact_event_match {
+ return Ok(false);
+ }
+
+ let value = &exact_event_match.value;
+
+ let haystack = if let Some(haystack) = self.flattened_keys.get(&*exact_event_match.key) {
+ haystack
+ } else {
+ return Ok(false);
+ };
+
+ Ok(haystack == &**value)
+ }
+
/// Evaluates a `related_event_match` condition. (MSC3664)
fn match_related_event_match(
&self,
@@ -410,7 +441,7 @@ impl PushRuleEvaluator {
return Ok(false);
};
- let haystack = if let Some(haystack) = event.get(&**key) {
+ let haystack = if let Some(SimpleJsonValue::Str(haystack)) = event.get(&**key) {
haystack
} else {
return Ok(false);
@@ -455,7 +486,10 @@ impl PushRuleEvaluator {
#[test]
fn push_rule_evaluator() {
let mut flattened_keys = BTreeMap::new();
- flattened_keys.insert("content.body".to_string(), "foo bar bob hello".to_string());
+ flattened_keys.insert(
+ "content.body".to_string(),
+ SimpleJsonValue::Str("foo bar bob hello".to_string()),
+ );
let evaluator = PushRuleEvaluator::py_new(
flattened_keys,
false,
@@ -468,6 +502,7 @@ fn push_rule_evaluator() {
true,
vec![],
true,
+ true,
)
.unwrap();
@@ -482,7 +517,10 @@ fn test_requires_room_version_supports_condition() {
use crate::push::{PushRule, PushRules};
let mut flattened_keys = BTreeMap::new();
- flattened_keys.insert("content.body".to_string(), "foo bar bob hello".to_string());
+ flattened_keys.insert(
+ "content.body".to_string(),
+ SimpleJsonValue::Str("foo bar bob hello".to_string()),
+ );
let flags = vec![RoomVersionFeatures::ExtensibleEvents.as_str().to_string()];
let evaluator = PushRuleEvaluator::py_new(
flattened_keys,
@@ -496,6 +534,7 @@ fn test_requires_room_version_supports_condition() {
false,
flags,
true,
+ true,
)
.unwrap();
|