From 2f2cebe84d319608631273cef32c8236868e5baa Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Tue, 12 Nov 2024 03:46:31 +0000 Subject: [PATCH] implement local room preview Signed-off-by: Jason Volk --- src/api/client/room/initial_sync.rs | 72 +++++++++++++++++++++++++++++ src/api/client/room/mod.rs | 3 +- src/api/router.rs | 7 +-- 3 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 src/api/client/room/initial_sync.rs diff --git a/src/api/client/room/initial_sync.rs b/src/api/client/room/initial_sync.rs new file mode 100644 index 00000000..16b3a53b --- /dev/null +++ b/src/api/client/room/initial_sync.rs @@ -0,0 +1,72 @@ +use axum::extract::State; +use conduit::{at, utils::BoolExt, Err, Result}; +use futures::StreamExt; +use ruma::api::client::room::initial_sync::v3::{PaginationChunk, Request, Response}; + +use crate::Ruma; + +const LIMIT_MAX: usize = 100; + +pub(crate) async fn room_initial_sync_route( + State(services): State, body: Ruma, +) -> Result { + let room_id = &body.room_id; + + if !services + .rooms + .state_accessor + .user_can_see_state_events(body.sender_user(), room_id) + .await + { + return Err!(Request(Forbidden("No room preview available."))); + } + + let limit = LIMIT_MAX; + let events: Vec<_> = services + .rooms + .timeline + .pdus_rev(None, room_id, None) + .await? + .take(limit) + .collect() + .await; + + let state: Vec<_> = services + .rooms + .state_accessor + .room_state_full_pdus(room_id) + .await? + .into_iter() + .map(|pdu| pdu.to_state_event()) + .collect(); + + let messages = PaginationChunk { + start: events.last().map(at!(0)).as_ref().map(ToString::to_string), + + end: events + .first() + .map(at!(0)) + .as_ref() + .map(ToString::to_string) + .unwrap_or_default(), + + chunk: events + .into_iter() + .map(at!(1)) + .map(|pdu| pdu.to_room_event()) + .collect(), + }; + + Ok(Response { + room_id: room_id.to_owned(), + account_data: None, + state: state.into(), + messages: messages.chunk.is_empty().or_some(messages), + visibility: services.rooms.directory.visibility(room_id).await.into(), + membership: services + .rooms + .state_cache + .user_membership(body.sender_user(), room_id) + .await, + }) +} diff --git a/src/api/client/room/mod.rs b/src/api/client/room/mod.rs index fa2d168f..16fcadab 100644 --- a/src/api/client/room/mod.rs +++ b/src/api/client/room/mod.rs @@ -1,9 +1,10 @@ mod aliases; mod create; mod event; +mod initial_sync; mod upgrade; pub(crate) use self::{ aliases::get_room_aliases_route, create::create_room_route, event::get_room_event_route, - upgrade::upgrade_room_route, + initial_sync::room_initial_sync_route, upgrade::upgrade_room_route, }; diff --git a/src/api/router.rs b/src/api/router.rs index 1df4342f..4bdd692d 100644 --- a/src/api/router.rs +++ b/src/api/router.rs @@ -183,8 +183,7 @@ pub fn build(router: Router, server: &Server) -> Router { .ruma_route(&client::well_known_support) .ruma_route(&client::well_known_client) .route("/_conduwuit/server_version", get(client::conduwuit_server_version)) - .route("/_matrix/client/r0/rooms/:room_id/initialSync", get(initial_sync)) - .route("/_matrix/client/v3/rooms/:room_id/initialSync", get(initial_sync)) + .ruma_route(&client::room_initial_sync_route) .route("/client/server.json", get(client::syncv3_client_server_json)); if config.allow_federation { @@ -285,10 +284,6 @@ async fn redirect_legacy_preview(uri: Uri) -> impl IntoResponse { Redirect::temporary(&uri) } -async fn initial_sync(_uri: Uri) -> impl IntoResponse { - err!(Request(GuestAccessForbidden("Guest access not implemented"))) -} - async fn legacy_media_disabled() -> impl IntoResponse { err!(Request(Forbidden("Unauthenticated media is disabled."))) } async fn federation_disabled() -> impl IntoResponse { err!(Request(Forbidden("Federation is disabled."))) }