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