diff --git a/matrix_sdk/src/client.rs b/matrix_sdk/src/client.rs index c9addca4..ac477288 100644 --- a/matrix_sdk/src/client.rs +++ b/matrix_sdk/src/client.rs @@ -927,6 +927,7 @@ impl Client { /// # let homeserver = Url::parse("http://localhost:8080").unwrap(); /// # let client = Client::new(homeserver).unwrap(); /// use matrix_sdk::{ + /// deserialized_responses::EncryptionInfo, /// room::Room, /// ruma::{ /// events::{ @@ -952,10 +953,20 @@ impl Client { /// ) /// .await /// .register_event_handler( + /// |ev: SyncMessageEvent, + /// room: Room, + /// encryption_info: Option| async move { + /// // An `Option` parameter lets you distinguish between + /// // unencrypted events and events that were decrypted by the SDK. + /// }, + /// ) + /// .await + /// .register_event_handler( /// |ev: SyncStateEvent| async move { - /// // Also possible: Omit any or all arguments after the first. + /// // You can omit any or all arguments after the first. /// } - /// ).await; + /// ) + /// .await; /// /// // Custom events work exactly the same way, you just need to declare /// // the content struct and use the EventContent derive macro on it. diff --git a/matrix_sdk/src/event_handler.rs b/matrix_sdk/src/event_handler.rs index 60799eab..71fa8702 100644 --- a/matrix_sdk/src/event_handler.rs +++ b/matrix_sdk/src/event_handler.rs @@ -32,7 +32,7 @@ use std::{borrow::Cow, future::Future, ops::Deref}; -use matrix_sdk_base::deserialized_responses::SyncRoomEvent; +use matrix_sdk_base::deserialized_responses::{EncryptionInfo, SyncRoomEvent}; use ruma::{events::AnySyncStateEvent, serde::Raw}; use serde::Deserialize; use serde_json::value::RawValue as RawJsonValue; @@ -117,6 +117,7 @@ pub struct EventHandlerData<'a> { pub client: Client, pub room: Option, pub raw: &'a RawJsonValue, + pub encryption_info: Option<&'a EncryptionInfo>, } /// Context for an event handler. @@ -169,6 +170,12 @@ impl EventHandlerContext for RawEvent { } } +impl EventHandlerContext for Option { + fn from_data(data: &EventHandlerData<'_>) -> Option { + Some(data.encryption_info.cloned()) + } +} + /// Return types supported for event handlers implement this trait. /// /// It is not meant to be implemented outside of matrix-sdk. @@ -211,7 +218,19 @@ impl Client { room: &Option, events: &[Raw], ) -> serde_json::Result<()> { - self.handle_sync_events_wrapped(kind, room, events, |x| x).await + #[derive(Deserialize)] + struct ExtractType<'a> { + #[serde(borrow, rename = "type")] + event_type: Cow<'a, str>, + } + + self.handle_sync_events_wrapped_with( + room, + events, + |ev| (ev, None), + |raw| Ok((kind, raw.deserialize_as::()?.event_type)), + ) + .await } pub(crate) async fn handle_sync_state_events( @@ -226,11 +245,16 @@ impl Client { unsigned: Option, } - self.handle_sync_events_wrapped_with(room, state_events, std::convert::identity, |raw| { - let StateEventDetails { event_type, unsigned } = raw.deserialize_as()?; - let redacted = unsigned.and_then(|u| u.redacted_because).is_some(); - Ok((EventKind::State { redacted }, event_type)) - }) + self.handle_sync_events_wrapped_with( + room, + state_events, + |ev| (ev, None), + |raw| { + let StateEventDetails { event_type, unsigned } = raw.deserialize_as()?; + let redacted = unsigned.and_then(|u| u.redacted_because).is_some(); + Ok((EventKind::State { redacted }, event_type)) + }, + ) .await } @@ -239,7 +263,6 @@ impl Client { room: &Option, timeline_events: &[SyncRoomEvent], ) -> serde_json::Result<()> { - // FIXME: add EncryptionInfo to context #[derive(Deserialize)] struct TimelineEventDetails<'a> { #[serde(borrow, rename = "type")] @@ -251,7 +274,7 @@ impl Client { self.handle_sync_events_wrapped_with( room, timeline_events, - |e| &e.event, + |e| (&e.event, e.encryption_info.as_ref()), |raw| { let TimelineEventDetails { event_type, state_key, unsigned } = raw.deserialize_as()?; @@ -268,35 +291,16 @@ impl Client { .await } - async fn handle_sync_events_wrapped<'a, T: 'a, U: 'a>( - &self, - kind: EventKind, - room: &Option, - events: &'a [U], - get_event: impl Fn(&'a U) -> &'a Raw, - ) -> Result<(), serde_json::Error> { - #[derive(Deserialize)] - struct ExtractType<'a> { - #[serde(borrow, rename = "type")] - event_type: Cow<'a, str>, - } - - self.handle_sync_events_wrapped_with(room, events, get_event, |raw| { - Ok((kind, raw.deserialize_as::()?.event_type)) - }) - .await - } - async fn handle_sync_events_wrapped_with<'a, T: 'a, U: 'a>( &self, room: &Option, list: &'a [U], - get_event: impl Fn(&'a U) -> &'a Raw, + get_event_details: impl Fn(&'a U) -> (&'a Raw, Option<&'a EncryptionInfo>), get_id: impl Fn(&Raw) -> serde_json::Result<(EventKind, Cow<'_, str>)>, ) -> serde_json::Result<()> { for x in list { - let event = get_event(x); - let (ev_kind, ev_type) = get_id(event)?; + let (raw_event, encryption_info) = get_event_details(x); + let (ev_kind, ev_type) = get_id(raw_event)?; let event_handler_id = (ev_kind, &*ev_type); if let Some(handlers) = self.event_handlers.read().await.get(&event_handler_id) { @@ -304,7 +308,8 @@ impl Client { let data = EventHandlerData { client: self.clone(), room: room.clone(), - raw: event.json(), + raw: raw_event.json(), + encryption_info, }; matrix_sdk_common::executor::spawn((handler)(data)); }