use std::hash::{Hash, Hasher};
use indexmap::Equivalent;
use salvo::prelude::*;
use serde::{Deserialize, Serialize};
use crate::push::FlattenedJson;
use crate::push::condition::RoomVersionFeature;
use crate::push::{Action, PredefinedOverrideRuleId, PushCondition, PushConditionRoomCtx, PushRule};
#[derive(ToSchema, Deserialize, Serialize, Clone, Debug)]
pub struct ConditionalPushRule {
pub actions: Vec<Action>,
pub default: bool,
pub enabled: bool,
pub rule_id: String,
#[serde(default)]
pub conditions: Vec<PushCondition>,
}
impl ConditionalPushRule {
pub fn applies(&self, event: &FlattenedJson, context: &PushConditionRoomCtx) -> bool {
if !self.enabled {
return false;
}
if self.rule_id != PredefinedOverrideRuleId::Master.as_ref() {
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;
}
}
if event.contains_mentions() {
return false;
}
self.conditions.iter().all(|cond| cond.applies(event, context))
}
}
#[derive(Debug)]
#[allow(clippy::exhaustive_structs)]
pub struct ConditionalPushRuleInit {
pub actions: Vec<Action>,
pub default: bool,
pub enabled: bool,
pub rule_id: String,
pub conditions: Vec<PushCondition>,
}
impl From<ConditionalPushRuleInit> for ConditionalPushRule {
fn from(init: ConditionalPushRuleInit) -> Self {
let ConditionalPushRuleInit {
actions,
default,
enabled,
rule_id,
conditions,
} = init;
Self {
actions,
default,
enabled,
rule_id,
conditions,
}
}
}
impl Hash for ConditionalPushRule {
fn hash<H: Hasher>(&self, state: &mut H) {
self.rule_id.hash(state);
}
}
impl PartialEq for ConditionalPushRule {
fn eq(&self, other: &Self) -> bool {
self.rule_id == other.rule_id
}
}
impl Eq for ConditionalPushRule {}
impl Equivalent<ConditionalPushRule> for str {
fn equivalent(&self, key: &ConditionalPushRule) -> bool {
self == key.rule_id
}
}
#[derive(ToSchema, Deserialize, Serialize, Clone, Debug)]
pub struct NewConditionalPushRule {
pub rule_id: String,
#[serde(default)]
pub conditions: Vec<PushCondition>,
pub actions: Vec<Action>,
}
impl NewConditionalPushRule {
pub fn new(rule_id: String, conditions: Vec<PushCondition>, actions: Vec<Action>) -> Self {
Self {
rule_id,
conditions,
actions,
}
}
}
impl From<ConditionalPushRule> for PushRule {
fn from(push_rule: ConditionalPushRule) -> Self {
let ConditionalPushRule {
actions,
default,
enabled,
rule_id,
conditions,
..
} = push_rule;
Self {
actions,
default,
enabled,
rule_id,
conditions: Some(conditions),
pattern: None,
}
}
}
impl From<NewConditionalPushRule> for ConditionalPushRule {
fn from(new_rule: NewConditionalPushRule) -> Self {
let NewConditionalPushRule {
rule_id,
conditions,
actions,
} = new_rule;
Self {
actions,
default: false,
enabled: true,
rule_id,
conditions,
}
}
}
impl From<ConditionalPushRuleInit> for PushRule {
fn from(init: ConditionalPushRuleInit) -> Self {
let ConditionalPushRuleInit {
actions,
default,
enabled,
rule_id,
conditions,
} = init;
Self {
actions,
default,
enabled,
rule_id,
pattern: None,
conditions: Some(conditions),
}
}
}
impl From<PushRule> for ConditionalPushRule {
fn from(push_rule: PushRule) -> Self {
let PushRule {
actions,
default,
enabled,
rule_id,
conditions,
..
} = push_rule;
ConditionalPushRuleInit {
actions,
default,
enabled,
rule_id,
conditions: conditions.unwrap_or_default(),
}
.into()
}
}