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