mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-05-11 04:34:56 -04:00
Implement MSC3952: Intentional mentions (#14823)
MSC3952 defines push rules which searches for mentions in a list of Matrix IDs in the event body, instead of searching the entire event body for display name / local part. This is implemented behind an experimental configuration flag and does not yet implement the backwards compatibility pieces of the MSC.
This commit is contained in:
parent
faecc6c083
commit
2a51f3ec36
11 changed files with 263 additions and 11 deletions
|
@ -131,6 +131,14 @@ pub const BASE_APPEND_OVERRIDE_RULES: &[PushRule] = &[
|
|||
default: true,
|
||||
default_enabled: true,
|
||||
},
|
||||
PushRule {
|
||||
rule_id: Cow::Borrowed(".org.matrix.msc3952.is_user_mentioned"),
|
||||
priority_class: 5,
|
||||
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::IsUserMention)]),
|
||||
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_ACTION, SOUND_ACTION]),
|
||||
default: true,
|
||||
default_enabled: true,
|
||||
},
|
||||
PushRule {
|
||||
rule_id: Cow::Borrowed("global/override/.m.rule.contains_display_name"),
|
||||
priority_class: 5,
|
||||
|
@ -139,6 +147,19 @@ pub const BASE_APPEND_OVERRIDE_RULES: &[PushRule] = &[
|
|||
default: true,
|
||||
default_enabled: true,
|
||||
},
|
||||
PushRule {
|
||||
rule_id: Cow::Borrowed(".org.matrix.msc3952.is_room_mentioned"),
|
||||
priority_class: 5,
|
||||
conditions: Cow::Borrowed(&[
|
||||
Condition::Known(KnownCondition::IsRoomMention),
|
||||
Condition::Known(KnownCondition::SenderNotificationPermission {
|
||||
key: Cow::Borrowed("room"),
|
||||
}),
|
||||
]),
|
||||
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_ACTION, SOUND_ACTION]),
|
||||
default: true,
|
||||
default_enabled: true,
|
||||
},
|
||||
PushRule {
|
||||
rule_id: Cow::Borrowed("global/override/.m.rule.roomnotif"),
|
||||
priority_class: 5,
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
use anyhow::{Context, Error};
|
||||
use lazy_static::lazy_static;
|
||||
|
@ -68,6 +68,11 @@ pub struct PushRuleEvaluator {
|
|||
/// The "content.body", if any.
|
||||
body: String,
|
||||
|
||||
/// The user mentions that were part of the message.
|
||||
user_mentions: BTreeSet<String>,
|
||||
/// True if the message is a room message.
|
||||
room_mention: bool,
|
||||
|
||||
/// The number of users in the room.
|
||||
room_member_count: u64,
|
||||
|
||||
|
@ -100,6 +105,8 @@ impl PushRuleEvaluator {
|
|||
#[new]
|
||||
pub fn py_new(
|
||||
flattened_keys: BTreeMap<String, String>,
|
||||
user_mentions: BTreeSet<String>,
|
||||
room_mention: bool,
|
||||
room_member_count: u64,
|
||||
sender_power_level: Option<i64>,
|
||||
notification_power_levels: BTreeMap<String, i64>,
|
||||
|
@ -116,6 +123,8 @@ impl PushRuleEvaluator {
|
|||
Ok(PushRuleEvaluator {
|
||||
flattened_keys,
|
||||
body,
|
||||
user_mentions,
|
||||
room_mention,
|
||||
room_member_count,
|
||||
notification_power_levels,
|
||||
sender_power_level,
|
||||
|
@ -229,6 +238,14 @@ impl PushRuleEvaluator {
|
|||
KnownCondition::RelatedEventMatch(event_match) => {
|
||||
self.match_related_event_match(event_match, user_id)?
|
||||
}
|
||||
KnownCondition::IsUserMention => {
|
||||
if let Some(uid) = user_id {
|
||||
self.user_mentions.contains(uid)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
KnownCondition::IsRoomMention => self.room_mention,
|
||||
KnownCondition::ContainsDisplayName => {
|
||||
if let Some(dn) = display_name {
|
||||
if !dn.is_empty() {
|
||||
|
@ -424,6 +441,8 @@ fn push_rule_evaluator() {
|
|||
flattened_keys.insert("content.body".to_string(), "foo bar bob hello".to_string());
|
||||
let evaluator = PushRuleEvaluator::py_new(
|
||||
flattened_keys,
|
||||
BTreeSet::new(),
|
||||
false,
|
||||
10,
|
||||
Some(0),
|
||||
BTreeMap::new(),
|
||||
|
@ -449,6 +468,8 @@ fn test_requires_room_version_supports_condition() {
|
|||
let flags = vec![RoomVersionFeatures::ExtensibleEvents.as_str().to_string()];
|
||||
let evaluator = PushRuleEvaluator::py_new(
|
||||
flattened_keys,
|
||||
BTreeSet::new(),
|
||||
false,
|
||||
10,
|
||||
Some(0),
|
||||
BTreeMap::new(),
|
||||
|
@ -483,7 +504,7 @@ fn test_requires_room_version_supports_condition() {
|
|||
};
|
||||
let rules = PushRules::new(vec![custom_rule]);
|
||||
result = evaluator.run(
|
||||
&FilteredPushRules::py_new(rules, BTreeMap::new(), true, false, true),
|
||||
&FilteredPushRules::py_new(rules, BTreeMap::new(), true, false, true, false),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
|
|
@ -269,6 +269,10 @@ pub enum KnownCondition {
|
|||
EventMatch(EventMatchCondition),
|
||||
#[serde(rename = "im.nheko.msc3664.related_event_match")]
|
||||
RelatedEventMatch(RelatedEventMatchCondition),
|
||||
#[serde(rename = "org.matrix.msc3952.is_user_mention")]
|
||||
IsUserMention,
|
||||
#[serde(rename = "org.matrix.msc3952.is_room_mention")]
|
||||
IsRoomMention,
|
||||
ContainsDisplayName,
|
||||
RoomMemberCount {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
|
@ -414,6 +418,7 @@ pub struct FilteredPushRules {
|
|||
msc1767_enabled: bool,
|
||||
msc3381_polls_enabled: bool,
|
||||
msc3664_enabled: bool,
|
||||
msc3952_intentional_mentions: bool,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
|
@ -425,6 +430,7 @@ impl FilteredPushRules {
|
|||
msc1767_enabled: bool,
|
||||
msc3381_polls_enabled: bool,
|
||||
msc3664_enabled: bool,
|
||||
msc3952_intentional_mentions: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
push_rules,
|
||||
|
@ -432,6 +438,7 @@ impl FilteredPushRules {
|
|||
msc1767_enabled,
|
||||
msc3381_polls_enabled,
|
||||
msc3664_enabled,
|
||||
msc3952_intentional_mentions,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -465,6 +472,11 @@ impl FilteredPushRules {
|
|||
return false;
|
||||
}
|
||||
|
||||
if !self.msc3952_intentional_mentions && rule.rule_id.contains("org.matrix.msc3952")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
})
|
||||
.map(|r| {
|
||||
|
@ -522,6 +534,28 @@ fn test_deserialize_unstable_msc3931_condition() {
|
|||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_unstable_msc3952_user_condition() {
|
||||
let json = r#"{"kind":"org.matrix.msc3952.is_user_mention"}"#;
|
||||
|
||||
let condition: Condition = serde_json::from_str(json).unwrap();
|
||||
assert!(matches!(
|
||||
condition,
|
||||
Condition::Known(KnownCondition::IsUserMention)
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_unstable_msc3952_room_condition() {
|
||||
let json = r#"{"kind":"org.matrix.msc3952.is_room_mention"}"#;
|
||||
|
||||
let condition: Condition = serde_json::from_str(json).unwrap();
|
||||
assert!(matches!(
|
||||
condition,
|
||||
Condition::Known(KnownCondition::IsRoomMention)
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_custom_condition() {
|
||||
let json = r#"{"kind":"custom_tag"}"#;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue