mirror of
https://mau.dev/maunium/synapse.git
synced 2024-12-15 16:13:51 +01:00
Add is_dm
room field to Sliding Sync /sync
(#17429)
Based on [MSC3575](https://github.com/matrix-org/matrix-spec-proposals/pull/3575): Sliding Sync
This commit is contained in:
parent
5a97bbd895
commit
fb66e938b2
3 changed files with 70 additions and 29 deletions
1
changelog.d/17429.feature
Normal file
1
changelog.d/17429.feature
Normal file
|
@ -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.
|
|
@ -291,6 +291,7 @@ class _RoomMembershipForUser:
|
||||||
sender: The person who sent the membership event
|
sender: The person who sent the membership event
|
||||||
newly_joined: Whether the user newly joined the room during the given token
|
newly_joined: Whether the user newly joined the room during the given token
|
||||||
range
|
range
|
||||||
|
is_dm: Whether this user considers this room as a direct-message (DM) room
|
||||||
"""
|
"""
|
||||||
|
|
||||||
room_id: str
|
room_id: str
|
||||||
|
@ -299,6 +300,7 @@ class _RoomMembershipForUser:
|
||||||
membership: str
|
membership: str
|
||||||
sender: Optional[str]
|
sender: Optional[str]
|
||||||
newly_joined: bool
|
newly_joined: bool
|
||||||
|
is_dm: bool
|
||||||
|
|
||||||
def copy_and_replace(self, **kwds: Any) -> "_RoomMembershipForUser":
|
def copy_and_replace(self, **kwds: Any) -> "_RoomMembershipForUser":
|
||||||
return attr.evolve(self, **kwds)
|
return attr.evolve(self, **kwds)
|
||||||
|
@ -613,6 +615,7 @@ class SlidingSyncHandler:
|
||||||
membership=room_for_user.membership,
|
membership=room_for_user.membership,
|
||||||
sender=room_for_user.sender,
|
sender=room_for_user.sender,
|
||||||
newly_joined=False,
|
newly_joined=False,
|
||||||
|
is_dm=False,
|
||||||
)
|
)
|
||||||
for room_for_user in room_for_user_list
|
for room_for_user in room_for_user_list
|
||||||
}
|
}
|
||||||
|
@ -652,6 +655,7 @@ class SlidingSyncHandler:
|
||||||
# - 1c) Update room membership events to the point in time of the `to_token`
|
# - 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`)
|
# - 2) Add back newly_left rooms (> `from_token` and <= `to_token`)
|
||||||
# - 3) Figure out which rooms are `newly_joined`
|
# - 3) Figure out which rooms are `newly_joined`
|
||||||
|
# - 4) Figure out which rooms are DM's
|
||||||
|
|
||||||
# 1) -----------------------------------------------------
|
# 1) -----------------------------------------------------
|
||||||
|
|
||||||
|
@ -714,6 +718,7 @@ class SlidingSyncHandler:
|
||||||
membership=first_membership_change_after_to_token.prev_membership,
|
membership=first_membership_change_after_to_token.prev_membership,
|
||||||
sender=first_membership_change_after_to_token.prev_sender,
|
sender=first_membership_change_after_to_token.prev_sender,
|
||||||
newly_joined=False,
|
newly_joined=False,
|
||||||
|
is_dm=False,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# If we can't find the previous membership event, we shouldn't
|
# If we can't find the previous membership event, we shouldn't
|
||||||
|
@ -809,6 +814,7 @@ class SlidingSyncHandler:
|
||||||
membership=last_membership_change_in_from_to_range.membership,
|
membership=last_membership_change_in_from_to_range.membership,
|
||||||
sender=last_membership_change_in_from_to_range.sender,
|
sender=last_membership_change_in_from_to_range.sender,
|
||||||
newly_joined=False,
|
newly_joined=False,
|
||||||
|
is_dm=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
# 3) Figure out `newly_joined`
|
# 3) Figure out `newly_joined`
|
||||||
|
@ -846,6 +852,35 @@ class SlidingSyncHandler:
|
||||||
room_id
|
room_id
|
||||||
].copy_and_replace(newly_joined=True)
|
].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
|
return filtered_sync_room_id_set
|
||||||
|
|
||||||
async def filter_rooms(
|
async def filter_rooms(
|
||||||
|
@ -869,41 +904,24 @@ class SlidingSyncHandler:
|
||||||
A filtered dictionary of room IDs along with membership information in the
|
A filtered dictionary of room IDs along with membership information in the
|
||||||
room at the time of `to_token`.
|
room at the time of `to_token`.
|
||||||
"""
|
"""
|
||||||
user_id = user.to_string()
|
|
||||||
|
|
||||||
# TODO: Apply filters
|
|
||||||
|
|
||||||
filtered_room_id_set = set(sync_room_map.keys())
|
filtered_room_id_set = set(sync_room_map.keys())
|
||||||
|
|
||||||
# Filter for Direct-Message (DM) rooms
|
# Filter for Direct-Message (DM) rooms
|
||||||
if filters.is_dm is not None:
|
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:
|
if filters.is_dm:
|
||||||
# Only DM rooms please
|
# 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:
|
else:
|
||||||
# Only non-DM rooms please
|
# 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:
|
if filters.spaces:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
@ -1538,8 +1556,7 @@ class SlidingSyncHandler:
|
||||||
name=room_name,
|
name=room_name,
|
||||||
avatar=room_avatar,
|
avatar=room_avatar,
|
||||||
heroes=heroes,
|
heroes=heroes,
|
||||||
# TODO: Dummy value
|
is_dm=room_membership_for_user_at_to_token.is_dm,
|
||||||
is_dm=False,
|
|
||||||
initial=initial,
|
initial=initial,
|
||||||
required_state=list(required_room_state.values()),
|
required_state=list(required_room_state.values()),
|
||||||
timeline_events=timeline_events,
|
timeline_events=timeline_events,
|
||||||
|
|
|
@ -1662,6 +1662,20 @@ class SlidingSyncTestCase(unittest.HomeserverTestCase):
|
||||||
list(channel.json_body["lists"]["room-invites"]),
|
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:
|
def test_sort_list(self) -> None:
|
||||||
"""
|
"""
|
||||||
Test that the `lists` are sorted by `stream_ordering`
|
Test that the `lists` are sorted by `stream_ordering`
|
||||||
|
@ -1874,6 +1888,9 @@ class SlidingSyncTestCase(unittest.HomeserverTestCase):
|
||||||
channel.json_body["rooms"][room_id1]["invited_count"],
|
channel.json_body["rooms"][room_id1]["invited_count"],
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
|
self.assertIsNone(
|
||||||
|
channel.json_body["rooms"][room_id1].get("is_dm"),
|
||||||
|
)
|
||||||
|
|
||||||
def test_rooms_meta_when_invited(self) -> None:
|
def test_rooms_meta_when_invited(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -1955,6 +1972,9 @@ class SlidingSyncTestCase(unittest.HomeserverTestCase):
|
||||||
channel.json_body["rooms"][room_id1]["invited_count"],
|
channel.json_body["rooms"][room_id1]["invited_count"],
|
||||||
1,
|
1,
|
||||||
)
|
)
|
||||||
|
self.assertIsNone(
|
||||||
|
channel.json_body["rooms"][room_id1].get("is_dm"),
|
||||||
|
)
|
||||||
|
|
||||||
def test_rooms_meta_when_banned(self) -> None:
|
def test_rooms_meta_when_banned(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -2037,6 +2057,9 @@ class SlidingSyncTestCase(unittest.HomeserverTestCase):
|
||||||
channel.json_body["rooms"][room_id1]["invited_count"],
|
channel.json_body["rooms"][room_id1]["invited_count"],
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
|
self.assertIsNone(
|
||||||
|
channel.json_body["rooms"][room_id1].get("is_dm"),
|
||||||
|
)
|
||||||
|
|
||||||
def test_rooms_meta_heroes(self) -> None:
|
def test_rooms_meta_heroes(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in a new issue