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