1//! Types for the [`m.room.create`] event.
2//!
3//! [`m.room.create`]: https://spec.matrix.org/latest/client-server-api/#mroomcreate
45use ruma_common::{
6 room::RoomType, room_version_rules::RedactionRules, OwnedEventId, OwnedRoomId, OwnedUserId,
7 RoomVersionId,
8};
9use ruma_macros::EventContent;
10use serde::{Deserialize, Serialize};
1112use crate::{EmptyStateKey, RedactContent, RedactedStateEventContent};
1314/// The content of an `m.room.create` event.
15///
16/// This is the first event in a room and cannot be changed.
17///
18/// It acts as the root of all other events.
19#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
20#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
21#[ruma_event(type = "m.room.create", kind = State, state_key_type = EmptyStateKey, custom_redacted)]
22pub struct RoomCreateEventContent {
23/// The `user_id` of the room creator.
24 ///
25 /// This is set by the homeserver.
26 ///
27 /// This is required in room versions 1 trough 10, but is removed starting from room version
28 /// 11.
29#[serde(skip_serializing_if = "Option::is_none")]
30 #[deprecated = "Since Matrix 1.8. This field was removed in Room version 11, clients should use the event's sender instead"]
31pub creator: Option<OwnedUserId>,
3233/// Whether or not this room's data should be transferred to other homeservers.
34#[serde(
35 rename = "m.federate",
36 default = "ruma_common::serde::default_true",
37 skip_serializing_if = "ruma_common::serde::is_true"
38)]
39pub federate: bool,
4041/// The version of the room.
42 ///
43 /// Defaults to `RoomVersionId::V1`.
44#[serde(default = "default_room_version_id")]
45pub room_version: RoomVersionId,
4647/// A reference to the room this room replaces, if the previous room was upgraded.
48#[serde(skip_serializing_if = "Option::is_none")]
49pub predecessor: Option<PreviousRoom>,
5051/// The room type.
52 ///
53 /// This is currently only used for spaces.
54#[serde(skip_serializing_if = "Option::is_none", rename = "type")]
55pub room_type: Option<RoomType>,
56}
5758impl RoomCreateEventContent {
59/// Creates a new `RoomCreateEventContent` with the given creator, as required for room versions
60 /// 1 through 10.
61pub fn new_v1(creator: OwnedUserId) -> Self {
62#[allow(deprecated)]
63Self {
64 creator: Some(creator),
65 federate: true,
66 room_version: default_room_version_id(),
67 predecessor: None,
68 room_type: None,
69 }
70 }
7172/// Creates a new `RoomCreateEventContent` with the default values and no creator, as introduced
73 /// in room version 11.
74 ///
75 /// The room version is set to [`RoomVersionId::V11`].
76pub fn new_v11() -> Self {
77#[allow(deprecated)]
78Self {
79 creator: None,
80 federate: true,
81 room_version: RoomVersionId::V11,
82 predecessor: None,
83 room_type: None,
84 }
85 }
86}
8788impl RedactContent for RoomCreateEventContent {
89type Redacted = RedactedRoomCreateEventContent;
9091fn redact(self, rules: &RedactionRules) -> Self::Redacted {
92#[allow(deprecated)]
93if rules.keep_room_create_content {
94self
95} else {
96Self {
97 room_version: default_room_version_id(),
98 creator: self.creator,
99 ..Self::new_v11()
100 }
101 }
102 }
103}
104105/// A reference to an old room replaced during a room version upgrade.
106#[derive(Clone, Debug, Deserialize, Serialize)]
107#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
108pub struct PreviousRoom {
109/// The ID of the old room.
110pub room_id: OwnedRoomId,
111112/// The event ID of the last known event in the old room.
113pub event_id: OwnedEventId,
114}
115116impl PreviousRoom {
117/// Creates a new `PreviousRoom` from the given room and event IDs.
118pub fn new(room_id: OwnedRoomId, event_id: OwnedEventId) -> Self {
119Self { room_id, event_id }
120 }
121}
122123/// Used to default the `room_version` field to room version 1.
124fn default_room_version_id() -> RoomVersionId {
125 RoomVersionId::V1
126}
127128/// Redacted form of [`RoomCreateEventContent`].
129///
130/// The redaction rules of this event changed with room version 11:
131///
132/// - In room versions 1 through 10, the `creator` field was preserved during redaction, starting
133/// from room version 11 the field is removed.
134/// - In room versions 1 through 10, all the other fields were redacted, starting from room version
135/// 11 all the fields are preserved.
136pub type RedactedRoomCreateEventContent = RoomCreateEventContent;
137138impl RedactedStateEventContent for RedactedRoomCreateEventContent {
139type StateKey = EmptyStateKey;
140}
141142#[cfg(test)]
143mod tests {
144use assert_matches2::assert_matches;
145use ruma_common::{owned_user_id, RoomVersionId};
146use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
147148use super::{RoomCreateEventContent, RoomType};
149150#[test]
151fn serialization() {
152#[allow(deprecated)]
153let content = RoomCreateEventContent {
154 creator: Some(owned_user_id!("@carl:example.com")),
155 federate: false,
156 room_version: RoomVersionId::V4,
157 predecessor: None,
158 room_type: None,
159 };
160161let json = json!({
162"creator": "@carl:example.com",
163"m.federate": false,
164"room_version": "4"
165});
166167assert_eq!(to_json_value(&content).unwrap(), json);
168 }
169170#[test]
171fn space_serialization() {
172#[allow(deprecated)]
173let content = RoomCreateEventContent {
174 creator: Some(owned_user_id!("@carl:example.com")),
175 federate: false,
176 room_version: RoomVersionId::V4,
177 predecessor: None,
178 room_type: Some(RoomType::Space),
179 };
180181let json = json!({
182"creator": "@carl:example.com",
183"m.federate": false,
184"room_version": "4",
185"type": "m.space"
186});
187188assert_eq!(to_json_value(&content).unwrap(), json);
189 }
190191#[test]
192 #[allow(deprecated)]
193fn deserialization() {
194let json = json!({
195"creator": "@carl:example.com",
196"m.federate": true,
197"room_version": "4"
198});
199200let content = from_json_value::<RoomCreateEventContent>(json).unwrap();
201assert_eq!(content.creator.unwrap(), "@carl:example.com");
202assert!(content.federate);
203assert_eq!(content.room_version, RoomVersionId::V4);
204assert_matches!(content.predecessor, None);
205assert_eq!(content.room_type, None);
206 }
207208#[test]
209 #[allow(deprecated)]
210fn space_deserialization() {
211let json = json!({
212"creator": "@carl:example.com",
213"m.federate": true,
214"room_version": "4",
215"type": "m.space"
216});
217218let content = from_json_value::<RoomCreateEventContent>(json).unwrap();
219assert_eq!(content.creator.unwrap(), "@carl:example.com");
220assert!(content.federate);
221assert_eq!(content.room_version, RoomVersionId::V4);
222assert_matches!(content.predecessor, None);
223assert_eq!(content.room_type, Some(RoomType::Space));
224 }
225}