123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- from time import time
- from typing import Any, Collection, Dict, List
- from synapse.api.constants import EventTypes
- from synapse.api.room_versions import RoomVersions
- from synapse.config.experimental import ExperimentalConfig
- from synapse.events import EventBase, make_event_from_dict
- from synapse.push.baserules import FilteredPushRules, PushRules
- from synapse.push.push_rule_evaluator import PushRuleEvaluatorForEvent
- def compute_push_actions(
- experimental_config: ExperimentalConfig,
- evaluator: PushRuleEvaluatorForEvent,
- event: EventBase,
- rules_by_user: Dict[str, FilteredPushRules],
- profiles: Dict[str, Any],
- count_as_unread: bool,
- uids_with_visibility: Collection[str],
- ) -> Dict[str, List]:
- actions_by_user = {}
- default_rules = FilteredPushRules(PushRules(), {}, experimental_config)
- matching_default_rule = None
- for rule, _ in default_rules:
- if not rule.default_enabled:
- continue
- matches = evaluator.check_conditions(rule.conditions, "uid", None)
- if matches:
- matching_default_rule = rule
- break
- joining_user = None
- if event.type == EventTypes.Member:
- joining_user = event.state_key
- for uid, rules in rules_by_user.items():
- if event.sender == uid:
- try:
- actions_by_user.pop(uid)
- except KeyError:
- pass
- continue
- if uid not in uids_with_visibility:
- try:
- actions_by_user.pop(uid)
- except KeyError:
- pass
- continue
- display_name = None
- profile = profiles.get(uid)
- if profile:
- display_name = profile.display_name
- if not display_name and joining_user:
- # Handle the case where we are pushing a membership event to
- # that user, as they might not be already joined.
- if joining_user == uid:
- display_name = event.content.get("displayname", None)
- if not isinstance(display_name, str):
- display_name = None
- if count_as_unread:
- # Add an element for the current user if the event needs to be marked as
- # unread, so that add_push_actions_to_staging iterates over it.
- # If the event shouldn't be marked as unread but should notify the
- # current user, it'll be added to the dict later.
- actions_by_user[uid] = []
- matched_default = False
- if matching_default_rule:
- if not rules.enabled_map.get(matching_default_rule.rule_id, True):
- continue
- matched_default = True
- override = rules.push_rules.overriden_base_rules.get(
- matching_default_rule.rule_id
- )
- if override:
- actions = override.actions
- else:
- actions = matching_default_rule.actions
- actions = [x for x in actions if x != "dont_notify"]
- if actions and "notify" in actions:
- actions_by_user[uid] = matching_default_rule.actions
- for rule, enabled in rules.user_specific_rules():
- if not enabled:
- continue
- if (
- matched_default
- and rule.priority_class < matching_default_rule.priority_class
- ):
- break
- matches = evaluator.check_conditions(rule.conditions, uid, display_name)
- if matches:
- actions = [x for x in rule.actions if x != "dont_notify"]
- if actions and "notify" in actions:
- # Push rules say we should notify the user of this event
- actions_by_user[uid] = actions
- else:
- try:
- actions_by_user.pop(uid)
- except KeyError:
- pass
- break
- return actions_by_user
- if __name__ == "__main__":
- event = make_event_from_dict(
- {
- "auth_events": [
- "$Y6V1n3kQq_G2Q2gqma4tXbS0TtZQYne-zk8EGymcErI",
- "$RWzLUHmF5Hc6kr5hJuCY7gcDt3bVXS2JL6oJD7lTEdo",
- "$uIZRw93tT3lXnpMj40J8aPbnDkXeaWtgJWBVrfeQsYs",
- ],
- "prev_events": ["$6lCOe9WyCBREZrvfdShVHO7OgBZ3HA82AN-TsGzsj94"],
- "type": "m.room.message",
- "room_id": "!mWlQLVyRcFtLrKOgEl:localhost:8448",
- "sender": "@user-nn87-main:localhost:8448",
- "content": {
- "org.matrix.msc1767.text": "test",
- "body": "test",
- "msgtype": "m.text",
- },
- "depth": 5006,
- "prev_state": [],
- "origin": "localhost:8448",
- "origin_server_ts": 1660738396696,
- "hashes": {"sha256": "j2X9zgQU6jUqARb9blCdX5UL8SKKJgG1cTxb7uZOiLI"},
- "signatures": {
- "localhost:8448": {
- "ed25519:a_ERAh": "BsToq2Bf2DqksU5i7vsMN2hxgRBmou+5++IK4+Af8GLt46E9Po1L5Iv1JLxe4eN/zN/jYW03ULGdrzzJkCzaDA"
- }
- },
- "unsigned": {"age_ts": 1660738396696},
- },
- RoomVersions.V10,
- )
- evaluator = PushRuleEvaluatorForEvent(event, 5000, 0, {}, {}, False)
- experimental_config = ExperimentalConfig()
- experimental_config.read_config({})
- rules_by_user = {
- f"@user-{i}:localhost": FilteredPushRules(PushRules(), {}, experimental_config)
- for i in range(5000)
- }
- uids_with_visibility = set(rules_by_user)
- start = time()
- number = 100
- for _ in range(number):
- result = compute_push_actions(
- experimental_config,
- evaluator,
- event,
- rules_by_user,
- {},
- True,
- uids_with_visibility,
- )
- end = time()
- print(f"Average time: {(end - start)*1000/number:.3}ms")
|