Notify ASes for events sent by other users in a room which an AS user is a part of.

This commit is contained in:
Kegan Dougal 2015-02-11 10:36:08 +00:00
parent 9978c5c103
commit c7783d6fee
4 changed files with 56 additions and 11 deletions

View file

@ -74,7 +74,7 @@ class ApplicationService(object):
return True return True
return False return False
def _matches_user(self, event): def _matches_user(self, event, member_list):
if (hasattr(event, "sender") and if (hasattr(event, "sender") and
self.is_interested_in_user(event.sender)): self.is_interested_in_user(event.sender)):
return True return True
@ -83,6 +83,10 @@ class ApplicationService(object):
and hasattr(event, "state_key") and hasattr(event, "state_key")
and self.is_interested_in_user(event.state_key)): and self.is_interested_in_user(event.state_key)):
return True return True
# check joined member events
for member in member_list:
if self.is_interested_in_user(member.state_key):
return True
return False return False
def _matches_room_id(self, event): def _matches_room_id(self, event):
@ -96,7 +100,8 @@ class ApplicationService(object):
return True return True
return False 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. """Check if this service is interested in this event.
Args: Args:
@ -104,18 +109,22 @@ class ApplicationService(object):
restrict_to(str): The namespace to restrict regex tests to. restrict_to(str): The namespace to restrict regex tests to.
aliases_for_event(list): A list of all the known room aliases for aliases_for_event(list): A list of all the known room aliases for
this event. this event.
member_list(list): A list of all joined room members in this room.
Returns: Returns:
bool: True if this service would like to know about this event. bool: True if this service would like to know about this event.
""" """
if aliases_for_event is None: if aliases_for_event is None:
aliases_for_event = [] aliases_for_event = []
if member_list is None:
member_list = []
if restrict_to and restrict_to not in ApplicationService.NS_LIST: if restrict_to and restrict_to not in ApplicationService.NS_LIST:
# this is a programming error, so fail early and raise a general # this is a programming error, so fail early and raise a general
# exception # exception
raise Exception("Unexpected restrict_to value: %s". restrict_to) raise Exception("Unexpected restrict_to value: %s". restrict_to)
if not 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_aliases(event, aliases_for_event)
or self._matches_room_id(event)) or self._matches_room_id(event))
elif restrict_to == ApplicationService.NS_ALIASES: elif restrict_to == ApplicationService.NS_ALIASES:
@ -123,7 +132,7 @@ class ApplicationService(object):
elif restrict_to == ApplicationService.NS_ROOMS: elif restrict_to == ApplicationService.NS_ROOMS:
return self._matches_room_id(event) return self._matches_room_id(event)
elif restrict_to == ApplicationService.NS_USERS: 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): def is_interested_in_user(self, user_id):
return self._matches_regex(user_id, ApplicationService.NS_USERS) return self._matches_regex(user_id, ApplicationService.NS_USERS)

View file

@ -15,7 +15,7 @@
from twisted.internet import defer 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.api.errors import Codes, StoreError, SynapseError
from synapse.appservice import ApplicationService from synapse.appservice import ApplicationService
from synapse.types import UserID from synapse.types import UserID
@ -154,14 +154,25 @@ class ApplicationServicesHandler(object):
list<ApplicationService>: A list of services interested in this list<ApplicationService>: A list of services interested in this
event based on the service regex. event based on the service regex.
""" """
# We need to know the aliases associated with this event.room_id, if any member_list = None
if not alias_list: if hasattr(event, "room_id"):
alias_list = yield self.store.get_aliases_for_room(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() services = yield self.store.get_app_services()
interested_list = [ interested_list = [
s for s in services if ( 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) defer.returnValue(interested_list)

View file

@ -21,7 +21,7 @@ class AppServiceRestResource(JsonResource):
"""A resource for version 1 of the matrix application service API.""" """A resource for version 1 of the matrix application service API."""
def __init__(self, hs): def __init__(self, hs):
JsonResource.__init__(self) JsonResource.__init__(self, hs)
self.register_servlets(self, hs) self.register_servlets(self, hs)
@staticmethod @staticmethod

View file

@ -143,3 +143,28 @@ class ApplicationServiceTestCase(unittest.TestCase):
restrict_to=ApplicationService.NS_USERS, restrict_to=ApplicationService.NS_USERS,
aliases_for_event=["#xmpp_barfoo:matrix.org"] 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
))