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