use palpo_macros::StringEnum;
use super::{Action, ConditionalPushRule, PushCondition::*, RoomMemberCountIs, RuleKind, Ruleset, Tweak};
use crate::{PrivOwnedStr, UserId};
impl Ruleset {
pub fn server_default(user_id: &UserId) -> Self {
Self {
content: Default::default(),
override_: [
ConditionalPushRule::master(),
ConditionalPushRule::suppress_notices(),
ConditionalPushRule::invite_for_me(user_id),
ConditionalPushRule::member_event(),
ConditionalPushRule::is_user_mention(user_id),
ConditionalPushRule::is_room_mention(),
ConditionalPushRule::tombstone(),
ConditionalPushRule::reaction(),
ConditionalPushRule::server_acl(),
ConditionalPushRule::suppress_edits(),
#[cfg(feature = "unstable-msc3930")]
ConditionalPushRule::poll_response(),
]
.into(),
underride: [
ConditionalPushRule::call(),
ConditionalPushRule::encrypted_room_one_to_one(),
ConditionalPushRule::room_one_to_one(),
ConditionalPushRule::message(),
ConditionalPushRule::encrypted(),
#[cfg(feature = "unstable-msc3930")]
ConditionalPushRule::poll_start_one_to_one(),
#[cfg(feature = "unstable-msc3930")]
ConditionalPushRule::poll_start(),
#[cfg(feature = "unstable-msc3930")]
ConditionalPushRule::poll_end_one_to_one(),
#[cfg(feature = "unstable-msc3930")]
ConditionalPushRule::poll_end(),
]
.into(),
..Default::default()
}
}
pub fn update_with_server_default(&mut self, mut new_server_default: Ruleset) {
macro_rules! copy_rules_state {
($new_ruleset:ident, $old_ruleset:ident, @fields $($field_name:ident),+) => {
$(
$new_ruleset.$field_name = $new_ruleset
.$field_name
.into_iter()
.map(|mut new_rule| {
if let Some(old_rule) =
$old_ruleset.$field_name.swap_take(new_rule.rule_id.as_str())
{
new_rule.enabled = old_rule.enabled;
new_rule.actions = old_rule.actions;
}
new_rule
})
.collect();
)+
};
}
copy_rules_state!(new_server_default, self, @fields override_, content, room, sender, underride);
macro_rules! remove_remaining_default_rules {
($ruleset:ident, @fields $($field_name:ident),+) => {
$(
$ruleset.$field_name.retain(|rule| !rule.default);
)+
};
}
remove_remaining_default_rules!(self, @fields override_, content, room, sender, underride);
if let Some(master_rule) = new_server_default
.override_
.take(PredefinedOverrideRuleId::Master.as_str())
{
let (pos, _) = self.override_.insert_full(master_rule);
self.override_.move_index(pos, 0);
}
macro_rules! merge_rules {
($old_ruleset:ident, $new_ruleset:ident, @fields $($field_name:ident),+) => {
$(
$old_ruleset.$field_name.extend($new_ruleset.$field_name);
)+
};
}
merge_rules!(self, new_server_default, @fields override_, content, room, sender, underride);
}
}
impl ConditionalPushRule {
pub fn master() -> Self {
Self {
actions: vec![],
default: true,
enabled: false,
rule_id: PredefinedOverrideRuleId::Master.to_string(),
conditions: vec![],
}
}
pub fn suppress_notices() -> Self {
Self {
actions: vec![],
default: true,
enabled: true,
rule_id: PredefinedOverrideRuleId::SuppressNotices.to_string(),
conditions: vec![EventMatch {
key: "content.msgtype".into(),
pattern: "m.notice".into(),
}],
}
}
pub fn invite_for_me(user_id: &UserId) -> Self {
Self {
actions: vec![
Action::Notify,
Action::SetTweak(Tweak::Sound("default".into())),
Action::SetTweak(Tweak::Highlight(false)),
],
default: true,
enabled: true,
rule_id: PredefinedOverrideRuleId::InviteForMe.to_string(),
conditions: vec![
EventMatch {
key: "type".into(),
pattern: "m.room.member".into(),
},
EventMatch {
key: "content.membership".into(),
pattern: "invite".into(),
},
EventMatch {
key: "state_key".into(),
pattern: user_id.to_string(),
},
],
}
}
pub fn member_event() -> Self {
Self {
actions: vec![],
default: true,
enabled: true,
rule_id: PredefinedOverrideRuleId::MemberEvent.to_string(),
conditions: vec![EventMatch {
key: "type".into(),
pattern: "m.room.member".into(),
}],
}
}
pub fn is_user_mention(user_id: &UserId) -> Self {
Self {
actions: vec![
Action::Notify,
Action::SetTweak(Tweak::Sound("default".to_owned())),
Action::SetTweak(Tweak::Highlight(true)),
],
default: true,
enabled: true,
rule_id: PredefinedOverrideRuleId::IsUserMention.to_string(),
conditions: vec![EventPropertyContains {
key: r"content.m\.mentions.user_ids".to_owned(),
value: user_id.as_str().into(),
}],
}
}
pub fn tombstone() -> Self {
Self {
actions: vec![Action::Notify, Action::SetTweak(Tweak::Highlight(true))],
default: true,
enabled: true,
rule_id: PredefinedOverrideRuleId::Tombstone.to_string(),
conditions: vec![
EventMatch {
key: "type".into(),
pattern: "m.room.tombstone".into(),
},
EventMatch {
key: "state_key".into(),
pattern: "".into(),
},
],
}
}
pub fn is_room_mention() -> Self {
Self {
actions: vec![Action::Notify, Action::SetTweak(Tweak::Highlight(true))],
default: true,
enabled: true,
rule_id: PredefinedOverrideRuleId::IsRoomMention.to_string(),
conditions: vec![
EventPropertyIs {
key: r"content.m\.mentions.room".to_owned(),
value: true.into(),
},
SenderNotificationPermission { key: "room".to_owned() },
],
}
}
pub fn reaction() -> Self {
Self {
actions: vec![],
default: true,
enabled: true,
rule_id: PredefinedOverrideRuleId::Reaction.to_string(),
conditions: vec![EventMatch {
key: "type".into(),
pattern: "m.reaction".into(),
}],
}
}
pub fn server_acl() -> Self {
Self {
actions: vec![],
default: true,
enabled: true,
rule_id: PredefinedOverrideRuleId::RoomServerAcl.to_string(),
conditions: vec![
EventMatch {
key: "type".into(),
pattern: "m.room.server_acl".into(),
},
EventMatch {
key: "state_key".into(),
pattern: "".into(),
},
],
}
}
pub fn suppress_edits() -> Self {
Self {
actions: vec![],
default: true,
enabled: true,
rule_id: PredefinedOverrideRuleId::SuppressEdits.to_string(),
conditions: vec![EventPropertyIs {
key: r"content.m\.relates_to.rel_type".to_owned(),
value: "m.replace".into(),
}],
}
}
#[cfg(feature = "unstable-msc3930")]
pub fn poll_response() -> Self {
Self {
rule_id: PredefinedOverrideRuleId::PollResponse.to_string(),
default: true,
enabled: true,
conditions: vec![EventPropertyIs {
key: "type".to_owned(),
value: "org.matrix.msc3381.poll.response".into(),
}],
actions: vec![],
}
}
}
impl ConditionalPushRule {
pub fn call() -> Self {
Self {
rule_id: PredefinedUnderrideRuleId::Call.to_string(),
default: true,
enabled: true,
conditions: vec![EventMatch {
key: "type".into(),
pattern: "m.call.invite".into(),
}],
actions: vec![
Action::Notify,
Action::SetTweak(Tweak::Sound("ring".into())),
Action::SetTweak(Tweak::Highlight(false)),
],
}
}
pub fn encrypted_room_one_to_one() -> Self {
Self {
rule_id: PredefinedUnderrideRuleId::EncryptedRoomOneToOne.to_string(),
default: true,
enabled: true,
conditions: vec![
RoomMemberCount {
is: RoomMemberCountIs::from(2),
},
EventMatch {
key: "type".into(),
pattern: "m.room.encrypted".into(),
},
],
actions: vec![
Action::Notify,
Action::SetTweak(Tweak::Sound("default".into())),
Action::SetTweak(Tweak::Highlight(false)),
],
}
}
pub fn room_one_to_one() -> Self {
Self {
rule_id: PredefinedUnderrideRuleId::RoomOneToOne.to_string(),
default: true,
enabled: true,
conditions: vec![
RoomMemberCount {
is: RoomMemberCountIs::from(2),
},
EventMatch {
key: "type".into(),
pattern: "m.room.message".into(),
},
],
actions: vec![
Action::Notify,
Action::SetTweak(Tweak::Sound("default".into())),
Action::SetTweak(Tweak::Highlight(false)),
],
}
}
pub fn message() -> Self {
Self {
rule_id: PredefinedUnderrideRuleId::Message.to_string(),
default: true,
enabled: true,
conditions: vec![EventMatch {
key: "type".into(),
pattern: "m.room.message".into(),
}],
actions: vec![Action::Notify, Action::SetTweak(Tweak::Highlight(false))],
}
}
pub fn encrypted() -> Self {
Self {
rule_id: PredefinedUnderrideRuleId::Encrypted.to_string(),
default: true,
enabled: true,
conditions: vec![EventMatch {
key: "type".into(),
pattern: "m.room.encrypted".into(),
}],
actions: vec![Action::Notify, Action::SetTweak(Tweak::Highlight(false))],
}
}
#[cfg(feature = "unstable-msc3930")]
pub fn poll_start_one_to_one() -> Self {
Self {
rule_id: PredefinedUnderrideRuleId::PollStartOneToOne.to_string(),
default: true,
enabled: true,
conditions: vec![
RoomMemberCount {
is: RoomMemberCountIs::from(2),
},
EventPropertyIs {
key: "type".to_owned(),
value: "org.matrix.msc3381.poll.start".into(),
},
],
actions: vec![Notify, SetTweak(Tweak::Sound("default".into()))],
}
}
#[cfg(feature = "unstable-msc3930")]
pub fn poll_start() -> Self {
Self {
rule_id: PredefinedUnderrideRuleId::PollStart.to_string(),
default: true,
enabled: true,
conditions: vec![EventPropertyIs {
key: "type".to_owned(),
value: "org.matrix.msc3381.poll.start".into(),
}],
actions: vec![Notify],
}
}
#[cfg(feature = "unstable-msc3930")]
pub fn poll_end_one_to_one() -> Self {
Self {
rule_id: PredefinedUnderrideRuleId::PollEndOneToOne.to_string(),
default: true,
enabled: true,
conditions: vec![
RoomMemberCount {
is: RoomMemberCountIs::from(2),
},
EventPropertyIs {
key: "type".to_owned(),
value: "org.matrix.msc3381.poll.end".into(),
},
],
actions: vec![Notify, SetTweak(Tweak::Sound("default".into()))],
}
}
#[cfg(feature = "unstable-msc3930")]
pub fn poll_end() -> Self {
Self {
rule_id: PredefinedUnderrideRuleId::PollEnd.to_string(),
default: true,
enabled: true,
conditions: vec![EventPropertyIs {
key: "type".to_owned(),
value: "org.matrix.msc3381.poll.end".into(),
}],
actions: vec![Notify],
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[non_exhaustive]
pub enum PredefinedRuleId {
Override(PredefinedOverrideRuleId),
Underride(PredefinedUnderrideRuleId),
Content(PredefinedContentRuleId),
}
impl PredefinedRuleId {
pub fn as_str(&self) -> &str {
match self {
Self::Override(id) => id.as_str(),
Self::Underride(id) => id.as_str(),
Self::Content(id) => id.as_str(),
}
}
pub fn kind(&self) -> RuleKind {
match self {
Self::Override(id) => id.kind(),
Self::Underride(id) => id.kind(),
Self::Content(id) => id.kind(),
}
}
}
impl AsRef<str> for PredefinedRuleId {
fn as_ref(&self) -> &str {
self.as_str()
}
}
#[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/doc/string_enum.md"))]
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, StringEnum)]
#[palpo_enum(rename_all = ".m.rule.snake_case")]
#[non_exhaustive]
pub enum PredefinedOverrideRuleId {
Master,
SuppressNotices,
InviteForMe,
MemberEvent,
IsUserMention,
IsRoomMention,
Tombstone,
Reaction,
#[palpo_enum(rename = ".m.rule.room.server_acl")]
RoomServerAcl,
SuppressEdits,
#[cfg(feature = "unstable-msc3930")]
#[palpo_enum(rename = ".org.matrix.msc3930.rule.poll_response")]
PollResponse,
#[doc(hidden)]
_Custom(PrivOwnedStr),
}
impl PredefinedOverrideRuleId {
pub fn kind(&self) -> RuleKind {
RuleKind::Override
}
}
#[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/doc/string_enum.md"))]
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, StringEnum)]
#[palpo_enum(rename_all = ".m.rule.snake_case")]
#[non_exhaustive]
pub enum PredefinedUnderrideRuleId {
Call,
EncryptedRoomOneToOne,
RoomOneToOne,
Message,
Encrypted,
#[cfg(feature = "unstable-msc3930")]
#[palpo_enum(rename = ".org.matrix.msc3930.rule.poll_start_one_to_one")]
PollStartOneToOne,
#[cfg(feature = "unstable-msc3930")]
#[palpo_enum(rename = ".org.matrix.msc3930.rule.poll_start")]
PollStart,
#[cfg(feature = "unstable-msc3930")]
#[palpo_enum(rename = ".org.matrix.msc3930.rule.poll_end_one_to_one")]
PollEndOneToOne,
#[cfg(feature = "unstable-msc3930")]
#[palpo_enum(rename = ".org.matrix.msc3930.rule.poll_end")]
PollEnd,
#[doc(hidden)]
_Custom(PrivOwnedStr),
}
impl PredefinedUnderrideRuleId {
pub fn kind(&self) -> RuleKind {
RuleKind::Underride
}
}
#[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/doc/string_enum.md"))]
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, StringEnum)]
#[palpo_enum(rename_all = ".m.rule.snake_case")]
#[non_exhaustive]
pub enum PredefinedContentRuleId {
#[doc(hidden)]
_Custom(PrivOwnedStr),
}
impl PredefinedContentRuleId {
pub fn kind(&self) -> RuleKind {
RuleKind::Content
}
}