summary refs log tree commit diff
path: root/eval.py
diff options
context:
space:
mode:
Diffstat (limited to 'eval.py')
-rw-r--r--eval.py179
1 files changed, 179 insertions, 0 deletions
diff --git a/eval.py b/eval.py
new file mode 100644

index 0000000000..8a7b501eb9 --- /dev/null +++ b/eval.py
@@ -0,0 +1,179 @@ +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")