diff --git a/rust/src/push/evaluator.rs b/rust/src/push/evaluator.rs
index 95d847cac0..3e217ba706 100644
--- a/rust/src/push/evaluator.rs
+++ b/rust/src/push/evaluator.rs
@@ -1,7 +1,7 @@
use std::collections::{BTreeMap, BTreeSet};
use anyhow::{Context, Error};
-use log::warn;
+use log::{info, warn};
use pyo3::prelude::*;
use super::{
@@ -14,10 +14,10 @@ pub struct PushRuleEvaluator {
flattened_keys: BTreeMap<String, String>,
body: String,
room_member_count: u64,
- power_levels: BTreeMap<String, BTreeMap<String, u64>>,
+ notification_power_levels: BTreeMap<String, i64>,
relations: BTreeMap<String, BTreeSet<(String, String)>>,
relation_match_enabled: bool,
- sender_power_level: u64,
+ sender_power_level: i64,
}
#[pymethods]
@@ -26,8 +26,8 @@ impl PushRuleEvaluator {
fn py_new(
flattened_keys: BTreeMap<String, String>,
room_member_count: u64,
- sender_power_level: u64,
- power_levels: BTreeMap<String, BTreeMap<String, u64>>,
+ sender_power_level: i64,
+ notification_power_levels: BTreeMap<String, i64>,
relations: BTreeMap<String, BTreeSet<(String, String)>>,
relation_match_enabled: bool,
) -> Result<Self, Error> {
@@ -40,7 +40,7 @@ impl PushRuleEvaluator {
flattened_keys,
body,
room_member_count,
- power_levels,
+ notification_power_levels,
relations,
relation_match_enabled,
sender_power_level,
@@ -111,12 +111,16 @@ impl PushRuleEvaluator {
}
Condition::SenderNotificationPermission { key } => {
let required_level = self
- .power_levels
- .get("notifications")
- .and_then(|m| m.get(key.as_ref()))
+ .notification_power_levels
+ .get(key.as_ref())
.copied()
.unwrap_or(50);
+ info!(
+ "Power level {required_level} vs {}",
+ self.sender_power_level
+ );
+
self.sender_power_level >= required_level
}
Condition::RelationMatch {
diff --git a/rust/src/push/mod.rs b/rust/src/push/mod.rs
index 33b2bc5d47..99e9fc3943 100644
--- a/rust/src/push/mod.rs
+++ b/rust/src/push/mod.rs
@@ -123,6 +123,8 @@ impl IntoPy<PyObject> for Action {
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct SetTweak {
set_tweak: Cow<'static, str>,
+
+ #[serde(skip_serializing_if = "Option::is_none")]
value: Option<TweakValue>,
// This picks saves any other fields that may have been added as clients.
diff --git a/rust/src/push/utils.rs b/rust/src/push/utils.rs
index d070d8f0d2..dcf1a39bc5 100644
--- a/rust/src/push/utils.rs
+++ b/rust/src/push/utils.rs
@@ -52,7 +52,10 @@ pub(crate) fn glob_to_regex(glob: &str, match_type: GlobMatchType) -> Result<Reg
let regex_str = match match_type {
GlobMatchType::Whole => format!(r"\A{joined}\z"),
- GlobMatchType::Word => format!(r"\b{joined}\b"),
+
+ // `^|\W` and `\W|$` handle the case where `pattern` starts or ends with a non-word
+ // character.
+ GlobMatchType::Word => format!(r"(?:^|\W|\b){joined}(?:\b|\W|$)"),
};
Ok(RegexBuilder::new(®ex_str)
|