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