use indexmap::set::{IntoIter as IndexSetIntoIter, Iter as IndexSetIter};
use super::{
condition, Action, ConditionalPushRule, FlattenedJson, PatternedPushRule, PushConditionRoomCtx,
Ruleset, SimplePushRule,
};
use crate::{OwnedRoomId, OwnedUserId};
#[derive(Clone, Debug)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub enum AnyPushRule {
Override(ConditionalPushRule),
Content(PatternedPushRule),
Room(SimplePushRule<OwnedRoomId>),
Sender(SimplePushRule<OwnedUserId>),
Underride(ConditionalPushRule),
}
impl AnyPushRule {
pub fn as_ref(&self) -> AnyPushRuleRef<'_> {
match self {
Self::Override(o) => AnyPushRuleRef::Override(o),
Self::Content(c) => AnyPushRuleRef::Content(c),
Self::Room(r) => AnyPushRuleRef::Room(r),
Self::Sender(s) => AnyPushRuleRef::Sender(s),
Self::Underride(u) => AnyPushRuleRef::Underride(u),
}
}
pub fn enabled(&self) -> bool {
self.as_ref().enabled()
}
pub fn actions(&self) -> &[Action] {
self.as_ref().actions()
}
pub fn triggers_highlight(&self) -> bool {
self.as_ref().triggers_highlight()
}
pub fn triggers_notification(&self) -> bool {
self.as_ref().triggers_notification()
}
pub fn triggers_sound(&self) -> Option<&str> {
self.as_ref().triggers_sound()
}
pub fn rule_id(&self) -> &str {
self.as_ref().rule_id()
}
pub fn is_server_default(&self) -> bool {
self.as_ref().is_server_default()
}
pub fn applies(&self, event: &FlattenedJson, context: &PushConditionRoomCtx) -> bool {
self.as_ref().applies(event, context)
}
}
#[derive(Debug)]
pub struct RulesetIntoIter {
content: IndexSetIntoIter<PatternedPushRule>,
override_: IndexSetIntoIter<ConditionalPushRule>,
room: IndexSetIntoIter<SimplePushRule<OwnedRoomId>>,
sender: IndexSetIntoIter<SimplePushRule<OwnedUserId>>,
underride: IndexSetIntoIter<ConditionalPushRule>,
}
impl Iterator for RulesetIntoIter {
type Item = AnyPushRule;
fn next(&mut self) -> Option<Self::Item> {
self.override_
.next()
.map(AnyPushRule::Override)
.or_else(|| self.content.next().map(AnyPushRule::Content))
.or_else(|| self.room.next().map(AnyPushRule::Room))
.or_else(|| self.sender.next().map(AnyPushRule::Sender))
.or_else(|| self.underride.next().map(AnyPushRule::Underride))
}
}
impl IntoIterator for Ruleset {
type Item = AnyPushRule;
type IntoIter = RulesetIntoIter;
fn into_iter(self) -> Self::IntoIter {
RulesetIntoIter {
content: self.content.into_iter(),
override_: self.override_.into_iter(),
room: self.room.into_iter(),
sender: self.sender.into_iter(),
underride: self.underride.into_iter(),
}
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub enum AnyPushRuleRef<'a> {
Override(&'a ConditionalPushRule),
Content(&'a PatternedPushRule),
Room(&'a SimplePushRule<OwnedRoomId>),
Sender(&'a SimplePushRule<OwnedUserId>),
Underride(&'a ConditionalPushRule),
}
impl<'a> AnyPushRuleRef<'a> {
pub fn to_owned(self) -> AnyPushRule {
match self {
Self::Override(o) => AnyPushRule::Override(o.clone()),
Self::Content(c) => AnyPushRule::Content(c.clone()),
Self::Room(r) => AnyPushRule::Room(r.clone()),
Self::Sender(s) => AnyPushRule::Sender(s.clone()),
Self::Underride(u) => AnyPushRule::Underride(u.clone()),
}
}
pub fn enabled(self) -> bool {
match self {
Self::Override(rule) => rule.enabled,
Self::Underride(rule) => rule.enabled,
Self::Content(rule) => rule.enabled,
Self::Room(rule) => rule.enabled,
Self::Sender(rule) => rule.enabled,
}
}
pub fn actions(self) -> &'a [Action] {
match self {
Self::Override(rule) => &rule.actions,
Self::Underride(rule) => &rule.actions,
Self::Content(rule) => &rule.actions,
Self::Room(rule) => &rule.actions,
Self::Sender(rule) => &rule.actions,
}
}
pub fn triggers_highlight(self) -> bool {
self.actions().iter().any(|a| a.is_highlight())
}
pub fn triggers_notification(self) -> bool {
self.actions().iter().any(|a| a.should_notify())
}
pub fn triggers_sound(self) -> Option<&'a str> {
self.actions().iter().find_map(|a| a.sound())
}
pub fn rule_id(self) -> &'a str {
match self {
Self::Override(rule) => &rule.rule_id,
Self::Underride(rule) => &rule.rule_id,
Self::Content(rule) => &rule.rule_id,
Self::Room(rule) => rule.rule_id.as_ref(),
Self::Sender(rule) => rule.rule_id.as_ref(),
}
}
pub fn is_server_default(self) -> bool {
match self {
Self::Override(rule) => rule.default,
Self::Underride(rule) => rule.default,
Self::Content(rule) => rule.default,
Self::Room(rule) => rule.default,
Self::Sender(rule) => rule.default,
}
}
pub fn applies(self, event: &FlattenedJson, context: &PushConditionRoomCtx) -> bool {
if event.get_str("sender").is_some_and(|sender| sender == context.user_id) {
return false;
}
match self {
Self::Override(rule) => rule.applies(event, context),
Self::Underride(rule) => rule.applies(event, context),
Self::Content(rule) => rule.applies_to("content.body", event, context),
Self::Room(rule) => {
rule.enabled
&& condition::check_event_match(
event,
"room_id",
rule.rule_id.as_ref(),
context,
)
}
Self::Sender(rule) => {
rule.enabled
&& condition::check_event_match(event, "sender", rule.rule_id.as_ref(), context)
}
}
}
}
#[derive(Debug)]
pub struct RulesetIter<'a> {
content: IndexSetIter<'a, PatternedPushRule>,
override_: IndexSetIter<'a, ConditionalPushRule>,
room: IndexSetIter<'a, SimplePushRule<OwnedRoomId>>,
sender: IndexSetIter<'a, SimplePushRule<OwnedUserId>>,
underride: IndexSetIter<'a, ConditionalPushRule>,
}
impl<'a> Iterator for RulesetIter<'a> {
type Item = AnyPushRuleRef<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.override_
.next()
.map(AnyPushRuleRef::Override)
.or_else(|| self.content.next().map(AnyPushRuleRef::Content))
.or_else(|| self.room.next().map(AnyPushRuleRef::Room))
.or_else(|| self.sender.next().map(AnyPushRuleRef::Sender))
.or_else(|| self.underride.next().map(AnyPushRuleRef::Underride))
}
}
impl<'a> IntoIterator for &'a Ruleset {
type Item = AnyPushRuleRef<'a>;
type IntoIter = RulesetIter<'a>;
fn into_iter(self) -> Self::IntoIter {
RulesetIter {
content: self.content.iter(),
override_: self.override_.iter(),
room: self.room.iter(),
sender: self.sender.iter(),
underride: self.underride.iter(),
}
}
}