diff --git a/matrix_sdk/examples/command_bot.rs b/matrix_sdk/examples/command_bot.rs index a89e2219..2a84c1d6 100644 --- a/matrix_sdk/examples/command_bot.rs +++ b/matrix_sdk/examples/command_bot.rs @@ -2,7 +2,10 @@ use std::{env, process::exit}; use matrix_sdk::{ self, - events::room::message::{MessageEvent, MessageEventContent, TextMessageEventContent}, + events::{ + room::message::{MessageEventContent, TextMessageEventContent}, + MessageEventStub, + }, Client, ClientConfig, EventEmitter, JsonStore, SyncRoom, SyncSettings, }; use matrix_sdk_common_macros::async_trait; @@ -22,9 +25,9 @@ impl CommandBot { #[async_trait] impl EventEmitter for CommandBot { - async fn on_room_message(&self, room: SyncRoom, event: &MessageEvent) { + async fn on_room_message(&self, room: SyncRoom, event: &MessageEventStub) { if let SyncRoom::Joined(room) = room { - let msg_body = if let MessageEvent { + let msg_body = if let MessageEventStub { content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }), .. } = event @@ -37,8 +40,7 @@ impl EventEmitter for CommandBot { if msg_body.contains("!party") { let content = MessageEventContent::Text(TextMessageEventContent { body: "๐ŸŽ‰๐ŸŽŠ๐Ÿฅณ let's PARTY!! ๐Ÿฅณ๐ŸŽŠ๐ŸŽ‰".to_string(), - format: None, - formatted_body: None, + formatted: None, relates_to: None, }); // we clone here to hold the lock for as little time as possible. diff --git a/matrix_sdk/examples/login.rs b/matrix_sdk/examples/login.rs index 8eb30cb3..73559a6d 100644 --- a/matrix_sdk/examples/login.rs +++ b/matrix_sdk/examples/login.rs @@ -3,7 +3,10 @@ use url::Url; use matrix_sdk::{ self, - events::room::message::{MessageEvent, MessageEventContent, TextMessageEventContent}, + events::{ + room::message::{MessageEventContent, TextMessageEventContent}, + MessageEventStub, + }, Client, ClientConfig, EventEmitter, SyncRoom, SyncSettings, }; use matrix_sdk_common_macros::async_trait; @@ -12,9 +15,9 @@ struct EventCallback; #[async_trait] impl EventEmitter for EventCallback { - async fn on_room_message(&self, room: SyncRoom, event: &MessageEvent) { + async fn on_room_message(&self, room: SyncRoom, event: &MessageEventStub) { if let SyncRoom::Joined(room) = room { - if let MessageEvent { + if let MessageEventStub { content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }), sender, .. diff --git a/matrix_sdk/examples/wasm_command_bot/src/lib.rs b/matrix_sdk/examples/wasm_command_bot/src/lib.rs index 34b0a58e..1d40b6df 100644 --- a/matrix_sdk/examples/wasm_command_bot/src/lib.rs +++ b/matrix_sdk/examples/wasm_command_bot/src/lib.rs @@ -1,7 +1,7 @@ use matrix_sdk::{ api::r0::sync::sync_events::Response as SyncResponse, - events::collections::all::RoomEvent, - events::room::message::{MessageEvent, MessageEventContent, TextMessageEventContent}, + events::room::message::{MessageEventContent, TextMessageEventContent}, + events::MessageEventStub, identifiers::RoomId, Client, ClientConfig, SyncSettings, }; @@ -12,11 +12,15 @@ use web_sys::console; struct WasmBot(Client); impl WasmBot { - async fn on_room_message(&self, room_id: &RoomId, event: RoomEvent) { - let msg_body = if let RoomEvent::RoomMessage(MessageEvent { + async fn on_room_message( + &self, + room_id: &RoomId, + event: MessageEventStub, + ) { + let msg_body = if let MessageEventStub { content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }), .. - }) = event + } = event { msg_body.clone() } else { diff --git a/matrix_sdk/src/client.rs b/matrix_sdk/src/client.rs index 25b6acee..adb02442 100644 --- a/matrix_sdk/src/client.rs +++ b/matrix_sdk/src/client.rs @@ -773,7 +773,7 @@ impl Client { /// /// # let homeserver = Url::parse("http://example.com").unwrap(); /// let mut builder = RoomBuilder::default(); - /// builder.creation_content(false) + /// builder.creation_content(false, None) /// .initial_state(vec![]) /// .visibility(Visibility::Public) /// .name("name") @@ -939,9 +939,9 @@ impl Client { /// # use matrix_sdk::{Client, SyncSettings}; /// # use url::Url; /// # use futures::executor::block_on; - /// # use ruma_identifiers::RoomId; + /// # use matrix_sdk::identifiers::RoomId; /// # use std::convert::TryFrom; - /// use matrix_sdk::events::room::message::{MessageEventContent, TextMessageEventContent}; + /// use matrix_sdk::events::room::message::{FormattedBody, MessageEventContent, TextMessageEventContent}; /// # block_on(async { /// # let homeserver = Url::parse("http://localhost:8080").unwrap(); /// # let mut client = Client::new(homeserver).unwrap(); @@ -950,8 +950,7 @@ impl Client { /// /// let content = MessageEventContent::Text(TextMessageEventContent { /// body: "Hello world".to_owned(), - /// format: None, - /// formatted_body: None, + /// formatted: None, /// relates_to: None, /// }); /// let txn_id = Uuid::new_v4(); @@ -1515,8 +1514,9 @@ mod test { set_read_marker, Invite3pid, MessageEventContent, }; use super::{Client, ClientConfig, Session, SyncSettings, Url}; - use crate::events::collections::all::RoomEvent; + use crate::events::room::member::MembershipState; use crate::events::room::message::TextMessageEventContent; + use crate::identifiers::{EventId, RoomId, RoomIdOrAliasId, UserId}; use crate::{RegistrationBuilder, RoomListFilterBuilder}; @@ -1639,8 +1639,8 @@ mod test { client.restore_login(session).await.unwrap(); let mut response = EventBuilder::default() - .add_room_event(EventsJson::Member, RoomEvent::RoomMember) - .add_room_event(EventsJson::PowerLevels, RoomEvent::RoomPowerLevels) + .add_state_event(EventsFile::Member) + .add_state_event(EventsFile::PowerLevels) .build_sync_response(); client @@ -2069,7 +2069,7 @@ mod test { let homeserver = Url::from_str(&mockito::server_url()).unwrap(); let user_id = UserId::try_from("@example:localhost").unwrap(); let room_id = RoomId::try_from("!testroom:example.org").unwrap(); - let event_id = EventId::new("example.org").unwrap(); + let event_id = EventId::try_from("$xxxxxx:example.org").unwrap(); let session = Session { access_token: "1234".to_owned(), @@ -2105,7 +2105,7 @@ mod test { let homeserver = Url::from_str(&mockito::server_url()).unwrap(); let user_id = UserId::try_from("@example:localhost").unwrap(); let room_id = RoomId::try_from("!testroom:example.org").unwrap(); - let event_id = EventId::new("example.org").unwrap(); + let event_id = EventId::try_from("$xxxxxx:example.org").unwrap(); let session = Session { access_token: "1234".to_owned(), @@ -2205,9 +2205,8 @@ mod test { let content = MessageEventContent::Text(TextMessageEventContent { body: "Hello world".to_owned(), - format: None, - formatted_body: None, relates_to: None, + formatted: None, }); let txn_id = Uuid::new_v4(); let response = client diff --git a/matrix_sdk/src/request_builder.rs b/matrix_sdk/src/request_builder.rs index adf64a0c..39d4dc8e 100644 --- a/matrix_sdk/src/request_builder.rs +++ b/matrix_sdk/src/request_builder.rs @@ -29,7 +29,7 @@ use matrix_sdk_common::{ /// # let mut rt = tokio::runtime::Runtime::new().unwrap(); /// # rt.block_on(async { /// let mut builder = RoomBuilder::default(); -/// builder.creation_content(false) +/// builder.creation_content(false, None) /// .initial_state(vec![]) /// .visibility(Visibility::Public) /// .name("name") @@ -63,9 +63,15 @@ impl RoomBuilder { /// Set the `CreationContent`. /// /// Weather users on other servers can join this room. - pub fn creation_content(&mut self, federate: bool) -> &mut Self { - let federate = Some(federate); - self.creation_content = Some(CreationContent { federate }); + pub fn creation_content( + &mut self, + federate: bool, + predecessor: Option, + ) -> &mut Self { + self.creation_content = Some(CreationContent { + federate, + predecessor, + }); self } @@ -500,7 +506,7 @@ mod test { let mut builder = RoomBuilder::new(); builder - .creation_content(false) + .creation_content(false, None) .initial_state(vec![]) .visibility(Visibility::Public) .name("room_name") diff --git a/matrix_sdk_base/src/client.rs b/matrix_sdk_base/src/client.rs index 06e6ade0..81f0df15 100644 --- a/matrix_sdk_base/src/client.rs +++ b/matrix_sdk_base/src/client.rs @@ -25,21 +25,22 @@ use std::result::Result as StdResult; use crate::api::r0 as api; use crate::error::Result; -use crate::events::collections::all::{RoomEvent, StateEvent}; use crate::events::presence::PresenceEvent; // `NonRoomEvent` is what it is aliased as use crate::event_emitter::CustomOrRawEvent; -use crate::events::collections::only::Event as NonRoomEvent; use crate::events::ignored_user_list::IgnoredUserListEvent; -use crate::events::push_rules::{PushRulesEvent, Ruleset}; +use crate::events::push_rules::PushRulesEvent; use crate::events::room::member::MemberEventContent; -use crate::events::stripped::AnyStrippedStateEvent; -use crate::events::EventJson; use crate::identifiers::{RoomId, UserId}; use crate::models::Room; +use crate::push::Ruleset; use crate::session::Session; use crate::state::{AllRooms, ClientState, StateStore}; use crate::EventEmitter; +use matrix_sdk_common::events::{ + AnyBasicEvent, AnyEphemeralRoomEvent, AnyMessageEventStub, AnyRoomEventStub, AnyStateEventStub, + AnyStrippedStateEventStub, EventJson, +}; #[cfg(feature = "encryption")] use matrix_sdk_common::locks::Mutex; @@ -54,7 +55,9 @@ use crate::api::r0::keys::{ #[cfg(feature = "encryption")] use crate::api::r0::to_device::send_event_to_device; #[cfg(feature = "encryption")] -use crate::events::room::{encrypted::EncryptedEventContent, message::MessageEventContent}; +use crate::events::room::{ + encrypted::EncryptedEventContent, message::MessageEventContent as MsgEventContent, +}; #[cfg(feature = "encryption")] use crate::identifiers::DeviceId; #[cfg(not(target_arch = "wasm32"))] @@ -90,7 +93,9 @@ pub struct AdditionalUnsignedData { /// /// [synapse-bug]: /// [discussion]: -fn hoist_room_event_prev_content(event: &mut EventJson) -> Option> { +fn hoist_room_event_prev_content( + event: &EventJson, +) -> Option> { let prev_content = serde_json::from_str::(event.json().get()) .map(|more_unsigned| more_unsigned.unsigned) .map(|additional| additional.prev_content) @@ -98,6 +103,7 @@ fn hoist_room_event_prev_content(event: &mut EventJson) -> Option { if let Ok(prev) = prev_content.deserialize() { @@ -113,7 +119,9 @@ fn hoist_room_event_prev_content(event: &mut EventJson) -> Option) -> Option> { +fn hoist_state_event_prev_content( + event: &EventJson, +) -> Option> { let prev_content = serde_json::from_str::(event.json().get()) .map(|more_unsigned| more_unsigned.unsigned) .map(|additional| additional.prev_content) @@ -122,11 +130,10 @@ fn hoist_state_event_prev_content(event: &EventJson) -> Option { - if let Ok(prev) = prev_content.deserialize() { - member.prev_content = Some(prev) - } - + AnyRoomEventStub::State(AnyStateEventStub::RoomMember(ref mut member)) + if member.prev_content.is_none() => + { + member.prev_content = Some(prev_content.deserialize().ok()?); Some(EventJson::from(ev)) } _ => None, @@ -134,7 +141,7 @@ fn hoist_state_event_prev_content(event: &EventJson) -> Option, + event: &EventJson, ) -> Option { serde_json::from_str::(event.json().get()) .map(|more_unsigned| more_unsigned.unsigned) @@ -733,8 +740,8 @@ impl BaseClient { let room_lock = self.get_or_create_joined_room(&room_id).await?; let mut room = room_lock.write().await; - if let RoomEvent::RoomMember(mem_event) = &mut e { - let changed = room.handle_membership(mem_event); + if let AnyRoomEventStub::State(AnyStateEventStub::RoomMember(mem_event)) = &mut e { + let changed = room.handle_membership(mem_event, room_id); // The memberlist of the room changed, invalidate the group session // of the room. @@ -765,13 +772,13 @@ impl BaseClient { pub async fn receive_joined_state_event( &self, room_id: &RoomId, - event: &StateEvent, + event: &AnyStateEventStub, ) -> Result { let room_lock = self.get_or_create_joined_room(room_id).await?; let mut room = room_lock.write().await; - if let StateEvent::RoomMember(e) = event { - let changed = room.handle_membership(e); + if let AnyStateEventStub::RoomMember(e) = event { + let changed = room.handle_membership(e, room_id); // The memberlist of the room changed, invalidate the group session // of the room. @@ -782,7 +789,7 @@ impl BaseClient { Ok(changed) } else { - Ok(room.receive_state_event(event)) + Ok(room.receive_state_event(event, room_id)) } } @@ -799,7 +806,7 @@ impl BaseClient { pub async fn receive_invite_state_event( &self, room_id: &RoomId, - event: &AnyStrippedStateEvent, + event: &AnyStrippedStateEventStub, ) -> Result { let room_lock = self.get_or_create_invited_room(room_id).await?; let mut room = room_lock.write().await; @@ -819,13 +826,13 @@ impl BaseClient { pub async fn receive_left_timeline_event( &self, room_id: &RoomId, - event: &EventJson, + event: &EventJson, ) -> Result { match event.deserialize() { Ok(e) => { let room_lock = self.get_or_create_left_room(room_id).await?; let mut room = room_lock.write().await; - Ok(room.receive_timeline_event(&e)) + Ok(room.receive_timeline_event(&e, room_id)) } _ => Ok(false), } @@ -844,11 +851,11 @@ impl BaseClient { pub async fn receive_left_state_event( &self, room_id: &RoomId, - event: &StateEvent, + event: &AnyStateEventStub, ) -> Result { let room_lock = self.get_or_create_left_room(room_id).await?; let mut room = room_lock.write().await; - Ok(room.receive_state_event(event)) + Ok(room.receive_state_event(event, room_id)) } /// Receive a presence event from a sync response and updates the client state. @@ -880,11 +887,10 @@ impl BaseClient { /// * `room_id` - The unique id of the room the event belongs to. /// /// * `event` - The presence event for a specified room member. - pub async fn receive_account_data_event(&self, room_id: &RoomId, event: &NonRoomEvent) -> bool { - match event { - NonRoomEvent::IgnoredUserList(iu) => self.handle_ignored_users(iu).await, - NonRoomEvent::Presence(p) => self.receive_presence_event(room_id, p).await, - NonRoomEvent::PushRules(pr) => self.handle_push_rules(pr).await, + pub async fn receive_account_data_event(&self, _: &RoomId, event: &AnyBasicEvent) -> bool { + match &event { + AnyBasicEvent::IgnoredUserList(event) => self.handle_ignored_users(&event).await, + AnyBasicEvent::PushRules(event) => self.handle_push_rules(&event).await, _ => false, } } @@ -898,13 +904,18 @@ impl BaseClient { /// * `room_id` - The unique id of the room the event belongs to. /// /// * `event` - The presence event for a specified room member. - pub async fn receive_ephemeral_event(&self, room_id: &RoomId, event: &NonRoomEvent) -> bool { - match event { - NonRoomEvent::IgnoredUserList(iu) => self.handle_ignored_users(iu).await, - NonRoomEvent::Presence(p) => self.receive_presence_event(room_id, p).await, - NonRoomEvent::PushRules(pr) => self.handle_push_rules(pr).await, - _ => false, - } + pub async fn receive_ephemeral_event( + &self, + _room_id: &RoomId, + event: &AnyEphemeralRoomEvent, + ) -> bool { + match &event { + AnyEphemeralRoomEvent::FullyRead(_) => {} + AnyEphemeralRoomEvent::Receipt(_) => {} + AnyEphemeralRoomEvent::Typing(_) => {} + _ => {} + }; + false } /// Get the current, if any, sync token of the client. @@ -1055,6 +1066,8 @@ impl BaseClient { self.emit_account_data_event(room_id, &e, RoomStateType::Joined) .await; } + self.emit_account_data_event(room_id, &e, RoomStateType::Joined) + .await; } } } @@ -1190,7 +1203,7 @@ impl BaseClient { if let Ok(mut e) = event.deserialize() { // if the event is a m.room.member event the server will sometimes // send the `prev_content` field as part of the unsigned field. - if let AnyStrippedStateEvent::RoomMember(_) = &mut e { + if let AnyStrippedStateEventStub::RoomMember(_) = &mut e { if let Some(raw_content) = stripped_deserialize_prev_content(event) { let prev_content = match raw_content.prev_content { Some(json) => json.deserialize().ok(), @@ -1313,7 +1326,7 @@ impl BaseClient { pub async fn encrypt( &self, room_id: &RoomId, - content: MessageEventContent, + content: MsgEventContent, ) -> Result { let mut olm = self.olm.lock().await; @@ -1430,7 +1443,7 @@ impl BaseClient { pub(crate) async fn emit_timeline_event( &self, room_id: &RoomId, - event: &RoomEvent, + event: &AnyRoomEventStub, room_state: RoomStateType, ) { let lock = self.event_emitter.read().await; @@ -1464,42 +1477,58 @@ impl BaseClient { } }; - match event { - RoomEvent::RoomMember(mem) => event_emitter.on_room_member(room, &mem).await, - RoomEvent::RoomName(name) => event_emitter.on_room_name(room, &name).await, - RoomEvent::RoomCanonicalAlias(canonical) => { - event_emitter - .on_room_canonical_alias(room, &canonical) - .await - } - RoomEvent::RoomAliases(aliases) => event_emitter.on_room_aliases(room, &aliases).await, - RoomEvent::RoomAvatar(avatar) => event_emitter.on_room_avatar(room, &avatar).await, - RoomEvent::RoomMessage(msg) => event_emitter.on_room_message(room, &msg).await, - RoomEvent::RoomMessageFeedback(msg_feedback) => { - event_emitter - .on_room_message_feedback(room, &msg_feedback) - .await - } - RoomEvent::RoomRedaction(redaction) => { - event_emitter.on_room_redaction(room, &redaction).await - } - RoomEvent::RoomPowerLevels(power) => { - event_emitter.on_room_power_levels(room, &power).await - } - RoomEvent::RoomTombstone(tomb) => event_emitter.on_room_tombstone(room, &tomb).await, - RoomEvent::CustomRoom(custom) => { - event_emitter - .on_unrecognized_event(room, &CustomOrRawEvent::CustomRoom(custom)) - .await - } - _ => {} + match &event { + AnyRoomEventStub::State(event) => match &event { + AnyStateEventStub::RoomMember(e) => event_emitter.on_room_member(room, &e).await, + AnyStateEventStub::RoomName(e) => event_emitter.on_room_name(room, &e).await, + AnyStateEventStub::RoomCanonicalAlias(e) => { + event_emitter.on_room_canonical_alias(room, &e).await + } + AnyStateEventStub::RoomAliases(e) => event_emitter.on_room_aliases(room, &e).await, + AnyStateEventStub::RoomAvatar(e) => event_emitter.on_room_avatar(room, &e).await, + AnyStateEventStub::RoomPowerLevels(e) => { + event_emitter.on_room_power_levels(room, &e).await + } + AnyStateEventStub::RoomTombstone(e) => { + event_emitter.on_room_tombstone(room, &e).await + } + AnyStateEventStub::RoomJoinRules(_e) => { + // TODO is this needed ?? + + // event_emitter + // .on_room_join_rules(room, &e).await + } + AnyStateEventStub::Custom(e) => { + event_emitter + .on_unrecognized_event(room, &CustomOrRawEvent::State(&e)) + .await + } + _ => {} + }, + AnyRoomEventStub::Message(event) => match &event { + AnyMessageEventStub::RoomMessage(e) => { + event_emitter.on_room_message(room, &e).await + } + AnyMessageEventStub::RoomMessageFeedback(e) => { + event_emitter.on_room_message_feedback(room, &e).await + } + AnyMessageEventStub::RoomRedaction(e) => { + event_emitter.on_room_redaction(room, e).await + } + AnyMessageEventStub::Custom(e) => { + event_emitter + .on_unrecognized_event(room, &CustomOrRawEvent::Message(&e)) + .await + } + _ => {} + }, } } pub(crate) async fn emit_state_event( &self, room_id: &RoomId, - event: &StateEvent, + event: &AnyStateEventStub, room_state: RoomStateType, ) { let lock = self.event_emitter.read().await; @@ -1534,27 +1563,34 @@ impl BaseClient { }; match event { - StateEvent::RoomMember(member) => event_emitter.on_state_member(room, &member).await, - StateEvent::RoomName(name) => event_emitter.on_state_name(room, &name).await, - StateEvent::RoomCanonicalAlias(canonical) => { + AnyStateEventStub::RoomMember(member) => { + event_emitter.on_state_member(room, &member).await + } + AnyStateEventStub::RoomName(name) => event_emitter.on_state_name(room, &name).await, + AnyStateEventStub::RoomCanonicalAlias(canonical) => { event_emitter .on_state_canonical_alias(room, &canonical) .await } - StateEvent::RoomAliases(aliases) => { + AnyStateEventStub::RoomAliases(aliases) => { event_emitter.on_state_aliases(room, &aliases).await } - StateEvent::RoomAvatar(avatar) => event_emitter.on_state_avatar(room, &avatar).await, - StateEvent::RoomPowerLevels(power) => { + AnyStateEventStub::RoomAvatar(avatar) => { + event_emitter.on_state_avatar(room, &avatar).await + } + AnyStateEventStub::RoomPowerLevels(power) => { event_emitter.on_state_power_levels(room, &power).await } - StateEvent::RoomJoinRules(rules) => { + AnyStateEventStub::RoomJoinRules(rules) => { event_emitter.on_state_join_rules(room, &rules).await } - StateEvent::RoomTombstone(tomb) => event_emitter.on_room_tombstone(room, &tomb).await, - StateEvent::CustomState(custom) => { + AnyStateEventStub::RoomTombstone(tomb) => { + // TODO make `on_state_tombstone` method + event_emitter.on_room_tombstone(room, &tomb).await + } + AnyStateEventStub::Custom(custom) => { event_emitter - .on_unrecognized_event(room, &CustomOrRawEvent::CustomState(custom)) + .on_unrecognized_event(room, &CustomOrRawEvent::State(custom)) .await } _ => {} @@ -1564,7 +1600,7 @@ impl BaseClient { pub(crate) async fn emit_stripped_state_event( &self, room_id: &RoomId, - event: &AnyStrippedStateEvent, + event: &AnyStrippedStateEventStub, prev_content: Option, room_state: RoomStateType, ) { @@ -1600,33 +1636,33 @@ impl BaseClient { }; match event { - AnyStrippedStateEvent::RoomMember(member) => { + AnyStrippedStateEventStub::RoomMember(member) => { event_emitter .on_stripped_state_member(room, &member, prev_content) .await } - AnyStrippedStateEvent::RoomName(name) => { + AnyStrippedStateEventStub::RoomName(name) => { event_emitter.on_stripped_state_name(room, &name).await } - AnyStrippedStateEvent::RoomCanonicalAlias(canonical) => { + AnyStrippedStateEventStub::RoomCanonicalAlias(canonical) => { event_emitter .on_stripped_state_canonical_alias(room, &canonical) .await } - AnyStrippedStateEvent::RoomAliases(aliases) => { + AnyStrippedStateEventStub::RoomAliases(aliases) => { event_emitter .on_stripped_state_aliases(room, &aliases) .await } - AnyStrippedStateEvent::RoomAvatar(avatar) => { + AnyStrippedStateEventStub::RoomAvatar(avatar) => { event_emitter.on_stripped_state_avatar(room, &avatar).await } - AnyStrippedStateEvent::RoomPowerLevels(power) => { + AnyStrippedStateEventStub::RoomPowerLevels(power) => { event_emitter .on_stripped_state_power_levels(room, &power) .await } - AnyStrippedStateEvent::RoomJoinRules(rules) => { + AnyStrippedStateEventStub::RoomJoinRules(rules) => { event_emitter .on_stripped_state_join_rules(room, &rules) .await @@ -1638,7 +1674,7 @@ impl BaseClient { pub(crate) async fn emit_account_data_event( &self, room_id: &RoomId, - event: &NonRoomEvent, + event: &AnyBasicEvent, room_state: RoomStateType, ) { let lock = self.event_emitter.read().await; @@ -1673,21 +1709,17 @@ impl BaseClient { }; match event { - NonRoomEvent::Presence(presence) => { + AnyBasicEvent::Presence(presence) => { event_emitter.on_non_room_presence(room, &presence).await } - NonRoomEvent::IgnoredUserList(ignored) => { + AnyBasicEvent::IgnoredUserList(ignored) => { event_emitter .on_non_room_ignored_users(room, &ignored) .await } - NonRoomEvent::PushRules(rules) => { + AnyBasicEvent::PushRules(rules) => { event_emitter.on_non_room_push_rules(room, &rules).await } - NonRoomEvent::FullyRead(full_read) => { - event_emitter.on_non_room_fully_read(room, &full_read).await - } - NonRoomEvent::Typing(typing) => event_emitter.on_non_room_typing(room, &typing).await, _ => {} } } @@ -1695,7 +1727,7 @@ impl BaseClient { pub(crate) async fn emit_ephemeral_event( &self, room_id: &RoomId, - event: &NonRoomEvent, + event: &AnyEphemeralRoomEvent, room_state: RoomStateType, ) { let lock = self.event_emitter.read().await; @@ -1730,21 +1762,15 @@ impl BaseClient { }; match event { - NonRoomEvent::Presence(presence) => { - event_emitter.on_non_room_presence(room, &presence).await - } - NonRoomEvent::IgnoredUserList(ignored) => { - event_emitter - .on_non_room_ignored_users(room, &ignored) - .await - } - NonRoomEvent::PushRules(rules) => { - event_emitter.on_non_room_push_rules(room, &rules).await - } - NonRoomEvent::FullyRead(full_read) => { + AnyEphemeralRoomEvent::FullyRead(full_read) => { event_emitter.on_non_room_fully_read(room, &full_read).await } - NonRoomEvent::Typing(typing) => event_emitter.on_non_room_typing(room, &typing).await, + AnyEphemeralRoomEvent::Typing(typing) => { + event_emitter.on_non_room_typing(room, &typing).await + } + AnyEphemeralRoomEvent::Receipt(receipt) => { + event_emitter.on_non_room_receipt(room, &receipt).await + } _ => {} } } @@ -1822,12 +1848,9 @@ impl BaseClient { #[cfg(test)] mod test { use crate::identifiers::{RoomId, UserId}; - use crate::{ - events::{collections::all::RoomEvent, stripped::AnyStrippedStateEvent}, - BaseClient, Session, - }; + use crate::{events::AnyRoomEventStub, BaseClient, Session}; use matrix_sdk_common_macros::async_trait; - use matrix_sdk_test::{async_test, test_json, EventBuilder, EventsJson}; + use matrix_sdk_test::{async_test, test_json, EventBuilder, EventsFile}; use serde_json::json; use std::convert::TryFrom; @@ -1860,14 +1883,14 @@ mod test { "origin_server_ts": 0, "sender": "@example:localhost", "state_key": "@example:localhost", - "type": "m.room.member", + "type": "m.room.member" }) } #[async_test] async fn test_joined_room_creation() { let mut sync_response = EventBuilder::default() - .add_room_event(EventsJson::Member, RoomEvent::RoomMember) + .add_state_event(EventsFile::Member) .build_sync_response(); let client = get_client().await; let room_id = get_room_id(); @@ -1887,7 +1910,7 @@ mod test { assert!(room.is_some()); let mut sync_response = EventBuilder::default() - .add_custom_left_event(&room_id, member_event(), RoomEvent::RoomMember) + .add_custom_left_event(&room_id, member_event(), AnyRoomEventStub::State) .build_sync_response(); sync_response.next_batch = "Hello".to_owned(); @@ -1908,7 +1931,7 @@ mod test { async fn test_left_room_creation() { let room_id = RoomId::try_from("!left_room:localhost").unwrap(); let mut sync_response = EventBuilder::default() - .add_custom_left_event(&room_id, member_event(), RoomEvent::RoomMember) + .add_custom_left_event(&room_id, member_event(), AnyRoomEventStub::State) .build_sync_response(); let client = get_client().await; @@ -1925,7 +1948,7 @@ mod test { assert!(room.is_some()); let mut sync_response = EventBuilder::default() - .add_custom_joined_event(&room_id, member_event(), RoomEvent::RoomMember) + .add_custom_joined_event(&room_id, member_event(), AnyRoomEventStub::State) .build_sync_response(); sync_response.next_batch = "Hello".to_owned(); @@ -1946,7 +1969,7 @@ mod test { async fn test_invited_room_creation() { let room_id = RoomId::try_from("!invited_room:localhost").unwrap(); let mut sync_response = EventBuilder::default() - .add_custom_invited_event(&room_id, member_event(), AnyStrippedStateEvent::RoomMember) + .add_custom_invited_event(&room_id, member_event()) .build_sync_response(); let client = get_client().await; @@ -1963,7 +1986,7 @@ mod test { assert!(room.is_some()); let mut sync_response = EventBuilder::default() - .add_custom_joined_event(&room_id, member_event(), RoomEvent::RoomMember) + .add_custom_joined_event(&room_id, member_event(), AnyRoomEventStub::State) .build_sync_response(); sync_response.next_batch = "Hello".to_owned(); @@ -1985,7 +2008,10 @@ mod test { use super::*; use crate::{EventEmitter, SyncRoom}; - use matrix_sdk_common::events::room::member::{MemberEvent, MembershipChange}; + use matrix_sdk_common::events::{ + room::member::{MemberEventContent, MembershipChange}, + StateEventStub, + }; use matrix_sdk_common::locks::RwLock; use std::sync::{ atomic::{AtomicBool, Ordering}, @@ -1995,14 +2021,15 @@ mod test { struct EE(Arc); #[async_trait] impl EventEmitter for EE { - async fn on_room_member(&self, room: SyncRoom, event: &MemberEvent) { + async fn on_room_member( + &self, + room: SyncRoom, + event: &StateEventStub, + ) { if let SyncRoom::Joined(_) = room { - match event.membership_change() { - MembershipChange::Joined => { - self.0.swap(true, Ordering::SeqCst); - } - _ => {} - }; + if let MembershipChange::Joined = event.membership_change() { + self.0.swap(true, Ordering::SeqCst); + } } if event.prev_content.is_none() { self.0.swap(false, Ordering::SeqCst); @@ -2237,6 +2264,7 @@ mod test { use super::*; use crate::{EventEmitter, SyncRoom}; + use matrix_sdk_common::api::r0::sync::sync_events; use matrix_sdk_common::locks::RwLock; use std::sync::{ atomic::{AtomicBool, Ordering}, @@ -2248,9 +2276,9 @@ mod test { impl EventEmitter for EE { async fn on_unrecognized_event(&self, room: SyncRoom, event: &CustomOrRawEvent<'_>) { if let SyncRoom::Joined(_) = room { - if let CustomOrRawEvent::CustomRoom(custom) = event { - if custom.event_type == "m.reaction" - && custom.content.get("m.relates_to").is_some() + if let CustomOrRawEvent::Message(custom) = event { + if custom.content.event_type == "m.reaction" + && custom.content.json.get("m.relates_to").is_some() { self.0.swap(true, Ordering::SeqCst); } @@ -2316,8 +2344,7 @@ mod test { let response = http::Response::builder() .body(serde_json::to_vec(&body).unwrap()) .unwrap(); - let mut sync = - matrix_sdk_common::api::r0::sync::sync_events::Response::try_from(response).unwrap(); + let mut sync = sync_events::Response::try_from(response).unwrap(); client.receive_sync_response(&mut sync).await.unwrap(); @@ -2331,7 +2358,7 @@ mod test { let room_id = get_room_id(); let mut sync_response = EventBuilder::default() - .add_room_event(EventsJson::Member, RoomEvent::RoomMember) + .add_state_event(EventsFile::Member) .build_sync_response(); client diff --git a/matrix_sdk_base/src/event_emitter/mod.rs b/matrix_sdk_base/src/event_emitter/mod.rs index e767587d..8a68706a 100644 --- a/matrix_sdk_base/src/event_emitter/mod.rs +++ b/matrix_sdk_base/src/event_emitter/mod.rs @@ -18,29 +18,26 @@ use matrix_sdk_common::locks::RwLock; use serde_json::value::RawValue as RawJsonValue; use crate::events::{ - fully_read::FullyReadEvent, - ignored_user_list::IgnoredUserListEvent, + custom::CustomEventContent, + fully_read::FullyReadEventContent, + ignored_user_list::IgnoredUserListEventContent, presence::PresenceEvent, - push_rules::PushRulesEvent, - receipt::ReceiptEvent, + push_rules::PushRulesEventContent, + receipt::ReceiptEventContent, room::{ - aliases::AliasesEvent, - avatar::AvatarEvent, - canonical_alias::CanonicalAliasEvent, - join_rules::JoinRulesEvent, - member::{MemberEvent, MemberEventContent}, - message::{feedback::FeedbackEvent, MessageEvent}, - name::NameEvent, - power_levels::PowerLevelsEvent, - redaction::RedactionEvent, - tombstone::TombstoneEvent, + aliases::AliasesEventContent, + avatar::AvatarEventContent, + canonical_alias::CanonicalAliasEventContent, + join_rules::JoinRulesEventContent, + member::MemberEventContent, + message::{feedback::FeedbackEventContent, MessageEventContent as MsgEventContent}, + name::NameEventContent, + power_levels::PowerLevelsEventContent, + redaction::RedactionEventStub, + tombstone::TombstoneEventContent, }, - stripped::{ - StrippedRoomAliases, StrippedRoomAvatar, StrippedRoomCanonicalAlias, StrippedRoomJoinRules, - StrippedRoomMember, StrippedRoomName, StrippedRoomPowerLevels, - }, - typing::TypingEvent, - CustomEvent, CustomRoomEvent, CustomStateEvent, + typing::TypingEventContent, + BasicEvent, EphemeralRoomEvent, MessageEventStub, StateEventStub, StrippedStateEventStub, }; use crate::{Room, RoomState}; use matrix_sdk_common_macros::async_trait; @@ -52,15 +49,17 @@ pub type SyncRoom = RoomState>>; #[derive(Clone, Copy, Debug)] pub enum CustomOrRawEvent<'c> { /// When an event can not be deserialized by ruma. - /// - /// This will be mostly obsolete when ruma-events is updated. RawJson(&'c RawJsonValue), - /// A custom event. - Custom(&'c CustomEvent), + /// A custom basic event. + Basic(&'c BasicEvent), + /// A custom basic event. + EphemeralRoom(&'c EphemeralRoomEvent), /// A custom room event. - CustomRoom(&'c CustomRoomEvent), + Message(&'c MessageEventStub), /// A custom state event. - CustomState(&'c CustomStateEvent), + State(&'c StateEventStub), + /// A custom stripped state event. + StrippedState(&'c StrippedStateEventStub), } /// This trait allows any type implementing `EventEmitter` to specify event callbacks for each event. @@ -74,7 +73,8 @@ pub enum CustomOrRawEvent<'c> { /// # use matrix_sdk_base::{ /// # self, /// # events::{ -/// # room::message::{MessageEvent, MessageEventContent, TextMessageEventContent}, +/// # room::message::{MessageEventContent, TextMessageEventContent}, +/// # MessageEventStub /// # }, /// # EventEmitter, SyncRoom /// # }; @@ -85,9 +85,9 @@ pub enum CustomOrRawEvent<'c> { /// /// #[async_trait] /// impl EventEmitter for EventCallback { -/// async fn on_room_message(&self, room: SyncRoom, event: &MessageEvent) { +/// async fn on_room_message(&self, room: SyncRoom, event: &MessageEventStub) { /// if let SyncRoom::Joined(room) = room { -/// if let MessageEvent { +/// if let MessageEventStub { /// content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }), /// sender, /// .. @@ -112,80 +112,140 @@ pub enum CustomOrRawEvent<'c> { pub trait EventEmitter: Send + Sync { // ROOM EVENTS from `IncomingTimeline` /// Fires when `Client` receives a `RoomEvent::RoomMember` event. - async fn on_room_member(&self, _: SyncRoom, _: &MemberEvent) {} + async fn on_room_member(&self, _: SyncRoom, _: &StateEventStub) {} /// Fires when `Client` receives a `RoomEvent::RoomName` event. - async fn on_room_name(&self, _: SyncRoom, _: &NameEvent) {} + async fn on_room_name(&self, _: SyncRoom, _: &StateEventStub) {} /// Fires when `Client` receives a `RoomEvent::RoomCanonicalAlias` event. - async fn on_room_canonical_alias(&self, _: SyncRoom, _: &CanonicalAliasEvent) {} + async fn on_room_canonical_alias( + &self, + _: SyncRoom, + _: &StateEventStub, + ) { + } /// Fires when `Client` receives a `RoomEvent::RoomAliases` event. - async fn on_room_aliases(&self, _: SyncRoom, _: &AliasesEvent) {} + async fn on_room_aliases(&self, _: SyncRoom, _: &StateEventStub) {} /// Fires when `Client` receives a `RoomEvent::RoomAvatar` event. - async fn on_room_avatar(&self, _: SyncRoom, _: &AvatarEvent) {} + async fn on_room_avatar(&self, _: SyncRoom, _: &StateEventStub) {} /// Fires when `Client` receives a `RoomEvent::RoomMessage` event. - async fn on_room_message(&self, _: SyncRoom, _: &MessageEvent) {} + async fn on_room_message(&self, _: SyncRoom, _: &MessageEventStub) {} /// Fires when `Client` receives a `RoomEvent::RoomMessageFeedback` event. - async fn on_room_message_feedback(&self, _: SyncRoom, _: &FeedbackEvent) {} + async fn on_room_message_feedback( + &self, + _: SyncRoom, + _: &MessageEventStub, + ) { + } /// Fires when `Client` receives a `RoomEvent::RoomRedaction` event. - async fn on_room_redaction(&self, _: SyncRoom, _: &RedactionEvent) {} + async fn on_room_redaction(&self, _: SyncRoom, _: &RedactionEventStub) {} /// Fires when `Client` receives a `RoomEvent::RoomPowerLevels` event. - async fn on_room_power_levels(&self, _: SyncRoom, _: &PowerLevelsEvent) {} + async fn on_room_power_levels(&self, _: SyncRoom, _: &StateEventStub) { + } /// Fires when `Client` receives a `RoomEvent::Tombstone` event. - async fn on_room_tombstone(&self, _: SyncRoom, _: &TombstoneEvent) {} + async fn on_room_tombstone(&self, _: SyncRoom, _: &StateEventStub) {} // `RoomEvent`s from `IncomingState` /// Fires when `Client` receives a `StateEvent::RoomMember` event. - async fn on_state_member(&self, _: SyncRoom, _: &MemberEvent) {} + async fn on_state_member(&self, _: SyncRoom, _: &StateEventStub) {} /// Fires when `Client` receives a `StateEvent::RoomName` event. - async fn on_state_name(&self, _: SyncRoom, _: &NameEvent) {} + async fn on_state_name(&self, _: SyncRoom, _: &StateEventStub) {} /// Fires when `Client` receives a `StateEvent::RoomCanonicalAlias` event. - async fn on_state_canonical_alias(&self, _: SyncRoom, _: &CanonicalAliasEvent) {} + async fn on_state_canonical_alias( + &self, + _: SyncRoom, + _: &StateEventStub, + ) { + } /// Fires when `Client` receives a `StateEvent::RoomAliases` event. - async fn on_state_aliases(&self, _: SyncRoom, _: &AliasesEvent) {} + async fn on_state_aliases(&self, _: SyncRoom, _: &StateEventStub) {} /// Fires when `Client` receives a `StateEvent::RoomAvatar` event. - async fn on_state_avatar(&self, _: SyncRoom, _: &AvatarEvent) {} + async fn on_state_avatar(&self, _: SyncRoom, _: &StateEventStub) {} /// Fires when `Client` receives a `StateEvent::RoomPowerLevels` event. - async fn on_state_power_levels(&self, _: SyncRoom, _: &PowerLevelsEvent) {} + async fn on_state_power_levels( + &self, + _: SyncRoom, + _: &StateEventStub, + ) { + } /// Fires when `Client` receives a `StateEvent::RoomJoinRules` event. - async fn on_state_join_rules(&self, _: SyncRoom, _: &JoinRulesEvent) {} + async fn on_state_join_rules(&self, _: SyncRoom, _: &StateEventStub) {} // `AnyStrippedStateEvent`s /// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomMember` event. async fn on_stripped_state_member( &self, _: SyncRoom, - _: &StrippedRoomMember, + _: &StrippedStateEventStub, _: Option, ) { } /// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomName` event. - async fn on_stripped_state_name(&self, _: SyncRoom, _: &StrippedRoomName) {} + async fn on_stripped_state_name( + &self, + _: SyncRoom, + _: &StrippedStateEventStub, + ) { + } /// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomCanonicalAlias` event. - async fn on_stripped_state_canonical_alias(&self, _: SyncRoom, _: &StrippedRoomCanonicalAlias) { + async fn on_stripped_state_canonical_alias( + &self, + _: SyncRoom, + _: &StrippedStateEventStub, + ) { } /// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomAliases` event. - async fn on_stripped_state_aliases(&self, _: SyncRoom, _: &StrippedRoomAliases) {} + async fn on_stripped_state_aliases( + &self, + _: SyncRoom, + _: &StrippedStateEventStub, + ) { + } /// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomAvatar` event. - async fn on_stripped_state_avatar(&self, _: SyncRoom, _: &StrippedRoomAvatar) {} + async fn on_stripped_state_avatar( + &self, + _: SyncRoom, + _: &StrippedStateEventStub, + ) { + } /// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomPowerLevels` event. - async fn on_stripped_state_power_levels(&self, _: SyncRoom, _: &StrippedRoomPowerLevels) {} + async fn on_stripped_state_power_levels( + &self, + _: SyncRoom, + _: &StrippedStateEventStub, + ) { + } /// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomJoinRules` event. - async fn on_stripped_state_join_rules(&self, _: SyncRoom, _: &StrippedRoomJoinRules) {} + async fn on_stripped_state_join_rules( + &self, + _: SyncRoom, + _: &StrippedStateEventStub, + ) { + } // `NonRoomEvent` (this is a type alias from ruma_events) /// Fires when `Client` receives a `NonRoomEvent::RoomPresence` event. async fn on_non_room_presence(&self, _: SyncRoom, _: &PresenceEvent) {} /// Fires when `Client` receives a `NonRoomEvent::RoomName` event. - async fn on_non_room_ignored_users(&self, _: SyncRoom, _: &IgnoredUserListEvent) {} + async fn on_non_room_ignored_users( + &self, + _: SyncRoom, + _: &BasicEvent, + ) { + } /// Fires when `Client` receives a `NonRoomEvent::RoomCanonicalAlias` event. - async fn on_non_room_push_rules(&self, _: SyncRoom, _: &PushRulesEvent) {} + async fn on_non_room_push_rules(&self, _: SyncRoom, _: &BasicEvent) {} /// Fires when `Client` receives a `NonRoomEvent::RoomAliases` event. - async fn on_non_room_fully_read(&self, _: SyncRoom, _: &FullyReadEvent) {} + async fn on_non_room_fully_read( + &self, + _: SyncRoom, + _: &EphemeralRoomEvent, + ) { + } /// Fires when `Client` receives a `NonRoomEvent::Typing` event. - async fn on_non_room_typing(&self, _: SyncRoom, _: &TypingEvent) {} + async fn on_non_room_typing(&self, _: SyncRoom, _: &EphemeralRoomEvent) {} /// Fires when `Client` receives a `NonRoomEvent::Receipt` event. /// /// This is always a read receipt. - async fn on_non_room_receipt(&self, _: SyncRoom, _: &ReceiptEvent) {} + async fn on_non_room_receipt(&self, _: SyncRoom, _: &EphemeralRoomEvent) {} // `PresenceEvent` is a struct so there is only the one method /// Fires when `Client` receives a `NonRoomEvent::RoomAliases` event. @@ -214,63 +274,89 @@ mod test { #[async_trait] impl EventEmitter for EvEmitterTest { - async fn on_room_member(&self, _: SyncRoom, _: &MemberEvent) { + async fn on_room_member(&self, _: SyncRoom, _: &StateEventStub) { self.0.lock().await.push("member".to_string()) } - async fn on_room_name(&self, _: SyncRoom, _: &NameEvent) { + async fn on_room_name(&self, _: SyncRoom, _: &StateEventStub) { self.0.lock().await.push("name".to_string()) } - async fn on_room_canonical_alias(&self, _: SyncRoom, _: &CanonicalAliasEvent) { + async fn on_room_canonical_alias( + &self, + _: SyncRoom, + _: &StateEventStub, + ) { self.0.lock().await.push("canonical".to_string()) } - async fn on_room_aliases(&self, _: SyncRoom, _: &AliasesEvent) { + async fn on_room_aliases(&self, _: SyncRoom, _: &StateEventStub) { self.0.lock().await.push("aliases".to_string()) } - async fn on_room_avatar(&self, _: SyncRoom, _: &AvatarEvent) { + async fn on_room_avatar(&self, _: SyncRoom, _: &StateEventStub) { self.0.lock().await.push("avatar".to_string()) } - async fn on_room_message(&self, _: SyncRoom, _: &MessageEvent) { + async fn on_room_message(&self, _: SyncRoom, _: &MessageEventStub) { self.0.lock().await.push("message".to_string()) } - async fn on_room_message_feedback(&self, _: SyncRoom, _: &FeedbackEvent) { + async fn on_room_message_feedback( + &self, + _: SyncRoom, + _: &MessageEventStub, + ) { self.0.lock().await.push("feedback".to_string()) } - async fn on_room_redaction(&self, _: SyncRoom, _: &RedactionEvent) { + async fn on_room_redaction(&self, _: SyncRoom, _: &RedactionEventStub) { self.0.lock().await.push("redaction".to_string()) } - async fn on_room_power_levels(&self, _: SyncRoom, _: &PowerLevelsEvent) { + async fn on_room_power_levels( + &self, + _: SyncRoom, + _: &StateEventStub, + ) { self.0.lock().await.push("power".to_string()) } - async fn on_room_tombstone(&self, _: SyncRoom, _: &TombstoneEvent) { + async fn on_room_tombstone(&self, _: SyncRoom, _: &StateEventStub) { self.0.lock().await.push("tombstone".to_string()) } - async fn on_state_member(&self, _: SyncRoom, _: &MemberEvent) { + async fn on_state_member(&self, _: SyncRoom, _: &StateEventStub) { self.0.lock().await.push("state member".to_string()) } - async fn on_state_name(&self, _: SyncRoom, _: &NameEvent) { + async fn on_state_name(&self, _: SyncRoom, _: &StateEventStub) { self.0.lock().await.push("state name".to_string()) } - async fn on_state_canonical_alias(&self, _: SyncRoom, _: &CanonicalAliasEvent) { + async fn on_state_canonical_alias( + &self, + _: SyncRoom, + _: &StateEventStub, + ) { self.0.lock().await.push("state canonical".to_string()) } - async fn on_state_aliases(&self, _: SyncRoom, _: &AliasesEvent) { + async fn on_state_aliases(&self, _: SyncRoom, _: &StateEventStub) { self.0.lock().await.push("state aliases".to_string()) } - async fn on_state_avatar(&self, _: SyncRoom, _: &AvatarEvent) { + async fn on_state_avatar(&self, _: SyncRoom, _: &StateEventStub) { self.0.lock().await.push("state avatar".to_string()) } - async fn on_state_power_levels(&self, _: SyncRoom, _: &PowerLevelsEvent) { + async fn on_state_power_levels( + &self, + _: SyncRoom, + _: &StateEventStub, + ) { self.0.lock().await.push("state power".to_string()) } - async fn on_state_join_rules(&self, _: SyncRoom, _: &JoinRulesEvent) { + async fn on_state_join_rules( + &self, + _: SyncRoom, + _: &StateEventStub, + ) { self.0.lock().await.push("state rules".to_string()) } + // `AnyStrippedStateEvent`s + /// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomMember` event. async fn on_stripped_state_member( &self, _: SyncRoom, - _: &StrippedRoomMember, + _: &StrippedStateEventStub, _: Option, ) { self.0 @@ -278,57 +364,103 @@ mod test { .await .push("stripped state member".to_string()) } - async fn on_stripped_state_name(&self, _: SyncRoom, _: &StrippedRoomName) { + /// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomName` event. + async fn on_stripped_state_name( + &self, + _: SyncRoom, + _: &StrippedStateEventStub, + ) { self.0.lock().await.push("stripped state name".to_string()) } + /// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomCanonicalAlias` event. async fn on_stripped_state_canonical_alias( &self, _: SyncRoom, - _: &StrippedRoomCanonicalAlias, + _: &StrippedStateEventStub, ) { self.0 .lock() .await .push("stripped state canonical".to_string()) } - async fn on_stripped_state_aliases(&self, _: SyncRoom, _: &StrippedRoomAliases) { + /// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomAliases` event. + async fn on_stripped_state_aliases( + &self, + _: SyncRoom, + _: &StrippedStateEventStub, + ) { self.0 .lock() .await .push("stripped state aliases".to_string()) } - async fn on_stripped_state_avatar(&self, _: SyncRoom, _: &StrippedRoomAvatar) { + /// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomAvatar` event. + async fn on_stripped_state_avatar( + &self, + _: SyncRoom, + _: &StrippedStateEventStub, + ) { self.0 .lock() .await .push("stripped state avatar".to_string()) } - async fn on_stripped_state_power_levels(&self, _: SyncRoom, _: &StrippedRoomPowerLevels) { + /// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomPowerLevels` event. + async fn on_stripped_state_power_levels( + &self, + _: SyncRoom, + _: &StrippedStateEventStub, + ) { self.0.lock().await.push("stripped state power".to_string()) } - async fn on_stripped_state_join_rules(&self, _: SyncRoom, _: &StrippedRoomJoinRules) { + /// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomJoinRules` event. + async fn on_stripped_state_join_rules( + &self, + _: SyncRoom, + _: &StrippedStateEventStub, + ) { self.0.lock().await.push("stripped state rules".to_string()) } async fn on_non_room_presence(&self, _: SyncRoom, _: &PresenceEvent) { - self.0.lock().await.push("account presence".to_string()) + self.0.lock().await.push("presence".to_string()) } - async fn on_non_room_ignored_users(&self, _: SyncRoom, _: &IgnoredUserListEvent) { + async fn on_non_room_ignored_users( + &self, + _: SyncRoom, + _: &BasicEvent, + ) { self.0.lock().await.push("account ignore".to_string()) } - async fn on_non_room_push_rules(&self, _: SyncRoom, _: &PushRulesEvent) { + async fn on_non_room_push_rules(&self, _: SyncRoom, _: &BasicEvent) { self.0.lock().await.push("account push rules".to_string()) } - async fn on_non_room_fully_read(&self, _: SyncRoom, _: &FullyReadEvent) { + async fn on_non_room_fully_read( + &self, + _: SyncRoom, + _: &EphemeralRoomEvent, + ) { self.0.lock().await.push("account read".to_string()) } - async fn on_non_room_typing(&self, _: SyncRoom, _: &TypingEvent) { + async fn on_non_room_typing( + &self, + _: SyncRoom, + _: &EphemeralRoomEvent, + ) { self.0.lock().await.push("typing event".to_string()) } + async fn on_non_room_receipt( + &self, + _: SyncRoom, + _: &EphemeralRoomEvent, + ) { + self.0.lock().await.push("receipt event".to_string()) + } async fn on_presence_event(&self, _: SyncRoom, _: &PresenceEvent) { self.0.lock().await.push("presence event".to_string()) } - async fn on_unrecognized_event(&self, _: SyncRoom, _: &CustomOrRawEvent<'_>) { + async fn on_unrecognized_event(&self, _: SyncRoom, event: &CustomOrRawEvent<'_>) { + println!("{:#?}", event); self.0.lock().await.push("unrecognized event".to_string()) } } @@ -373,9 +505,10 @@ mod test { "state member", "state member", "message", - "account read", "account ignore", - "presence event" + "presence event", + "receipt event", + "account read", ], ) } @@ -448,6 +581,7 @@ mod test { "redaction", "unrecognized event", "unrecognized event", + "receipt event", "typing event" ], ) diff --git a/matrix_sdk_base/src/models/event_deser.rs b/matrix_sdk_base/src/models/event_deser.rs deleted file mode 100644 index c1bfa920..00000000 --- a/matrix_sdk_base/src/models/event_deser.rs +++ /dev/null @@ -1,55 +0,0 @@ -//! De-/serialization functions to and from json strings, allows the type to be used as a query string. - -use serde::de::{Deserialize, Deserializer, Error as _}; - -use crate::events::collections::all::Event; -use crate::events::presence::PresenceEvent; -use crate::events::EventJson; - -pub fn deserialize_events<'de, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - let mut events = vec![]; - let ev = Vec::>::deserialize(deserializer)?; - for event in ev { - events.push(event.deserialize().map_err(D::Error::custom)?); - } - - Ok(events) -} - -pub fn deserialize_presence<'de, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - let mut events = vec![]; - let ev = Vec::>::deserialize(deserializer)?; - for event in ev { - events.push(event.deserialize().map_err(D::Error::custom)?); - } - - Ok(events) -} - -#[cfg(test)] -mod test { - use crate::events::room::member::MemberEvent; - use crate::events::EventJson; - use crate::models::RoomMember; - use matrix_sdk_test::test_json; - - #[test] - fn events_and_presence_deserialization() { - let ev_json = test_json::MEMBER.to_string(); - let ev = serde_json::from_str::>(&ev_json) - .unwrap() - .deserialize() - .unwrap(); - let member = RoomMember::new(&ev); - - let member_json = serde_json::to_string(&member).unwrap(); - let mem = serde_json::from_str::(&member_json).unwrap(); - assert_eq!(member, mem); - } -} diff --git a/matrix_sdk_base/src/models/message.rs b/matrix_sdk_base/src/models/message.rs index b78ea1a7..56c645fb 100644 --- a/matrix_sdk_base/src/models/message.rs +++ b/matrix_sdk_base/src/models/message.rs @@ -7,11 +7,12 @@ use std::cmp::Ordering; use std::ops::Deref; use std::vec::IntoIter; -use crate::events::room::message::MessageEvent; -use crate::events::EventJson; +use crate::events::room::message::MessageEventContent; +use crate::events::MessageEventStub; use serde::{de, ser, Serialize}; +type MessageEvent = MessageEventStub; /// A queue that holds the 10 most recent messages received from the server. #[derive(Clone, Debug, Default)] pub struct MessageQueue { @@ -115,13 +116,10 @@ pub(crate) mod ser_deser { where D: de::Deserializer<'de>, { - use serde::de::Error; - - let messages: Vec> = de::Deserialize::deserialize(deserializer)?; + let messages: Vec = de::Deserialize::deserialize(deserializer)?; let mut msgs = vec![]; - for json in messages { - let msg = json.deserialize().map_err(D::Error::custom)?; + for msg in messages { msgs.push(MessageWrapper(msg)); } @@ -160,17 +158,11 @@ mod test { let mut room = Room::new(&id, &user); let json: &serde_json::Value = &test_json::MESSAGE_TEXT; - let event = serde_json::from_value::>(json.clone()).unwrap(); + let msg = serde_json::from_value::(json.clone()).unwrap(); let mut msgs = MessageQueue::new(); - let message = if let RoomEvent::RoomMessage(msg) = event.deserialize().unwrap() { - msgs.push(msg.clone()); - msg - } else { - panic!("this should always be a RoomMessage") - }; - room.messages = msgs.clone(); - + msgs.push(msg.clone()); + room.messages = msgs; let mut joined_rooms = HashMap::new(); joined_rooms.insert(id, room); @@ -191,7 +183,7 @@ mod test { "creator": null, "joined_members": {}, "invited_members": {}, - "messages": [ message ], + "messages": [ msg ], "typing_users": [], "power_levels": null, "encrypted": null, @@ -212,19 +204,14 @@ mod test { let mut room = Room::new(&id, &user); let json: &serde_json::Value = &test_json::MESSAGE_TEXT; - let event = serde_json::from_value::>(json.clone()).unwrap(); + let msg = serde_json::from_value::(json.clone()).unwrap(); let mut msgs = MessageQueue::new(); - let message = if let RoomEvent::RoomMessage(msg) = event.deserialize().unwrap() { - msgs.push(msg.clone()); - msg - } else { - panic!("this should always be a RoomMessage") - }; + msgs.push(msg.clone()); room.messages = msgs; let mut joined_rooms = HashMap::new(); - joined_rooms.insert(id, room.clone()); + joined_rooms.insert(id, room); let json = serde_json::json!({ "!roomid:example.com": { @@ -242,7 +229,7 @@ mod test { "creator": null, "joined_members": {}, "invited_members": {}, - "messages": [ message ], + "messages": [ msg ], "typing_users": [], "power_levels": null, "encrypted": null, diff --git a/matrix_sdk_base/src/models/mod.rs b/matrix_sdk_base/src/models/mod.rs index 218cf28b..211e5b5d 100644 --- a/matrix_sdk_base/src/models/mod.rs +++ b/matrix_sdk_base/src/models/mod.rs @@ -1,4 +1,3 @@ -mod event_deser; #[cfg(feature = "messages")] #[cfg_attr(docsrs, doc(cfg(feature = "messages")))] mod message; diff --git a/matrix_sdk_base/src/models/room.rs b/matrix_sdk_base/src/models/room.rs index e7c3f175..321b4979 100644 --- a/matrix_sdk_base/src/models/room.rs +++ b/matrix_sdk_base/src/models/room.rs @@ -22,28 +22,35 @@ use super::message::MessageQueue; use super::RoomMember; use crate::api::r0::sync::sync_events::{RoomSummary, UnreadNotificationsCount}; -use crate::events::collections::all::{RoomEvent, StateEvent}; use crate::events::presence::PresenceEvent; use crate::events::room::{ - aliases::AliasesEvent, - canonical_alias::CanonicalAliasEvent, - encryption::EncryptionEvent, - member::{MemberEvent, MembershipChange}, - name::NameEvent, - power_levels::{NotificationPowerLevels, PowerLevelsEvent, PowerLevelsEventContent}, - tombstone::TombstoneEvent, + aliases::AliasesEventContent, + canonical_alias::CanonicalAliasEventContent, + encryption::EncryptionEventContent, + member::{MemberEventContent, MembershipChange}, + name::NameEventContent, + power_levels::{NotificationPowerLevels, PowerLevelsEventContent}, + tombstone::TombstoneEventContent, +}; + +use crate::events::{ + Algorithm, AnyMessageEventStub, AnyRoomEventStub, AnyStateEventStub, AnyStrippedStateEventStub, + EventType, StateEventStub, StrippedStateEventStub, }; -use crate::events::stripped::{AnyStrippedStateEvent, StrippedRoomName}; -use crate::events::{Algorithm, EventType}; #[cfg(feature = "messages")] -use crate::events::room::message::MessageEvent; +use crate::events::{room::message::MessageEventContent as MsgContent, MessageEventStub}; use crate::identifiers::{RoomAliasId, RoomId, UserId}; use crate::js_int::{Int, UInt}; use serde::{Deserialize, Serialize}; + +#[cfg(feature = "messages")] +type SentMessageEvent = MessageEventStub; + #[derive(Debug, Default, PartialEq, Serialize, Deserialize, Clone)] +#[cfg_attr(test, derive(Clone))] /// `RoomName` allows the calculation of a text room name. pub struct RoomName { /// The displayed name of the room. @@ -123,8 +130,8 @@ impl EncryptionInfo { } } -impl From<&EncryptionEvent> for EncryptionInfo { - fn from(event: &EncryptionEvent) -> Self { +impl From<&StateEventStub> for EncryptionInfo { + fn from(event: &StateEventStub) -> Self { EncryptionInfo { algorithm: event.content.algorithm.clone(), rotation_period_ms: event @@ -357,29 +364,15 @@ impl Room { } } - /// Process the member event of an entering user. - /// - /// Returns true if this made a change to the room's state, false otherwise. - fn add_member(&mut self, event: &MemberEvent) -> bool { - let new_member = RoomMember::new(event); - - if self.joined_members.contains_key(&new_member.user_id) - || self.invited_members.contains_key(&new_member.user_id) + fn add_member(&mut self, event: &StateEventStub, room_id: &RoomId) -> bool { + if self + .members + .contains_key(&UserId::try_from(event.state_key.as_str()).unwrap()) { return false; } - match event.membership_change() { - MembershipChange::Joined => self - .joined_members - .insert(new_member.user_id.clone(), new_member.clone()), - MembershipChange::Invited => self - .invited_members - .insert(new_member.user_id.clone(), new_member.clone()), - _ => { - panic!("Room::add_member called on an event that is neither a join nor an invite.") - } - }; + let member = RoomMember::new(event, room_id); // Perform display name disambiguations, if necessary. let disambiguations = self.disambiguation_updates(&new_member, MemberDirection::Entering); @@ -396,7 +389,7 @@ impl Room { /// Process the member event of a leaving user. /// /// Returns true if this made a change to the room's state, false otherwise. - fn remove_member(&mut self, event: &MemberEvent) -> bool { + fn remove_member(&mut self, event: &StateEventStub) -> bool { let leaving_member = RoomMember::new(event); // Perform display name disambiguations, if necessary. @@ -535,7 +528,7 @@ impl Room { true } - fn set_room_power_level(&mut self, event: &PowerLevelsEvent) -> bool { + fn set_room_power_level(&mut self, event: &StateEventStub) -> bool { let PowerLevelsEventContent { ban, events, @@ -583,7 +576,11 @@ impl Room { /// Handle a room.member updating the room state if necessary. /// /// Returns true if the joined member list changed, false otherwise. - pub fn handle_membership(&mut self, event: &MemberEvent) -> bool { + pub fn handle_membership( + &mut self, + event: &StateEventStub, + room_id: &RoomId, + ) -> bool { use MembershipChange::*; // TODO: This would not be handled correctly as all the MemberEvents have the `prev_content` @@ -594,7 +591,7 @@ impl Room { self.remove_member(event) } ProfileChanged => { - let user_id = if let Ok(id) = UserId::try_from(event.state_key.as_str()) { + let user = if let Ok(id) = UserId::try_from(event.state_key.as_str()) { id } else { return false; @@ -617,14 +614,14 @@ impl Room { /// Returns true if `MessageQueue` was added to. #[cfg(feature = "messages")] #[cfg_attr(docsrs, doc(cfg(feature = "messages")))] - pub fn handle_message(&mut self, event: &MessageEvent) -> bool { + pub fn handle_message(&mut self, event: &SentMessageEvent) -> bool { self.messages.push(event.clone()) } /// Handle a room.aliases event, updating the room state if necessary. /// /// Returns true if the room name changed, false otherwise. - pub fn handle_room_aliases(&mut self, event: &AliasesEvent) -> bool { + pub fn handle_room_aliases(&mut self, event: &StateEventStub) -> bool { match event.content.aliases.as_slice() { [alias] => self.push_room_alias(alias), [alias, ..] => self.push_room_alias(alias), @@ -635,7 +632,7 @@ impl Room { /// Handle a room.canonical_alias event, updating the room state if necessary. /// /// Returns true if the room name changed, false otherwise. - pub fn handle_canonical(&mut self, event: &CanonicalAliasEvent) -> bool { + pub fn handle_canonical(&mut self, event: &StateEventStub) -> bool { match &event.content.alias { Some(name) => self.canonical_alias(&name), _ => false, @@ -645,7 +642,7 @@ impl Room { /// Handle a room.name event, updating the room state if necessary. /// /// Returns true if the room name changed, false otherwise. - pub fn handle_room_name(&mut self, event: &NameEvent) -> bool { + pub fn handle_room_name(&mut self, event: &StateEventStub) -> bool { match event.content.name() { Some(name) => self.set_room_name(name), _ => false, @@ -655,7 +652,10 @@ impl Room { /// Handle a room.name event, updating the room state if necessary. /// /// Returns true if the room name changed, false otherwise. - pub fn handle_stripped_room_name(&mut self, event: &StrippedRoomName) -> bool { + pub fn handle_stripped_room_name( + &mut self, + event: &StrippedStateEventStub, + ) -> bool { match event.content.name() { Some(name) => self.set_room_name(name), _ => false, @@ -665,7 +665,7 @@ impl Room { /// Handle a room.power_levels event, updating the room state if necessary. /// /// Returns true if the room name changed, false otherwise. - pub fn handle_power_level(&mut self, event: &PowerLevelsEvent) -> bool { + pub fn handle_power_level(&mut self, event: &StateEventStub) -> bool { // NOTE: this is always true, we assume that if we get an event their is an update. let mut updated = self.set_room_power_level(event); @@ -684,7 +684,7 @@ impl Room { updated } - fn handle_tombstone(&mut self, event: &TombstoneEvent) -> bool { + fn handle_tombstone(&mut self, event: &StateEventStub) -> bool { self.tombstone = Some(Tombstone { body: event.content.body.clone(), replacement: event.content.replacement_room.clone(), @@ -692,7 +692,7 @@ impl Room { true } - fn handle_encryption_event(&mut self, event: &EncryptionEvent) -> bool { + fn handle_encryption_event(&mut self, event: &StateEventStub) -> bool { self.encrypted = Some(event.into()); true } @@ -704,21 +704,28 @@ impl Room { /// # Arguments /// /// * `event` - The event of the room. - pub fn receive_timeline_event(&mut self, event: &RoomEvent) -> bool { - match event { - // update to the current members of the room - RoomEvent::RoomMember(member) => self.handle_membership(member), - // finds all events related to the name of the room for later use - RoomEvent::RoomName(name) => self.handle_room_name(name), - RoomEvent::RoomCanonicalAlias(c_alias) => self.handle_canonical(c_alias), - RoomEvent::RoomAliases(alias) => self.handle_room_aliases(alias), - // power levels of the room members - RoomEvent::RoomPowerLevels(power) => self.handle_power_level(power), - RoomEvent::RoomTombstone(tomb) => self.handle_tombstone(tomb), - RoomEvent::RoomEncryption(encrypt) => self.handle_encryption_event(encrypt), - #[cfg(feature = "messages")] - RoomEvent::RoomMessage(msg) => self.handle_message(msg), - _ => false, + pub fn receive_timeline_event(&mut self, event: &AnyRoomEventStub, room_id: &RoomId) -> bool { + match &event { + AnyRoomEventStub::State(event) => match &event { + // update to the current members of the room + AnyStateEventStub::RoomMember(event) => self.handle_membership(&event, room_id), + // finds all events related to the name of the room for later use + AnyStateEventStub::RoomName(event) => self.handle_room_name(&event), + AnyStateEventStub::RoomCanonicalAlias(event) => self.handle_canonical(&event), + AnyStateEventStub::RoomAliases(event) => self.handle_room_aliases(&event), + // power levels of the room members + AnyStateEventStub::RoomPowerLevels(event) => self.handle_power_level(&event), + AnyStateEventStub::RoomTombstone(event) => self.handle_tombstone(&event), + AnyStateEventStub::RoomEncryption(event) => self.handle_encryption_event(&event), + _ => false, + }, + AnyRoomEventStub::Message(event) => match &event { + #[cfg(feature = "messages")] + AnyMessageEventStub::RoomMessage(event) => self.handle_message(&event), + // TODO if a redaction event deletes one of our saved messages delete it? + AnyMessageEventStub::RoomRedaction(_) => false, + _ => false, + }, } } @@ -729,18 +736,18 @@ impl Room { /// # Arguments /// /// * `event` - The event of the room. - pub fn receive_state_event(&mut self, event: &StateEvent) -> bool { + pub fn receive_state_event(&mut self, event: &AnyStateEventStub, room_id: &RoomId) -> bool { match event { // update to the current members of the room - StateEvent::RoomMember(member) => self.handle_membership(member), + AnyStateEventStub::RoomMember(member) => self.handle_membership(member, room_id), // finds all events related to the name of the room for later use - StateEvent::RoomName(name) => self.handle_room_name(name), - StateEvent::RoomCanonicalAlias(c_alias) => self.handle_canonical(c_alias), - StateEvent::RoomAliases(alias) => self.handle_room_aliases(alias), + AnyStateEventStub::RoomName(name) => self.handle_room_name(name), + AnyStateEventStub::RoomCanonicalAlias(c_alias) => self.handle_canonical(c_alias), + AnyStateEventStub::RoomAliases(alias) => self.handle_room_aliases(alias), // power levels of the room members - StateEvent::RoomPowerLevels(power) => self.handle_power_level(power), - StateEvent::RoomTombstone(tomb) => self.handle_tombstone(tomb), - StateEvent::RoomEncryption(encrypt) => self.handle_encryption_event(encrypt), + AnyStateEventStub::RoomPowerLevels(power) => self.handle_power_level(power), + AnyStateEventStub::RoomTombstone(tomb) => self.handle_tombstone(tomb), + AnyStateEventStub::RoomEncryption(encrypt) => self.handle_encryption_event(encrypt), _ => false, } } @@ -753,9 +760,9 @@ impl Room { /// /// * `event` - The `AnyStrippedStateEvent` sent by the server for invited but not /// joined rooms. - pub fn receive_stripped_state_event(&mut self, event: &AnyStrippedStateEvent) -> bool { - match event { - AnyStrippedStateEvent::RoomName(n) => self.handle_stripped_room_name(n), + pub fn receive_stripped_state_event(&mut self, event: &AnyStrippedStateEventStub) -> bool { + match &event { + AnyStrippedStateEventStub::RoomName(event) => self.handle_stripped_room_name(event), _ => false, } } @@ -1025,8 +1032,8 @@ mod test { let user_id = UserId::try_from("@example:localhost").unwrap(); let mut response = EventBuilder::default() - .add_room_event(EventsJson::Member, RoomEvent::RoomMember) - .add_room_event(EventsJson::PowerLevels, RoomEvent::RoomPowerLevels) + .add_state_event(EventsFile::Member) + .add_state_event(EventsFile::PowerLevels) .build_sync_response(); client.receive_sync_response(&mut response).await.unwrap(); @@ -1054,7 +1061,7 @@ mod test { let room_id = get_room_id(); let mut response = EventBuilder::default() - .add_state_event(EventsJson::Aliases, StateEvent::RoomAliases) + .add_state_event(EventsFile::Aliases) .build_sync_response(); client.receive_sync_response(&mut response).await.unwrap(); @@ -1072,7 +1079,7 @@ mod test { let room_id = get_room_id(); let mut response = EventBuilder::default() - .add_state_event(EventsJson::Alias, StateEvent::RoomCanonicalAlias) + .add_state_event(EventsFile::Alias) .build_sync_response(); client.receive_sync_response(&mut response).await.unwrap(); @@ -1090,7 +1097,7 @@ mod test { let room_id = get_room_id(); let mut response = EventBuilder::default() - .add_state_event(EventsJson::Name, StateEvent::RoomName) + .add_state_event(EventsFile::Name) .build_sync_response(); client.receive_sync_response(&mut response).await.unwrap(); @@ -1125,6 +1132,8 @@ mod test { #[async_test] #[cfg(not(target_arch = "wasm32"))] async fn encryption_info_test() { + let room_id = get_room_id(); + let mut response = sync_response(SyncResponseFile::DefaultWithSummary); let user_id = UserId::try_from("@example:localhost").unwrap(); @@ -1137,7 +1146,7 @@ mod test { client.restore_login(session).await.unwrap(); client.receive_sync_response(&mut response).await.unwrap(); - let event = EncryptionEvent { + let event = StateEventStub { event_id: EventId::try_from("$h29iv0s8:example.com").unwrap(), origin_server_ts: SystemTime::now(), sender: user_id, @@ -1149,10 +1158,8 @@ mod test { rotation_period_msgs: Some(100u32.into()), }, prev_content: None, - room_id: None, }; - let room_id = get_room_id(); let room = client.get_joined_room(&room_id).await.unwrap(); assert!(!room.read().await.is_encrypted()); diff --git a/matrix_sdk_base/src/models/room_member.rs b/matrix_sdk_base/src/models/room_member.rs index 9834b716..2556c114 100644 --- a/matrix_sdk_base/src/models/room_member.rs +++ b/matrix_sdk_base/src/models/room_member.rs @@ -15,13 +15,13 @@ use std::convert::TryFrom; -use crate::events::collections::all::Event; use crate::events::presence::{PresenceEvent, PresenceEventContent, PresenceState}; use crate::events::room::{ - member::{MemberEvent, MembershipChange}, - power_levels::PowerLevelsEvent, + member::{MemberEventContent, MembershipChange, MembershipState}, + power_levels::PowerLevelsEventContent, }; -use crate::identifiers::UserId; +use crate::events::StateEventStub; +use crate::identifiers::{RoomId, UserId}; use crate::js_int::{Int, UInt}; use serde::{Deserialize, Serialize}; @@ -29,7 +29,6 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize, Clone)] /// A Matrix room member. -/// pub struct RoomMember { /// The unique MXID of the user. pub user_id: UserId, @@ -42,7 +41,7 @@ pub struct RoomMember { /// If the user should be considered active. pub currently_active: Option, /// The unique id of the room. - pub room_id: Option, + pub room_id: Option, /// If the member is typing. pub typing: Option, /// The presence of the user, if found. @@ -53,13 +52,11 @@ pub struct RoomMember { pub power_level: Option, /// The normalized power level of this `RoomMember` (0-100). pub power_level_norm: Option, + /// The `MembershipState` of this `RoomMember`. + pub membership: MembershipState, /// The human readable name of this room member. pub name: String, - /// The events that created the state of this room member. - #[serde(deserialize_with = "super::event_deser::deserialize_events")] - pub events: Vec, /// The `PresenceEvent`s connected to this user. - #[serde(deserialize_with = "super::event_deser::deserialize_presence")] pub presence_events: Vec, } @@ -76,10 +73,10 @@ impl PartialEq for RoomMember { } impl RoomMember { - pub fn new(event: &MemberEvent) -> Self { + pub fn new(event: &StateEventStub, room_id: &RoomId) -> Self { Self { name: event.state_key.clone(), - room_id: event.room_id.as_ref().map(|id| id.to_string()), + room_id: Some(room_id.clone()), user_id: UserId::try_from(event.state_key.as_str()).unwrap(), display_name: event.content.displayname.clone(), avatar_url: event.content.avatar_url.clone(), @@ -90,8 +87,8 @@ impl RoomMember { typing: None, power_level: None, power_level_norm: None, - presence_events: Vec::default(), - events: vec![Event::RoomMember(event.clone())], + membership: event.content.membership, + presence_events: vec![], } } @@ -116,7 +113,7 @@ impl RoomMember { } /// Handle profile updates. - pub(crate) fn update_profile(&mut self, event: &MemberEvent) -> bool { + pub(crate) fn update_profile(&mut self, event: &StateEventStub) -> bool { use MembershipChange::*; match event.membership_change() { @@ -131,7 +128,11 @@ impl RoomMember { } } - pub fn update_power(&mut self, event: &PowerLevelsEvent, max_power: Int) -> bool { + pub fn update_power( + &mut self, + event: &StateEventStub, + max_power: Int, + ) -> bool { let changed; if let Some(user_power) = event.content.users.get(&self.user_id) { changed = self.power_level != Some(*user_power); @@ -211,7 +212,7 @@ impl RoomMember { mod test { use matrix_sdk_test::{async_test, EventBuilder, EventsJson}; - use crate::events::collections::all::RoomEvent; + use crate::events::room::member::MembershipState; use crate::identifiers::{RoomId, UserId}; use crate::{BaseClient, Session}; @@ -244,8 +245,8 @@ mod test { let room_id = get_room_id(); let mut response = EventBuilder::default() - .add_room_event(EventsJson::Member, RoomEvent::RoomMember) - .add_room_event(EventsJson::PowerLevels, RoomEvent::RoomPowerLevels) + .add_state_event(EventsFile::Member) + .add_state_event(EventsFile::PowerLevels) .build_sync_response(); client.receive_sync_response(&mut response).await.unwrap(); @@ -267,9 +268,9 @@ mod test { let room_id = get_room_id(); let mut response = EventBuilder::default() - .add_room_event(EventsJson::Member, RoomEvent::RoomMember) - .add_room_event(EventsJson::PowerLevels, RoomEvent::RoomPowerLevels) - .add_presence_event(EventsJson::Presence) + .add_state_event(EventsFile::Member) + .add_state_event(EventsFile::PowerLevels) + .add_presence_event(EventsFile::Presence) .build_sync_response(); client.receive_sync_response(&mut response).await.unwrap(); diff --git a/matrix_sdk_base/src/state/json_store.rs b/matrix_sdk_base/src/state/json_store.rs index 4d286ed4..f4114af9 100644 --- a/matrix_sdk_base/src/state/json_store.rs +++ b/matrix_sdk_base/src/state/json_store.rs @@ -201,6 +201,7 @@ mod test { use tempfile::tempdir; use crate::identifiers::{RoomId, UserId}; + use crate::push::Ruleset; use crate::{BaseClient, BaseClientConfig, Session}; use matrix_sdk_test::{sync_response, SyncResponseFile}; @@ -221,7 +222,7 @@ mod test { let state = ClientState { sync_token: Some("hello".into()), ignored_users: vec![user], - push_ruleset: None, + push_ruleset: None::, }; let mut path_with_user = PathBuf::from(path); diff --git a/matrix_sdk_base/src/state/mod.rs b/matrix_sdk_base/src/state/mod.rs index 6bd18820..c26f13bb 100644 --- a/matrix_sdk_base/src/state/mod.rs +++ b/matrix_sdk_base/src/state/mod.rs @@ -23,8 +23,8 @@ mod json_store; pub use json_store::JsonStore; use crate::client::{BaseClient, Token}; -use crate::events::push_rules::Ruleset; use crate::identifiers::{RoomId, UserId}; +use crate::push::Ruleset; use crate::{Result, Room, RoomState, Session}; #[cfg(not(target_arch = "wasm32"))] diff --git a/matrix_sdk_common/Cargo.toml b/matrix_sdk_common/Cargo.toml index ed93e2a4..438fa871 100644 --- a/matrix_sdk_common/Cargo.toml +++ b/matrix_sdk_common/Cargo.toml @@ -1,5 +1,5 @@ [package] -authors = ["Damir Jeliฤ‡ "] +authors = ["Damir Jeliฤ‡ OlmResult<(EventJson, String)> { + ) -> OlmResult<(EventJson, String)> { // First try to decrypt using an existing session. let plaintext = if let Some(p) = self .try_decrypt_olm_message(sender, sender_key, &message) @@ -894,7 +893,7 @@ impl OlmMachine { &self, sender: &UserId, plaintext: &str, - ) -> OlmResult<(EventJson, String)> { + ) -> OlmResult<(EventJson, String)> { // TODO make the errors a bit more specific. let decrypted_json: Value = serde_json::from_str(&plaintext)?; @@ -939,7 +938,8 @@ impl OlmMachine { .ok_or(EventError::MissingSigningKey)?; Ok(( - serde_json::from_value::>(decrypted_json)?, + // FIXME EventJson fails to deserialize still? + EventJson::from(serde_json::from_value::(decrypted_json)?), signing_key.to_owned(), )) } @@ -954,8 +954,8 @@ impl OlmMachine { /// * `event` - The to-device event that should be decrypted. async fn decrypt_to_device_event( &mut self, - event: &ToDeviceEncrypted, - ) -> OlmResult> { + event: &ToDeviceEvent, + ) -> OlmResult> { info!("Decrypting to-device event"); let content = if let EncryptedEventContent::OlmV1Curve25519AesSha2(c) = &event.content { @@ -1018,8 +1018,8 @@ impl OlmMachine { &mut self, sender_key: &str, signing_key: &str, - event: &mut ToDeviceRoomKey, - ) -> OlmResult>> { + event: &mut ToDeviceEvent, + ) -> OlmResult>> { match event.content.algorithm { Algorithm::MegolmV1AesSha2 => { let session_key = GroupSessionKey(mem::take(&mut event.content.session_key)); @@ -1031,16 +1031,8 @@ impl OlmMachine { session_key, )?; let _ = self.store.save_inbound_group_session(session).await?; - // TODO ideally we would rewrap the event again just like so - // let event = EventJson::from(ToDeviceEvent::RoomKey(event.clone())); - // This saidly lacks a type once it's serialized again, fix - // this in Ruma. - let mut json = serde_json::to_value(event.clone())?; - json.as_object_mut() - .unwrap() - .insert("type".to_owned(), Value::String("m.room_key".to_owned())); - let event = serde_json::from_value::>(json)?; + let event = EventJson::from(AnyToDeviceEvent::RoomKey(event.clone())); Ok(Some(event)) } _ => { @@ -1324,7 +1316,7 @@ impl OlmMachine { &self, _sender_key: &str, _signing_key: &str, - _event: &ToDeviceForwardedRoomKey, + _event: &ToDeviceEvent, ) -> OlmResult<()> { Ok(()) // TODO @@ -1343,8 +1335,8 @@ impl OlmMachine { &mut self, sender_key: &str, signing_key: &str, - event: &EventJson, - ) -> OlmResult>> { + event: &EventJson, + ) -> OlmResult>> { let event = if let Ok(e) = event.deserialize() { e } else { @@ -1353,10 +1345,10 @@ impl OlmMachine { }; match event { - ToDeviceEvent::RoomKey(mut e) => { + AnyToDeviceEvent::RoomKey(mut e) => { Ok(self.add_room_key(sender_key, signing_key, &mut e).await?) } - ToDeviceEvent::ForwardedRoomKey(e) => { + AnyToDeviceEvent::ForwardedRoomKey(e) => { self.add_forwarded_room_key(sender_key, signing_key, &e)?; Ok(None) } @@ -1367,11 +1359,11 @@ impl OlmMachine { } } - fn handle_room_key_request(&self, _: &ToDeviceRoomKeyRequest) { + fn handle_room_key_request(&self, _: &ToDeviceEvent) { // TODO handle room key requests here. } - fn handle_verification_event(&self, _: &ToDeviceEvent) { + fn handle_verification_event(&self, _: &AnyToDeviceEvent) { // TODO handle to-device verification events here. } @@ -1394,17 +1386,9 @@ impl OlmMachine { let count: u64 = one_time_key_count.map_or(0, |c| (*c).into()); self.update_key_count(count); - if let Some(device_list) = &response.device_lists { - for user_id in &device_list.changed { - let user_id = if let Ok(u) = UserId::try_from(user_id.to_owned()) { - u - } else { - continue; - }; - - if let Err(e) = self.mark_user_as_changed(&user_id).await { - error!("Error marking a tracked user as changed {:?}", e); - } + for user_id in &response.device_lists.changed { + if let Err(e) = self.mark_user_as_changed(&user_id).await { + error!("Error marking a tracked user as changed {:?}", e); } } @@ -1420,8 +1404,8 @@ impl OlmMachine { info!("Received a to-device event {:?}", event); match &event { - ToDeviceEvent::RoomEncrypted(e) => { - let decrypted_event = match self.decrypt_to_device_event(e).await { + AnyToDeviceEvent::RoomEncrypted(e) => { + let decrypted_event = match self.decrypt_to_device_event(&e).await { Ok(e) => e, Err(err) => { warn!( @@ -1438,13 +1422,15 @@ impl OlmMachine { // before we replace the result. *event_result = decrypted_event; } - ToDeviceEvent::RoomKeyRequest(e) => self.handle_room_key_request(e), - ToDeviceEvent::KeyVerificationAccept(..) - | ToDeviceEvent::KeyVerificationCancel(..) - | ToDeviceEvent::KeyVerificationKey(..) - | ToDeviceEvent::KeyVerificationMac(..) - | ToDeviceEvent::KeyVerificationRequest(..) - | ToDeviceEvent::KeyVerificationStart(..) => self.handle_verification_event(&event), + AnyToDeviceEvent::RoomKeyRequest(e) => self.handle_room_key_request(&e), + AnyToDeviceEvent::KeyVerificationAccept(..) + | AnyToDeviceEvent::KeyVerificationCancel(..) + | AnyToDeviceEvent::KeyVerificationKey(..) + | AnyToDeviceEvent::KeyVerificationMac(..) + | AnyToDeviceEvent::KeyVerificationRequest(..) + | AnyToDeviceEvent::KeyVerificationStart(..) => { + self.handle_verification_event(&event) + } _ => continue, } } @@ -1457,18 +1443,17 @@ impl OlmMachine { /// * `event` - The event that should be decrypted. pub async fn decrypt_room_event( &mut self, - event: &EncryptedEvent, - ) -> MegolmResult> { + event: &MessageEventStub, + room_id: &RoomId, + ) -> MegolmResult> { let content = match &event.content { EncryptedEventContent::MegolmV1AesSha2(c) => c, _ => return Err(EventError::UnsupportedAlgorithm.into()), }; - let room_id = event.room_id.as_ref().unwrap(); - let session = self .store - .get_inbound_group_session(&room_id, &content.sender_key, &content.session_id) + .get_inbound_group_session(room_id, &content.sender_key, &content.session_id) .await?; // TODO check if the Olm session is wedged and re-request the key. let session = session.ok_or(MegolmError::MissingSession)?; @@ -1499,7 +1484,8 @@ impl OlmMachine { serde_json::to_value(&event.unsigned).unwrap_or_default(), ); - let decrypted_event = serde_json::from_value::>(decrypted_value)?; + let decrypted_event = + serde_json::from_value::>(decrypted_value)?; trace!("Successfully decrypted Megolm event {:?}", decrypted_event); // TODO set the encryption info on the event (is it verified, was it // decrypted, sender key...) @@ -1587,13 +1573,12 @@ mod test { keys, to_device::send_event_to_device::Request as ToDeviceRequest, }; use matrix_sdk_common::events::{ - collections::all::RoomEvent, room::{ - encrypted::{EncryptedEvent, EncryptedEventContent}, + encrypted::EncryptedEventContent, message::{MessageEventContent, TextMessageEventContent}, }, - to_device::{AnyToDeviceEvent, ToDeviceEncrypted}, - EventJson, EventType, UnsignedData, + AnyMessageEventStub, AnyRoomEventStub, AnyToDeviceEvent, EventJson, EventType, + MessageEventStub, ToDeviceEvent, UnsignedData, }; use matrix_sdk_common::identifiers::{DeviceId, EventId, RoomId, UserId}; use matrix_sdk_test::test_json; @@ -1732,7 +1717,7 @@ mod test { .unwrap() .unwrap(); - let event = ToDeviceEncrypted { + let event = ToDeviceEvent { sender: alice.user_id.clone(), content: alice .olm_encrypt(session, &bob_device, EventType::Dummy, json!({})) @@ -2025,7 +2010,7 @@ mod test { .unwrap() .unwrap(); - let event = ToDeviceEncrypted { + let event = ToDeviceEvent { sender: alice.user_id.clone(), content: alice .olm_encrypt(session, &bob_device, EventType::Dummy, json!({})) @@ -2033,12 +2018,17 @@ mod test { .unwrap(), }; - let event = bob.decrypt_to_device_event(&event).await.unwrap(); + let event = bob + .decrypt_to_device_event(&event) + .await + .unwrap() + .deserialize() + .unwrap(); - if let AnyToDeviceEvent::Dummy(e) = event.deserialize().unwrap() { + if let AnyToDeviceEvent::Dummy(e) = event { assert_eq!(e.sender, alice.user_id); } else { - panic!("Event had the wrong type"); + panic!("Wrong event type found {:?}", event); } } @@ -2053,20 +2043,25 @@ mod test { .await .unwrap(); - let event = ToDeviceEncrypted { + let event = ToDeviceEvent { sender: alice.user_id.clone(), content: to_device_requests_to_content(to_device_requests), }; let alice_session = alice.outbound_group_sessions.get(&room_id).unwrap(); - let event = bob.decrypt_to_device_event(&event).await.unwrap(); + let event = bob + .decrypt_to_device_event(&event) + .await + .unwrap() + .deserialize() + .unwrap(); - if let AnyToDeviceEvent::RoomKey(e) = event.deserialize().unwrap() { - assert_eq!(e.sender, alice.user_id); - assert!(e.content.session_key.is_empty()) + if let AnyToDeviceEvent::RoomKey(event) = event { + assert_eq!(event.sender, alice.user_id); + assert!(event.content.session_key.is_empty()); } else { - panic!("Event had the wrong type"); + panic!("expected RoomKeyEvent found {:?}", event); } let session = bob @@ -2091,8 +2086,8 @@ mod test { .await .unwrap(); - let event = ToDeviceEncrypted { - sender: alice.user_id().clone(), + let event = ToDeviceEvent { + sender: alice.user_id.clone(), content: to_device_requests_to_content(to_device_requests), }; @@ -2104,33 +2099,35 @@ mod test { let encrypted_content = alice.encrypt(&room_id, content.clone()).await.unwrap(); - let event = EncryptedEvent { - event_id: EventId::new("example.org").unwrap(), + let event = MessageEventStub { + event_id: EventId::try_from("$xxxxx:example.org").unwrap(), origin_server_ts: SystemTime::now(), - room_id: Some(room_id.clone()), sender: alice.user_id().clone(), content: encrypted_content, unsigned: UnsignedData::default(), }; let decrypted_event = bob - .decrypt_room_event(&event) + .decrypt_room_event(&event, &room_id) .await .unwrap() .deserialize() .unwrap(); - let decrypted_event = match decrypted_event { - RoomEvent::RoomMessage(e) => e, + match decrypted_event { + AnyRoomEventStub::Message(AnyMessageEventStub::RoomMessage(MessageEventStub { + sender, + content, + .. + })) => { + assert_eq!(&sender, alice.user_id()); + if let MessageEventContent::Text(c) = &content { + assert_eq!(&c.body, plaintext); + } else { + panic!("Decrypted event has a missmatched content"); + } + } _ => panic!("Decrypted room event has the wrong type"), - }; - - assert_eq!(&decrypted_event.sender, alice.user_id()); - assert_eq!(&decrypted_event.room_id, &Some(room_id)); - if let MessageEventContent::Text(c) = &decrypted_event.content { - assert_eq!(&c.body, plaintext); - } else { - panic!("Decrypted event has a missmatched content"); } } } diff --git a/matrix_sdk_test/Cargo.toml b/matrix_sdk_test/Cargo.toml index 52be0255..694a69ac 100644 --- a/matrix_sdk_test/Cargo.toml +++ b/matrix_sdk_test/Cargo.toml @@ -16,3 +16,4 @@ http = "0.2.1" matrix-sdk-common = { version = "0.1.0", path = "../matrix_sdk_common" } matrix-sdk-test-macros = { version = "0.1.0", path = "../matrix_sdk_test_macros" } lazy_static = "1.4.0" +serde = "1.0.111" diff --git a/matrix_sdk_test/src/lib.rs b/matrix_sdk_test/src/lib.rs index 80bba176..97414086 100644 --- a/matrix_sdk_test/src/lib.rs +++ b/matrix_sdk_test/src/lib.rs @@ -6,13 +6,8 @@ use http::Response; use matrix_sdk_common::api::r0::sync::sync_events::Response as SyncResponse; use matrix_sdk_common::events::{ - collections::{ - all::{RoomEvent, StateEvent}, - only::Event, - }, - presence::PresenceEvent, - stripped::AnyStrippedStateEvent, - EventJson, TryFromRaw, + presence::PresenceEvent, AnyBasicEvent, AnyEphemeralRoomEventContent, AnyRoomEventStub, + AnyStateEventStub, EphemeralRoomEventStub, }; use matrix_sdk_common::identifiers::RoomId; use serde_json::Value as JsonValue; @@ -22,6 +17,9 @@ pub use matrix_sdk_test_macros::async_test; pub mod test_json; /// Static `serde_json::Value`s +type AnyEphemeralRoomEventStub = EphemeralRoomEventStub; + +/// Embedded event files #[derive(Debug)] pub enum EventsJson { Alias, @@ -51,19 +49,19 @@ pub enum EventsJson { #[derive(Default)] pub struct EventBuilder { /// The events that determine the state of a `Room`. - joined_room_events: HashMap>, + joined_room_events: HashMap>, /// The events that determine the state of a `Room`. - invited_room_events: HashMap>, + invited_room_events: HashMap>, /// The events that determine the state of a `Room`. - left_room_events: HashMap>, + left_room_events: HashMap>, /// The presence events that determine the presence state of a `RoomMember`. presence_events: Vec, /// The state events that determine the state of a `Room`. - state_events: Vec, + state_events: Vec, /// The ephemeral room events that determine the state of a `Room`. - ephemeral: Vec, + ephemeral: Vec, /// The account data events that determine the state of a `Room`. - account_data: Vec, + account_data: Vec, /// Internal counter to enable the `prev_batch` and `next_batch` of each sync response to vary. batch_counter: i64, } @@ -75,11 +73,11 @@ impl EventBuilder { } /// Add an event to the room events `Vec`. - pub fn add_ephemeral( - &mut self, - json: EventsJson, - variant: fn(Ev) -> Event, - ) -> &mut Self { + pub fn add_ephemeral( + mut self, + file: EventsFile, + variant: fn(Ev) -> AnyEphemeralRoomEventStub, + ) -> Self { let val: &JsonValue = match json { EventsJson::Typing => &test_json::TYPING, _ => panic!("unknown ephemeral event {:?}", json), @@ -89,6 +87,7 @@ impl EventBuilder { .unwrap() .deserialize() .unwrap(); + self.ephemeral.push(variant(event)); self } @@ -112,77 +111,64 @@ impl EventBuilder { self } - /// Add an event to the room events `Vec`. - pub fn add_room_event( - &mut self, - json: EventsJson, - variant: fn(Ev) -> RoomEvent, - ) -> &mut Self { - let val: &JsonValue = match json { - EventsJson::Member => &test_json::MEMBER, - EventsJson::PowerLevels => &test_json::POWER_LEVELS, - _ => panic!("unknown room event json {:?}", json), - }; + // /// Add an event to the room events `Vec`. + // pub fn add_room_event( + // &mut self, + // json: EventsJson, + // variant: fn(Ev) -> AnyRoomEventStub, + // ) -> &mut Self { + // let val: &JsonValue = match json { + // EventsJson::Member => &test_json::MEMBER, + // EventsJson::PowerLevels => &test_json::POWER_LEVELS, + // _ => panic!("unknown room event json {:?}", json), + // }; - let event = serde_json::from_value::>(val.clone()) - .unwrap() - .deserialize() - .unwrap(); - self.add_joined_event( - &RoomId::try_from("!SVkFJHzfwvuaIEawgC:localhost").unwrap(), - variant(event), - ); - self - } + // let event = serde_json::from_value::>(val.clone()) + // .unwrap() + // .deserialize() + // .unwrap(); - pub fn add_custom_joined_event( - &mut self, + // self.add_joined_event( + // &RoomId::try_from("!SVkFJHzfwvuaIEawgC:localhost").unwrap(), + // variant(event), + // ); + // self + // } + + pub fn add_custom_joined_event( + mut self, room_id: &RoomId, event: serde_json::Value, - variant: fn(Ev) -> RoomEvent, - ) -> &mut Self { - let event = serde_json::from_value::>(event) - .unwrap() - .deserialize() - .unwrap(); + variant: fn(Ev) -> AnyRoomEventStub, + ) -> Self { + let event = serde_json::from_value::(event).unwrap(); self.add_joined_event(room_id, variant(event)); self } - fn add_joined_event(&mut self, room_id: &RoomId, event: RoomEvent) { + fn add_joined_event(&mut self, room_id: &RoomId, event: AnyRoomEventStub) { self.joined_room_events .entry(room_id.clone()) .or_insert_with(Vec::new) .push(event); } - pub fn add_custom_invited_event( - &mut self, - room_id: &RoomId, - event: serde_json::Value, - variant: fn(Ev) -> AnyStrippedStateEvent, - ) -> &mut Self { - let event = serde_json::from_value::>(event) - .unwrap() - .deserialize() - .unwrap(); + pub fn add_custom_invited_event(mut self, room_id: &RoomId, event: serde_json::Value) -> Self { + let event = serde_json::from_value::(event).unwrap(); self.invited_room_events .entry(room_id.clone()) .or_insert_with(Vec::new) - .push(variant(event)); + .push(event); self } - pub fn add_custom_left_event( - &mut self, + pub fn add_custom_left_event( + mut self, room_id: &RoomId, event: serde_json::Value, - variant: fn(Ev) -> RoomEvent, - ) -> &mut Self { - let event = serde_json::from_value::>(event) - .unwrap() - .deserialize() - .unwrap(); + variant: fn(Ev) -> AnyRoomEventStub, + ) -> Self { + let event = serde_json::from_value::(event).unwrap(); self.left_room_events .entry(room_id.clone()) .or_insert_with(Vec::new) @@ -194,7 +180,6 @@ impl EventBuilder { pub fn add_state_event( &mut self, json: EventsJson, - variant: fn(Ev) -> StateEvent, ) -> &mut Self { let val: &JsonValue = match json { EventsJson::Alias => &test_json::ALIAS, @@ -203,9 +188,7 @@ impl EventBuilder { _ => panic!("unknown state event {:?}", json), }; - let event = serde_json::from_value::>(val.clone()) - .unwrap() - .deserialize() + let event = serde_json::from_value::(val.clone()) .unwrap(); self.state_events.push(variant(event)); self @@ -218,9 +201,7 @@ impl EventBuilder { _ => panic!("unknown presence event {:?}", json), }; - let event = serde_json::from_value::>(val.clone()) - .unwrap() - .deserialize() + let event = serde_json::from_value::(val.clone()) .unwrap(); self.presence_events.push(event); self