Add default push rules including setting a sound for messages mentioning your username / display name
parent
4bdfce30d7
commit
1235f7f383
|
@ -16,9 +16,10 @@
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
|
|
||||||
from synapse.streams.config import PaginationConfig
|
from synapse.streams.config import PaginationConfig
|
||||||
from synapse.types import StreamToken
|
from synapse.types import StreamToken, UserID
|
||||||
|
|
||||||
import synapse.util.async
|
import synapse.util.async
|
||||||
|
import baserules
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import fnmatch
|
import fnmatch
|
||||||
|
@ -75,14 +76,34 @@ class Pusher(object):
|
||||||
|
|
||||||
rules = yield self.store.get_push_rules_for_user_name(self.user_name)
|
rules = yield self.store.get_push_rules_for_user_name(self.user_name)
|
||||||
|
|
||||||
|
for r in rules:
|
||||||
|
r['conditions'] = json.loads(r['conditions'])
|
||||||
|
r['actions'] = json.loads(r['actions'])
|
||||||
|
|
||||||
|
user_name_localpart = UserID.from_string(self.user_name).localpart
|
||||||
|
|
||||||
|
rules.extend(baserules.make_base_rules(user_name_localpart))
|
||||||
|
|
||||||
|
# get *our* member event for display name matching
|
||||||
|
member_events_for_room = yield self.store.get_current_state(
|
||||||
|
room_id=ev['room_id'],
|
||||||
|
event_type='m.room.member',
|
||||||
|
state_key=self.user_name
|
||||||
|
)
|
||||||
|
my_display_name = None
|
||||||
|
if len(member_events_for_room) > 0:
|
||||||
|
my_display_name = member_events_for_room[0].content['displayname']
|
||||||
|
|
||||||
for r in rules:
|
for r in rules:
|
||||||
matches = True
|
matches = True
|
||||||
|
|
||||||
conditions = json.loads(r['conditions'])
|
conditions = r['conditions']
|
||||||
actions = json.loads(r['actions'])
|
actions = r['actions']
|
||||||
|
|
||||||
for c in conditions:
|
for c in conditions:
|
||||||
matches &= self._event_fulfills_condition(ev, c)
|
matches &= self._event_fulfills_condition(
|
||||||
|
ev, c, display_name=my_display_name
|
||||||
|
)
|
||||||
# ignore rules with no actions (we have an explict 'dont_notify'
|
# ignore rules with no actions (we have an explict 'dont_notify'
|
||||||
if len(actions) == 0:
|
if len(actions) == 0:
|
||||||
logger.warn(
|
logger.warn(
|
||||||
|
@ -95,7 +116,7 @@ class Pusher(object):
|
||||||
|
|
||||||
defer.returnValue(Pusher.DEFAULT_ACTIONS)
|
defer.returnValue(Pusher.DEFAULT_ACTIONS)
|
||||||
|
|
||||||
def _event_fulfills_condition(self, ev, condition):
|
def _event_fulfills_condition(self, ev, condition, display_name):
|
||||||
if condition['kind'] == 'event_match':
|
if condition['kind'] == 'event_match':
|
||||||
if 'pattern' not in condition:
|
if 'pattern' not in condition:
|
||||||
logger.warn("event_match condition with no pattern")
|
logger.warn("event_match condition with no pattern")
|
||||||
|
@ -103,13 +124,23 @@ class Pusher(object):
|
||||||
pat = condition['pattern']
|
pat = condition['pattern']
|
||||||
|
|
||||||
val = _value_for_dotted_key(condition['key'], ev)
|
val = _value_for_dotted_key(condition['key'], ev)
|
||||||
if fnmatch.fnmatch(val, pat):
|
if val is None:
|
||||||
return True
|
|
||||||
return False
|
return False
|
||||||
|
return fnmatch.fnmatch(val.upper(), pat.upper())
|
||||||
elif condition['kind'] == 'device':
|
elif condition['kind'] == 'device':
|
||||||
if 'instance_handle' not in condition:
|
if 'instance_handle' not in condition:
|
||||||
return True
|
return True
|
||||||
return condition['instance_handle'] == self.instance_handle
|
return condition['instance_handle'] == self.instance_handle
|
||||||
|
elif condition['kind'] == 'contains_display_name':
|
||||||
|
# This is special because display names can be different
|
||||||
|
# between rooms and so you can't really hard code it in a rule.
|
||||||
|
# Optimisation: we should cache these names and update them from
|
||||||
|
# the event stream.
|
||||||
|
if 'content' not in ev or 'body' not in ev['content']:
|
||||||
|
return False
|
||||||
|
return fnmatch.fnmatch(
|
||||||
|
ev['content']['body'].upper(), "*%s*" % (display_name.upper(),)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
def make_base_rules(user_name):
|
||||||
|
"""
|
||||||
|
Nominally we reserve priority class 0 for these rules, although
|
||||||
|
in practice we just append them to the end so we don't actually need it.
|
||||||
|
"""
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
'conditions': [
|
||||||
|
{
|
||||||
|
'kind': 'event_match',
|
||||||
|
'key': 'content.body',
|
||||||
|
'pattern': '*%s*' % (user_name,), # Matrix ID match
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'actions': [
|
||||||
|
'notify',
|
||||||
|
{
|
||||||
|
'set_sound': 'default'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'conditions': [
|
||||||
|
{
|
||||||
|
'kind': 'contains_display_name'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'actions': [
|
||||||
|
'notify',
|
||||||
|
{
|
||||||
|
'set_sound': 'default'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]
|
Loading…
Reference in New Issue