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