forked from MirrorHub/synapse
Merge pull request #2501 from matrix-org/dbkr/channel_notifications
Support for channel notifications
This commit is contained in:
commit
dfbf73408c
3 changed files with 85 additions and 7 deletions
|
@ -1,4 +1,5 @@
|
||||||
# Copyright 2015, 2016 OpenMarket Ltd
|
# Copyright 2015, 2016 OpenMarket Ltd
|
||||||
|
# Copyright 2017 New Vector Ltd
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
|
@ -238,6 +239,28 @@ BASE_APPEND_OVERRIDE_RULES = [
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'rule_id': 'global/override/.m.rule.roomnotif',
|
||||||
|
'conditions': [
|
||||||
|
{
|
||||||
|
'kind': 'event_match',
|
||||||
|
'key': 'content.body',
|
||||||
|
'pattern': '*@room*',
|
||||||
|
'_id': '_roomnotif_content',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'kind': 'sender_notification_permission',
|
||||||
|
'key': 'room',
|
||||||
|
'_id': '_roomnotif_pl',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'actions': [
|
||||||
|
'notify', {
|
||||||
|
'set_tweak': 'highlight',
|
||||||
|
'value': True,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright 2015 OpenMarket Ltd
|
# Copyright 2015 OpenMarket Ltd
|
||||||
|
# Copyright 2017 New Vector Ltd
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
|
@ -19,11 +20,13 @@ from twisted.internet import defer
|
||||||
|
|
||||||
from .push_rule_evaluator import PushRuleEvaluatorForEvent
|
from .push_rule_evaluator import PushRuleEvaluatorForEvent
|
||||||
|
|
||||||
|
from synapse.event_auth import get_user_power_level
|
||||||
from synapse.api.constants import EventTypes, Membership
|
from synapse.api.constants import EventTypes, Membership
|
||||||
from synapse.metrics import get_metrics_for
|
from synapse.metrics import get_metrics_for
|
||||||
from synapse.util.caches import metrics as cache_metrics
|
from synapse.util.caches import metrics as cache_metrics
|
||||||
from synapse.util.caches.descriptors import cached
|
from synapse.util.caches.descriptors import cached
|
||||||
from synapse.util.async import Linearizer
|
from synapse.util.async import Linearizer
|
||||||
|
from synapse.state import POWER_KEY
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
@ -59,6 +62,7 @@ class BulkPushRuleEvaluator(object):
|
||||||
def __init__(self, hs):
|
def __init__(self, hs):
|
||||||
self.hs = hs
|
self.hs = hs
|
||||||
self.store = hs.get_datastore()
|
self.store = hs.get_datastore()
|
||||||
|
self.auth = hs.get_auth()
|
||||||
|
|
||||||
self.room_push_rule_cache_metrics = cache_metrics.register_cache(
|
self.room_push_rule_cache_metrics = cache_metrics.register_cache(
|
||||||
"cache",
|
"cache",
|
||||||
|
@ -108,6 +112,29 @@ class BulkPushRuleEvaluator(object):
|
||||||
self.room_push_rule_cache_metrics,
|
self.room_push_rule_cache_metrics,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def _get_power_levels_and_sender_level(self, event, context):
|
||||||
|
pl_event_id = context.prev_state_ids.get(POWER_KEY)
|
||||||
|
if pl_event_id:
|
||||||
|
# fastpath: if there's a power level event, that's all we need, and
|
||||||
|
# not having a power level event is an extreme edge case
|
||||||
|
pl_event = yield self.store.get_event(pl_event_id)
|
||||||
|
auth_events = {POWER_KEY: pl_event}
|
||||||
|
else:
|
||||||
|
auth_events_ids = yield self.auth.compute_auth_events(
|
||||||
|
event, context.prev_state_ids, for_verification=False,
|
||||||
|
)
|
||||||
|
auth_events = yield self.store.get_events(auth_events_ids)
|
||||||
|
auth_events = {
|
||||||
|
(e.type, e.state_key): e for e in auth_events.itervalues()
|
||||||
|
}
|
||||||
|
|
||||||
|
sender_level = get_user_power_level(event.sender, auth_events)
|
||||||
|
|
||||||
|
pl_event = auth_events.get(POWER_KEY)
|
||||||
|
|
||||||
|
defer.returnValue((pl_event.content if pl_event else {}, sender_level))
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def action_for_event_by_user(self, event, context):
|
def action_for_event_by_user(self, event, context):
|
||||||
"""Given an event and context, evaluate the push rules and return
|
"""Given an event and context, evaluate the push rules and return
|
||||||
|
@ -123,7 +150,13 @@ class BulkPushRuleEvaluator(object):
|
||||||
event, context
|
event, context
|
||||||
)
|
)
|
||||||
|
|
||||||
evaluator = PushRuleEvaluatorForEvent(event, len(room_members))
|
(power_levels, sender_power_level) = (
|
||||||
|
yield self._get_power_levels_and_sender_level(event, context)
|
||||||
|
)
|
||||||
|
|
||||||
|
evaluator = PushRuleEvaluatorForEvent(
|
||||||
|
event, len(room_members), sender_power_level, power_levels,
|
||||||
|
)
|
||||||
|
|
||||||
condition_cache = {}
|
condition_cache = {}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright 2015, 2016 OpenMarket Ltd
|
# Copyright 2015, 2016 OpenMarket Ltd
|
||||||
|
# Copyright 2017 New Vector Ltd
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
|
@ -29,6 +30,21 @@ INEQUALITY_EXPR = re.compile("^([=<>]*)([0-9]*)$")
|
||||||
|
|
||||||
|
|
||||||
def _room_member_count(ev, condition, room_member_count):
|
def _room_member_count(ev, condition, room_member_count):
|
||||||
|
return _test_ineq_condition(condition, room_member_count)
|
||||||
|
|
||||||
|
|
||||||
|
def _sender_notification_permission(ev, condition, sender_power_level, power_levels):
|
||||||
|
notif_level_key = condition.get('key')
|
||||||
|
if notif_level_key is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
notif_levels = power_levels.get('notifications', {})
|
||||||
|
room_notif_level = notif_levels.get(notif_level_key, 50)
|
||||||
|
|
||||||
|
return sender_power_level >= room_notif_level
|
||||||
|
|
||||||
|
|
||||||
|
def _test_ineq_condition(condition, number):
|
||||||
if 'is' not in condition:
|
if 'is' not in condition:
|
||||||
return False
|
return False
|
||||||
m = INEQUALITY_EXPR.match(condition['is'])
|
m = INEQUALITY_EXPR.match(condition['is'])
|
||||||
|
@ -41,15 +57,15 @@ def _room_member_count(ev, condition, room_member_count):
|
||||||
rhs = int(rhs)
|
rhs = int(rhs)
|
||||||
|
|
||||||
if ineq == '' or ineq == '==':
|
if ineq == '' or ineq == '==':
|
||||||
return room_member_count == rhs
|
return number == rhs
|
||||||
elif ineq == '<':
|
elif ineq == '<':
|
||||||
return room_member_count < rhs
|
return number < rhs
|
||||||
elif ineq == '>':
|
elif ineq == '>':
|
||||||
return room_member_count > rhs
|
return number > rhs
|
||||||
elif ineq == '>=':
|
elif ineq == '>=':
|
||||||
return room_member_count >= rhs
|
return number >= rhs
|
||||||
elif ineq == '<=':
|
elif ineq == '<=':
|
||||||
return room_member_count <= rhs
|
return number <= rhs
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -65,9 +81,11 @@ def tweaks_for_actions(actions):
|
||||||
|
|
||||||
|
|
||||||
class PushRuleEvaluatorForEvent(object):
|
class PushRuleEvaluatorForEvent(object):
|
||||||
def __init__(self, event, room_member_count):
|
def __init__(self, event, room_member_count, sender_power_level, power_levels):
|
||||||
self._event = event
|
self._event = event
|
||||||
self._room_member_count = room_member_count
|
self._room_member_count = room_member_count
|
||||||
|
self._sender_power_level = sender_power_level
|
||||||
|
self._power_levels = power_levels
|
||||||
|
|
||||||
# Maps strings of e.g. 'content.body' -> event["content"]["body"]
|
# Maps strings of e.g. 'content.body' -> event["content"]["body"]
|
||||||
self._value_cache = _flatten_dict(event)
|
self._value_cache = _flatten_dict(event)
|
||||||
|
@ -81,6 +99,10 @@ class PushRuleEvaluatorForEvent(object):
|
||||||
return _room_member_count(
|
return _room_member_count(
|
||||||
self._event, condition, self._room_member_count
|
self._event, condition, self._room_member_count
|
||||||
)
|
)
|
||||||
|
elif condition['kind'] == 'sender_notification_permission':
|
||||||
|
return _sender_notification_permission(
|
||||||
|
self._event, condition, self._sender_power_level, self._power_levels,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue