summary refs log tree commit diff
path: root/synapse
diff options
context:
space:
mode:
authorPaul Evans <leonerd@leonerd.org.uk>2014-11-18 16:44:25 +0000
committerPaul Evans <leonerd@leonerd.org.uk>2014-11-18 16:44:25 +0000
commit11fd81e3984f4efc292b9f89c733e0790e1f3c2c (patch)
tree21aaab20cee6e630eb75c9b2e723afccc8af8813 /synapse
parentRevert accidental commit of bad file (diff)
parentEnsure to parse a real pagination config object out of room initialSync reque... (diff)
downloadsynapse-11fd81e3984f4efc292b9f89c733e0790e1f3c2c.tar.xz
Merge pull request #17 from matrix-org/room-initial-sync
Room initial sync
Diffstat (limited to 'synapse')
-rw-r--r--synapse/handlers/message.py62
-rw-r--r--synapse/handlers/presence.py23
-rw-r--r--synapse/rest/room.py29
3 files changed, 88 insertions, 26 deletions
diff --git a/synapse/handlers/message.py b/synapse/handlers/message.py
index d8f8ea80cc..081030dbb8 100644
--- a/synapse/handlers/message.py
+++ b/synapse/handlers/message.py
@@ -293,3 +293,65 @@ class MessageHandler(BaseHandler):
         }
 
         defer.returnValue(ret)
+
+    @defer.inlineCallbacks
+    def room_initial_sync(self, user_id, room_id, pagin_config=None,
+                      feedback=False):
+        yield self.auth.check_joined_room(room_id, user_id)
+
+        # TODO(paul): I wish I was called with user objects not user_id
+        #   strings...
+        auth_user = self.hs.parse_userid(user_id)
+
+        # TODO: These concurrently
+        state_tuples = yield self.store.get_current_state(room_id)
+        state = [self.hs.serialize_event(x) for x in state_tuples]
+
+        member_event = (yield self.store.get_room_member(
+            user_id=user_id,
+            room_id=room_id
+        ))
+
+        now_token = yield self.hs.get_event_sources().get_current_token()
+
+        limit = pagin_config.limit if pagin_config else None
+        if limit is None:
+            limit = 10
+
+        messages, token = yield self.store.get_recent_events_for_room(
+            room_id,
+            limit=limit,
+            end_token=now_token.room_key,
+        )
+
+        start_token = now_token.copy_and_replace("room_key", token[0])
+        end_token = now_token.copy_and_replace("room_key", token[1])
+
+        room_members = yield self.store.get_room_members(room_id)
+
+        presence_handler = self.hs.get_handlers().presence_handler
+        presence = []
+        for m in room_members:
+            try:
+                member_presence = yield presence_handler.get_state(
+                    target_user=self.hs.parse_userid(m.user_id),
+                    auth_user=auth_user,
+                    as_event=True,
+                )
+                presence.append(member_presence)
+            except Exception as e:
+                logger.exception("Failed to get member presence of %r",
+                    m.user_id
+                )
+
+        defer.returnValue({
+            "membership": member_event.membership,
+            "room_id": room_id,
+            "messages": {
+                "chunk": [self.hs.serialize_event(m) for m in messages],
+                "start": start_token.to_string(),
+                "end": end_token.to_string(),
+            },
+            "state": state,
+            "presence": presence
+        })
diff --git a/synapse/handlers/presence.py b/synapse/handlers/presence.py
index 2ccc2245b7..325ae45257 100644
--- a/synapse/handlers/presence.py
+++ b/synapse/handlers/presence.py
@@ -165,7 +165,7 @@ class PresenceHandler(BaseHandler):
         defer.returnValue(False)
 
     @defer.inlineCallbacks
-    def get_state(self, target_user, auth_user):
+    def get_state(self, target_user, auth_user, as_event=False):
         if target_user.is_mine:
             visible = yield self.is_presence_visible(
                 observer_user=auth_user,
@@ -180,9 +180,9 @@ class PresenceHandler(BaseHandler):
             state["presence"] = state.pop("state")
 
             if target_user in self._user_cachemap:
-                state["last_active"] = (
-                    self._user_cachemap[target_user].get_state()["last_active"]
-                )
+                cached_state = self._user_cachemap[target_user].get_state()
+                if "last_active" in cached_state:
+                    state["last_active"] = cached_state["last_active"]
         else:
             # TODO(paul): Have remote server send us permissions set
             state = self._get_or_offline_usercache(target_user).get_state()
@@ -191,7 +191,20 @@ class PresenceHandler(BaseHandler):
             state["last_active_ago"] = int(
                 self.clock.time_msec() - state.pop("last_active")
             )
-        defer.returnValue(state)
+
+        if as_event:
+            content = state
+
+            content["user_id"] = target_user.to_string()
+
+            if "last_active" in content:
+                content["last_active_ago"] = int(
+                    self._clock.time_msec() - content.pop("last_active")
+                )
+
+            defer.returnValue({"type": "m.presence", "content": content})
+        else:
+            defer.returnValue(state)
 
     @defer.inlineCallbacks
     @log_function
diff --git a/synapse/rest/room.py b/synapse/rest/room.py
index 05da0be090..17322ee9bb 100644
--- a/synapse/rest/room.py
+++ b/synapse/rest/room.py
@@ -361,27 +361,14 @@ class RoomInitialSyncRestServlet(RestServlet):
 
     @defer.inlineCallbacks
     def on_GET(self, request, room_id):
-        yield self.auth.get_user_by_req(request)
-        # TODO: Get all the initial sync data for this room and return in the
-        # same format as initial sync, that is:
-        # {
-        #   membership: join,
-        #   messages: [
-        #       chunk: [ msg events ],
-        #       start: s_tok,
-        #       end: e_tok
-        #   ],
-        #   room_id: foo,
-        #   state: [
-        #       { state event } , { state event }
-        #   ]
-        # }
-        # Probably worth keeping the keys room_id and membership for parity
-        # with /initialSync even though they must be joined to sync this and
-        # know the room ID, so clients can reuse the same code (room_id and
-        # membership are MANDATORY for /initialSync, so the code will expect
-        # it to be there)
-        defer.returnValue((200, {}))
+        user = yield self.auth.get_user_by_req(request)
+        pagination_config = PaginationConfig.from_request(request)
+        content = yield self.handlers.message_handler.room_initial_sync(
+            room_id=room_id,
+            user_id=user.to_string(),
+            pagin_config=pagination_config,
+        )
+        defer.returnValue((200, content))
 
 
 class RoomTriggerBackfill(RestServlet):