grapevine/src/api/client_server/sync.rs
2025-08-10 10:49:50 +00:00

81 lines
2.3 KiB
Rust

use ruma::{events::StateEventType, RoomId, UserId};
use tracing::error;
use crate::{
service::rooms::timeline::PduCount, services, Error, PduEvent, Result,
};
pub(crate) mod msc3575;
pub(crate) mod v3;
fn load_timeline(
sender_user: &UserId,
room_id: &RoomId,
roomsincecount: PduCount,
limit: u64,
) -> Result<(Vec<(PduCount, PduEvent)>, bool), Error> {
let timeline_pdus;
let limited;
if services().rooms.timeline.last_timeline_count(sender_user, room_id)?
> roomsincecount
{
let mut non_timeline_pdus = services()
.rooms
.timeline
.pdus_until(sender_user, room_id, PduCount::MAX)?
.filter_map(|x| match x {
Ok(x) => Some(x),
Err(error) => {
error!(%error, "Bad PDU in pdus_since");
None
}
})
.take_while(|(pducount, _)| pducount > &roomsincecount);
// Take the last events for the timeline
timeline_pdus = non_timeline_pdus
.by_ref()
.take(limit.try_into().expect("limit should fit in usize"))
.collect::<Vec<_>>()
.into_iter()
.rev()
.collect::<Vec<_>>();
// They /sync response doesn't always return all messages, so we say the
// output is limited unless there are events in
// non_timeline_pdus
limited = non_timeline_pdus.next().is_some();
} else {
timeline_pdus = Vec::new();
limited = false;
}
Ok((timeline_pdus, limited))
}
fn share_encrypted_room(
sender_user: &UserId,
user_id: &UserId,
ignore_room: &RoomId,
) -> Result<bool> {
Ok(services()
.rooms
.user
.get_shared_rooms(vec![sender_user.to_owned(), user_id.to_owned()])?
.filter_map(Result::ok)
.filter(|room_id| room_id != ignore_room)
.filter_map(|other_room_id| {
Some(
services()
.rooms
.state_accessor
.room_state_get(
&other_room_id,
&StateEventType::RoomEncryption,
"",
)
.ok()?
.is_some(),
)
})
.any(|encrypted| encrypted))
}