Add default push rules including setting a sound for messages mentioning your username / display name

pull/46/head
David Baker 2015-01-29 18:38:22 +00:00
parent 4bdfce30d7
commit 1235f7f383
2 changed files with 74 additions and 8 deletions

View File

@ -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

35
synapse/push/baserules.py Normal file
View File

@ -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'
}
]
},
]