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