29
29
from prometheus_client import Counter
30
30
31
31
from synapse .api .constants import MAIN_TIMELINE , EventTypes , Membership , RelationTypes
32
+ from synapse .api .room_versions import PushRuleRoomFlag , RoomDisposition , RoomVersion
32
33
from synapse .event_auth import auth_types_for_event , get_user_power_level
33
34
from synapse .events import EventBase , relation_from_event
34
35
from synapse .events .snapshot import EventContext
@@ -343,7 +344,7 @@ async def _action_for_event_by_user(
343
344
room_version_features = []
344
345
345
346
evaluator = PushRuleEvaluator (
346
- _flatten_dict (event ),
347
+ _flatten_dict (event , room_version = event . room_version ),
347
348
room_member_count ,
348
349
sender_power_level ,
349
350
notification_levels ,
@@ -426,6 +427,7 @@ async def _action_for_event_by_user(
426
427
427
428
def _flatten_dict (
428
429
d : Union [EventBase , Mapping [str , Any ]],
430
+ room_version : Optional [RoomVersion ] = None ,
429
431
prefix : Optional [List [str ]] = None ,
430
432
result : Optional [Dict [str , str ]] = None ,
431
433
) -> Dict [str , str ]:
@@ -437,6 +439,31 @@ def _flatten_dict(
437
439
if isinstance (value , str ):
438
440
result ["." .join (prefix + [key ])] = value .lower ()
439
441
elif isinstance (value , Mapping ):
442
+ # do not set `room_version` due to recursion considerations below
440
443
_flatten_dict (value , prefix = (prefix + [key ]), result = result )
441
444
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 ("org.matrix.msc1767.markup" )
454
+ if room_version .disposition == RoomDisposition .STABLE :
455
+ markup = d .get ("content" ).get ("m.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
+
442
469
return result
0 commit comments