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