@@ -1506,16 +1506,22 @@ async def _generate_sync_entry_for_rooms(
1506
1506
account_data_by_room: Dictionary of per room account data
1507
1507
1508
1508
Returns:
1509
- Returns a 4-tuple whose entries are:
1509
+ Returns a 4-tuple describing rooms the user has joined or left, and users who've
1510
+ joined or left rooms any rooms the user is in. This gets used later in
1511
+ `_generate_sync_entry_for_device_list`.
1512
+
1513
+ Its entries are:
1510
1514
- newly_joined_rooms
1511
1515
- newly_joined_or_invited_or_knocked_users
1512
1516
- newly_left_rooms
1513
1517
- newly_left_users
1514
1518
"""
1515
- # Start by fetching all ephemeral events in rooms we've joined (if required).
1519
+ since_token = sync_result_builder .since_token
1520
+
1521
+ # 1. Start by fetching all ephemeral events in rooms we've joined (if required).
1516
1522
user_id = sync_result_builder .sync_config .user .to_string ()
1517
1523
block_all_room_ephemeral = (
1518
- sync_result_builder . since_token is None
1524
+ since_token is None
1519
1525
and sync_result_builder .sync_config .filter_collection .blocks_all_room_ephemeral ()
1520
1526
)
1521
1527
@@ -1529,9 +1535,8 @@ async def _generate_sync_entry_for_rooms(
1529
1535
)
1530
1536
sync_result_builder .now_token = now_token
1531
1537
1532
- # We check up front if anything has changed, if it hasn't then there is
1538
+ # 2. We check up front if anything has changed, if it hasn't then there is
1533
1539
# no point in going further.
1534
- since_token = sync_result_builder .since_token
1535
1540
if not sync_result_builder .full_state :
1536
1541
if since_token and not ephemeral_by_room and not account_data_by_room :
1537
1542
have_changed = await self ._have_rooms_changed (sync_result_builder )
@@ -1544,20 +1549,8 @@ async def _generate_sync_entry_for_rooms(
1544
1549
logger .debug ("no-oping sync" )
1545
1550
return set (), set (), set (), set ()
1546
1551
1547
- ignored_account_data = (
1548
- await self .store .get_global_account_data_by_type_for_user (
1549
- AccountDataTypes .IGNORED_USER_LIST , user_id = user_id
1550
- )
1551
- )
1552
-
1553
- # If there is ignored users account data and it matches the proper type,
1554
- # then use it.
1555
- ignored_users : FrozenSet [str ] = frozenset ()
1556
- if ignored_account_data :
1557
- ignored_users_data = ignored_account_data .get ("ignored_users" , {})
1558
- if isinstance (ignored_users_data , dict ):
1559
- ignored_users = frozenset (ignored_users_data .keys ())
1560
-
1552
+ # 3. Work out which rooms need reporting in the sync response.
1553
+ ignored_users = await self ._get_ignored_users (user_id )
1561
1554
if since_token :
1562
1555
room_changes = await self ._get_rooms_changed (
1563
1556
sync_result_builder , ignored_users
@@ -1567,7 +1560,6 @@ async def _generate_sync_entry_for_rooms(
1567
1560
)
1568
1561
else :
1569
1562
room_changes = await self ._get_all_rooms (sync_result_builder , ignored_users )
1570
-
1571
1563
tags_by_room = await self .store .get_tags_for_user (user_id )
1572
1564
1573
1565
log_kv ({"rooms_changed" : len (room_changes .room_entries )})
@@ -1578,6 +1570,8 @@ async def _generate_sync_entry_for_rooms(
1578
1570
newly_joined_rooms = room_changes .newly_joined_rooms
1579
1571
newly_left_rooms = room_changes .newly_left_rooms
1580
1572
1573
+ # 4. We need to apply further processing to `room_entries` (rooms considered
1574
+ # joined or archived).
1581
1575
async def handle_room_entries (room_entry : "RoomSyncResultBuilder" ) -> None :
1582
1576
logger .debug ("Generating room entry for %s" , room_entry .room_id )
1583
1577
await self ._generate_room_entry (
@@ -1596,31 +1590,13 @@ async def handle_room_entries(room_entry: "RoomSyncResultBuilder") -> None:
1596
1590
sync_result_builder .invited .extend (invited )
1597
1591
sync_result_builder .knocked .extend (knocked )
1598
1592
1599
- # Now we want to get any newly joined, invited or knocking users
1600
- newly_joined_or_invited_or_knocked_users = set ()
1601
- newly_left_users = set ()
1602
- if since_token :
1603
- for joined_sync in sync_result_builder .joined :
1604
- it = itertools .chain (
1605
- joined_sync .timeline .events , joined_sync .state .values ()
1606
- )
1607
- for event in it :
1608
- if event .type == EventTypes .Member :
1609
- if (
1610
- event .membership == Membership .JOIN
1611
- or event .membership == Membership .INVITE
1612
- or event .membership == Membership .KNOCK
1613
- ):
1614
- newly_joined_or_invited_or_knocked_users .add (
1615
- event .state_key
1616
- )
1617
- else :
1618
- prev_content = event .unsigned .get ("prev_content" , {})
1619
- prev_membership = prev_content .get ("membership" , None )
1620
- if prev_membership == Membership .JOIN :
1621
- newly_left_users .add (event .state_key )
1622
-
1623
- newly_left_users -= newly_joined_or_invited_or_knocked_users
1593
+ # 5. Work out which users have joined or left rooms we're in. We use this
1594
+ # to build the device_list part of the sync response in
1595
+ # `_generate_sync_entry_for_device_list`.
1596
+ (
1597
+ newly_joined_or_invited_or_knocked_users ,
1598
+ newly_left_users ,
1599
+ ) = sync_result_builder .calculate_user_changes ()
1624
1600
1625
1601
return (
1626
1602
set (newly_joined_rooms ),
@@ -1629,6 +1605,29 @@ async def handle_room_entries(room_entry: "RoomSyncResultBuilder") -> None:
1629
1605
newly_left_users ,
1630
1606
)
1631
1607
1608
+ async def _get_ignored_users (self , user_id : str ) -> FrozenSet [str ]:
1609
+ """Retrieve the users ignored by the given user from their global account_data.
1610
+
1611
+ Returns an empty set if
1612
+ - there is no global account_data entry for ignored_users
1613
+ - there is such an entry, but it's not a JSON object.
1614
+ """
1615
+ # TODO: Can we `SELECT ignored_user_id FROM ignored_users WHERE ignorer_user_id=?;` instead?
1616
+ ignored_account_data = (
1617
+ await self .store .get_global_account_data_by_type_for_user (
1618
+ AccountDataTypes .IGNORED_USER_LIST , user_id = user_id
1619
+ )
1620
+ )
1621
+
1622
+ # If there is ignored users account data and it matches the proper type,
1623
+ # then use it.
1624
+ ignored_users : FrozenSet [str ] = frozenset ()
1625
+ if ignored_account_data :
1626
+ ignored_users_data = ignored_account_data .get ("ignored_users" , {})
1627
+ if isinstance (ignored_users_data , dict ):
1628
+ ignored_users = frozenset (ignored_users_data .keys ())
1629
+ return ignored_users
1630
+
1632
1631
async def _have_rooms_changed (
1633
1632
self , sync_result_builder : "SyncResultBuilder"
1634
1633
) -> bool :
@@ -2341,6 +2340,39 @@ class SyncResultBuilder:
2341
2340
groups : Optional [GroupsSyncResult ] = None
2342
2341
to_device : List [JsonDict ] = attr .Factory (list )
2343
2342
2343
+ def calculate_user_changes (self ) -> Tuple [Set [str ], Set [str ]]:
2344
+ """Work out which other users have joined or left rooms we are joined to.
2345
+
2346
+ This data only is only useful for an incremental sync.
2347
+
2348
+ The SyncResultBuilder is not modified by this function.
2349
+ """
2350
+ newly_joined_or_invited_or_knocked_users = set ()
2351
+ newly_left_users = set ()
2352
+ if self .since_token :
2353
+ for joined_sync in self .joined :
2354
+ it = itertools .chain (
2355
+ joined_sync .timeline .events , joined_sync .state .values ()
2356
+ )
2357
+ for event in it :
2358
+ if event .type == EventTypes .Member :
2359
+ if (
2360
+ event .membership == Membership .JOIN
2361
+ or event .membership == Membership .INVITE
2362
+ or event .membership == Membership .KNOCK
2363
+ ):
2364
+ newly_joined_or_invited_or_knocked_users .add (
2365
+ event .state_key
2366
+ )
2367
+ else :
2368
+ prev_content = event .unsigned .get ("prev_content" , {})
2369
+ prev_membership = prev_content .get ("membership" , None )
2370
+ if prev_membership == Membership .JOIN :
2371
+ newly_left_users .add (event .state_key )
2372
+
2373
+ newly_left_users -= newly_joined_or_invited_or_knocked_users
2374
+ return newly_joined_or_invited_or_knocked_users , newly_left_users
2375
+
2344
2376
2345
2377
@attr .s (slots = True , auto_attribs = True )
2346
2378
class RoomSyncResultBuilder :
0 commit comments