kill off fnmatch in favour of word-boundary based push alerts (untested)

This commit is contained in:
Matthew Hodgson 2015-02-08 00:34:11 +00:00
parent b2b29efb75
commit 8be07e0db4
1 changed files with 20 additions and 12 deletions

View File

@ -22,7 +22,6 @@ import synapse.util.async
import baserules import baserules
import logging import logging
import fnmatch
import json import json
import re import re
@ -130,26 +129,35 @@ class Pusher(object):
defer.returnValue(Pusher.DEFAULT_ACTIONS) defer.returnValue(Pusher.DEFAULT_ACTIONS)
@staticmethod
def _glob_to_regexp(glob):
r = re.escape(glob)
r = re.sub(r'\\\*', r'.*', r)
r = re.sub(r'\\\?', r'.', r)
# handle [abc], [a-z] and [!a-z] style ranges.
r = re.sub(r'\\\[(\\\!|)(.*)\\\]',
lambda x: ('[%s%s]' % (x.group(1) and '^' or '',
re.sub(r'\\\-', '-', x.group(2)))), r)
return r
def _event_fulfills_condition(self, ev, condition, display_name, room_member_count): def _event_fulfills_condition(self, ev, condition, display_name, room_member_count):
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")
return False return False
pat = condition['pattern'] # XXX: optimisation: cache our pattern regexps
r = r'\b%s\b' % _glob_to_regexp(condition['pattern'])
if pat.strip("*?[]") == pat:
# no special glob characters so we assume the user means
# 'contains this string' rather than 'is this string'
pat = "*%s*" % (pat,)
val = _value_for_dotted_key(condition['key'], ev) val = _value_for_dotted_key(condition['key'], ev)
if val is None: if val is None:
return False return False
return fnmatch.fnmatch(val.upper(), pat.upper()) return re.match(r, val, flags=re.IGNORECASE) != None
elif condition['kind'] == 'device': elif condition['kind'] == 'device':
if 'profile_tag' not in condition: if 'profile_tag' not in condition:
return True return True
return condition['profile_tag'] == self.profile_tag return condition['profile_tag'] == self.profile_tag
elif condition['kind'] == 'contains_display_name': elif condition['kind'] == 'contains_display_name':
# This is special because display names can be different # This is special because display names can be different
# between rooms and so you can't really hard code it in a rule. # between rooms and so you can't really hard code it in a rule.
@ -159,9 +167,9 @@ class Pusher(object):
return False return False
if not display_name: if not display_name:
return False return False
return fnmatch.fnmatch( return re.match("\b%s\b" % re.escape(display_name),
ev['content']['body'].upper(), "*%s*" % (display_name.upper(),) ev['content']['body'], flags=re.IGNORECASE) != None
)
elif condition['kind'] == 'room_member_count': elif condition['kind'] == 'room_member_count':
if 'is' not in condition: if 'is' not in condition:
return False return False