Skip to content
Snippets Groups Projects
sync.rs 40.4 KiB
Newer Older
  • Learn to ignore specific revisions
  •                 let (joined_member_count, invited_member_count, heroes) = if send_member_count {
                        calculate_counts()?
                    } else {
                        (None, None, Vec::new())
                    };
    
                    (
                        heroes,
                        joined_member_count,
                        invited_member_count,
                        joined_since_last_sync,
                        state_events,
                    )
                }
    
        // Look for device list updates in this room
        device_list_updates.extend(
            services()
                .users
                .keys_changed(room_id.as_ref(), since, None)
                .filter_map(|r| r.ok()),
        );
    
        let notification_count = if send_notification_counts {
            Some(
                services()
                    .rooms
                    .user
                    .notification_count(&sender_user, &room_id)?
                    .try_into()
                    .expect("notification count can't go that high"),
            )
        } else {
            None
        };
    
        let highlight_count = if send_notification_counts {
            Some(
                services()
                    .rooms
                    .user
                    .highlight_count(&sender_user, &room_id)?
                    .try_into()
                    .expect("highlight count can't go that high"),
            )
        } else {
            None
        };
    
        let prev_batch = timeline_pdus
            .first()
            .map_or(Ok::<_, Error>(None), |(pdu_count, _)| {
                Ok(Some(match pdu_count {
                    PduCount::Backfilled(_) => {
                        error!("timeline in backfill state?!");
                        "0".to_owned()
                    }
                    PduCount::Normal(c) => c.to_string(),
                }))
            })?;
    
        let room_events: Vec<_> = timeline_pdus
            .iter()
            .map(|(_, pdu)| pdu.to_sync_room_event())
            .collect();
    
        let mut edus: Vec<_> = services()
            .rooms
            .edus
            .read_receipt
            .readreceipts_since(&room_id, since)
            .filter_map(|r| r.ok()) // Filter out buggy events
            .map(|(_, _, v)| v)
            .collect();
    
        if services().rooms.edus.typing.last_typing_update(&room_id)? > since {
            edus.push(
                serde_json::from_str(
                    &serde_json::to_string(&services().rooms.edus.typing.typings_all(&room_id)?)
                        .expect("event is valid, we just created it"),
                )
                .expect("event is valid, we just created it"),
            );
    
        // Save the state after this sync so we can send the correct state diff next sync
        services().rooms.user.associate_token_shortstatehash(
            &room_id,
            next_batch,
            current_shortstatehash,
        )?;
    
        Ok(JoinedRoom {
            account_data: RoomAccountData {
    
                events: services()
    
                    .account_data
    
                    .changes_since(Some(&room_id), &sender_user, since)?
    
                    .into_iter()
                    .filter_map(|(_, v)| {
                        serde_json::from_str(v.json().get())
                            .map_err(|_| Error::bad_database("Invalid account event in database."))
                            .ok()
                    })
    
    Jonas Platte's avatar
    Jonas Platte committed
                    .collect(),
    
            summary: RoomSummary {
                heroes,
                joined_member_count: joined_member_count.map(|n| (n as u32).into()),
                invited_member_count: invited_member_count.map(|n| (n as u32).into()),
    
            unread_notifications: UnreadNotificationsCount {
                highlight_count,
                notification_count,
    
            timeline: Timeline {
                limited: limited || joined_since_last_sync,
                prev_batch,
                events: room_events,
            },
            state: State {
                events: state_events
                    .iter()
                    .map(|pdu| pdu.to_sync_state_event())
                    .collect(),
            },
            ephemeral: Ephemeral { events: edus },
            unread_thread_notifications: BTreeMap::new(),
        })
    
    
    fn share_encrypted_room(
    
        sender_user: &UserId,
    
        user_id: &UserId,
        ignore_room: &RoomId,
    
    ) -> Result<bool> {
    
        Ok(services()
    
    Timo Kösters's avatar
    Timo Kösters committed
            .user
    
    Jonas Platte's avatar
    Jonas Platte committed
            .get_shared_rooms(vec![sender_user.to_owned(), user_id.to_owned()])?
    
            .filter_map(|r| r.ok())
            .filter(|room_id| room_id != ignore_room)
            .filter_map(|other_room_id| {
                Some(
    
    Timo Kösters's avatar
    Timo Kösters committed
                    services()
                        .rooms
                        .state_accessor
    
    Timo Kösters's avatar
    Timo Kösters committed
                        .room_state_get(&other_room_id, &StateEventType::RoomEncryption, "")
    
                        .ok()?
                        .is_some(),
                )
            })
    
            .any(|encrypted| encrypted))