mirror of
https://github.com/element-hq/synapse.git
synced 2026-11-04 13:28:04 +00:00
Deliver announcement rooms in the sync that carries the user's leave
This commit is contained in:
2 files changed
+38
-5
No files matched your search
@@ -3096,6 +3096,7 @@ class SyncHandler:
|
||||
sync_result_builder.forced_newly_joined_room_ids
|
||||
)
|
||||
newly_left_rooms: list[str] = []
|
||||
left_announcement_room_ids: set[str] = set()
|
||||
room_entries: list[RoomSyncResultBuilder] = []
|
||||
invited: list[InvitedSyncResult] = []
|
||||
knocked: list[KnockedSyncResult] = []
|
||||
@@ -3200,6 +3201,7 @@ class SyncHandler:
|
||||
knocked.append(knock_room_sync)
|
||||
|
||||
if room_id in sync_result_builder.announcement_room_ids:
|
||||
left_announcement_room_ids.add(room_id)
|
||||
continue
|
||||
|
||||
# Always include leave/ban events. Just take the last one.
|
||||
@@ -3311,7 +3313,9 @@ class SyncHandler:
|
||||
|
||||
room_entries.extend(
|
||||
await self._get_announcement_room_entries(
|
||||
sync_result_builder, sync_result_builder.announcement_room_ids
|
||||
sync_result_builder,
|
||||
sync_result_builder.announcement_room_ids,
|
||||
left_room_ids=left_announcement_room_ids,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -3327,6 +3331,7 @@ class SyncHandler:
|
||||
self,
|
||||
sync_result_builder: "SyncResultBuilder",
|
||||
room_ids: AbstractSet[str],
|
||||
left_room_ids: AbstractSet[str] = frozenset(),
|
||||
) -> list["RoomSyncResultBuilder"]:
|
||||
"""Returns entries for the given announcement rooms that have an
|
||||
announcement to show, i.e. a non-state event.
|
||||
@@ -3336,9 +3341,15 @@ class SyncHandler:
|
||||
most recent events hold an announcement. On an initial sync, a room is
|
||||
included if its most recent events hold an announcement.
|
||||
|
||||
Rooms in `left_room_ids` are included even without an announcement, so
|
||||
that the client replaces the user's real membership with the synthetic
|
||||
join and gets the room's current state.
|
||||
|
||||
Args:
|
||||
sync_result_builder
|
||||
room_ids: The announcement rooms to consider.
|
||||
left_room_ids: Rooms among `room_ids` that the user left or was
|
||||
removed from since the `since_token`.
|
||||
"""
|
||||
since_token = sync_result_builder.since_token
|
||||
now_token = sync_result_builder.now_token
|
||||
@@ -3357,7 +3368,7 @@ class SyncHandler:
|
||||
room_id
|
||||
for room_id, (events, _, _) in room_to_events.items()
|
||||
if not all(event.is_state() for event in events)
|
||||
}
|
||||
} | (left_room_ids & room_ids)
|
||||
|
||||
if since_token and sync_result_builder.full_state:
|
||||
recent_room_to_events = await self.store.get_room_events_stream_for_rooms(
|
||||
|
||||
@@ -2242,6 +2242,9 @@ class ServerAnnouncementsSyncTestCase(unittest.HomeserverTestCase):
|
||||
def _timeline_ids(self, room: JsonDict) -> list[str]:
|
||||
return [event["event_id"] for event in room["timeline"]["events"]]
|
||||
|
||||
def _timeline_types(self, room: JsonDict) -> list[str]:
|
||||
return [event["type"] for event in room["timeline"]["events"]]
|
||||
|
||||
def _state_types(self, room: JsonDict) -> set[str]:
|
||||
return {event["type"] for event in room["state"]["events"]}
|
||||
|
||||
@@ -2342,8 +2345,9 @@ class ServerAnnouncementsSyncTestCase(unittest.HomeserverTestCase):
|
||||
)
|
||||
|
||||
def test_removed_member(self) -> None:
|
||||
"""A member removed from the room by the config does not get their leave,
|
||||
then gets later announcements as a non-member, on initial sync too.
|
||||
"""A member removed from the room by the config switches straight to the
|
||||
synthetic join and the room's current power levels, then gets later
|
||||
announcements as a non-member, on initial sync too.
|
||||
"""
|
||||
since = self._sync(self.former_tok)["next_batch"]
|
||||
|
||||
@@ -2352,7 +2356,14 @@ class ServerAnnouncementsSyncTestCase(unittest.HomeserverTestCase):
|
||||
]
|
||||
self.get_success(self.handler.reconcile_rooms())
|
||||
response = self._sync(self.former_tok, since)
|
||||
self._assert_not_delivered(response)
|
||||
room = self._assert_delivered(response, self.former)
|
||||
self.assertNotIn(EventTypes.Message, self._timeline_types(room))
|
||||
power_levels = [
|
||||
event
|
||||
for event in room["state"]["events"] + room["timeline"]["events"]
|
||||
if event["type"] == EventTypes.PowerLevels
|
||||
][-1]
|
||||
self.assertNotIn(self.former, power_levels["content"]["users"])
|
||||
|
||||
event_id = self._announce("hello")
|
||||
room = self._assert_delivered(
|
||||
@@ -2380,6 +2391,17 @@ class ServerAnnouncementsSyncTestCase(unittest.HomeserverTestCase):
|
||||
room = self._assert_delivered(response, self.former)
|
||||
self.assertEqual(self._timeline_ids(room)[-2:], event_ids)
|
||||
|
||||
def test_member_leaving(self) -> None:
|
||||
"""A member who leaves the room on their own switches straight to the
|
||||
synthetic join, even when no announcement is sent.
|
||||
"""
|
||||
since = self._sync(self.former_tok)["next_batch"]
|
||||
|
||||
self.helper.leave(self.room_id, self.former, tok=self.former_tok)
|
||||
|
||||
room = self._assert_delivered(self._sync(self.former_tok, since), self.former)
|
||||
self.assertEqual(self._timeline_ids(room), [])
|
||||
|
||||
def test_initial_sync_after_leaving(self) -> None:
|
||||
"""A former member who left on their own gets a single, synthetic join
|
||||
on initial sync, even when their real leave is among the recent events.
|
||||
|
||||
Reference in new issue
Block a user