1use ruma_common::{
2 serde::from_raw_json_value, EventId, MilliSecondsSinceUnixEpoch, OwnedRoomId, RoomId,
3 TransactionId, UserId,
4};
5use ruma_macros::{event_enum, EventEnumFromEvent};
6use serde::{de, Deserialize};
7use serde_json::value::RawValue as RawJsonValue;
8
9use super::room::encrypted;
10
11pub const RECOMMENDED_STRIPPED_STATE_EVENT_TYPES: &[StateEventType] = &[
16 StateEventType::RoomCreate,
17 StateEventType::RoomName,
18 StateEventType::RoomAvatar,
19 StateEventType::RoomTopic,
20 StateEventType::RoomJoinRules,
21 StateEventType::RoomCanonicalAlias,
22 StateEventType::RoomEncryption,
23];
24
25event_enum! {
26 enum GlobalAccountData {
28 "m.direct" => super::direct,
29 "m.identity_server" => super::identity_server,
30 "m.ignored_user_list" => super::ignored_user_list,
31 "m.push_rules" => super::push_rules,
32 "m.secret_storage.default_key" => super::secret_storage::default_key,
33 "m.secret_storage.key.*" => super::secret_storage::key,
34 #[cfg(feature = "unstable-msc4278")]
35 "m.media_preview_config" => super::media_preview_config,
36 #[cfg(feature = "unstable-msc4278")]
37 #[ruma_enum(ident = UnstableMediaPreviewConfig)]
38 "io.element.msc4278.media_preview_config" => super::media_preview_config,
39 #[cfg(feature = "unstable-msc2545")]
40 #[ruma_enum(ident = AccountImagePack, alias = "m.image_pack")]
41 "im.ponies.user_emotes" => super::image_pack,
42 #[cfg(feature = "unstable-msc2545")]
43 #[ruma_enum(ident = ImagePackRooms, alias = "m.image_pack.rooms")]
44 "im.ponies.emote_rooms" => super::image_pack,
45 }
46
47 enum RoomAccountData {
49 "m.fully_read" => super::fully_read,
50 "m.tag" => super::tag,
51 "m.marked_unread" => super::marked_unread,
52 #[cfg(feature = "unstable-msc2867")]
53 #[ruma_enum(ident = UnstableMarkedUnread)]
54 "com.famedly.marked_unread" => super::marked_unread,
55 #[cfg(feature = "unstable-msc4278")]
56 "m.media_preview_config" => super::media_preview_config,
57 #[cfg(feature = "unstable-msc4278")]
58 #[ruma_enum(ident = UnstableMediaPreviewConfig)]
59 "io.element.msc4278.media_preview_config" => super::media_preview_config,
60 }
61
62 enum EphemeralRoom {
64 "m.receipt" => super::receipt,
65 "m.typing" => super::typing,
66 }
67
68 enum MessageLike {
70 #[cfg(feature = "unstable-msc3927")]
71 #[ruma_enum(alias = "m.audio")]
72 "org.matrix.msc1767.audio" => super::audio,
73 "m.call.answer" => super::call::answer,
74 "m.call.invite" => super::call::invite,
75 "m.call.hangup" => super::call::hangup,
76 "m.call.candidates" => super::call::candidates,
77 "m.call.negotiate" => super::call::negotiate,
78 "m.call.reject" => super::call::reject,
79 #[ruma_enum(alias = "org.matrix.call.sdp_stream_metadata_changed")]
80 "m.call.sdp_stream_metadata_changed" => super::call::sdp_stream_metadata_changed,
81 "m.call.select_answer" => super::call::select_answer,
82 #[cfg(feature = "unstable-msc3954")]
83 #[ruma_enum(alias = "m.emote")]
84 "org.matrix.msc1767.emote" => super::emote,
85 #[cfg(feature = "unstable-msc3956")]
86 #[ruma_enum(alias = "m.encrypted")]
87 "org.matrix.msc1767.encrypted" => super::encrypted,
88 #[cfg(feature = "unstable-msc3551")]
89 #[ruma_enum(alias = "m.file")]
90 "org.matrix.msc1767.file" => super::file,
91 #[cfg(feature = "unstable-msc3552")]
92 #[ruma_enum(alias = "m.image")]
93 "org.matrix.msc1767.image" => super::image,
94 "m.key.verification.ready" => super::key::verification::ready,
95 "m.key.verification.start" => super::key::verification::start,
96 "m.key.verification.cancel" => super::key::verification::cancel,
97 "m.key.verification.accept" => super::key::verification::accept,
98 "m.key.verification.key" => super::key::verification::key,
99 "m.key.verification.mac" => super::key::verification::mac,
100 "m.key.verification.done" => super::key::verification::done,
101 #[cfg(feature = "unstable-msc3488")]
102 "m.location" => super::location,
103 #[cfg(feature = "unstable-msc1767")]
104 #[ruma_enum(alias = "m.message")]
105 "org.matrix.msc1767.message" => super::message,
106 #[cfg(feature = "unstable-msc3381")]
107 "m.poll.start" => super::poll::start,
108 #[cfg(feature = "unstable-msc3381")]
109 #[ruma_enum(ident = UnstablePollStart)]
110 "org.matrix.msc3381.poll.start" => super::poll::unstable_start,
111 #[cfg(feature = "unstable-msc3381")]
112 "m.poll.response" => super::poll::response,
113 #[cfg(feature = "unstable-msc3381")]
114 #[ruma_enum(ident = UnstablePollResponse)]
115 "org.matrix.msc3381.poll.response" => super::poll::unstable_response,
116 #[cfg(feature = "unstable-msc3381")]
117 "m.poll.end" => super::poll::end,
118 #[cfg(feature = "unstable-msc3381")]
119 #[ruma_enum(ident = UnstablePollEnd)]
120 "org.matrix.msc3381.poll.end" => super::poll::unstable_end,
121 #[cfg(feature = "unstable-msc3489")]
122 #[ruma_enum(alias = "m.beacon")]
123 "org.matrix.msc3672.beacon" => super::beacon,
124 "m.reaction" => super::reaction,
125 "m.room.encrypted" => super::room::encrypted,
126 "m.room.message" => super::room::message,
127 "m.room.redaction" => super::room::redaction,
128 "m.sticker" => super::sticker,
129 #[cfg(feature = "unstable-msc3553")]
130 #[ruma_enum(alias = "m.video")]
131 "org.matrix.msc1767.video" => super::video,
132 #[cfg(feature = "unstable-msc3245")]
133 #[ruma_enum(alias = "m.voice")]
134 "org.matrix.msc3245.voice.v2" => super::voice,
135 #[cfg(feature = "unstable-msc4075")]
136 #[ruma_enum(alias = "m.call.notify")]
137 "org.matrix.msc4075.call.notify" => super::call::notify,
138 }
139
140 enum State {
142 "m.policy.rule.room" => super::policy::rule::room,
143 "m.policy.rule.server" => super::policy::rule::server,
144 "m.policy.rule.user" => super::policy::rule::user,
145 "m.room.aliases" => super::room::aliases,
146 "m.room.avatar" => super::room::avatar,
147 "m.room.canonical_alias" => super::room::canonical_alias,
148 "m.room.create" => super::room::create,
149 "m.room.encryption" => super::room::encryption,
150 #[cfg(feature = "unstable-msc3414")]
151 "m.room.encrypted" => super::room::encrypted::unstable_state,
152 "m.room.guest_access" => super::room::guest_access,
153 "m.room.history_visibility" => super::room::history_visibility,
154 "m.room.join_rules" => super::room::join_rules,
155 "m.room.member" => super::room::member,
156 "m.room.name" => super::room::name,
157 "m.room.pinned_events" => super::room::pinned_events,
158 "m.room.power_levels" => super::room::power_levels,
159 "m.room.server_acl" => super::room::server_acl,
160 "m.room.third_party_invite" => super::room::third_party_invite,
161 "m.room.tombstone" => super::room::tombstone,
162 "m.room.topic" => super::room::topic,
163 "m.space.child" => super::space::child,
164 "m.space.parent" => super::space::parent,
165 #[cfg(feature = "unstable-msc2545")]
166 #[ruma_enum(ident = RoomImagePack, alias = "m.image_pack")]
167 "im.ponies.room_emotes" => super::image_pack,
168 #[cfg(feature = "unstable-msc3489")]
169 #[ruma_enum(alias = "m.beacon_info")]
170 "org.matrix.msc3672.beacon_info" => super::beacon_info,
171 #[cfg(feature = "unstable-msc3401")]
172 #[ruma_enum(alias = "m.call.member")]
173 "org.matrix.msc3401.call.member" => super::call::member,
174 #[cfg(feature = "unstable-msc4171")]
175 #[ruma_enum(alias = "m.member_hints")]
176 "io.element.functional_members" => super::member_hints,
177 }
178
179 enum ToDevice {
181 "m.dummy" => super::dummy,
182 "m.room_key" => super::room_key,
183 #[cfg(feature = "unstable-msc4268")]
184 #[ruma_enum(alias = "m.room_key_bundle")]
185 "io.element.msc4268.room_key_bundle" => super::room_key_bundle,
186 "m.room_key_request" => super::room_key_request,
187 "m.room_key.withheld" => super::room_key::withheld,
188 "m.forwarded_room_key" => super::forwarded_room_key,
189 "m.key.verification.request" => super::key::verification::request,
190 "m.key.verification.ready" => super::key::verification::ready,
191 "m.key.verification.start" => super::key::verification::start,
192 "m.key.verification.cancel" => super::key::verification::cancel,
193 "m.key.verification.accept" => super::key::verification::accept,
194 "m.key.verification.key" => super::key::verification::key,
195 "m.key.verification.mac" => super::key::verification::mac,
196 "m.key.verification.done" => super::key::verification::done,
197 "m.room.encrypted" => super::room::encrypted,
198 "m.secret.request"=> super::secret::request,
199 "m.secret.send" => super::secret::send,
200 }
201}
202
203macro_rules! timeline_event_accessors {
204 (
205 $(
206 #[doc = $docs:literal]
207 pub fn $field:ident(&self) -> $ty:ty;
208 )*
209 ) => {
210 $(
211 #[doc = $docs]
212 pub fn $field(&self) -> $ty {
213 match self {
214 Self::MessageLike(ev) => ev.$field(),
215 Self::State(ev) => ev.$field(),
216 }
217 }
218 )*
219 };
220}
221
222#[allow(clippy::large_enum_variant, clippy::exhaustive_enums)]
224#[derive(Clone, Debug, EventEnumFromEvent)]
225pub enum AnyTimelineEvent {
226 MessageLike(AnyMessageLikeEvent),
228
229 State(AnyStateEvent),
231}
232
233impl AnyTimelineEvent {
234 timeline_event_accessors! {
235 pub fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch;
237
238 pub fn room_id(&self) -> &RoomId;
240
241 pub fn event_id(&self) -> &EventId;
243
244 pub fn sender(&self) -> &UserId;
246
247 pub fn transaction_id(&self) -> Option<&TransactionId>;
249 }
250
251 pub fn event_type(&self) -> TimelineEventType {
253 match self {
254 Self::MessageLike(e) => e.event_type().into(),
255 Self::State(e) => e.event_type().into(),
256 }
257 }
258}
259
260#[allow(clippy::large_enum_variant, clippy::exhaustive_enums)]
264#[derive(Clone, Debug, EventEnumFromEvent)]
265pub enum AnySyncTimelineEvent {
266 MessageLike(AnySyncMessageLikeEvent),
268
269 State(AnySyncStateEvent),
271}
272
273impl AnySyncTimelineEvent {
274 timeline_event_accessors! {
275 pub fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch;
277
278 pub fn event_id(&self) -> &EventId;
280
281 pub fn sender(&self) -> &UserId;
283
284 pub fn transaction_id(&self) -> Option<&TransactionId>;
286 }
287
288 pub fn event_type(&self) -> TimelineEventType {
290 match self {
291 Self::MessageLike(e) => e.event_type().into(),
292 Self::State(e) => e.event_type().into(),
293 }
294 }
295
296 pub fn into_full_event(self, room_id: OwnedRoomId) -> AnyTimelineEvent {
298 match self {
299 Self::MessageLike(ev) => AnyTimelineEvent::MessageLike(ev.into_full_event(room_id)),
300 Self::State(ev) => AnyTimelineEvent::State(ev.into_full_event(room_id)),
301 }
302 }
303}
304
305impl From<AnyTimelineEvent> for AnySyncTimelineEvent {
306 fn from(ev: AnyTimelineEvent) -> Self {
307 match ev {
308 AnyTimelineEvent::MessageLike(ev) => Self::MessageLike(ev.into()),
309 AnyTimelineEvent::State(ev) => Self::State(ev.into()),
310 }
311 }
312}
313
314#[derive(Deserialize)]
315#[allow(clippy::exhaustive_structs)]
316struct EventDeHelper {
317 state_key: Option<de::IgnoredAny>,
318}
319
320impl<'de> Deserialize<'de> for AnyTimelineEvent {
321 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
322 where
323 D: de::Deserializer<'de>,
324 {
325 let json = Box::<RawJsonValue>::deserialize(deserializer)?;
326 let EventDeHelper { state_key } = from_raw_json_value(&json)?;
327
328 if state_key.is_some() {
329 Ok(AnyTimelineEvent::State(from_raw_json_value(&json)?))
330 } else {
331 Ok(AnyTimelineEvent::MessageLike(from_raw_json_value(&json)?))
332 }
333 }
334}
335
336impl<'de> Deserialize<'de> for AnySyncTimelineEvent {
337 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
338 where
339 D: de::Deserializer<'de>,
340 {
341 let json = Box::<RawJsonValue>::deserialize(deserializer)?;
342 let EventDeHelper { state_key } = from_raw_json_value(&json)?;
343
344 if state_key.is_some() {
345 Ok(AnySyncTimelineEvent::State(from_raw_json_value(&json)?))
346 } else {
347 Ok(AnySyncTimelineEvent::MessageLike(from_raw_json_value(&json)?))
348 }
349 }
350}
351
352impl AnyMessageLikeEventContent {
353 pub fn relation(&self) -> Option<encrypted::Relation> {
358 #[cfg(feature = "unstable-msc3489")]
359 use super::beacon::BeaconEventContent;
360 use super::key::verification::{
361 accept::KeyVerificationAcceptEventContent, cancel::KeyVerificationCancelEventContent,
362 done::KeyVerificationDoneEventContent, key::KeyVerificationKeyEventContent,
363 mac::KeyVerificationMacEventContent, ready::KeyVerificationReadyEventContent,
364 start::KeyVerificationStartEventContent,
365 };
366 #[cfg(feature = "unstable-msc3381")]
367 use super::poll::{
368 end::PollEndEventContent, response::PollResponseEventContent,
369 unstable_end::UnstablePollEndEventContent,
370 unstable_response::UnstablePollResponseEventContent,
371 };
372
373 match self {
374 #[rustfmt::skip]
375 Self::KeyVerificationReady(KeyVerificationReadyEventContent { relates_to, .. })
376 | Self::KeyVerificationStart(KeyVerificationStartEventContent { relates_to, .. })
377 | Self::KeyVerificationCancel(KeyVerificationCancelEventContent { relates_to, .. })
378 | Self::KeyVerificationAccept(KeyVerificationAcceptEventContent { relates_to, .. })
379 | Self::KeyVerificationKey(KeyVerificationKeyEventContent { relates_to, .. })
380 | Self::KeyVerificationMac(KeyVerificationMacEventContent { relates_to, .. })
381 | Self::KeyVerificationDone(KeyVerificationDoneEventContent { relates_to, .. }) => {
382 Some(encrypted::Relation::Reference(relates_to.clone()))
383 },
384 Self::Reaction(ev) => Some(encrypted::Relation::Annotation(ev.relates_to.clone())),
385 Self::RoomEncrypted(ev) => ev.relates_to.clone(),
386 Self::RoomMessage(ev) => ev.relates_to.clone().map(Into::into),
387 #[cfg(feature = "unstable-msc1767")]
388 Self::Message(ev) => ev.relates_to.clone().map(Into::into),
389 #[cfg(feature = "unstable-msc3954")]
390 Self::Emote(ev) => ev.relates_to.clone().map(Into::into),
391 #[cfg(feature = "unstable-msc3956")]
392 Self::Encrypted(ev) => ev.relates_to.clone(),
393 #[cfg(feature = "unstable-msc3245")]
394 Self::Voice(ev) => ev.relates_to.clone().map(Into::into),
395 #[cfg(feature = "unstable-msc3927")]
396 Self::Audio(ev) => ev.relates_to.clone().map(Into::into),
397 #[cfg(feature = "unstable-msc3488")]
398 Self::Location(ev) => ev.relates_to.clone().map(Into::into),
399 #[cfg(feature = "unstable-msc3551")]
400 Self::File(ev) => ev.relates_to.clone().map(Into::into),
401 #[cfg(feature = "unstable-msc3552")]
402 Self::Image(ev) => ev.relates_to.clone().map(Into::into),
403 #[cfg(feature = "unstable-msc3553")]
404 Self::Video(ev) => ev.relates_to.clone().map(Into::into),
405 #[cfg(feature = "unstable-msc3381")]
406 Self::PollResponse(PollResponseEventContent { relates_to, .. })
407 | Self::UnstablePollResponse(UnstablePollResponseEventContent { relates_to, .. })
408 | Self::PollEnd(PollEndEventContent { relates_to, .. })
409 | Self::UnstablePollEnd(UnstablePollEndEventContent { relates_to, .. }) => {
410 Some(encrypted::Relation::Reference(relates_to.clone()))
411 }
412 #[cfg(feature = "unstable-msc3489")]
413 Self::Beacon(BeaconEventContent { relates_to, .. }) => {
414 Some(encrypted::Relation::Reference(relates_to.clone()))
415 }
416 #[cfg(feature = "unstable-msc3381")]
417 Self::PollStart(_) | Self::UnstablePollStart(_) => None,
418 #[cfg(feature = "unstable-msc4075")]
419 Self::CallNotify(_) => None,
420 Self::CallSdpStreamMetadataChanged(_)
421 | Self::CallNegotiate(_)
422 | Self::CallReject(_)
423 | Self::CallSelectAnswer(_)
424 | Self::CallAnswer(_)
425 | Self::CallInvite(_)
426 | Self::CallHangup(_)
427 | Self::CallCandidates(_)
428 | Self::RoomRedaction(_)
429 | Self::Sticker(_)
430 | Self::_Custom { .. } => None,
431 }
432 }
433}