push: Make power levels optional in PushConditionRoomCtx
This commit is contained in:
parent
4efca6fba5
commit
90d3605b87
@ -1,5 +1,11 @@
|
||||
# [unreleased]
|
||||
|
||||
Breaking changes:
|
||||
- The power levels fields in `PushConditionRoomCtx` are grouped in an optional `power_levels` field.
|
||||
If the field is missing, push rules that depend on it will never match. However, this allows to
|
||||
match the `.m.rule.invite_for_me` push rule because usually the `invite_state` doesn't include
|
||||
`m.room.power_levels`.
|
||||
|
||||
Improvements:
|
||||
|
||||
- Stabilize support for `.m.rule.suppress_edits` push rule (MSC3958 / Matrix 1.9)
|
||||
|
@ -38,8 +38,9 @@ pub use self::condition::RoomVersionFeature;
|
||||
pub use self::{
|
||||
action::{Action, Tweak},
|
||||
condition::{
|
||||
ComparisonOperator, FlattenedJson, FlattenedJsonValue, PushCondition, PushConditionRoomCtx,
|
||||
RoomMemberCountIs, ScalarJsonValue, _CustomPushCondition,
|
||||
ComparisonOperator, FlattenedJson, FlattenedJsonValue, PushCondition,
|
||||
PushConditionPowerLevelsCtx, PushConditionRoomCtx, RoomMemberCountIs, ScalarJsonValue,
|
||||
_CustomPushCondition,
|
||||
},
|
||||
iter::{AnyPushRule, AnyPushRuleRef, RulesetIntoIter, RulesetIter},
|
||||
predefined::{
|
||||
@ -988,7 +989,9 @@ mod tests {
|
||||
|
||||
use super::{
|
||||
action::{Action, Tweak},
|
||||
condition::{PushCondition, PushConditionRoomCtx, RoomMemberCountIs},
|
||||
condition::{
|
||||
PushCondition, PushConditionPowerLevelsCtx, PushConditionRoomCtx, RoomMemberCountIs,
|
||||
},
|
||||
AnyPushRule, ConditionalPushRule, PatternedPushRule, Ruleset, SimplePushRule,
|
||||
};
|
||||
use crate::{
|
||||
@ -1016,6 +1019,14 @@ mod tests {
|
||||
set
|
||||
}
|
||||
|
||||
fn power_levels() -> PushConditionPowerLevelsCtx {
|
||||
PushConditionPowerLevelsCtx {
|
||||
users: BTreeMap::new(),
|
||||
users_default: int!(50),
|
||||
notifications: NotificationPowerLevels { room: int!(50) },
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iter() {
|
||||
let mut set = example_ruleset();
|
||||
@ -1431,9 +1442,7 @@ mod tests {
|
||||
member_count: uint!(2),
|
||||
user_id: owned_user_id!("@jj:server.name"),
|
||||
user_display_name: "Jolly Jumper".into(),
|
||||
users_power_levels: BTreeMap::new(),
|
||||
default_power_level: int!(50),
|
||||
notification_power_levels: NotificationPowerLevels { room: int!(50) },
|
||||
power_levels: Some(power_levels()),
|
||||
#[cfg(feature = "unstable-msc3931")]
|
||||
supported_features: Default::default(),
|
||||
};
|
||||
@ -1443,9 +1452,7 @@ mod tests {
|
||||
member_count: uint!(100),
|
||||
user_id: owned_user_id!("@jj:server.name"),
|
||||
user_display_name: "Jolly Jumper".into(),
|
||||
users_power_levels: BTreeMap::new(),
|
||||
default_power_level: int!(50),
|
||||
notification_power_levels: NotificationPowerLevels { room: int!(50) },
|
||||
power_levels: Some(power_levels()),
|
||||
#[cfg(feature = "unstable-msc3931")]
|
||||
supported_features: Default::default(),
|
||||
};
|
||||
@ -1536,9 +1543,7 @@ mod tests {
|
||||
member_count: uint!(2),
|
||||
user_id: owned_user_id!("@jj:server.name"),
|
||||
user_display_name: "Jolly Jumper".into(),
|
||||
users_power_levels: BTreeMap::new(),
|
||||
default_power_level: int!(50),
|
||||
notification_power_levels: NotificationPowerLevels { room: int!(50) },
|
||||
power_levels: Some(power_levels()),
|
||||
#[cfg(feature = "unstable-msc3931")]
|
||||
supported_features: Default::default(),
|
||||
};
|
||||
@ -1677,9 +1682,7 @@ mod tests {
|
||||
member_count: uint!(100),
|
||||
user_id: owned_user_id!("@jj:server.name"),
|
||||
user_display_name: "Jolly Jumper".into(),
|
||||
users_power_levels: BTreeMap::new(),
|
||||
default_power_level: int!(50),
|
||||
notification_power_levels: NotificationPowerLevels { room: int!(50) },
|
||||
power_levels: Some(power_levels()),
|
||||
#[cfg(feature = "unstable-msc3931")]
|
||||
supported_features: Default::default(),
|
||||
};
|
||||
@ -1789,9 +1792,7 @@ mod tests {
|
||||
member_count: uint!(100),
|
||||
user_id: owned_user_id!("@jj:server.name"),
|
||||
user_display_name: "Jolly Jumper".into(),
|
||||
users_power_levels: BTreeMap::new(),
|
||||
default_power_level: int!(50),
|
||||
notification_power_levels: NotificationPowerLevels { room: int!(50) },
|
||||
power_levels: Some(power_levels()),
|
||||
#[cfg(feature = "unstable-msc3931")]
|
||||
supported_features: Default::default(),
|
||||
};
|
||||
@ -1834,4 +1835,37 @@ mod tests {
|
||||
PredefinedOverrideRuleId::IsRoomMention.as_ref()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invite_for_me_applies() {
|
||||
let set = Ruleset::server_default(user_id!("@jolly_jumper:server.name"));
|
||||
|
||||
let context = &PushConditionRoomCtx {
|
||||
room_id: owned_room_id!("!far_west:server.name"),
|
||||
member_count: uint!(100),
|
||||
user_id: owned_user_id!("@jj:server.name"),
|
||||
user_display_name: "Jolly Jumper".into(),
|
||||
// `invite_state` usually doesn't include the power levels.
|
||||
power_levels: None,
|
||||
#[cfg(feature = "unstable-msc3931")]
|
||||
supported_features: Default::default(),
|
||||
};
|
||||
|
||||
let message = serde_json::from_str::<Raw<JsonValue>>(
|
||||
r#"{
|
||||
"content": {
|
||||
"membership": "invite"
|
||||
},
|
||||
"state_key": "@jolly_jumper:server.name",
|
||||
"sender": "@admin:server.name",
|
||||
"type": "m.room.member"
|
||||
}"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
set.get_match(&message, context).unwrap().rule_id(),
|
||||
PredefinedOverrideRuleId::InviteForMe.as_ref()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -155,7 +155,8 @@ impl PushCondition {
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `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. If the power levels context
|
||||
/// is missing from it, conditions that depend on it will never apply.
|
||||
pub fn applies(&self, event: &FlattenedJson, context: &PushConditionRoomCtx) -> bool {
|
||||
if event.get_str("sender").is_some_and(|sender| sender == context.user_id) {
|
||||
return false;
|
||||
@ -173,6 +174,10 @@ impl PushCondition {
|
||||
}
|
||||
Self::RoomMemberCount { is } => is.contains(&context.member_count),
|
||||
Self::SenderNotificationPermission { key } => {
|
||||
let Some(power_levels) = &context.power_levels else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let sender_id = match event.get_str("sender") {
|
||||
Some(v) => match <&UserId>::try_from(v) {
|
||||
Ok(u) => u,
|
||||
@ -181,12 +186,10 @@ impl PushCondition {
|
||||
None => return false,
|
||||
};
|
||||
|
||||
let sender_level = context
|
||||
.users_power_levels
|
||||
.get(sender_id)
|
||||
.unwrap_or(&context.default_power_level);
|
||||
let sender_level =
|
||||
power_levels.users.get(sender_id).unwrap_or(&power_levels.users_default);
|
||||
|
||||
match context.notification_power_levels.get(key) {
|
||||
match power_levels.notifications.get(key) {
|
||||
Some(l) => sender_level >= l,
|
||||
None => false,
|
||||
}
|
||||
@ -231,24 +234,34 @@ pub struct PushConditionRoomCtx {
|
||||
/// The number of members in the room.
|
||||
pub member_count: UInt,
|
||||
|
||||
/// The users matrix ID.
|
||||
/// The user's matrix ID.
|
||||
pub user_id: OwnedUserId,
|
||||
|
||||
/// The display name of the current user in the room.
|
||||
pub user_display_name: String,
|
||||
|
||||
/// The room power levels context for the room.
|
||||
///
|
||||
/// If this is missing, push rules that require this will never match.
|
||||
pub power_levels: Option<PushConditionPowerLevelsCtx>,
|
||||
|
||||
/// The list of features this room's version or the room itself supports.
|
||||
#[cfg(feature = "unstable-msc3931")]
|
||||
pub supported_features: Vec<RoomVersionFeature>,
|
||||
}
|
||||
|
||||
/// The room power levels context to be able to test the corresponding push conditions.
|
||||
#[derive(Clone, Debug)]
|
||||
#[allow(clippy::exhaustive_structs)]
|
||||
pub struct PushConditionPowerLevelsCtx {
|
||||
/// The power levels of the users of the room.
|
||||
pub users_power_levels: BTreeMap<OwnedUserId, Int>,
|
||||
pub users: BTreeMap<OwnedUserId, Int>,
|
||||
|
||||
/// The default power level of the users of the room.
|
||||
pub default_power_level: Int,
|
||||
pub users_default: Int,
|
||||
|
||||
/// 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>,
|
||||
pub notifications: NotificationPowerLevels,
|
||||
}
|
||||
|
||||
/// Additional functions for character matching.
|
||||
@ -451,7 +464,10 @@ mod tests {
|
||||
from_value as from_json_value, json, to_value as to_json_value, Value as JsonValue,
|
||||
};
|
||||
|
||||
use super::{FlattenedJson, PushCondition, PushConditionRoomCtx, RoomMemberCountIs, StrExt};
|
||||
use super::{
|
||||
FlattenedJson, PushCondition, PushConditionPowerLevelsCtx, PushConditionRoomCtx,
|
||||
RoomMemberCountIs, StrExt,
|
||||
};
|
||||
use crate::{
|
||||
owned_room_id, owned_user_id, power_levels::NotificationPowerLevels, serde::Raw,
|
||||
OwnedUserId,
|
||||
@ -647,17 +663,21 @@ mod tests {
|
||||
}
|
||||
|
||||
fn push_context() -> PushConditionRoomCtx {
|
||||
let mut users_power_levels = BTreeMap::new();
|
||||
users_power_levels.insert(sender(), int!(25));
|
||||
let mut users = BTreeMap::new();
|
||||
users.insert(sender(), int!(25));
|
||||
|
||||
let power_levels = PushConditionPowerLevelsCtx {
|
||||
users,
|
||||
users_default: int!(50),
|
||||
notifications: NotificationPowerLevels { room: int!(50) },
|
||||
};
|
||||
|
||||
PushConditionRoomCtx {
|
||||
room_id: owned_room_id!("!room:server.name"),
|
||||
member_count: uint!(3),
|
||||
user_id: owned_user_id!("@gorilla:server.name"),
|
||||
user_display_name: "Groovy Gorilla".into(),
|
||||
users_power_levels,
|
||||
default_power_level: int!(50),
|
||||
notification_power_levels: NotificationPowerLevels { room: int!(50) },
|
||||
power_levels: Some(power_levels),
|
||||
#[cfg(feature = "unstable-msc3931")]
|
||||
supported_features: Default::default(),
|
||||
}
|
||||
@ -776,9 +796,7 @@ mod tests {
|
||||
member_count: uint!(3),
|
||||
user_id: owned_user_id!("@gorilla:server.name"),
|
||||
user_display_name: "Groovy Gorilla".into(),
|
||||
users_power_levels: context_not_matching.users_power_levels.clone(),
|
||||
default_power_level: int!(50),
|
||||
notification_power_levels: NotificationPowerLevels { room: int!(50) },
|
||||
power_levels: context_not_matching.power_levels.clone(),
|
||||
supported_features: vec![super::RoomVersionFeature::ExtensibleEvents],
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user