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