summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--synapse/appservice/__init__.py17
-rw-r--r--synapse/handlers/appservice.py21
-rw-r--r--synapse/rest/appservice/v1/__init__.py4
-rw-r--r--tests/appservice/test_appservice.py25
4 files changed, 56 insertions, 11 deletions
diff --git a/synapse/appservice/__init__.py b/synapse/appservice/__init__.py
index fb9bfffe5d..381b4cfc4a 100644
--- a/synapse/appservice/__init__.py
+++ b/synapse/appservice/__init__.py
@@ -74,7 +74,7 @@ class ApplicationService(object):
                 return True
         return False
 
-    def _matches_user(self, event):
+    def _matches_user(self, event, member_list):
         if (hasattr(event, "sender") and
                 self.is_interested_in_user(event.sender)):
             return True
@@ -83,6 +83,10 @@ class ApplicationService(object):
                 and hasattr(event, "state_key")
                 and self.is_interested_in_user(event.state_key)):
             return True
+        # check joined member events
+        for member in member_list:
+            if self.is_interested_in_user(member.state_key):
+                return True
         return False
 
     def _matches_room_id(self, event):
@@ -96,7 +100,8 @@ class ApplicationService(object):
                 return True
         return False
 
-    def is_interested(self, event, restrict_to=None, aliases_for_event=None):
+    def is_interested(self, event, restrict_to=None, aliases_for_event=None,
+                      member_list=None):
         """Check if this service is interested in this event.
 
         Args:
@@ -104,18 +109,22 @@ class ApplicationService(object):
             restrict_to(str): The namespace to restrict regex tests to.
             aliases_for_event(list): A list of all the known room aliases for
             this event.
+            member_list(list): A list of all joined room members in this room.
         Returns:
             bool: True if this service would like to know about this event.
         """
         if aliases_for_event is None:
             aliases_for_event = []
+        if member_list is None:
+            member_list = []
+
         if restrict_to and restrict_to not in ApplicationService.NS_LIST:
             # this is a programming error, so fail early and raise a general
             # exception
             raise Exception("Unexpected restrict_to value: %s". restrict_to)
 
         if not restrict_to:
-            return (self._matches_user(event)
+            return (self._matches_user(event, member_list)
                     or self._matches_aliases(event, aliases_for_event)
                     or self._matches_room_id(event))
         elif restrict_to == ApplicationService.NS_ALIASES:
@@ -123,7 +132,7 @@ class ApplicationService(object):
         elif restrict_to == ApplicationService.NS_ROOMS:
             return self._matches_room_id(event)
         elif restrict_to == ApplicationService.NS_USERS:
-            return self._matches_user(event)
+            return self._matches_user(event, member_list)
 
     def is_interested_in_user(self, user_id):
         return self._matches_regex(user_id, ApplicationService.NS_USERS)
diff --git a/synapse/handlers/appservice.py b/synapse/handlers/appservice.py
index 8591a77bf3..2c488a46f6 100644
--- a/synapse/handlers/appservice.py
+++ b/synapse/handlers/appservice.py
@@ -15,7 +15,7 @@
 
 from twisted.internet import defer
 
-from synapse.api.constants import EventTypes
+from synapse.api.constants import EventTypes, Membership
 from synapse.api.errors import Codes, StoreError, SynapseError
 from synapse.appservice import ApplicationService
 from synapse.types import UserID
@@ -154,14 +154,25 @@ class ApplicationServicesHandler(object):
             list<ApplicationService>: A list of services interested in this
             event based on the service regex.
         """
-        # We need to know the aliases associated with this event.room_id, if any
-        if not alias_list:
-            alias_list = yield self.store.get_aliases_for_room(event.room_id)
+        member_list = None
+        if hasattr(event, "room_id"):
+            # We need to know the aliases associated with this event.room_id,
+            # if any.
+            if not alias_list:
+                alias_list = yield self.store.get_aliases_for_room(
+                    event.room_id
+                )
+            # We need to know the members associated with this event.room_id,
+            # if any.
+            member_list = yield self.store.get_room_members(
+                room_id=event.room_id,
+                membership=Membership.JOIN
+            )
 
         services = yield self.store.get_app_services()
         interested_list = [
             s for s in services if (
-                s.is_interested(event, restrict_to, alias_list)
+                s.is_interested(event, restrict_to, alias_list, member_list)
             )
         ]
         defer.returnValue(interested_list)
diff --git a/synapse/rest/appservice/v1/__init__.py b/synapse/rest/appservice/v1/__init__.py
index bf243b6180..a7877609ad 100644
--- a/synapse/rest/appservice/v1/__init__.py
+++ b/synapse/rest/appservice/v1/__init__.py
@@ -21,9 +21,9 @@ class AppServiceRestResource(JsonResource):
     """A resource for version 1 of the matrix application service API."""
 
     def __init__(self, hs):
-        JsonResource.__init__(self)
+        JsonResource.__init__(self, hs)
         self.register_servlets(self, hs)
 
     @staticmethod
     def register_servlets(appservice_resource, hs):
-        register.register_servlets(hs, appservice_resource)
\ No newline at end of file
+        register.register_servlets(hs, appservice_resource)
diff --git a/tests/appservice/test_appservice.py b/tests/appservice/test_appservice.py
index c0aaf12785..d12e4f2644 100644
--- a/tests/appservice/test_appservice.py
+++ b/tests/appservice/test_appservice.py
@@ -143,3 +143,28 @@ class ApplicationServiceTestCase(unittest.TestCase):
             restrict_to=ApplicationService.NS_USERS,
             aliases_for_event=["#xmpp_barfoo:matrix.org"]
         ))
+
+    def test_member_list_match(self):
+        self.service.namespaces[ApplicationService.NS_USERS].append(
+            "@irc_.*"
+        )
+        join_list = [
+            Mock(
+                type="m.room.member", room_id="!foo:bar", sender="@alice:here",
+                state_key="@alice:here"
+            ),
+            Mock(
+                type="m.room.member", room_id="!foo:bar", sender="@irc_fo:here",
+                state_key="@irc_fo:here"  # AS user
+            ),
+            Mock(
+                type="m.room.member", room_id="!foo:bar", sender="@bob:here",
+                state_key="@bob:here"
+            )
+        ]
+
+        self.event.sender = "@xmpp_foobar:matrix.org"
+        self.assertTrue(self.service.is_interested(
+            event=self.event,
+            member_list=join_list
+        ))