Change PushCondition from using newtype variants to struct variants
This commit is contained in:
parent
da7a97d490
commit
7395f940a7
@ -5,6 +5,11 @@ Breaking changes:
|
|||||||
* Add `alt_aliases` to `CanonicalAliasEventContent`
|
* Add `alt_aliases` to `CanonicalAliasEventContent`
|
||||||
* Replace `format` and `formatted_body` fields in `TextMessagEventContent`,
|
* Replace `format` and `formatted_body` fields in `TextMessagEventContent`,
|
||||||
`NoticeMessageEventContent` and `EmoteMessageEventContent` with `formatted: FormattedBody`
|
`NoticeMessageEventContent` and `EmoteMessageEventContent` with `formatted: FormattedBody`
|
||||||
|
* Rename `override_rules` in `push_rules::Ruleset` to `override_`
|
||||||
|
* Change `push_rules::PushCondition` variants from newtype variants with separate inner types to
|
||||||
|
struct variants
|
||||||
|
* This change removes the types `EventMatchCondition`, `RoomMemberCountCondition` and
|
||||||
|
`SenderNotificationPermissionCondition`
|
||||||
|
|
||||||
Improvements:
|
Improvements:
|
||||||
|
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
//! Types for the the *m.push_rules* event.
|
//! Types for the the *m.push_rules* event.
|
||||||
|
|
||||||
use ruma_events_macros::ruma_event;
|
use ruma_events_macros::ruma_event;
|
||||||
use serde::{
|
use serde::{Deserialize, Serialize};
|
||||||
de::Error, ser::SerializeStruct as _, Deserialize, Deserializer, Serialize, Serializer,
|
|
||||||
};
|
|
||||||
use serde_json::{from_value, Value as JsonValue};
|
|
||||||
|
|
||||||
ruma_event! {
|
ruma_event! {
|
||||||
/// Describes all push rules for a user.
|
/// Describes all push rules for a user.
|
||||||
@ -30,8 +27,11 @@ pub struct Ruleset {
|
|||||||
pub content: Vec<PatternedPushRule>,
|
pub content: Vec<PatternedPushRule>,
|
||||||
|
|
||||||
/// These user-configured rules are given the highest priority.
|
/// These user-configured rules are given the highest priority.
|
||||||
|
///
|
||||||
|
/// This field is named `override_` instead of `override` because the latter is a reserved
|
||||||
|
/// keyword in Rust.
|
||||||
#[serde(rename = "override")]
|
#[serde(rename = "override")]
|
||||||
pub override_rules: Vec<ConditionalPushRule>,
|
pub override_: Vec<ConditionalPushRule>,
|
||||||
|
|
||||||
/// These rules change the behaviour of all messages for a given room.
|
/// These rules change the behaviour of all messages for a given room.
|
||||||
pub room: Vec<PushRule>,
|
pub room: Vec<PushRule>,
|
||||||
@ -109,132 +109,43 @@ pub struct PatternedPushRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 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)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(tag = "kind", rename_all = "snake_case")]
|
||||||
pub enum PushCondition {
|
pub enum PushCondition {
|
||||||
/// This is a glob pattern match on a field of the event.
|
/// This is a glob pattern match on a field of the event.
|
||||||
EventMatch(EventMatchCondition),
|
EventMatch {
|
||||||
|
/// The dot-separated field of the event to match.
|
||||||
|
key: String,
|
||||||
|
|
||||||
|
/// The glob-style pattern to match against.
|
||||||
|
///
|
||||||
|
/// Patterns with no special glob characters should be treated as having asterisks prepended
|
||||||
|
/// and appended when testing the condition.
|
||||||
|
pattern: String,
|
||||||
|
},
|
||||||
|
|
||||||
/// This matches unencrypted messages where `content.body` contains the owner's display name in
|
/// This matches unencrypted messages where `content.body` contains the owner's display name in
|
||||||
/// that room.
|
/// that room.
|
||||||
ContainsDisplayName,
|
ContainsDisplayName,
|
||||||
|
|
||||||
/// This matches the current number of members in the room.
|
/// This matches the current number of members in the room.
|
||||||
RoomMemberCount(RoomMemberCountCondition),
|
RoomMemberCount {
|
||||||
|
/// A decimal integer optionally prefixed by one of `==`, `<`, `>`, `>=` or `<=`.
|
||||||
|
///
|
||||||
|
/// A prefix of `<` matches rooms where the member count is strictly less than the given
|
||||||
|
/// number and so forth. If no prefix is present, this parameter defaults to `==`.
|
||||||
|
is: String,
|
||||||
|
},
|
||||||
|
|
||||||
/// This takes into account the current power levels in the room, ensuring the sender of the
|
/// This takes into account the current power levels in the room, ensuring the sender of the
|
||||||
/// event has high enough power to trigger the notification.
|
/// event has high enough power to trigger the notification.
|
||||||
SenderNotificationPermission(SenderNotificationPermissionCondition),
|
SenderNotificationPermission {
|
||||||
}
|
/// The field in the power level event the user needs a minimum power level for.
|
||||||
|
///
|
||||||
impl Serialize for PushCondition {
|
/// Fields must be specified under the `notifications` property in the power level event's
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
/// `content`.
|
||||||
where
|
key: String,
|
||||||
S: Serializer,
|
},
|
||||||
{
|
|
||||||
match *self {
|
|
||||||
PushCondition::EventMatch(ref condition) => condition.serialize(serializer),
|
|
||||||
PushCondition::ContainsDisplayName => {
|
|
||||||
let mut state = serializer.serialize_struct("ContainsDisplayNameCondition", 1)?;
|
|
||||||
|
|
||||||
state.serialize_field("kind", "contains_display_name")?;
|
|
||||||
|
|
||||||
state.end()
|
|
||||||
}
|
|
||||||
PushCondition::RoomMemberCount(ref condition) => condition.serialize(serializer),
|
|
||||||
PushCondition::SenderNotificationPermission(ref condition) => {
|
|
||||||
condition.serialize(serializer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Derive
|
|
||||||
impl<'de> Deserialize<'de> for PushCondition {
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
let value: JsonValue = Deserialize::deserialize(deserializer)?;
|
|
||||||
|
|
||||||
let kind_value = match value.get("kind") {
|
|
||||||
Some(value) => value.clone(),
|
|
||||||
None => return Err(D::Error::missing_field("kind")),
|
|
||||||
};
|
|
||||||
|
|
||||||
let kind = match kind_value.as_str() {
|
|
||||||
Some(kind) => kind,
|
|
||||||
None => return Err(D::Error::custom("field `kind` must be a string")),
|
|
||||||
};
|
|
||||||
|
|
||||||
match kind {
|
|
||||||
"event_match" => {
|
|
||||||
let condition = match from_value::<EventMatchCondition>(value) {
|
|
||||||
Ok(condition) => condition,
|
|
||||||
Err(error) => return Err(D::Error::custom(error.to_string())),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(PushCondition::EventMatch(condition))
|
|
||||||
}
|
|
||||||
"contains_display_name" => Ok(PushCondition::ContainsDisplayName),
|
|
||||||
"room_member_count" => {
|
|
||||||
let condition = match from_value::<RoomMemberCountCondition>(value) {
|
|
||||||
Ok(condition) => condition,
|
|
||||||
Err(error) => return Err(D::Error::custom(error.to_string())),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(PushCondition::RoomMemberCount(condition))
|
|
||||||
}
|
|
||||||
"sender_notification_permission" => {
|
|
||||||
let condition = match from_value::<SenderNotificationPermissionCondition>(value) {
|
|
||||||
Ok(condition) => condition,
|
|
||||||
Err(error) => return Err(D::Error::custom(error.to_string())),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(PushCondition::SenderNotificationPermission(condition))
|
|
||||||
}
|
|
||||||
unknown_kind => Err(D::Error::custom(&format!(
|
|
||||||
"unknown condition kind `{}`",
|
|
||||||
unknown_kind
|
|
||||||
))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A push condition that matches a glob pattern match on a field of the event.
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
||||||
#[serde(tag = "kind", rename = "event_match")]
|
|
||||||
pub struct EventMatchCondition {
|
|
||||||
/// The dot-separated field of the event to match.
|
|
||||||
pub key: String,
|
|
||||||
|
|
||||||
/// The glob-style pattern to match against.
|
|
||||||
///
|
|
||||||
/// Patterns with no special glob characters should be treated as having asterisks prepended and
|
|
||||||
/// appended when testing the condition.
|
|
||||||
pub pattern: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A push condition that matches the current number of members in the room.
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
||||||
#[serde(tag = "kind", rename = "room_member_count")]
|
|
||||||
pub struct RoomMemberCountCondition {
|
|
||||||
/// A decimal integer optionally prefixed by one of `==`, `<`, `>`, `>=` or `<=`.
|
|
||||||
///
|
|
||||||
/// A prefix of `<` matches rooms where the member count is strictly less than the given number
|
|
||||||
/// and so forth. If no prefix is present, this parameter defaults to `==`.
|
|
||||||
pub is: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A push condition that takes into account the current power levels in the room, ensuring the
|
|
||||||
/// sender of the event has high enough power to trigger the notification.
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
||||||
#[serde(tag = "kind", rename = "sender_notification_permission")]
|
|
||||||
pub struct SenderNotificationPermissionCondition {
|
|
||||||
/// The field in the power level event the user needs a minimum power level for.
|
|
||||||
///
|
|
||||||
/// Fields must be specified under the `notifications` property in the power level event's
|
|
||||||
/// `content`.
|
|
||||||
pub key: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -242,10 +153,7 @@ mod tests {
|
|||||||
use matches::assert_matches;
|
use matches::assert_matches;
|
||||||
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
|
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
|
||||||
|
|
||||||
use super::{
|
use super::{PushCondition, PushRulesEvent};
|
||||||
EventMatchCondition, PushCondition, PushRulesEvent, RoomMemberCountCondition,
|
|
||||||
SenderNotificationPermissionCondition,
|
|
||||||
};
|
|
||||||
use crate::EventJson;
|
use crate::EventJson;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -256,10 +164,10 @@ mod tests {
|
|||||||
"pattern": "m.notice"
|
"pattern": "m.notice"
|
||||||
});
|
});
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
to_json_value(&PushCondition::EventMatch(EventMatchCondition {
|
to_json_value(&PushCondition::EventMatch {
|
||||||
key: "content.msgtype".to_string(),
|
key: "content.msgtype".to_string(),
|
||||||
pattern: "m.notice".to_string(),
|
pattern: "m.notice".to_string(),
|
||||||
}))
|
})
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
json_data
|
json_data
|
||||||
);
|
);
|
||||||
@ -280,9 +188,9 @@ mod tests {
|
|||||||
"kind": "room_member_count"
|
"kind": "room_member_count"
|
||||||
});
|
});
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
to_json_value(&PushCondition::RoomMemberCount(RoomMemberCountCondition {
|
to_json_value(&PushCondition::RoomMemberCount {
|
||||||
is: "2".to_string(),
|
is: "2".to_string(),
|
||||||
}))
|
})
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
json_data
|
json_data
|
||||||
);
|
);
|
||||||
@ -296,11 +204,9 @@ mod tests {
|
|||||||
});
|
});
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
json_data,
|
json_data,
|
||||||
to_json_value(&PushCondition::SenderNotificationPermission(
|
to_json_value(&PushCondition::SenderNotificationPermission {
|
||||||
SenderNotificationPermissionCondition {
|
key: "room".to_string(),
|
||||||
key: "room".to_string(),
|
})
|
||||||
}
|
|
||||||
))
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -314,7 +220,7 @@ mod tests {
|
|||||||
});
|
});
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
from_json_value::<PushCondition>(json_data).unwrap(),
|
from_json_value::<PushCondition>(json_data).unwrap(),
|
||||||
PushCondition::EventMatch(EventMatchCondition { key, pattern })
|
PushCondition::EventMatch { key, pattern }
|
||||||
if key == "content.msgtype" && pattern == "m.notice"
|
if key == "content.msgtype" && pattern == "m.notice"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -335,7 +241,7 @@ mod tests {
|
|||||||
});
|
});
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
from_json_value::<PushCondition>(json_data).unwrap(),
|
from_json_value::<PushCondition>(json_data).unwrap(),
|
||||||
PushCondition::RoomMemberCount(RoomMemberCountCondition { is })
|
PushCondition::RoomMemberCount { is }
|
||||||
if is == "2"
|
if is == "2"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -348,9 +254,9 @@ mod tests {
|
|||||||
});
|
});
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
from_json_value::<PushCondition>(json_data).unwrap(),
|
from_json_value::<PushCondition>(json_data).unwrap(),
|
||||||
PushCondition::SenderNotificationPermission(SenderNotificationPermissionCondition {
|
PushCondition::SenderNotificationPermission {
|
||||||
key
|
key
|
||||||
}) if key == "room"
|
} if key == "room"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,11 +299,11 @@ mod tests {
|
|||||||
"dont_notify"
|
"dont_notify"
|
||||||
],
|
],
|
||||||
"conditions": [
|
"conditions": [
|
||||||
{
|
{
|
||||||
"key": "content.msgtype",
|
"key": "content.msgtype",
|
||||||
"kind": "event_match",
|
"kind": "event_match",
|
||||||
"pattern": "m.notice"
|
"pattern": "m.notice"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": true,
|
"default": true,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
@ -420,11 +326,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"conditions": [
|
"conditions": [
|
||||||
{
|
{
|
||||||
"key": "type",
|
"key": "type",
|
||||||
"kind": "event_match",
|
"kind": "event_match",
|
||||||
"pattern": "m.call.invite"
|
"pattern": "m.call.invite"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": true,
|
"default": true,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
@ -463,10 +369,10 @@ mod tests {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"conditions": [
|
"conditions": [
|
||||||
{
|
{
|
||||||
"is": "2",
|
"is": "2",
|
||||||
"kind": "room_member_count"
|
"kind": "room_member_count"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": true,
|
"default": true,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
@ -485,21 +391,21 @@ mod tests {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"conditions": [
|
"conditions": [
|
||||||
{
|
{
|
||||||
"key": "type",
|
"key": "type",
|
||||||
"kind": "event_match",
|
"kind": "event_match",
|
||||||
"pattern": "m.room.member"
|
"pattern": "m.room.member"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "content.membership",
|
"key": "content.membership",
|
||||||
"kind": "event_match",
|
"kind": "event_match",
|
||||||
"pattern": "invite"
|
"pattern": "invite"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "state_key",
|
"key": "state_key",
|
||||||
"kind": "event_match",
|
"kind": "event_match",
|
||||||
"pattern": "@alice:example.com"
|
"pattern": "@alice:example.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": true,
|
"default": true,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
@ -514,11 +420,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"conditions": [
|
"conditions": [
|
||||||
{
|
{
|
||||||
"key": "type",
|
"key": "type",
|
||||||
"kind": "event_match",
|
"kind": "event_match",
|
||||||
"pattern": "m.room.member"
|
"pattern": "m.room.member"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": true,
|
"default": true,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user