180 lines
5.8 KiB
Python
180 lines
5.8 KiB
Python
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")
|