push: Add support for event_property_is push condition

According to MSC3758
This commit is contained in:
Kévin Commaille 2023-04-07 12:33:43 +02:00 committed by Kévin Commaille
parent 82b4257bfe
commit 2e7b67bb23
5 changed files with 102 additions and 0 deletions

View File

@ -20,6 +20,7 @@ Improvements:
- Add `InitialStateEvent::{new, to_raw, to_raw_any}`
- Add a convenience method to construct `RoomEncryptionEventContent` with the recommended defaults.
- `PushCondition::EventMatch` and `FlattenedJson` now use escaped dotted paths, according to MSC3873
- Add unstable support for `event_property_is` push condition according to MSC3758
# 0.11.3

View File

@ -42,6 +42,7 @@ unstable-msc3551 = ["unstable-msc3956"]
unstable-msc3552 = ["unstable-msc3551"]
unstable-msc3553 = ["unstable-msc3552"]
unstable-msc3554 = ["unstable-msc1767"]
unstable-msc3758 = []
unstable-msc3927 = ["unstable-msc3551"]
unstable-msc3931 = []
unstable-msc3932 = ["unstable-msc3931"]

View File

@ -106,6 +106,19 @@ pub enum PushCondition {
feature: RoomVersionFeature,
},
/// Exact value match on a property of the event.
#[cfg(feature = "unstable-msc3758")]
EventPropertyIs {
/// The dot-separated path of the property of the event to match. See [MSC3873] for its
/// format.
///
/// [MSC3873]: https://github.com/matrix-org/matrix-spec-proposals/pull/3873
key: String,
/// The value to match against.
value: ScalarJsonValue,
},
#[doc(hidden)]
_Custom(_CustomPushCondition),
}
@ -176,6 +189,8 @@ impl PushCondition {
}
RoomVersionFeature::_Custom(_) => false,
},
#[cfg(feature = "unstable-msc3758")]
Self::EventPropertyIs { key, value } => event.get(key).map_or(false, |v| v == value),
Self::_Custom(_) => false,
}
}
@ -770,4 +785,70 @@ mod tests {
assert!(room_version_condition.applies(&simple_event, &context_matching));
assert!(!room_version_condition.applies(&simple_event, &context_not_matching));
}
#[cfg(feature = "unstable-msc3758")]
#[test]
fn event_property_is_applies() {
use crate::push::condition::ScalarJsonValue;
let context = push_context();
let event_raw = serde_json::from_str::<Raw<JsonValue>>(
r#"{
"sender": "@worthy_whale:server.name",
"content": {
"msgtype": "m.text",
"body": "Boom!",
"org.fake.boolean": false,
"org.fake.number": 13,
"org.fake.null": null
}
}"#,
)
.unwrap();
let event = FlattenedJson::from_raw(&event_raw);
let string_match = PushCondition::EventPropertyIs {
key: "content.body".to_owned(),
value: "Boom!".into(),
};
assert!(string_match.applies(&event, &context));
let string_no_match =
PushCondition::EventPropertyIs { key: "content.body".to_owned(), value: "Boom".into() };
assert!(!string_no_match.applies(&event, &context));
let wrong_type =
PushCondition::EventPropertyIs { key: "content.body".to_owned(), value: false.into() };
assert!(!wrong_type.applies(&event, &context));
let bool_match = PushCondition::EventPropertyIs {
key: r"content.org\.fake\.boolean".to_owned(),
value: false.into(),
};
assert!(bool_match.applies(&event, &context));
let bool_no_match = PushCondition::EventPropertyIs {
key: r"content.org\.fake\.boolean".to_owned(),
value: true.into(),
};
assert!(!bool_no_match.applies(&event, &context));
let int_match = PushCondition::EventPropertyIs {
key: r"content.org\.fake\.number".to_owned(),
value: int!(13).into(),
};
assert!(int_match.applies(&event, &context));
let int_no_match = PushCondition::EventPropertyIs {
key: r"content.org\.fake\.number".to_owned(),
value: int!(130).into(),
};
assert!(!int_no_match.applies(&event, &context));
let null_match = PushCondition::EventPropertyIs {
key: r"content.org\.fake\.null".to_owned(),
value: ScalarJsonValue::Null,
};
assert!(null_match.applies(&event, &context));
}
}

View File

@ -5,6 +5,8 @@ use crate::serde::from_raw_json_value;
#[cfg(feature = "unstable-msc3931")]
use super::RoomVersionFeature;
#[cfg(feature = "unstable-msc3758")]
use super::ScalarJsonValue;
use super::{PushCondition, RoomMemberCountIs};
impl Serialize for PushCondition {
@ -40,6 +42,11 @@ impl<'de> Deserialize<'de> for PushCondition {
let helper: PushConditionSerDeHelper = from_raw_json_value(&json)?;
Ok(helper.into())
}
#[cfg(feature = "unstable-msc3758")]
"com.beeper.msc3758.exact_event_match" => {
let helper: PushConditionSerDeHelper = from_raw_json_value(&json)?;
Ok(helper.into())
}
_ => from_raw_json_value(&json).map(Self::_Custom),
}
}
@ -93,6 +100,10 @@ enum PushConditionSerDeHelper {
/// The feature the room must support for the push rule to apply.
feature: RoomVersionFeature,
},
#[cfg(feature = "unstable-msc3758")]
#[serde(rename = "com.beeper.msc3758.exact_event_match")]
EventPropertyIs { key: String, value: ScalarJsonValue },
}
impl From<PushConditionSerDeHelper> for PushCondition {
@ -110,6 +121,10 @@ impl From<PushConditionSerDeHelper> for PushCondition {
PushConditionSerDeHelper::RoomVersionSupports { feature } => {
Self::RoomVersionSupports { feature }
}
#[cfg(feature = "unstable-msc3758")]
PushConditionSerDeHelper::EventPropertyIs { key, value } => {
Self::EventPropertyIs { key, value }
}
}
}
}
@ -125,6 +140,8 @@ impl From<PushCondition> for PushConditionSerDeHelper {
}
#[cfg(feature = "unstable-msc3931")]
PushCondition::RoomVersionSupports { feature } => Self::RoomVersionSupports { feature },
#[cfg(feature = "unstable-msc3758")]
PushCondition::EventPropertyIs { key, value } => Self::EventPropertyIs { key, value },
PushCondition::_Custom(_) => unimplemented!(),
}
}

View File

@ -154,6 +154,7 @@ unstable-msc3554 = ["ruma-common/unstable-msc3554"]
unstable-msc3575 = ["ruma-client-api?/unstable-msc3575"]
unstable-msc3618 = ["ruma-federation-api?/unstable-msc3618"]
unstable-msc3723 = ["ruma-federation-api?/unstable-msc3723"]
unstable-msc3758 = ["ruma-common/unstable-msc3758"]
unstable-msc3927 = ["ruma-common/unstable-msc3927"]
unstable-msc3931 = ["ruma-common/unstable-msc3931"]
unstable-msc3932 = ["ruma-common/unstable-msc3932"]
@ -196,6 +197,7 @@ __ci = [
"unstable-msc3575",
"unstable-msc3618",
"unstable-msc3723",
"unstable-msc3758",
"unstable-msc3927",
"unstable-msc3932",
"unstable-msc3954",