feat: add support for unstable-msc3931/3932 style push conditions parsing

This commit is contained in:
Benjamin Kampmann 2022-12-14 18:02:04 +01:00 committed by Kévin Commaille
parent 89e06adecf
commit 9460702b00
4 changed files with 154 additions and 1 deletions

View File

@ -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 = []

View File

@ -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>>(

View File

@ -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>>(

View File

@ -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]