tuwunel_core/matrix/pdu/
format.rs1pub(super) mod check;
2
3use ruma::{
4 CanonicalJsonObject, CanonicalJsonValue, EventId, RoomId, RoomVersionId,
5 room_version_rules::{EventsReferenceFormatVersion, RoomVersionRules},
6};
7
8use crate::{extract_variant, is_equal_to, matrix::room_version};
9
10#[must_use]
11pub fn into_outgoing_federation(
12 mut pdu_json: CanonicalJsonObject,
13 room_version: &RoomVersionId,
14) -> CanonicalJsonObject {
15 if let Some(unsigned) = pdu_json
16 .get_mut("unsigned")
17 .and_then(|val| val.as_object_mut())
18 {
19 unsigned.remove("transaction_id");
20 }
21
22 let Ok(room_rules) = room_version::rules(room_version) else {
23 pdu_json.remove("event_id");
24 return pdu_json;
25 };
26
27 if !room_rules.event_format.require_event_id {
28 pdu_json.remove("event_id");
29 }
30
31 if !room_rules
32 .event_format
33 .require_room_create_room_id
34 && pdu_json
35 .get("type")
36 .and_then(CanonicalJsonValue::as_str)
37 .is_some_and(is_equal_to!("m.room.create"))
38 {
39 pdu_json.remove("room_id");
40 }
41
42 if matches!(room_rules.events_reference_format, EventsReferenceFormatVersion::V1) {
43 if let Some(value) = pdu_json.get_mut("auth_events") {
44 mutate_outgoing_reference_format(value);
45 }
46 if let Some(value) = pdu_json.get_mut("prev_events") {
47 mutate_outgoing_reference_format(value);
48 }
49 }
50
51 pdu_json
52}
53
54fn mutate_outgoing_reference_format(value: &mut CanonicalJsonValue) {
55 value
56 .as_array_mut()
57 .into_iter()
58 .flatten()
59 .for_each(|value| {
60 if let Some(event_id) = value.as_str().map(ToOwned::to_owned) {
61 *value = CanonicalJsonValue::Array(vec![
62 CanonicalJsonValue::String(event_id),
63 CanonicalJsonValue::Object([(Default::default(), "".into())].into()),
64 ]);
65 }
66 });
67}
68
69#[must_use]
70pub fn from_incoming_federation(
71 room_id: &RoomId,
72 event_id: &EventId,
73 mut pdu_json: CanonicalJsonObject,
74 room_rules: &RoomVersionRules,
75) -> CanonicalJsonObject {
76 if matches!(room_rules.events_reference_format, EventsReferenceFormatVersion::V1) {
77 if let Some(value) = pdu_json.get_mut("auth_events") {
78 mutate_incoming_reference_format(value);
79 }
80 if let Some(value) = pdu_json.get_mut("prev_events") {
81 mutate_incoming_reference_format(value);
82 }
83 }
84
85 if !room_rules
86 .event_format
87 .require_room_create_room_id
88 && pdu_json["type"] == "m.room.create"
89 {
90 pdu_json.insert("room_id".into(), CanonicalJsonValue::String(room_id.as_str().into()));
91 }
92
93 if !room_rules.event_format.require_event_id {
94 pdu_json.insert("event_id".into(), CanonicalJsonValue::String(event_id.into()));
95 }
96
97 pdu_json
98}
99
100fn mutate_incoming_reference_format(value: &mut CanonicalJsonValue) {
101 value
102 .as_array_mut()
103 .into_iter()
104 .flat_map(|vec| vec.iter_mut())
105 .for_each(|value| {
106 let event_id = value
107 .as_array()
108 .into_iter()
109 .find_map(|vec| vec.first())
110 .and_then(|val| extract_variant!(val, CanonicalJsonValue::String))
111 .cloned()
112 .unwrap_or_default();
113
114 *value = CanonicalJsonValue::String(event_id);
115 });
116}