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