Files
tuwunel/src/core/matrix/pdu/format.rs
2025-12-18 01:53:09 +00:00

121 lines
2.9 KiB
Rust

use ruma::{
CanonicalJsonObject, CanonicalJsonValue, EventId, RoomId, RoomVersionId,
room_version_rules::{EventsReferenceFormatVersion, RoomVersionRules},
};
use crate::{
Result, extract_variant, is_equal_to,
matrix::{PduEvent, room_version},
state_res::{self},
};
pub fn into_outgoing_federation(
mut pdu_json: CanonicalJsonObject,
room_version: &RoomVersionId,
) -> CanonicalJsonObject {
if let Some(unsigned) = pdu_json
.get_mut("unsigned")
.and_then(|val| val.as_object_mut())
{
unsigned.remove("transaction_id");
}
let Ok(room_rules) = room_version::rules(room_version) else {
pdu_json.remove("event_id");
return pdu_json;
};
if !room_rules.event_format.require_event_id {
pdu_json.remove("event_id");
}
if !room_rules
.event_format
.require_room_create_room_id
{
if pdu_json
.get("type")
.and_then(CanonicalJsonValue::as_str)
.is_some_and(is_equal_to!("m.room.create"))
{
pdu_json.remove("room_id");
}
}
if matches!(room_rules.events_reference_format, EventsReferenceFormatVersion::V1) {
if let Some(value) = pdu_json.get_mut("auth_events") {
mutate_outgoing_reference_format(value);
}
if let Some(value) = pdu_json.get_mut("prev_events") {
mutate_outgoing_reference_format(value);
}
}
pdu_json
}
fn mutate_outgoing_reference_format(value: &mut CanonicalJsonValue) {
value
.as_array_mut()
.into_iter()
.flatten()
.for_each(|value| {
if let Some(event_id) = value.as_str().map(ToOwned::to_owned) {
*value = CanonicalJsonValue::Array(vec![
CanonicalJsonValue::String(event_id),
CanonicalJsonValue::Object([(Default::default(), "".into())].into()),
]);
}
});
}
pub fn from_incoming_federation(
room_id: &RoomId,
event_id: &EventId,
pdu_json: &mut CanonicalJsonObject,
room_rules: &RoomVersionRules,
) -> Result<PduEvent> {
if matches!(room_rules.events_reference_format, EventsReferenceFormatVersion::V1) {
if let Some(value) = pdu_json.get_mut("auth_events") {
mutate_incoming_reference_format(value);
}
if let Some(value) = pdu_json.get_mut("prev_events") {
mutate_incoming_reference_format(value);
}
}
if !room_rules
.event_format
.require_room_create_room_id
&& pdu_json["type"] == "m.room.create"
{
pdu_json.insert("room_id".into(), CanonicalJsonValue::String(room_id.as_str().into()));
}
if !room_rules.event_format.require_event_id {
pdu_json.insert("event_id".into(), CanonicalJsonValue::String(event_id.into()));
}
state_res::check_pdu_format(pdu_json, &room_rules.event_format)?;
PduEvent::from_val(pdu_json)
}
fn mutate_incoming_reference_format(value: &mut CanonicalJsonValue) {
value
.as_array_mut()
.into_iter()
.flat_map(|vec| vec.iter_mut())
.for_each(|value| {
let event_id = value
.as_array()
.into_iter()
.find_map(|vec| vec.first())
.and_then(|val| extract_variant!(val, CanonicalJsonValue::String))
.cloned()
.unwrap_or_default();
*value = CanonicalJsonValue::String(event_id);
});
}