|
|
@ -108,6 +108,16 @@ class InvitedSyncResult(collections.namedtuple("InvitedSyncResult", [ |
|
|
|
return True |
|
|
|
return True |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DeviceLists(collections.namedtuple("DeviceLists", [ |
|
|
|
|
|
|
|
"changed", # list of user_ids whose devices may have changed |
|
|
|
|
|
|
|
"left", # list of user_ids whose devices we no longer track |
|
|
|
|
|
|
|
])): |
|
|
|
|
|
|
|
__slots__ = [] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __nonzero__(self): |
|
|
|
|
|
|
|
return bool(self.changed or self.left) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SyncResult(collections.namedtuple("SyncResult", [ |
|
|
|
class SyncResult(collections.namedtuple("SyncResult", [ |
|
|
|
"next_batch", # Token for the next sync |
|
|
|
"next_batch", # Token for the next sync |
|
|
|
"presence", # List of presence events for the user. |
|
|
|
"presence", # List of presence events for the user. |
|
|
@ -535,7 +545,8 @@ class SyncHandler(object): |
|
|
|
res = yield self._generate_sync_entry_for_rooms( |
|
|
|
res = yield self._generate_sync_entry_for_rooms( |
|
|
|
sync_result_builder, account_data_by_room |
|
|
|
sync_result_builder, account_data_by_room |
|
|
|
) |
|
|
|
) |
|
|
|
newly_joined_rooms, newly_joined_users = res |
|
|
|
newly_joined_rooms, newly_joined_users, _, _ = res |
|
|
|
|
|
|
|
_, _, newly_left_rooms, newly_left_users = res |
|
|
|
|
|
|
|
|
|
|
|
block_all_presence_data = ( |
|
|
|
block_all_presence_data = ( |
|
|
|
since_token is None and |
|
|
|
since_token is None and |
|
|
@ -549,7 +560,11 @@ class SyncHandler(object): |
|
|
|
yield self._generate_sync_entry_for_to_device(sync_result_builder) |
|
|
|
yield self._generate_sync_entry_for_to_device(sync_result_builder) |
|
|
|
|
|
|
|
|
|
|
|
device_lists = yield self._generate_sync_entry_for_device_list( |
|
|
|
device_lists = yield self._generate_sync_entry_for_device_list( |
|
|
|
sync_result_builder |
|
|
|
sync_result_builder, |
|
|
|
|
|
|
|
newly_joined_rooms=newly_joined_rooms, |
|
|
|
|
|
|
|
newly_joined_users=newly_joined_users, |
|
|
|
|
|
|
|
newly_left_rooms=newly_left_rooms, |
|
|
|
|
|
|
|
newly_left_users=newly_left_users, |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
device_id = sync_config.device_id |
|
|
|
device_id = sync_config.device_id |
|
|
@ -574,7 +589,9 @@ class SyncHandler(object): |
|
|
|
|
|
|
|
|
|
|
|
@measure_func("_generate_sync_entry_for_device_list") |
|
|
|
@measure_func("_generate_sync_entry_for_device_list") |
|
|
|
@defer.inlineCallbacks |
|
|
|
@defer.inlineCallbacks |
|
|
|
def _generate_sync_entry_for_device_list(self, sync_result_builder): |
|
|
|
def _generate_sync_entry_for_device_list(self, sync_result_builder, |
|
|
|
|
|
|
|
newly_joined_rooms, newly_joined_users, |
|
|
|
|
|
|
|
newly_left_rooms, newly_left_users): |
|
|
|
user_id = sync_result_builder.sync_config.user.to_string() |
|
|
|
user_id = sync_result_builder.sync_config.user.to_string() |
|
|
|
since_token = sync_result_builder.since_token |
|
|
|
since_token = sync_result_builder.since_token |
|
|
|
|
|
|
|
|
|
|
@ -582,16 +599,40 @@ class SyncHandler(object): |
|
|
|
changed = yield self.store.get_user_whose_devices_changed( |
|
|
|
changed = yield self.store.get_user_whose_devices_changed( |
|
|
|
since_token.device_list_key |
|
|
|
since_token.device_list_key |
|
|
|
) |
|
|
|
) |
|
|
|
if not changed: |
|
|
|
|
|
|
|
defer.returnValue([]) |
|
|
|
# TODO: Be more clever than this, i.e. remove users who we already |
|
|
|
|
|
|
|
# share a room with? |
|
|
|
|
|
|
|
for room_id in newly_joined_rooms: |
|
|
|
|
|
|
|
joined_users = yield self.state.get_current_user_in_room(room_id) |
|
|
|
|
|
|
|
newly_joined_users.update(joined_users) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for room_id in newly_left_rooms: |
|
|
|
|
|
|
|
left_users = yield self.state.get_current_user_in_room(room_id) |
|
|
|
|
|
|
|
newly_left_users.update(left_users) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# TODO: Check that these users are actually new, i.e. either they |
|
|
|
|
|
|
|
# weren't in the previous sync *or* they left and rejoined. |
|
|
|
|
|
|
|
changed.update(newly_joined_users) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if not changed and not newly_left_users: |
|
|
|
|
|
|
|
defer.returnValue(DeviceLists( |
|
|
|
|
|
|
|
changed=[], |
|
|
|
|
|
|
|
left=newly_left_users, |
|
|
|
|
|
|
|
)) |
|
|
|
|
|
|
|
|
|
|
|
users_who_share_room = yield self.store.get_users_who_share_room_with_user( |
|
|
|
users_who_share_room = yield self.store.get_users_who_share_room_with_user( |
|
|
|
user_id |
|
|
|
user_id |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
defer.returnValue(users_who_share_room & changed) |
|
|
|
defer.returnValue(DeviceLists( |
|
|
|
|
|
|
|
changed=users_who_share_room & changed, |
|
|
|
|
|
|
|
left=set(newly_left_users) - users_who_share_room, |
|
|
|
|
|
|
|
)) |
|
|
|
else: |
|
|
|
else: |
|
|
|
defer.returnValue([]) |
|
|
|
defer.returnValue(DeviceLists( |
|
|
|
|
|
|
|
changed=[], |
|
|
|
|
|
|
|
left=[], |
|
|
|
|
|
|
|
)) |
|
|
|
|
|
|
|
|
|
|
|
@defer.inlineCallbacks |
|
|
|
@defer.inlineCallbacks |
|
|
|
def _generate_sync_entry_for_to_device(self, sync_result_builder): |
|
|
|
def _generate_sync_entry_for_to_device(self, sync_result_builder): |
|
|
@ -755,8 +796,8 @@ class SyncHandler(object): |
|
|
|
account_data_by_room(dict): Dictionary of per room account data |
|
|
|
account_data_by_room(dict): Dictionary of per room account data |
|
|
|
|
|
|
|
|
|
|
|
Returns: |
|
|
|
Returns: |
|
|
|
Deferred(tuple): Returns a 2-tuple of |
|
|
|
Deferred(tuple): Returns a 4-tuple of |
|
|
|
`(newly_joined_rooms, newly_joined_users)` |
|
|
|
`(newly_joined_rooms, newly_joined_users, newly_left_rooms, newly_left_users)` |
|
|
|
""" |
|
|
|
""" |
|
|
|
user_id = sync_result_builder.sync_config.user.to_string() |
|
|
|
user_id = sync_result_builder.sync_config.user.to_string() |
|
|
|
block_all_room_ephemeral = ( |
|
|
|
block_all_room_ephemeral = ( |
|
|
@ -787,7 +828,7 @@ class SyncHandler(object): |
|
|
|
) |
|
|
|
) |
|
|
|
if not tags_by_room: |
|
|
|
if not tags_by_room: |
|
|
|
logger.debug("no-oping sync") |
|
|
|
logger.debug("no-oping sync") |
|
|
|
defer.returnValue(([], [])) |
|
|
|
defer.returnValue(([], [], [], [])) |
|
|
|
|
|
|
|
|
|
|
|
ignored_account_data = yield self.store.get_global_account_data_by_type_for_user( |
|
|
|
ignored_account_data = yield self.store.get_global_account_data_by_type_for_user( |
|
|
|
"m.ignored_user_list", user_id=user_id, |
|
|
|
"m.ignored_user_list", user_id=user_id, |
|
|
@ -800,7 +841,7 @@ class SyncHandler(object): |
|
|
|
|
|
|
|
|
|
|
|
if since_token: |
|
|
|
if since_token: |
|
|
|
res = yield self._get_rooms_changed(sync_result_builder, ignored_users) |
|
|
|
res = yield self._get_rooms_changed(sync_result_builder, ignored_users) |
|
|
|
room_entries, invited, newly_joined_rooms = res |
|
|
|
room_entries, invited, newly_joined_rooms, newly_left_rooms = res |
|
|
|
|
|
|
|
|
|
|
|
tags_by_room = yield self.store.get_updated_tags( |
|
|
|
tags_by_room = yield self.store.get_updated_tags( |
|
|
|
user_id, since_token.account_data_key, |
|
|
|
user_id, since_token.account_data_key, |
|
|
@ -808,6 +849,7 @@ class SyncHandler(object): |
|
|
|
else: |
|
|
|
else: |
|
|
|
res = yield self._get_all_rooms(sync_result_builder, ignored_users) |
|
|
|
res = yield self._get_all_rooms(sync_result_builder, ignored_users) |
|
|
|
room_entries, invited, newly_joined_rooms = res |
|
|
|
room_entries, invited, newly_joined_rooms = res |
|
|
|
|
|
|
|
newly_left_rooms = [] |
|
|
|
|
|
|
|
|
|
|
|
tags_by_room = yield self.store.get_tags_for_user(user_id) |
|
|
|
tags_by_room = yield self.store.get_tags_for_user(user_id) |
|
|
|
|
|
|
|
|
|
|
@ -828,17 +870,30 @@ class SyncHandler(object): |
|
|
|
|
|
|
|
|
|
|
|
# Now we want to get any newly joined users |
|
|
|
# Now we want to get any newly joined users |
|
|
|
newly_joined_users = set() |
|
|
|
newly_joined_users = set() |
|
|
|
|
|
|
|
newly_left_users = set() |
|
|
|
if since_token: |
|
|
|
if since_token: |
|
|
|
for joined_sync in sync_result_builder.joined: |
|
|
|
for joined_sync in sync_result_builder.joined: |
|
|
|
it = itertools.chain( |
|
|
|
it = itertools.chain( |
|
|
|
joined_sync.timeline.events, joined_sync.state.values() |
|
|
|
joined_sync.timeline.events, joined_sync.state.itervalues() |
|
|
|
) |
|
|
|
) |
|
|
|
for event in it: |
|
|
|
for event in it: |
|
|
|
if event.type == EventTypes.Member: |
|
|
|
if event.type == EventTypes.Member: |
|
|
|
if event.membership == Membership.JOIN: |
|
|
|
if event.membership == Membership.JOIN: |
|
|
|
newly_joined_users.add(event.state_key) |
|
|
|
newly_joined_users.add(event.state_key) |
|
|
|
|
|
|
|
else: |
|
|
|
defer.returnValue((newly_joined_rooms, newly_joined_users)) |
|
|
|
prev_content = event.unsigned.get("prev_content", {}) |
|
|
|
|
|
|
|
prev_membership = prev_content.get("membership", None) |
|
|
|
|
|
|
|
if prev_membership == Membership.JOIN: |
|
|
|
|
|
|
|
newly_left_users.add(event.state_key) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
newly_left_users -= newly_joined_users |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
defer.returnValue(( |
|
|
|
|
|
|
|
newly_joined_rooms, |
|
|
|
|
|
|
|
newly_joined_users, |
|
|
|
|
|
|
|
newly_left_rooms, |
|
|
|
|
|
|
|
newly_left_users, |
|
|
|
|
|
|
|
)) |
|
|
|
|
|
|
|
|
|
|
|
@defer.inlineCallbacks |
|
|
|
@defer.inlineCallbacks |
|
|
|
def _have_rooms_changed(self, sync_result_builder): |
|
|
|
def _have_rooms_changed(self, sync_result_builder): |
|
|
@ -908,15 +963,17 @@ class SyncHandler(object): |
|
|
|
mem_change_events_by_room_id.setdefault(event.room_id, []).append(event) |
|
|
|
mem_change_events_by_room_id.setdefault(event.room_id, []).append(event) |
|
|
|
|
|
|
|
|
|
|
|
newly_joined_rooms = [] |
|
|
|
newly_joined_rooms = [] |
|
|
|
|
|
|
|
newly_left_rooms = [] |
|
|
|
room_entries = [] |
|
|
|
room_entries = [] |
|
|
|
invited = [] |
|
|
|
invited = [] |
|
|
|
for room_id, events in mem_change_events_by_room_id.items(): |
|
|
|
for room_id, events in mem_change_events_by_room_id.iteritems(): |
|
|
|
non_joins = [e for e in events if e.membership != Membership.JOIN] |
|
|
|
non_joins = [e for e in events if e.membership != Membership.JOIN] |
|
|
|
has_join = len(non_joins) != len(events) |
|
|
|
has_join = len(non_joins) != len(events) |
|
|
|
|
|
|
|
|
|
|
|
# We want to figure out if we joined the room at some point since |
|
|
|
# We want to figure out if we joined the room at some point since |
|
|
|
# the last sync (even if we have since left). This is to make sure |
|
|
|
# the last sync (even if we have since left). This is to make sure |
|
|
|
# we do send down the room, and with full state, where necessary |
|
|
|
# we do send down the room, and with full state, where necessary |
|
|
|
|
|
|
|
old_state_ids = None |
|
|
|
if room_id in joined_room_ids or has_join: |
|
|
|
if room_id in joined_room_ids or has_join: |
|
|
|
old_state_ids = yield self.get_state_at(room_id, since_token) |
|
|
|
old_state_ids = yield self.get_state_at(room_id, since_token) |
|
|
|
old_mem_ev_id = old_state_ids.get((EventTypes.Member, user_id), None) |
|
|
|
old_mem_ev_id = old_state_ids.get((EventTypes.Member, user_id), None) |
|
|
@ -934,6 +991,26 @@ class SyncHandler(object): |
|
|
|
if not non_joins: |
|
|
|
if not non_joins: |
|
|
|
continue |
|
|
|
continue |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Check if we have left the room. This can either be because we were |
|
|
|
|
|
|
|
# joined before *or* that we since joined and then left. |
|
|
|
|
|
|
|
if events[-1].membership != Membership.JOIN: |
|
|
|
|
|
|
|
if has_join: |
|
|
|
|
|
|
|
newly_left_rooms.append(room_id) |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
if not old_state_ids: |
|
|
|
|
|
|
|
old_state_ids = yield self.get_state_at(room_id, since_token) |
|
|
|
|
|
|
|
old_mem_ev_id = old_state_ids.get( |
|
|
|
|
|
|
|
(EventTypes.Member, user_id), |
|
|
|
|
|
|
|
None, |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
old_mem_ev = None |
|
|
|
|
|
|
|
if old_mem_ev_id: |
|
|
|
|
|
|
|
old_mem_ev = yield self.store.get_event( |
|
|
|
|
|
|
|
old_mem_ev_id, allow_none=True |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
if old_mem_ev and old_mem_ev.membership == Membership.JOIN: |
|
|
|
|
|
|
|
newly_left_rooms.append(room_id) |
|
|
|
|
|
|
|
|
|
|
|
# Only bother if we're still currently invited |
|
|
|
# Only bother if we're still currently invited |
|
|
|
should_invite = non_joins[-1].membership == Membership.INVITE |
|
|
|
should_invite = non_joins[-1].membership == Membership.INVITE |
|
|
|
if should_invite: |
|
|
|
if should_invite: |
|
|
@ -1011,7 +1088,7 @@ class SyncHandler(object): |
|
|
|
upto_token=since_token, |
|
|
|
upto_token=since_token, |
|
|
|
)) |
|
|
|
)) |
|
|
|
|
|
|
|
|
|
|
|
defer.returnValue((room_entries, invited, newly_joined_rooms)) |
|
|
|
defer.returnValue((room_entries, invited, newly_joined_rooms, newly_left_rooms)) |
|
|
|
|
|
|
|
|
|
|
|
@defer.inlineCallbacks |
|
|
|
@defer.inlineCallbacks |
|
|
|
def _get_all_rooms(self, sync_result_builder, ignored_users): |
|
|
|
def _get_all_rooms(self, sync_result_builder, ignored_users): |
|
|
@ -1259,6 +1336,7 @@ class SyncResultBuilder(object): |
|
|
|
self.invited = [] |
|
|
|
self.invited = [] |
|
|
|
self.archived = [] |
|
|
|
self.archived = [] |
|
|
|
self.device = [] |
|
|
|
self.device = [] |
|
|
|
|
|
|
|
self.to_device = [] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class RoomSyncResultBuilder(object): |
|
|
|
class RoomSyncResultBuilder(object): |
|
|
|