continuwuity/src/api/client/threads.rs
Jade Ellis 69c66af0ea feat: Add bundled aggregations support
Add support for the m.replace and m.reference bundled
aggregations.
This should fix plenty of subtle client issues.
Threads are not included in the new code as they have
historically been written to the database. Replacing the
old system would result in issues when switching away from
continuwuity, so saved for later.
Some TODOs have been left re event visibility and ignored users.
These should be OK for now, though.
2025-06-18 14:39:08 -07:00

75 lines
1.7 KiB
Rust

use axum::extract::State;
use conduwuit::{
Result, at, debug_warn,
matrix::pdu::{PduCount, PduEvent},
};
use futures::StreamExt;
use ruma::{api::client::threads::get_threads, uint};
use crate::Ruma;
/// # `GET /_matrix/client/r0/rooms/{roomId}/threads`
pub(crate) async fn get_threads_route(
State(services): State<crate::State>,
ref body: Ruma<get_threads::v1::Request>,
) -> Result<get_threads::v1::Response> {
// Use limit or else 10, with maximum 100
let limit = body
.limit
.unwrap_or_else(|| uint!(10))
.try_into()
.unwrap_or(10)
.min(100);
let from: PduCount = body
.from
.as_deref()
.map(str::parse)
.transpose()?
.unwrap_or_else(PduCount::max);
// TODO: user_can_see_event and set_unsigned should be at the same level /
// function, so unsigned is only set for seen events.
let threads: Vec<(PduCount, PduEvent)> = services
.rooms
.threads
.threads_until(body.sender_user(), &body.room_id, from, &body.include)
.await?
.take(limit)
.filter_map(|(count, pdu)| async move {
services
.rooms
.state_accessor
.user_can_see_event(body.sender_user(), &body.room_id, &pdu.event_id)
.await
.then_some((count, pdu))
})
.then(|(count, mut pdu)| async move {
if let Err(e) = services
.rooms
.pdu_metadata
.add_bundled_aggregations_to_pdu(body.sender_user(), &mut pdu)
.await
{
debug_warn!("Failed to add bundled aggregations to thread: {e}");
}
(count, pdu)
})
.collect()
.await;
Ok(get_threads::v1::Response {
next_batch: threads
.last()
.filter(|_| threads.len() >= limit)
.map(at!(0))
.as_ref()
.map(ToString::to_string),
chunk: threads
.into_iter()
.map(at!(1))
.map(PduEvent::into_room_event)
.collect(),
})
}