Skip to main content

tuwunel_service/federation/
format.rs

1//! Outgoing federation event formatting.
2//!
3//! The formatter converts a canonical event object into the room-version shape
4//! expected by ruma's outgoing federation response types.
5
6use futures::future::OptionFuture;
7use ruma::{CanonicalJsonObject, CanonicalJsonValue, RoomId, RoomVersionId};
8use serde_json::value::{RawValue as RawJsonValue, to_raw_value};
9use tuwunel_core::{implement, matrix::pdu, utils::result::FlatOk};
10
11/// Formats an event object for an outgoing federation response.
12///
13/// The supplied room version takes precedence; otherwise the room ID is used to
14/// look it up. When no version can be resolved, only `event_id` is removed.
15/// The returned raw JSON satisfies ruma's response type and is not a full PDU.
16#[implement(super::Service)]
17pub async fn format_pdu_into(
18	&self,
19	mut pdu_json: CanonicalJsonObject,
20	room_version: Option<&RoomVersionId>,
21) -> Box<RawJsonValue> {
22	let room_id = pdu_json
23		.get("room_id")
24		.and_then(CanonicalJsonValue::as_str)
25		.map(RoomId::parse)
26		.flat_ok();
27
28	let query_room_version: OptionFuture<_> = room_id
29		.filter(|_| room_version.is_none())
30		.map(async |room_id| {
31			self.services
32				.state
33				.get_room_version(&room_id)
34				.await
35				.ok()
36		})
37		.into();
38
39	if let Some(room_version) = query_room_version
40		.await
41		.flatten()
42		.as_ref()
43		.or(room_version)
44	{
45		pdu_json = pdu::into_outgoing_federation(pdu_json, room_version);
46	} else {
47		pdu_json.remove("event_id");
48	}
49
50	to_raw_value(&pdu_json).expect("CanonicalJson is valid serde_json::Value")
51}