Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add is_dm room field to Sliding Sync /sync #17429

Merged
merged 28 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9deb387
Initial work of adding name/avatar to rooms response
MadLittleMods Jul 8, 2024
b0bb37f
Add tests
MadLittleMods Jul 8, 2024
b6e36ef
Add changelog
MadLittleMods Jul 8, 2024
6ef39dd
Actually test that invited should see current state
MadLittleMods Jul 8, 2024
32c5409
Start of heroes in Sliding Sync
MadLittleMods Jul 8, 2024
9641ca7
Merge branch 'develop' into madlittlemods/sliding-sync-room-name-avatar
MadLittleMods Jul 8, 2024
9692c76
Merge branch 'madlittlemods/sliding-sync-room-name-avatar' into madli…
MadLittleMods Jul 8, 2024
ee9114c
Merge branch 'develop' into madlittlemods/sliding-sync-heroes
MadLittleMods Jul 9, 2024
f58d6fc
`heroes` is not `required_state` for now
MadLittleMods Jul 9, 2024
82bf80c
Add changelog
MadLittleMods Jul 9, 2024
10f8540
Add tests
MadLittleMods Jul 9, 2024
62925b6
Remove unncessary check
MadLittleMods Jul 9, 2024
b9f1eb1
Test `joined_count`/`invited_count`
MadLittleMods Jul 9, 2024
e50bf86
Test invite before/after ban
MadLittleMods Jul 9, 2024
2fb77b3
Sort `leave` before `knock`
MadLittleMods Jul 9, 2024
275da50
Explain the order
MadLittleMods Jul 9, 2024
6060408
Add test to make sure we only return 5 heroes
MadLittleMods Jul 9, 2024
91cefaa
Fix lint
MadLittleMods Jul 9, 2024
4205159
Add `is_dm` fields to Sliding Sync
MadLittleMods Jul 10, 2024
1bd953b
Add tests for `is_dm`
MadLittleMods Jul 10, 2024
8681b7d
Add changelog
MadLittleMods Jul 10, 2024
868dcdc
Revert `heroes` order changes
MadLittleMods Jul 11, 2024
a4753bf
Better comment on what we expect
MadLittleMods Jul 11, 2024
5583ac1
Merge branch 'develop' into madlittlemods/sliding-sync-heroes
MadLittleMods Jul 11, 2024
e2138b7
Have to use basic assertion for now
MadLittleMods Jul 11, 2024
8ffddd5
Merge branch 'develop' into madlittlemods/sliding-sync-rooms-is-dm
MadLittleMods Jul 11, 2024
2b7ec13
Fix merge
MadLittleMods Jul 11, 2024
5850e59
Merge branch 'madlittlemods/sliding-sync-heroes' into madlittlemods/s…
MadLittleMods Jul 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/17429.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Populate `is_dm` room field in experimental [MSC3575](https://github.com/matrix-org/matrix-spec-proposals/pull/3575) Sliding Sync `/sync` endpoint.
75 changes: 46 additions & 29 deletions synapse/handlers/sliding_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ class _RoomMembershipForUser:
sender: The person who sent the membership event
newly_joined: Whether the user newly joined the room during the given token
range
is_dm: Whether this user considers this room as a direct-message (DM) room
"""

room_id: str
Expand All @@ -299,6 +300,7 @@ class _RoomMembershipForUser:
membership: str
sender: Optional[str]
newly_joined: bool
is_dm: bool

def copy_and_replace(self, **kwds: Any) -> "_RoomMembershipForUser":
return attr.evolve(self, **kwds)
Expand Down Expand Up @@ -613,6 +615,7 @@ async def get_sync_room_ids_for_user(
membership=room_for_user.membership,
sender=room_for_user.sender,
newly_joined=False,
is_dm=False,
)
for room_for_user in room_for_user_list
}
Expand Down Expand Up @@ -652,6 +655,7 @@ async def get_sync_room_ids_for_user(
# - 1c) Update room membership events to the point in time of the `to_token`
# - 2) Add back newly_left rooms (> `from_token` and <= `to_token`)
# - 3) Figure out which rooms are `newly_joined`
# - 4) Figure out which rooms are DM's

# 1) -----------------------------------------------------

Expand Down Expand Up @@ -714,6 +718,7 @@ async def get_sync_room_ids_for_user(
membership=first_membership_change_after_to_token.prev_membership,
sender=first_membership_change_after_to_token.prev_sender,
newly_joined=False,
is_dm=False,
)
else:
# If we can't find the previous membership event, we shouldn't
Expand Down Expand Up @@ -809,6 +814,7 @@ async def get_sync_room_ids_for_user(
membership=last_membership_change_in_from_to_range.membership,
sender=last_membership_change_in_from_to_range.sender,
newly_joined=False,
is_dm=False,
)

# 3) Figure out `newly_joined`
Expand Down Expand Up @@ -846,6 +852,35 @@ async def get_sync_room_ids_for_user(
room_id
].copy_and_replace(newly_joined=True)

# 4) Figure out which rooms the user considers to be direct-message (DM) rooms
#
# We're using global account data (`m.direct`) instead of checking for
# `is_direct` on membership events because that property only appears for
# the invitee membership event (doesn't show up for the inviter).
#
# We're unable to take `to_token` into account for global account data since
# we only keep track of the latest account data for the user.
dm_map = await self.store.get_global_account_data_by_type_for_user(
user_id, AccountDataTypes.DIRECT
)

# Flatten out the map. Account data is set by the client so it needs to be
# scrutinized.
dm_room_id_set = set()
if isinstance(dm_map, dict):
for room_ids in dm_map.values():
# Account data should be a list of room IDs. Ignore anything else
if isinstance(room_ids, list):
for room_id in room_ids:
if isinstance(room_id, str):
dm_room_id_set.add(room_id)

# 4) Fixup
for room_id in filtered_sync_room_id_set:
filtered_sync_room_id_set[room_id] = filtered_sync_room_id_set[
room_id
].copy_and_replace(is_dm=room_id in dm_room_id_set)

return filtered_sync_room_id_set

async def filter_rooms(
Expand All @@ -869,41 +904,24 @@ async def filter_rooms(
A filtered dictionary of room IDs along with membership information in the
room at the time of `to_token`.
"""
user_id = user.to_string()

# TODO: Apply filters

filtered_room_id_set = set(sync_room_map.keys())

# Filter for Direct-Message (DM) rooms
if filters.is_dm is not None:
# We're using global account data (`m.direct`) instead of checking for
# `is_direct` on membership events because that property only appears for
# the invitee membership event (doesn't show up for the inviter). Account
# data is set by the client so it needs to be scrutinized.
#
# We're unable to take `to_token` into account for global account data since
# we only keep track of the latest account data for the user.
dm_map = await self.store.get_global_account_data_by_type_for_user(
user_id, AccountDataTypes.DIRECT
)

# Flatten out the map
dm_room_id_set = set()
if isinstance(dm_map, dict):
for room_ids in dm_map.values():
# Account data should be a list of room IDs. Ignore anything else
if isinstance(room_ids, list):
for room_id in room_ids:
if isinstance(room_id, str):
dm_room_id_set.add(room_id)

if filters.is_dm:
# Only DM rooms please
filtered_room_id_set = filtered_room_id_set.intersection(dm_room_id_set)
filtered_room_id_set = {
room_id
for room_id in filtered_room_id_set
if sync_room_map[room_id].is_dm
}
else:
# Only non-DM rooms please
filtered_room_id_set = filtered_room_id_set.difference(dm_room_id_set)
filtered_room_id_set = {
room_id
for room_id in filtered_room_id_set
if not sync_room_map[room_id].is_dm
}

if filters.spaces:
raise NotImplementedError()
Expand Down Expand Up @@ -1538,8 +1556,7 @@ async def get_room_sync_data(
name=room_name,
avatar=room_avatar,
heroes=heroes,
# TODO: Dummy value
is_dm=False,
is_dm=room_membership_for_user_at_to_token.is_dm,
initial=initial,
required_state=list(required_room_state.values()),
timeline_events=timeline_events,
Expand Down
23 changes: 23 additions & 0 deletions tests/rest/client/test_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -1662,6 +1662,20 @@ def test_filter_list(self) -> None:
list(channel.json_body["lists"]["room-invites"]),
)

# Ensure DM's are correctly marked
self.assertDictEqual(
{
room_id: room.get("is_dm")
for room_id, room in channel.json_body["rooms"].items()
},
{
invite_room_id: None,
room_id: None,
invited_dm_room_id: True,
joined_dm_room_id: True,
},
)

def test_sort_list(self) -> None:
"""
Test that the `lists` are sorted by `stream_ordering`
Expand Down Expand Up @@ -1874,6 +1888,9 @@ def test_rooms_meta_when_joined(self) -> None:
channel.json_body["rooms"][room_id1]["invited_count"],
0,
)
self.assertIsNone(
channel.json_body["rooms"][room_id1].get("is_dm"),
)

def test_rooms_meta_when_invited(self) -> None:
"""
Expand Down Expand Up @@ -1955,6 +1972,9 @@ def test_rooms_meta_when_invited(self) -> None:
channel.json_body["rooms"][room_id1]["invited_count"],
1,
)
self.assertIsNone(
channel.json_body["rooms"][room_id1].get("is_dm"),
)

def test_rooms_meta_when_banned(self) -> None:
"""
Expand Down Expand Up @@ -2037,6 +2057,9 @@ def test_rooms_meta_when_banned(self) -> None:
channel.json_body["rooms"][room_id1]["invited_count"],
0,
)
self.assertIsNone(
channel.json_body["rooms"][room_id1].get("is_dm"),
)

def test_rooms_meta_heroes(self) -> None:
"""
Expand Down
Loading