Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 9ccc09f

Browse files
authored
Support MSC1767's content.body behaviour; Add base rules from MSC3933 (#14524)
* Support MSC1767's `content.body` behaviour in push rules * Add the base rules from MSC3933 * Changelog entry * Flip condition around for finding `m.markup` * Remove forgotten import
1 parent dd51828 commit 9ccc09f

File tree

7 files changed

+316
-4
lines changed

7 files changed

+316
-4
lines changed

changelog.d/14524.feature

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add unstable support for an Extensible Events room version (`org.matrix.msc1767.10`) via [MSC1767](https://github.com/matrix-org/matrix-spec-proposals/pull/1767), [MSC3931](https://github.com/matrix-org/matrix-spec-proposals/pull/3931), [MSC3932](https://github.com/matrix-org/matrix-spec-proposals/pull/3932), and [MSC3933](https://github.com/matrix-org/matrix-spec-proposals/pull/3933).

rust/src/push/base_rules.rs

+270
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,156 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
274274
default: true,
275275
default_enabled: true,
276276
},
277+
PushRule {
278+
rule_id: Cow::Borrowed(
279+
"global/underride/.org.matrix.msc3933.rule.extensible.encrypted_room_one_to_one",
280+
),
281+
priority_class: 1,
282+
conditions: Cow::Borrowed(&[
283+
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
284+
key: Cow::Borrowed("type"),
285+
// MSC3933: Type changed from template rule - see MSC.
286+
pattern: Some(Cow::Borrowed("org.matrix.msc1767.encrypted")),
287+
pattern_type: None,
288+
})),
289+
Condition::Known(KnownCondition::RoomMemberCount {
290+
is: Some(Cow::Borrowed("2")),
291+
}),
292+
// MSC3933: Add condition on top of template rule - see MSC.
293+
Condition::Known(KnownCondition::RoomVersionSupports {
294+
// RoomVersionFeatures::ExtensibleEvents.as_str(), ideally
295+
feature: Cow::Borrowed("org.matrix.msc3932.extensible_events"),
296+
}),
297+
]),
298+
actions: Cow::Borrowed(&[Action::Notify, SOUND_ACTION, HIGHLIGHT_FALSE_ACTION]),
299+
default: true,
300+
default_enabled: true,
301+
},
302+
PushRule {
303+
rule_id: Cow::Borrowed(
304+
"global/underride/.org.matrix.msc3933.rule.extensible.message.room_one_to_one",
305+
),
306+
priority_class: 1,
307+
conditions: Cow::Borrowed(&[
308+
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
309+
key: Cow::Borrowed("type"),
310+
// MSC3933: Type changed from template rule - see MSC.
311+
pattern: Some(Cow::Borrowed("org.matrix.msc1767.message")),
312+
pattern_type: None,
313+
})),
314+
Condition::Known(KnownCondition::RoomMemberCount {
315+
is: Some(Cow::Borrowed("2")),
316+
}),
317+
// MSC3933: Add condition on top of template rule - see MSC.
318+
Condition::Known(KnownCondition::RoomVersionSupports {
319+
// RoomVersionFeatures::ExtensibleEvents.as_str(), ideally
320+
feature: Cow::Borrowed("org.matrix.msc3932.extensible_events"),
321+
}),
322+
]),
323+
actions: Cow::Borrowed(&[Action::Notify, SOUND_ACTION, HIGHLIGHT_FALSE_ACTION]),
324+
default: true,
325+
default_enabled: true,
326+
},
327+
PushRule {
328+
rule_id: Cow::Borrowed(
329+
"global/underride/.org.matrix.msc3933.rule.extensible.file.room_one_to_one",
330+
),
331+
priority_class: 1,
332+
conditions: Cow::Borrowed(&[
333+
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
334+
key: Cow::Borrowed("type"),
335+
// MSC3933: Type changed from template rule - see MSC.
336+
pattern: Some(Cow::Borrowed("org.matrix.msc1767.file")),
337+
pattern_type: None,
338+
})),
339+
Condition::Known(KnownCondition::RoomMemberCount {
340+
is: Some(Cow::Borrowed("2")),
341+
}),
342+
// MSC3933: Add condition on top of template rule - see MSC.
343+
Condition::Known(KnownCondition::RoomVersionSupports {
344+
// RoomVersionFeatures::ExtensibleEvents.as_str(), ideally
345+
feature: Cow::Borrowed("org.matrix.msc3932.extensible_events"),
346+
}),
347+
]),
348+
actions: Cow::Borrowed(&[Action::Notify, SOUND_ACTION, HIGHLIGHT_FALSE_ACTION]),
349+
default: true,
350+
default_enabled: true,
351+
},
352+
PushRule {
353+
rule_id: Cow::Borrowed(
354+
"global/underride/.org.matrix.msc3933.rule.extensible.image.room_one_to_one",
355+
),
356+
priority_class: 1,
357+
conditions: Cow::Borrowed(&[
358+
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
359+
key: Cow::Borrowed("type"),
360+
// MSC3933: Type changed from template rule - see MSC.
361+
pattern: Some(Cow::Borrowed("org.matrix.msc1767.image")),
362+
pattern_type: None,
363+
})),
364+
Condition::Known(KnownCondition::RoomMemberCount {
365+
is: Some(Cow::Borrowed("2")),
366+
}),
367+
// MSC3933: Add condition on top of template rule - see MSC.
368+
Condition::Known(KnownCondition::RoomVersionSupports {
369+
// RoomVersionFeatures::ExtensibleEvents.as_str(), ideally
370+
feature: Cow::Borrowed("org.matrix.msc3932.extensible_events"),
371+
}),
372+
]),
373+
actions: Cow::Borrowed(&[Action::Notify, SOUND_ACTION, HIGHLIGHT_FALSE_ACTION]),
374+
default: true,
375+
default_enabled: true,
376+
},
377+
PushRule {
378+
rule_id: Cow::Borrowed(
379+
"global/underride/.org.matrix.msc3933.rule.extensible.video.room_one_to_one",
380+
),
381+
priority_class: 1,
382+
conditions: Cow::Borrowed(&[
383+
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
384+
key: Cow::Borrowed("type"),
385+
// MSC3933: Type changed from template rule - see MSC.
386+
pattern: Some(Cow::Borrowed("org.matrix.msc1767.video")),
387+
pattern_type: None,
388+
})),
389+
Condition::Known(KnownCondition::RoomMemberCount {
390+
is: Some(Cow::Borrowed("2")),
391+
}),
392+
// MSC3933: Add condition on top of template rule - see MSC.
393+
Condition::Known(KnownCondition::RoomVersionSupports {
394+
// RoomVersionFeatures::ExtensibleEvents.as_str(), ideally
395+
feature: Cow::Borrowed("org.matrix.msc3932.extensible_events"),
396+
}),
397+
]),
398+
actions: Cow::Borrowed(&[Action::Notify, SOUND_ACTION, HIGHLIGHT_FALSE_ACTION]),
399+
default: true,
400+
default_enabled: true,
401+
},
402+
PushRule {
403+
rule_id: Cow::Borrowed(
404+
"global/underride/.org.matrix.msc3933.rule.extensible.audio.room_one_to_one",
405+
),
406+
priority_class: 1,
407+
conditions: Cow::Borrowed(&[
408+
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
409+
key: Cow::Borrowed("type"),
410+
// MSC3933: Type changed from template rule - see MSC.
411+
pattern: Some(Cow::Borrowed("org.matrix.msc1767.audio")),
412+
pattern_type: None,
413+
})),
414+
Condition::Known(KnownCondition::RoomMemberCount {
415+
is: Some(Cow::Borrowed("2")),
416+
}),
417+
// MSC3933: Add condition on top of template rule - see MSC.
418+
Condition::Known(KnownCondition::RoomVersionSupports {
419+
// RoomVersionFeatures::ExtensibleEvents.as_str(), ideally
420+
feature: Cow::Borrowed("org.matrix.msc3932.extensible_events"),
421+
}),
422+
]),
423+
actions: Cow::Borrowed(&[Action::Notify, SOUND_ACTION, HIGHLIGHT_FALSE_ACTION]),
424+
default: true,
425+
default_enabled: true,
426+
},
277427
PushRule {
278428
rule_id: Cow::Borrowed("global/underride/.m.rule.message"),
279429
priority_class: 1,
@@ -302,6 +452,126 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
302452
default: true,
303453
default_enabled: true,
304454
},
455+
PushRule {
456+
rule_id: Cow::Borrowed("global/underride/.org.matrix.msc1767.rule.extensible.encrypted"),
457+
priority_class: 1,
458+
conditions: Cow::Borrowed(&[
459+
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
460+
key: Cow::Borrowed("type"),
461+
// MSC3933: Type changed from template rule - see MSC.
462+
pattern: Some(Cow::Borrowed("m.encrypted")),
463+
pattern_type: None,
464+
})),
465+
// MSC3933: Add condition on top of template rule - see MSC.
466+
Condition::Known(KnownCondition::RoomVersionSupports {
467+
// RoomVersionFeatures::ExtensibleEvents.as_str(), ideally
468+
feature: Cow::Borrowed("org.matrix.msc3932.extensible_events"),
469+
}),
470+
]),
471+
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_FALSE_ACTION]),
472+
default: true,
473+
default_enabled: true,
474+
},
475+
PushRule {
476+
rule_id: Cow::Borrowed("global/underride/.org.matrix.msc1767.rule.extensible.message"),
477+
priority_class: 1,
478+
conditions: Cow::Borrowed(&[
479+
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
480+
key: Cow::Borrowed("type"),
481+
// MSC3933: Type changed from template rule - see MSC.
482+
pattern: Some(Cow::Borrowed("m.message")),
483+
pattern_type: None,
484+
})),
485+
// MSC3933: Add condition on top of template rule - see MSC.
486+
Condition::Known(KnownCondition::RoomVersionSupports {
487+
// RoomVersionFeatures::ExtensibleEvents.as_str(), ideally
488+
feature: Cow::Borrowed("org.matrix.msc3932.extensible_events"),
489+
}),
490+
]),
491+
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_FALSE_ACTION]),
492+
default: true,
493+
default_enabled: true,
494+
},
495+
PushRule {
496+
rule_id: Cow::Borrowed("global/underride/.org.matrix.msc1767.rule.extensible.file"),
497+
priority_class: 1,
498+
conditions: Cow::Borrowed(&[
499+
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
500+
key: Cow::Borrowed("type"),
501+
// MSC3933: Type changed from template rule - see MSC.
502+
pattern: Some(Cow::Borrowed("m.file")),
503+
pattern_type: None,
504+
})),
505+
// MSC3933: Add condition on top of template rule - see MSC.
506+
Condition::Known(KnownCondition::RoomVersionSupports {
507+
// RoomVersionFeatures::ExtensibleEvents.as_str(), ideally
508+
feature: Cow::Borrowed("org.matrix.msc3932.extensible_events"),
509+
}),
510+
]),
511+
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_FALSE_ACTION]),
512+
default: true,
513+
default_enabled: true,
514+
},
515+
PushRule {
516+
rule_id: Cow::Borrowed("global/underride/.org.matrix.msc1767.rule.extensible.image"),
517+
priority_class: 1,
518+
conditions: Cow::Borrowed(&[
519+
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
520+
key: Cow::Borrowed("type"),
521+
// MSC3933: Type changed from template rule - see MSC.
522+
pattern: Some(Cow::Borrowed("m.image")),
523+
pattern_type: None,
524+
})),
525+
// MSC3933: Add condition on top of template rule - see MSC.
526+
Condition::Known(KnownCondition::RoomVersionSupports {
527+
// RoomVersionFeatures::ExtensibleEvents.as_str(), ideally
528+
feature: Cow::Borrowed("org.matrix.msc3932.extensible_events"),
529+
}),
530+
]),
531+
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_FALSE_ACTION]),
532+
default: true,
533+
default_enabled: true,
534+
},
535+
PushRule {
536+
rule_id: Cow::Borrowed("global/underride/.org.matrix.msc1767.rule.extensible.video"),
537+
priority_class: 1,
538+
conditions: Cow::Borrowed(&[
539+
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
540+
key: Cow::Borrowed("type"),
541+
// MSC3933: Type changed from template rule - see MSC.
542+
pattern: Some(Cow::Borrowed("m.video")),
543+
pattern_type: None,
544+
})),
545+
// MSC3933: Add condition on top of template rule - see MSC.
546+
Condition::Known(KnownCondition::RoomVersionSupports {
547+
// RoomVersionFeatures::ExtensibleEvents.as_str(), ideally
548+
feature: Cow::Borrowed("org.matrix.msc3932.extensible_events"),
549+
}),
550+
]),
551+
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_FALSE_ACTION]),
552+
default: true,
553+
default_enabled: true,
554+
},
555+
PushRule {
556+
rule_id: Cow::Borrowed("global/underride/.org.matrix.msc1767.rule.extensible.audio"),
557+
priority_class: 1,
558+
conditions: Cow::Borrowed(&[
559+
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
560+
key: Cow::Borrowed("type"),
561+
// MSC3933: Type changed from template rule - see MSC.
562+
pattern: Some(Cow::Borrowed("m.audio")),
563+
pattern_type: None,
564+
})),
565+
// MSC3933: Add condition on top of template rule - see MSC.
566+
Condition::Known(KnownCondition::RoomVersionSupports {
567+
// RoomVersionFeatures::ExtensibleEvents.as_str(), ideally
568+
feature: Cow::Borrowed("org.matrix.msc3932.extensible_events"),
569+
}),
570+
]),
571+
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_FALSE_ACTION]),
572+
default: true,
573+
default_enabled: true,
574+
},
305575
PushRule {
306576
rule_id: Cow::Borrowed("global/underride/.im.vector.jitsi"),
307577
priority_class: 1,

rust/src/push/evaluator.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ fn test_requires_room_version_supports_condition() {
483483
};
484484
let rules = PushRules::new(vec![custom_rule]);
485485
result = evaluator.run(
486-
&FilteredPushRules::py_new(rules, BTreeMap::new(), true),
486+
&FilteredPushRules::py_new(rules, BTreeMap::new(), true, true),
487487
None,
488488
None,
489489
);

rust/src/push/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ pub struct FilteredPushRules {
412412
push_rules: PushRules,
413413
enabled_map: BTreeMap<String, bool>,
414414
msc3664_enabled: bool,
415+
msc1767_enabled: bool,
415416
}
416417

417418
#[pymethods]
@@ -421,11 +422,13 @@ impl FilteredPushRules {
421422
push_rules: PushRules,
422423
enabled_map: BTreeMap<String, bool>,
423424
msc3664_enabled: bool,
425+
msc1767_enabled: bool,
424426
) -> Self {
425427
Self {
426428
push_rules,
427429
enabled_map,
428430
msc3664_enabled,
431+
msc1767_enabled,
429432
}
430433
}
431434

@@ -450,6 +453,10 @@ impl FilteredPushRules {
450453
return false;
451454
}
452455

456+
if !self.msc1767_enabled && rule.rule_id.contains("org.matrix.msc1767") {
457+
return false;
458+
}
459+
453460
true
454461
})
455462
.map(|r| {

stubs/synapse/synapse_rust/push.pyi

+5-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ class PushRules:
2626

2727
class FilteredPushRules:
2828
def __init__(
29-
self, push_rules: PushRules, enabled_map: Dict[str, bool], msc3664_enabled: bool
29+
self,
30+
push_rules: PushRules,
31+
enabled_map: Dict[str, bool],
32+
msc3664_enabled: bool,
33+
msc1767_enabled: bool,
3034
): ...
3135
def rules(self) -> Collection[Tuple[PushRule, bool]]: ...
3236

synapse/push/bulk_push_rule_evaluator.py

+28-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from prometheus_client import Counter
3030

3131
from synapse.api.constants import MAIN_TIMELINE, EventTypes, Membership, RelationTypes
32+
from synapse.api.room_versions import PushRuleRoomFlag, RoomVersion
3233
from synapse.event_auth import auth_types_for_event, get_user_power_level
3334
from synapse.events import EventBase, relation_from_event
3435
from synapse.events.snapshot import EventContext
@@ -343,7 +344,7 @@ async def _action_for_event_by_user(
343344
room_version_features = []
344345

345346
evaluator = PushRuleEvaluator(
346-
_flatten_dict(event),
347+
_flatten_dict(event, room_version=event.room_version),
347348
room_member_count,
348349
sender_power_level,
349350
notification_levels,
@@ -426,6 +427,7 @@ async def _action_for_event_by_user(
426427

427428
def _flatten_dict(
428429
d: Union[EventBase, Mapping[str, Any]],
430+
room_version: Optional[RoomVersion] = None,
429431
prefix: Optional[List[str]] = None,
430432
result: Optional[Dict[str, str]] = None,
431433
) -> Dict[str, str]:
@@ -437,6 +439,31 @@ def _flatten_dict(
437439
if isinstance(value, str):
438440
result[".".join(prefix + [key])] = value.lower()
439441
elif isinstance(value, Mapping):
442+
# do not set `room_version` due to recursion considerations below
440443
_flatten_dict(value, prefix=(prefix + [key]), result=result)
441444

445+
# `room_version` should only ever be set when looking at the top level of an event
446+
if (
447+
room_version is not None
448+
and PushRuleRoomFlag.EXTENSIBLE_EVENTS in room_version.msc3931_push_features
449+
and isinstance(d, EventBase)
450+
):
451+
# Room supports extensible events: replace `content.body` with the plain text
452+
# representation from `m.markup`, as per MSC1767.
453+
markup = d.get("content").get("m.markup")
454+
if room_version.identifier.startswith("org.matrix.msc1767."):
455+
markup = d.get("content").get("org.matrix.msc1767.markup")
456+
if markup is not None and isinstance(markup, list):
457+
text = ""
458+
for rep in markup:
459+
if not isinstance(rep, dict):
460+
# invalid markup - skip all processing
461+
break
462+
if rep.get("mimetype", "text/plain") == "text/plain":
463+
rep_text = rep.get("body")
464+
if rep_text is not None and isinstance(rep_text, str):
465+
text = rep_text.lower()
466+
break
467+
result["content.body"] = text
468+
442469
return result

0 commit comments

Comments
 (0)