1use ruma_common::{
2 EventId, MilliSecondsSinceUnixEpoch, OwnedRoomId, RoomId, TransactionId, UserId,
3 serde::{JsonCastable, 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, Serialize, 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
30pub const RECOMMENDED_TRANSFERABLE_STATE_EVENT_TYPES: &[StateEventType] = &[
35 StateEventType::RoomServerAcl,
36 StateEventType::RoomEncryption,
37 StateEventType::RoomName,
38 StateEventType::RoomAvatar,
39 StateEventType::RoomTopic,
40 StateEventType::RoomGuestAccess,
41 StateEventType::RoomHistoryVisibility,
42 StateEventType::RoomJoinRules,
43 StateEventType::RoomPowerLevels,
44 #[cfg(feature = "unstable-msc4495")]
45 StateEventType::RoomPresenceSharing,
46];
47
48event_enum! {
49 enum GlobalAccountData {
51 "m.direct" => super::direct,
52 #[cfg(feature = "unstable-msc4359")]
53 #[ruma_enum(ident = DoNotDisturb, alias = "m.do_not_disturb")]
54 "dm.filament.do_not_disturb" => super::do_not_disturb,
55 "m.identity_server" => super::identity_server,
56 "m.invite_permission_config" => super::invite_permission_config,
57 #[cfg(feature = "unstable-msc4380")]
58 #[ruma_enum(ident = UnstableInvitePermissionConfig)]
59 "org.matrix.msc4380.invite_permission_config" => super::invite_permission_config,
60 "m.ignored_user_list" => super::ignored_user_list,
61 "m.image_pack.rooms" => super::image_pack::rooms,
62 "m.push_rules" => super::push_rules,
63 "m.secret_storage.default_key" => super::secret_storage::default_key,
64 "m.secret_storage.key.*" => super::secret_storage::key,
65 #[cfg(feature = "unstable-msc4278")]
66 "m.media_preview_config" => super::media_preview_config,
67 #[cfg(feature = "unstable-msc4278")]
68 #[ruma_enum(ident = UnstableMediaPreviewConfig)]
69 "io.element.msc4278.media_preview_config" => super::media_preview_config,
70 "m.recent_emoji" => super::recent_emoji,
71 "m.key_backup" => super::key_backup,
72 #[cfg(feature = "unstable-msc4495")]
73 #[ruma_enum(ident = PresenceSharing)]
74 "org.continuwuity.presence_v2.msc4495.presence.sharing" => super::presence::sharing,
75 #[cfg(feature = "unstable-msc4495")]
76 #[ruma_enum(ident = PresencePrompted)]
77 "org.continuwuity.presence_v2.msc4495.presence.prompted" => super::presence::prompted,
78 }
79
80 enum RoomAccountData {
82 "m.fully_read" => super::fully_read,
83 "m.tag" => super::tag,
84 "m.marked_unread" => super::marked_unread,
85 #[cfg(feature = "unstable-msc2867")]
86 #[ruma_enum(ident = UnstableMarkedUnread)]
87 "com.famedly.marked_unread" => super::marked_unread,
88 #[cfg(feature = "unstable-msc4278")]
89 "m.media_preview_config" => super::media_preview_config,
90 #[cfg(feature = "unstable-msc4278")]
91 #[ruma_enum(ident = UnstableMediaPreviewConfig)]
92 "io.element.msc4278.media_preview_config" => super::media_preview_config,
93 #[cfg(feature = "unstable-msc3230")]
94 #[ruma_enum(alias = "m.space_order")]
95 "org.matrix.msc3230.space_order" => super::space_order,
96 }
97
98 enum EphemeralRoom {
100 "m.receipt" => super::receipt,
101 "m.typing" => super::typing,
102 }
103
104 enum MessageLike {
106 #[cfg(feature = "unstable-msc3927")]
107 #[ruma_enum(alias = "m.audio")]
108 "org.matrix.msc1767.audio" => super::audio,
109 "m.call.answer" => super::call::answer,
110 "m.call.invite" => super::call::invite,
111 "m.call.hangup" => super::call::hangup,
112 "m.call.candidates" => super::call::candidates,
113 "m.call.negotiate" => super::call::negotiate,
114 "m.call.reject" => super::call::reject,
115 #[ruma_enum(alias = "org.matrix.call.sdp_stream_metadata_changed")]
116 "m.call.sdp_stream_metadata_changed" => super::call::sdp_stream_metadata_changed,
117 "m.call.select_answer" => super::call::select_answer,
118 #[cfg(feature = "unstable-msc3954")]
119 #[ruma_enum(alias = "m.emote")]
120 "org.matrix.msc1767.emote" => super::emote,
121 #[cfg(feature = "unstable-msc3956")]
122 #[ruma_enum(alias = "m.encrypted")]
123 "org.matrix.msc1767.encrypted" => super::encrypted,
124 #[cfg(feature = "unstable-msc3551")]
125 #[ruma_enum(alias = "m.file")]
126 "org.matrix.msc1767.file" => super::file,
127 #[cfg(feature = "unstable-msc3552")]
128 #[ruma_enum(alias = "m.image")]
129 "org.matrix.msc1767.image" => super::image,
130 "m.key.verification.ready" => super::key::verification::ready,
131 "m.key.verification.start" => super::key::verification::start,
132 "m.key.verification.cancel" => super::key::verification::cancel,
133 "m.key.verification.accept" => super::key::verification::accept,
134 "m.key.verification.key" => super::key::verification::key,
135 "m.key.verification.mac" => super::key::verification::mac,
136 "m.key.verification.done" => super::key::verification::done,
137 #[cfg(feature = "unstable-msc3488")]
138 "m.location" => super::location,
139 #[cfg(feature = "unstable-msc1767")]
140 #[ruma_enum(alias = "m.message")]
141 "org.matrix.msc1767.message" => super::message,
142 #[cfg(feature = "unstable-msc3381")]
143 "m.poll.start" => super::poll::start,
144 #[cfg(feature = "unstable-msc3381")]
145 #[ruma_enum(ident = UnstablePollStart)]
146 "org.matrix.msc3381.poll.start" => super::poll::unstable_start,
147 #[cfg(feature = "unstable-msc3381")]
148 "m.poll.response" => super::poll::response,
149 #[cfg(feature = "unstable-msc3381")]
150 #[ruma_enum(ident = UnstablePollResponse)]
151 "org.matrix.msc3381.poll.response" => super::poll::unstable_response,
152 #[cfg(feature = "unstable-msc3381")]
153 "m.poll.end" => super::poll::end,
154 #[cfg(feature = "unstable-msc3381")]
155 #[ruma_enum(ident = UnstablePollEnd)]
156 "org.matrix.msc3381.poll.end" => super::poll::unstable_end,
157 #[cfg(feature = "unstable-msc3489")]
158 #[ruma_enum(alias = "m.beacon")]
159 "org.matrix.msc3672.beacon" => super::beacon,
160 "m.reaction" => super::reaction,
161 "m.room.encrypted" => super::room::encrypted,
162 "m.room.message" => super::room::message,
163 "m.room.redaction" => super::room::redaction,
164 "m.sticker" => super::sticker,
165 #[cfg(feature = "unstable-msc3553")]
166 #[ruma_enum(alias = "m.video")]
167 "org.matrix.msc1767.video" => super::video,
168 #[cfg(feature = "unstable-msc3245")]
169 #[ruma_enum(alias = "m.voice")]
170 "org.matrix.msc3245.voice.v2" => super::voice,
171 #[cfg(feature = "unstable-msc4075")]
172 #[ruma_enum(alias = "m.call.notify")]
173 #[allow(deprecated)]
174 "org.matrix.msc4075.call.notify" => super::call::notify,
175 #[cfg(feature = "unstable-msc4075")]
176 #[ruma_enum(alias = "m.rtc.notification")]
177 "org.matrix.msc4075.rtc.notification" => super::rtc::notification,
178 #[cfg(feature = "unstable-msc4310")]
179 #[ruma_enum(alias = "m.rtc.decline")]
180 "org.matrix.msc4310.rtc.decline" => super::rtc::decline,
181 }
182
183 enum State {
185 "m.policy.rule.room" => super::policy::rule::room,
186 "m.policy.rule.server" => super::policy::rule::server,
187 "m.policy.rule.user" => super::policy::rule::user,
188 "m.room.avatar" => super::room::avatar,
189 "m.room.canonical_alias" => super::room::canonical_alias,
190 "m.room.create" => super::room::create,
191 "m.room.encryption" => super::room::encryption,
192 #[cfg(feature = "unstable-msc4362")]
193 "m.room.encrypted" => super::room::encrypted::unstable_state,
194 "m.room.guest_access" => super::room::guest_access,
195 "m.room.history_visibility" => super::room::history_visibility,
196 "m.room.image_pack" => super::room::image_pack,
197 "m.room.join_rules" => super::room::join_rules,
198 #[cfg(feature = "unstable-msc4334")]
199 #[ruma_enum(alias = "m.room.language")]
200 "org.matrix.msc4334.room.language" => super::room::language,
201 "m.room.member" => super::room::member,
202 "m.room.name" => super::room::name,
203 "m.room.pinned_events" => super::room::pinned_events,
204 "m.room.policy" => super::room::policy,
205 "m.room.power_levels" => super::room::power_levels,
206 #[cfg(feature = "unstable-msc1763")]
207 #[ruma_enum(alias = "m.room.retention")]
208 "org.matrix.msc1763.retention" => super::room::retention,
209 "m.room.server_acl" => super::room::server_acl,
210 "m.room.third_party_invite" => super::room::third_party_invite,
211 "m.room.tombstone" => super::room::tombstone,
212 "m.room.topic" => super::room::topic,
213 #[cfg(feature = "unstable-msc4495")]
214 #[ruma_enum(alias = "m.room.presence_sharing")]
215 "org.continuwuity.presence_v2.msc4495.room.presence_sharing" => super::room::presence_sharing,
216 "m.space.child" => super::space::child,
217 "m.space.parent" => super::space::parent,
218 #[cfg(feature = "unstable-msc3489")]
219 #[ruma_enum(alias = "m.beacon_info")]
220 "org.matrix.msc3672.beacon_info" => super::beacon_info,
221 #[cfg(feature = "unstable-msc3401")]
222 #[ruma_enum(alias = "m.call.member")]
223 "org.matrix.msc3401.call.member" => super::call::member,
224 #[cfg(feature = "unstable-msc4171")]
225 #[ruma_enum(alias = "m.member_hints")]
226 "io.element.functional_members" => super::member_hints,
227 }
228
229 enum ToDevice {
231 "m.dummy" => super::dummy,
232 "m.room_key" => super::room_key,
233 "m.room_key_bundle" => super::room_key_bundle,
234 "m.room_key_request" => super::room_key_request,
235 "m.room_key.withheld" => super::room_key::withheld,
236 "m.forwarded_room_key" => super::forwarded_room_key,
237 "m.key.verification.request" => super::key::verification::request,
238 "m.key.verification.ready" => super::key::verification::ready,
239 "m.key.verification.start" => super::key::verification::start,
240 "m.key.verification.cancel" => super::key::verification::cancel,
241 "m.key.verification.accept" => super::key::verification::accept,
242 "m.key.verification.key" => super::key::verification::key,
243 "m.key.verification.mac" => super::key::verification::mac,
244 "m.key.verification.done" => super::key::verification::done,
245 "m.room.encrypted" => super::room::encrypted,
246 "m.secret.request"=> super::secret::request,
247 "m.secret.send" => super::secret::send,
248 #[cfg(feature = "unstable-msc4385")]
249 #[ruma_enum(alias = "m.secret.push")]
250 "io.element.msc4385.secret.push" => super::secret::push,
251 #[cfg(feature = "unstable-msc4471")]
252 #[ruma_enum(alias = "m.stream.subscribe")]
253 "org.matrix.msc4471.stream.subscribe" => super::stream::subscribe,
254 #[cfg(feature = "unstable-msc4471")]
255 #[ruma_enum(alias = "m.stream.cancel")]
256 "org.matrix.msc4471.stream.cancel" => super::stream::cancel,
257 #[cfg(feature = "unstable-msc4471")]
258 #[ruma_enum(alias = "m.stream.update")]
259 "org.matrix.msc4471.stream.update" => super::stream::update,
260 }
261}
262
263macro_rules! timeline_event_accessors {
264 (
265 $(
266 #[doc = $docs:literal]
267 pub fn $field:ident(&self) -> $ty:ty;
268 )*
269 ) => {
270 $(
271 #[doc = $docs]
272 pub fn $field(&self) -> $ty {
273 match self {
274 Self::MessageLike(ev) => ev.$field(),
275 Self::State(ev) => ev.$field(),
276 }
277 }
278 )*
279 };
280}
281
282#[allow(clippy::large_enum_variant, clippy::exhaustive_enums)]
284#[derive(Clone, Debug, EventEnumFromEvent)]
285pub enum AnyTimelineEvent {
286 MessageLike(AnyMessageLikeEvent),
288
289 State(AnyStateEvent),
291}
292
293impl AnyTimelineEvent {
294 timeline_event_accessors! {
295 pub fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch;
297
298 pub fn room_id(&self) -> &RoomId;
300
301 pub fn event_id(&self) -> &EventId;
303
304 pub fn sender(&self) -> &UserId;
306
307 pub fn transaction_id(&self) -> Option<&TransactionId>;
309
310 pub fn is_redacted(&self) -> bool;
312 }
313
314 pub fn event_type(&self) -> TimelineEventType {
316 match self {
317 Self::MessageLike(e) => e.event_type().into(),
318 Self::State(e) => e.event_type().into(),
319 }
320 }
321}
322
323#[allow(clippy::large_enum_variant, clippy::exhaustive_enums)]
327#[derive(Clone, Debug, EventEnumFromEvent)]
328pub enum AnySyncTimelineEvent {
329 MessageLike(AnySyncMessageLikeEvent),
331
332 State(AnySyncStateEvent),
334}
335
336impl AnySyncTimelineEvent {
337 timeline_event_accessors! {
338 pub fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch;
340
341 pub fn event_id(&self) -> &EventId;
343
344 pub fn sender(&self) -> &UserId;
346
347 pub fn transaction_id(&self) -> Option<&TransactionId>;
349
350 pub fn is_redacted(&self) -> bool;
352 }
353
354 pub fn event_type(&self) -> TimelineEventType {
356 match self {
357 Self::MessageLike(e) => e.event_type().into(),
358 Self::State(e) => e.event_type().into(),
359 }
360 }
361
362 pub fn into_full_event(self, room_id: OwnedRoomId) -> AnyTimelineEvent {
364 match self {
365 Self::MessageLike(ev) => AnyTimelineEvent::MessageLike(ev.into_full_event(room_id)),
366 Self::State(ev) => AnyTimelineEvent::State(ev.into_full_event(room_id)),
367 }
368 }
369}
370
371impl From<AnyTimelineEvent> for AnySyncTimelineEvent {
372 fn from(ev: AnyTimelineEvent) -> Self {
373 match ev {
374 AnyTimelineEvent::MessageLike(ev) => Self::MessageLike(ev.into()),
375 AnyTimelineEvent::State(ev) => Self::State(ev.into()),
376 }
377 }
378}
379
380#[allow(clippy::large_enum_variant, clippy::exhaustive_enums)]
382#[derive(Clone, Debug, EventEnumFromEvent, Serialize)]
383#[serde(untagged)]
384pub enum AnyTimelineEventContent {
385 MessageLike(AnyMessageLikeEventContent),
387
388 State(AnyStateEventContent),
390}
391
392impl AnyTimelineEventContent {
393 pub fn event_type(&self) -> TimelineEventType {
395 match self {
396 Self::MessageLike(content) => {
397 <AnyMessageLikeEventContent as crate::MessageLikeEventContent>::event_type(content)
398 .into()
399 }
400 Self::State(content) => {
401 <AnyStateEventContent as crate::StateEventContent>::event_type(content).into()
402 }
403 }
404 }
405}
406
407impl JsonCastable<AnyTimelineEventContent> for AnyMessageLikeEventContent {}
408impl JsonCastable<AnyTimelineEventContent> for AnyStateEventContent {}
409
410#[derive(Deserialize)]
411#[allow(clippy::exhaustive_structs)]
412struct EventDeHelper {
413 state_key: Option<de::IgnoredAny>,
414}
415
416impl<'de> Deserialize<'de> for AnyTimelineEvent {
417 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
418 where
419 D: de::Deserializer<'de>,
420 {
421 let json = Box::<RawJsonValue>::deserialize(deserializer)?;
422 let EventDeHelper { state_key } = from_raw_json_value(&json)?;
423
424 if state_key.is_some() {
425 Ok(AnyTimelineEvent::State(from_raw_json_value(&json)?))
426 } else {
427 Ok(AnyTimelineEvent::MessageLike(from_raw_json_value(&json)?))
428 }
429 }
430}
431
432impl<'de> Deserialize<'de> for AnySyncTimelineEvent {
433 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
434 where
435 D: de::Deserializer<'de>,
436 {
437 let json = Box::<RawJsonValue>::deserialize(deserializer)?;
438 let EventDeHelper { state_key } = from_raw_json_value(&json)?;
439
440 if state_key.is_some() {
441 Ok(AnySyncTimelineEvent::State(from_raw_json_value(&json)?))
442 } else {
443 Ok(AnySyncTimelineEvent::MessageLike(from_raw_json_value(&json)?))
444 }
445 }
446}
447
448impl AnyMessageLikeEventContent {
449 pub fn relation(&self) -> Option<encrypted::Relation> {
454 #[cfg(feature = "unstable-msc3489")]
455 use super::beacon::BeaconEventContent;
456 use super::key::verification::{
457 accept::KeyVerificationAcceptEventContent, cancel::KeyVerificationCancelEventContent,
458 done::KeyVerificationDoneEventContent, key::KeyVerificationKeyEventContent,
459 mac::KeyVerificationMacEventContent, ready::KeyVerificationReadyEventContent,
460 start::KeyVerificationStartEventContent,
461 };
462 #[cfg(feature = "unstable-msc3381")]
463 use super::poll::{
464 end::PollEndEventContent, response::PollResponseEventContent,
465 unstable_end::UnstablePollEndEventContent,
466 unstable_response::UnstablePollResponseEventContent,
467 };
468
469 match self {
470 #[rustfmt::skip]
471 Self::KeyVerificationReady(KeyVerificationReadyEventContent { relates_to, .. })
472 | Self::KeyVerificationStart(KeyVerificationStartEventContent { relates_to, .. })
473 | Self::KeyVerificationCancel(KeyVerificationCancelEventContent { relates_to, .. })
474 | Self::KeyVerificationAccept(KeyVerificationAcceptEventContent { relates_to, .. })
475 | Self::KeyVerificationKey(KeyVerificationKeyEventContent { relates_to, .. })
476 | Self::KeyVerificationMac(KeyVerificationMacEventContent { relates_to, .. })
477 | Self::KeyVerificationDone(KeyVerificationDoneEventContent { relates_to, .. }) => {
478 Some(encrypted::Relation::Reference(relates_to.clone()))
479 },
480 Self::Reaction(ev) => Some(encrypted::Relation::Annotation(ev.relates_to.clone())),
481 Self::RoomEncrypted(ev) => ev.relates_to.clone(),
482 Self::RoomMessage(ev) => ev.relates_to.clone().map(Into::into),
483 #[cfg(feature = "unstable-msc1767")]
484 Self::Message(ev) => ev.relates_to.clone().map(Into::into),
485 #[cfg(feature = "unstable-msc3954")]
486 Self::Emote(ev) => ev.relates_to.clone().map(Into::into),
487 #[cfg(feature = "unstable-msc3956")]
488 Self::Encrypted(ev) => ev.relates_to.clone(),
489 #[cfg(feature = "unstable-msc3245")]
490 Self::Voice(ev) => ev.relates_to.clone().map(Into::into),
491 #[cfg(feature = "unstable-msc3927")]
492 Self::Audio(ev) => ev.relates_to.clone().map(Into::into),
493 #[cfg(feature = "unstable-msc3488")]
494 Self::Location(ev) => ev.relates_to.clone().map(Into::into),
495 #[cfg(feature = "unstable-msc3551")]
496 Self::File(ev) => ev.relates_to.clone().map(Into::into),
497 #[cfg(feature = "unstable-msc3552")]
498 Self::Image(ev) => ev.relates_to.clone().map(Into::into),
499 #[cfg(feature = "unstable-msc3553")]
500 Self::Video(ev) => ev.relates_to.clone().map(Into::into),
501 #[cfg(feature = "unstable-msc3381")]
502 Self::PollResponse(PollResponseEventContent { relates_to, .. })
503 | Self::UnstablePollResponse(UnstablePollResponseEventContent { relates_to, .. })
504 | Self::PollEnd(PollEndEventContent { relates_to, .. })
505 | Self::UnstablePollEnd(UnstablePollEndEventContent { relates_to, .. }) => {
506 Some(encrypted::Relation::Reference(relates_to.clone()))
507 }
508 #[cfg(feature = "unstable-msc3489")]
509 Self::Beacon(BeaconEventContent { relates_to, .. }) => {
510 Some(encrypted::Relation::Reference(relates_to.clone()))
511 }
512 #[cfg(feature = "unstable-msc3381")]
513 Self::UnstablePollStart(UnstablePollStartEventContent::New(content)) => {
514 content.relates_to.clone().map(Into::into)
515 }
516 #[cfg(feature = "unstable-msc3381")]
517 Self::UnstablePollStart(UnstablePollStartEventContent::Replacement(content)) => {
518 Some(encrypted::Relation::Replacement(Replacement::new(
519 content.relates_to.event_id.clone(),
520 )))
521 }
522 #[cfg(feature = "unstable-msc3381")]
523 Self::PollStart(PollStartEventContent { relates_to, .. }) => {
524 relates_to.clone().map(Into::into)
525 }
526 #[cfg(feature = "unstable-msc4075")]
527 Self::CallNotify(_) => None,
528 #[cfg(feature = "unstable-msc4075")]
529 Self::RtcNotification(ev) => ev.relates_to.clone().map(encrypted::Relation::Reference),
530 #[cfg(feature = "unstable-msc4310")]
531 Self::RtcDecline(ev) => Some(encrypted::Relation::Reference(ev.relates_to.clone())),
532 Self::CallSdpStreamMetadataChanged(_)
533 | Self::CallNegotiate(_)
534 | Self::CallReject(_)
535 | Self::CallSelectAnswer(_)
536 | Self::CallAnswer(_)
537 | Self::CallInvite(_)
538 | Self::CallHangup(_)
539 | Self::CallCandidates(_)
540 | Self::RoomRedaction(_)
541 | Self::Sticker(_)
542 | Self::_Custom { .. } => None,
543 }
544 }
545}