diff --git a/Cargo.toml b/Cargo.toml index 44af39f9..9bc413a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,5 +2,5 @@ members = [ "matrix_sdk", "matrix_sdk_crypto", - "matrix_sdk_types", + "matrix_sdk_common", ] diff --git a/matrix_sdk/Cargo.toml b/matrix_sdk/Cargo.toml index 36e08cfa..b0346dd7 100644 --- a/matrix_sdk/Cargo.toml +++ b/matrix_sdk/Cargo.toml @@ -12,6 +12,7 @@ version = "0.1.0" [features] default = ["encryption", "sqlite-cryptostore"] +messages = [] encryption = ["matrix-sdk-crypto"] sqlite-cryptostore = ["matrix-sdk-crypto/sqlite-cryptostore"] @@ -26,7 +27,7 @@ serde = "1.0.106" serde_json = "1.0.52" uuid = { version = "0.8.1", features = ["v4"] } -matrix-sdk-types = { path = "../matrix_sdk_types" } +matrix-sdk-common = { path = "../matrix_sdk_common" } matrix-sdk-crypto = { path = "../matrix_sdk_crypto", optional = true } # Misc dependencies diff --git a/matrix_sdk/src/async_client.rs b/matrix_sdk/src/async_client.rs index 9510c4c0..44c17113 100644 --- a/matrix_sdk/src/async_client.rs +++ b/matrix_sdk/src/async_client.rs @@ -37,7 +37,7 @@ use url::Url; use crate::events::room::message::MessageEventContent; use crate::events::EventType; -use crate::identifiers::{RoomId, RoomIdOrAliasId, UserId}; +use crate::identifiers::{EventId, RoomId, RoomIdOrAliasId, UserId}; use crate::Endpoint; #[cfg(feature = "encryption")] @@ -213,21 +213,20 @@ impl SyncSettings { #[cfg(feature = "encryption")] use api::r0::keys::{claim_keys, get_keys, upload_keys, KeyAlgorithm}; -use api::r0::membership::join_room_by_id; -use api::r0::membership::join_room_by_id_or_alias; -use api::r0::membership::kick_user; -use api::r0::membership::leave_room; use api::r0::membership::{ + ban_user, forget_room, invite_user::{self, InvitationRecipient}, - Invite3pid, + join_room_by_id, join_room_by_id_or_alias, kick_user, leave_room, Invite3pid, }; use api::r0::message::create_message_event; use api::r0::message::get_message_events; +use api::r0::receipt::create_receipt; use api::r0::room::create_room; use api::r0::session::login; use api::r0::sync::sync_events; #[cfg(feature = "encryption")] use api::r0::to_device::send_event_to_device; +use api::r0::typing::create_typing_event; impl AsyncClient { /// Creates a new client for making HTTP requests to the given homeserver. @@ -368,6 +367,7 @@ impl AsyncClient { /// This allows `AsyncClient` to manually sync state with the provided `StateStore`. /// /// Returns true when a successful `StateStore` sync has completed. + /// /// # Examples /// /// ```no_run @@ -387,7 +387,7 @@ impl AsyncClient { /// // now state is restored without a request to the server /// let mut names = vec![]; /// for r in client.joined_rooms().read().await.values() { - /// names.push(r.read().await.calculate_name()); + /// names.push(r.read().await.display_name()); /// } /// assert_eq!(vec!["room".to_string(), "names".to_string()], names) /// # }); @@ -440,8 +440,8 @@ impl AsyncClient { /// /// # Arguments /// - /// * room_id - The `RoomId` of the room to be joined. - pub async fn join_room_by_id(&mut self, room_id: &RoomId) -> Result { + /// * `room_id` - The `RoomId` of the room to be joined. + pub async fn join_room_by_id(&self, room_id: &RoomId) -> Result { let request = join_room_by_id::Request { room_id: room_id.clone(), third_party_signed: None, @@ -456,7 +456,7 @@ impl AsyncClient { /// /// # Arguments /// - /// * alias - The `RoomId` or `RoomAliasId` of the room to be joined. + /// * `alias` - The `RoomId` or `RoomAliasId` of the room to be joined. /// An alias looks like this `#name:example.com` pub async fn join_room_by_id_or_alias( &self, @@ -471,17 +471,56 @@ impl AsyncClient { self.send(request).await } + /// Forget a room by `RoomId`. + /// + /// Returns a `forget_room::Response`, an empty response. + /// + /// # Arguments + /// + /// * `room_id` - The `RoomId` of the room to be forget. + pub async fn forget_room_by_id(&self, room_id: &RoomId) -> Result { + let request = forget_room::Request { + room_id: room_id.clone(), + }; + self.send(request).await + } + + /// Ban a user from a room by `RoomId` and `UserId`. + /// + /// Returns a `ban_user::Response`, an empty response. + /// + /// # Arguments + /// + /// * `room_id` - The `RoomId` of the room to ban the user from. + /// + /// * `user_id` - The user to ban by `UserId`. + /// + /// * `reason` - The reason for banning this user. + pub async fn ban_user( + &self, + room_id: &RoomId, + user_id: &UserId, + reason: Option, + ) -> Result { + let request = ban_user::Request { + reason, + room_id: room_id.clone(), + user_id: user_id.clone(), + }; + self.send(request).await + } + /// Kick a user out of the specified room. /// /// Returns a `kick_user::Response`, an empty response. /// /// # Arguments /// - /// * room_id - The `RoomId` of the room the user should be kicked out of. + /// * `room_id` - The `RoomId` of the room the user should be kicked out of. /// - /// * user_id - The `UserId` of the user that should be kicked out of the room. + /// * `user_id` - The `UserId` of the user that should be kicked out of the room. /// - /// * reason - Optional reason why the room member is being kicked out. + /// * `reason` - Optional reason why the room member is being kicked out. pub async fn kick_user( &self, room_id: &RoomId, @@ -502,7 +541,7 @@ impl AsyncClient { /// /// # Arguments /// - /// * room_id - The `RoomId` of the room to leave. + /// * `room_id` - The `RoomId` of the room to leave. /// pub async fn leave_room(&self, room_id: &RoomId) -> Result { let request = leave_room::Request { @@ -517,9 +556,9 @@ impl AsyncClient { /// /// # Arguments /// - /// * room_id - The `RoomId` of the room to invite the specified user to. + /// * `room_id` - The `RoomId` of the room to invite the specified user to. /// - /// * user_id - The `UserId` of the user to invite to the room. + /// * `user_id` - The `UserId` of the user to invite to the room. pub async fn invite_user_by_id( &self, room_id: &RoomId, @@ -540,9 +579,9 @@ impl AsyncClient { /// /// # Arguments /// - /// * room_id - The `RoomId` of the room to invite the specified user to. + /// * `room_id` - The `RoomId` of the room to invite the specified user to. /// - /// * invite_id - A third party id of a user to invite to the room. + /// * `invite_id` - A third party id of a user to invite to the room. pub async fn invite_user_by_3pid( &self, room_id: &RoomId, @@ -562,7 +601,7 @@ impl AsyncClient { /// /// # Arguments /// - /// * room - The easiest way to create this request is using the `RoomBuilder`. + /// * `room` - The easiest way to create this request is using the `RoomBuilder`. /// /// # Examples /// ```no_run @@ -601,7 +640,7 @@ impl AsyncClient { /// /// # Arguments /// - /// * request - The easiest way to create a `Request` is using the + /// * `request` - The easiest way to create a `Request` is using the /// `MessagesRequestBuilder`. /// /// # Examples @@ -636,6 +675,57 @@ impl AsyncClient { self.send(req).await } + /// Send a request to notify the room of a user typing. + /// + /// Returns a `create_typing_event::Response`, an empty response. + /// + /// # Arguments + /// + /// * `room_id` - The `RoomId` the user is typing in. + /// + /// * `user_id` - The `UserId` of the user that is typing. + /// + /// * `typing` - Whether the user is typing, if false `timeout` is not needed. + /// + /// * `timeout` - Length of time in milliseconds to mark user is typing. + pub async fn typing_notice( + &self, + room_id: &RoomId, + user_id: &UserId, + typing: bool, + timeout: Option, + ) -> Result { + let request = create_typing_event::Request { + room_id: room_id.clone(), + user_id: user_id.clone(), + timeout, + typing, + }; + self.send(request).await + } + + /// Send a request to notify the room of a user typing. + /// + /// Returns a `create_receipt::Response`, an empty response. + /// + /// # Arguments + /// + /// * `room_id` - The `RoomId` the user is typing in. + /// + /// * `event_id` - The `UserId` of the user that is typing. + pub async fn read_receipt( + &self, + room_id: &RoomId, + event_id: &EventId, + ) -> Result { + let request = create_receipt::Request { + room_id: room_id.clone(), + event_id: event_id.clone(), + receipt_type: create_receipt::ReceiptType::Read, + }; + self.send(request).await + } + /// Synchronize the client's state with the latest state on the server. /// /// If a `StateStore` is provided and this is the initial sync state will @@ -1104,15 +1194,50 @@ impl AsyncClient { #[cfg(test)] mod test { - use super::{AsyncClient, Url}; + use super::{ + ban_user, create_receipt, create_typing_event, forget_room, invite_user, kick_user, + leave_room, + }; + use super::{AsyncClient, Session, SyncSettings, Url}; use crate::events::collections::all::RoomEvent; - use crate::identifiers::{RoomId, UserId}; + use crate::events::room::member::MembershipState; + use crate::identifiers::{EventId, RoomId, UserId}; use crate::test_builder::EventBuilder; - use mockito::mock; + use mockito::{mock, Matcher}; use std::convert::TryFrom; use std::str::FromStr; + use std::time::Duration; + + #[tokio::test] + async fn account_data() { + let homeserver = Url::from_str(&mockito::server_url()).unwrap(); + + let session = Session { + access_token: "1234".to_owned(), + user_id: UserId::try_from("@example:example.com").unwrap(), + device_id: "DEVICEID".to_owned(), + }; + + let _m = mock( + "GET", + Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_string()), + ) + .with_status(200) + .with_body_from_file("../test_data/sync.json") + .create(); + + let client = AsyncClient::new(homeserver, Some(session)).unwrap(); + + let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000)); + + let _response = client.sync(sync_settings).await.unwrap(); + + let bc = &client.base_client; + let ignored_users = bc.ignored_users.read().await; + assert_eq!(1, ignored_users.len()) + } #[tokio::test] async fn client_runner() { @@ -1214,4 +1339,340 @@ mod test { panic!("this request should return an `Err` variant") } } + + #[tokio::test] + async fn join_room() { + let homeserver = Url::from_str(&mockito::server_url()).unwrap(); + + let session = Session { + access_token: "1234".to_owned(), + user_id: UserId::try_from("@example:localhost").unwrap(), + device_id: "DEVICEID".to_owned(), + }; + + let _m = mock( + "POST", + Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/join".to_string()), + ) + .with_status(200) + .with_body_from_file("../test_data/room_id.json") + .create(); + + let client = AsyncClient::new(homeserver, Some(session)).unwrap(); + let room_id = RoomId::try_from("!testroom:example.org").unwrap(); + + assert_eq!( + // this is the `join_by_room_id::Response` but since no PartialEq we check the RoomId field + client.join_room_by_id(&room_id).await.unwrap().room_id, + room_id + ); + } + + #[tokio::test] + #[allow(irrefutable_let_patterns)] + async fn invite_room() { + let homeserver = Url::from_str(&mockito::server_url()).unwrap(); + let user = UserId::try_from("@example:localhost").unwrap(); + let room_id = RoomId::try_from("!testroom:example.org").unwrap(); + + let session = Session { + access_token: "1234".to_owned(), + user_id: user.clone(), + device_id: "DEVICEID".to_owned(), + }; + + let _m = mock( + "POST", + Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/invite".to_string()), + ) + .with_status(200) + .with_body_from_file("../test_data/logout_response.json") + .create(); + + let client = AsyncClient::new(homeserver, Some(session)).unwrap(); + + if let invite_user::Response = client.invite_user_by_id(&room_id, &user).await.unwrap() {} + } + + #[tokio::test] + #[allow(irrefutable_let_patterns)] + async fn leave_room() { + let homeserver = Url::from_str(&mockito::server_url()).unwrap(); + + let session = Session { + access_token: "1234".to_owned(), + user_id: UserId::try_from("@example:localhost").unwrap(), + device_id: "DEVICEID".to_owned(), + }; + + let _m = mock( + "POST", + Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/leave".to_string()), + ) + .with_status(200) + // this is an empty JSON object + .with_body_from_file("../test_data/logout_response.json") + .create(); + + let client = AsyncClient::new(homeserver, Some(session)).unwrap(); + let room_id = RoomId::try_from("!testroom:example.org").unwrap(); + + let response = client.leave_room(&room_id).await.unwrap(); + if let leave_room::Response = response { + } else { + panic!( + "expected `ruma_client_api::leave_room::Response` found {:?}", + response + ) + } + } + + #[tokio::test] + #[allow(irrefutable_let_patterns)] + async fn ban_user() { + let homeserver = Url::from_str(&mockito::server_url()).unwrap(); + let user = UserId::try_from("@example:localhost").unwrap(); + let room_id = RoomId::try_from("!testroom:example.org").unwrap(); + + let session = Session { + access_token: "1234".to_owned(), + user_id: user.clone(), + device_id: "DEVICEID".to_owned(), + }; + + let _m = mock( + "POST", + Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/ban".to_string()), + ) + .with_status(200) + // this is an empty JSON object + .with_body_from_file("../test_data/logout_response.json") + .create(); + + let client = AsyncClient::new(homeserver, Some(session)).unwrap(); + + let response = client.ban_user(&room_id, &user, None).await.unwrap(); + if let ban_user::Response = response { + } else { + panic!( + "expected `ruma_client_api::ban_user::Response` found {:?}", + response + ) + } + } + + #[tokio::test] + #[allow(irrefutable_let_patterns)] + async fn kick_user() { + let homeserver = Url::from_str(&mockito::server_url()).unwrap(); + let user = UserId::try_from("@example:localhost").unwrap(); + let room_id = RoomId::try_from("!testroom:example.org").unwrap(); + + let session = Session { + access_token: "1234".to_owned(), + user_id: user.clone(), + device_id: "DEVICEID".to_owned(), + }; + + let _m = mock( + "POST", + Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/kick".to_string()), + ) + .with_status(200) + // this is an empty JSON object + .with_body_from_file("../test_data/logout_response.json") + .create(); + + let client = AsyncClient::new(homeserver, Some(session)).unwrap(); + + let response = client.kick_user(&room_id, &user, None).await.unwrap(); + if let kick_user::Response = response { + } else { + panic!( + "expected `ruma_client_api::kick_user::Response` found {:?}", + response + ) + } + } + + #[tokio::test] + #[allow(irrefutable_let_patterns)] + async fn forget_room() { + let homeserver = Url::from_str(&mockito::server_url()).unwrap(); + let user = UserId::try_from("@example:localhost").unwrap(); + let room_id = RoomId::try_from("!testroom:example.org").unwrap(); + + let session = Session { + access_token: "1234".to_owned(), + user_id: user.clone(), + device_id: "DEVICEID".to_owned(), + }; + + let _m = mock( + "POST", + Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/forget".to_string()), + ) + .with_status(200) + // this is an empty JSON object + .with_body_from_file("../test_data/logout_response.json") + .create(); + + let client = AsyncClient::new(homeserver, Some(session)).unwrap(); + + let response = client.forget_room_by_id(&room_id).await.unwrap(); + if let forget_room::Response = response { + } else { + panic!( + "expected `ruma_client_api::forget_room::Response` found {:?}", + response + ) + } + } + + #[tokio::test] + #[allow(irrefutable_let_patterns)] + async fn read_receipt() { + 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 session = Session { + access_token: "1234".to_owned(), + user_id, + device_id: "DEVICEID".to_owned(), + }; + + let _m = mock( + "POST", + Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/receipt".to_string()), + ) + .with_status(200) + // this is an empty JSON object + .with_body_from_file("../test_data/logout_response.json") + .create(); + + let client = AsyncClient::new(homeserver, Some(session)).unwrap(); + + let response = client.read_receipt(&room_id, &event_id).await.unwrap(); + if let create_receipt::Response = response { + } else { + panic!( + "expected `ruma_client_api::create_receipt::Response` found {:?}", + response + ) + } + } + + #[tokio::test] + #[allow(irrefutable_let_patterns)] + async fn typing_notice() { + let homeserver = Url::from_str(&mockito::server_url()).unwrap(); + let user = UserId::try_from("@example:localhost").unwrap(); + let room_id = RoomId::try_from("!testroom:example.org").unwrap(); + + let session = Session { + access_token: "1234".to_owned(), + user_id: user.clone(), + device_id: "DEVICEID".to_owned(), + }; + + let _m = mock( + "PUT", + Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/typing".to_string()), + ) + .with_status(200) + // this is an empty JSON object + .with_body_from_file("../test_data/logout_response.json") + .create(); + + let client = AsyncClient::new(homeserver, Some(session)).unwrap(); + + let response = client + .typing_notice( + &room_id, + &user, + true, + Some(std::time::Duration::from_secs(1)), + ) + .await + .unwrap(); + if let create_typing_event::Response = response { + } else { + panic!( + "expected `ruma_client_api::create_typing_event::Response` found {:?}", + response + ) + } + } + + #[tokio::test] + async fn user_presence() { + let homeserver = Url::from_str(&mockito::server_url()).unwrap(); + + let session = Session { + access_token: "1234".to_owned(), + user_id: UserId::try_from("@example:localhost").unwrap(), + device_id: "DEVICEID".to_owned(), + }; + + let _m = mock( + "GET", + Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_string()), + ) + .with_status(200) + .with_body_from_file("../test_data/sync.json") + .create(); + + let client = AsyncClient::new(homeserver, Some(session)).unwrap(); + + let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000)); + + let _response = client.sync(sync_settings).await.unwrap(); + + let rooms_lock = &client.base_client.joined_rooms(); + let rooms = rooms_lock.read().await; + let room = &rooms + .get(&RoomId::try_from("!SVkFJHzfwvuaIEawgC:localhost").unwrap()) + .unwrap() + .read() + .await; + + assert_eq!(2, room.members.len()); + for member in room.members.values() { + assert_eq!(MembershipState::Join, member.membership); + } + + assert!(room.power_levels.is_some()) + } + + #[tokio::test] + async fn calculate_room_names_from_summary() { + let homeserver = Url::from_str(&mockito::server_url()).unwrap(); + + let mut bld = EventBuilder::default().build_with_response( + // this sync has no room.name or room.alias events so only relies on summary + "../test_data/sync_with_summary.json", + "GET", + Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_string()), + ); + + let session = Session { + access_token: "1234".to_owned(), + user_id: UserId::try_from("@example:localhost").unwrap(), + device_id: "DEVICEID".to_owned(), + }; + let client = AsyncClient::new(homeserver, Some(session)).unwrap(); + let client = bld.set_client(client).to_client().await.unwrap(); + + let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000)); + let _response = client.sync(sync_settings).await.unwrap(); + + let mut room_names = vec![]; + for room in client.joined_rooms().read().await.values() { + room_names.push(room.read().await.display_name()) + } + + assert_eq!(vec!["example, example2"], room_names); + } } diff --git a/matrix_sdk/src/base_client.rs b/matrix_sdk/src/base_client.rs index 34504e6c..45ed81dc 100644 --- a/matrix_sdk/src/base_client.rs +++ b/matrix_sdk/src/base_client.rs @@ -1354,46 +1354,3 @@ impl Client { } } } - -#[cfg(test)] -mod test { - - use crate::identifiers::UserId; - use crate::{AsyncClient, Session, SyncSettings}; - - use mockito::{mock, Matcher}; - use url::Url; - - use std::convert::TryFrom; - use std::str::FromStr; - use std::time::Duration; - - #[tokio::test] - async fn account_data() { - let homeserver = Url::from_str(&mockito::server_url()).unwrap(); - - let session = Session { - access_token: "1234".to_owned(), - user_id: UserId::try_from("@example:example.com").unwrap(), - device_id: "DEVICEID".to_owned(), - }; - - let _m = mock( - "GET", - Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_string()), - ) - .with_status(200) - .with_body_from_file("../test_data/sync.json") - .create(); - - let client = AsyncClient::new(homeserver, Some(session)).unwrap(); - - let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000)); - - let _response = client.sync(sync_settings).await.unwrap(); - - let bc = &client.base_client; - let ignored_users = bc.ignored_users.read().await; - assert_eq!(1, ignored_users.len()) - } -} diff --git a/matrix_sdk/src/lib.rs b/matrix_sdk/src/lib.rs index ac07fb34..1fe1c108 100644 --- a/matrix_sdk/src/lib.rs +++ b/matrix_sdk/src/lib.rs @@ -27,7 +27,7 @@ #![deny(missing_docs)] pub use crate::{error::Error, error::Result, session::Session}; -pub use matrix_sdk_types::*; +pub use matrix_sdk_common::*; pub use reqwest::header::InvalidHeaderValue; mod async_client; diff --git a/matrix_sdk/src/models/message.rs b/matrix_sdk/src/models/message.rs new file mode 100644 index 00000000..2aed0ec5 --- /dev/null +++ b/matrix_sdk/src/models/message.rs @@ -0,0 +1,325 @@ +//! A queue that holds at most ten of the most recent messages. +//! +//! The `Room` struct optionally holds a `MessageQueue` if the "messages" +//! feature is enabled. + +use std::cmp::Ordering; +use std::ops::Deref; +use std::vec::IntoIter; + +use crate::events::room::message::MessageEvent; +use crate::events::EventJson; + +use serde::{de, ser, Serialize}; + +/// A queue that holds the 10 most recent messages received from the server. +#[derive(Clone, Debug, Default)] +pub struct MessageQueue { + msgs: Vec, +} + +#[derive(Clone, Debug, Serialize)] +pub struct MessageWrapper(MessageEvent); + +impl Deref for MessageWrapper { + type Target = MessageEvent; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl PartialEq for MessageWrapper { + fn eq(&self, other: &MessageWrapper) -> bool { + self.0.event_id == other.0.event_id + } +} + +impl Eq for MessageWrapper {} + +impl PartialOrd for MessageWrapper { + fn partial_cmp(&self, other: &MessageWrapper) -> Option { + Some(self.0.origin_server_ts.cmp(&other.0.origin_server_ts)) + } +} + +impl Ord for MessageWrapper { + fn cmp(&self, other: &MessageWrapper) -> Ordering { + self.partial_cmp(other).unwrap_or(Ordering::Equal) + } +} + +impl PartialEq for MessageQueue { + fn eq(&self, other: &MessageQueue) -> bool { + self.msgs.len() == other.msgs.len() + && self + .msgs + .iter() + .zip(other.msgs.iter()) + .all(|(msg_a, msg_b)| msg_a.event_id == msg_b.event_id) + } +} + +impl MessageQueue { + /// Create a new empty `MessageQueue`. + pub fn new() -> Self { + Self { + msgs: Vec::with_capacity(20), + } + } + + /// Inserts a `MessageEvent` into `MessageQueue`, sorted by by `origin_server_ts`. + /// + /// Removes the oldest element in the queue if there are more than 10 elements. + pub fn push(&mut self, msg: MessageEvent) -> bool { + // only push new messages into the queue + if let Some(latest) = self.msgs.last() { + if msg.origin_server_ts < latest.origin_server_ts && self.msgs.len() >= 10 { + return false; + } + } + + let message = MessageWrapper(msg); + match self.msgs.binary_search_by(|m| m.cmp(&message)) { + Ok(pos) => { + if self.msgs[pos] != message { + self.msgs.insert(pos, message) + } + } + Err(pos) => self.msgs.insert(pos, message), + } + if self.msgs.len() > 10 { + self.msgs.remove(0); + } + true + } + + pub fn iter(&self) -> impl Iterator { + self.msgs.iter() + } +} + +impl IntoIterator for MessageQueue { + type Item = MessageWrapper; + type IntoIter = IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.msgs.into_iter() + } +} + +pub(crate) mod ser_deser { + use super::*; + + pub fn deserialize<'de, D>(deserializer: D) -> Result + where + D: de::Deserializer<'de>, + { + use serde::de::Error; + + let messages: Vec> = de::Deserialize::deserialize(deserializer)?; + + let mut msgs = vec![]; + for json in messages { + let msg = json.deserialize().map_err(D::Error::custom)?; + msgs.push(MessageWrapper(msg)); + } + + Ok(MessageQueue { msgs }) + } + + pub fn serialize(msgs: &MessageQueue, serializer: S) -> Result + where + S: ser::Serializer, + { + msgs.msgs.serialize(serializer) + } +} + +#[cfg(test)] +mod test { + use super::*; + + use std::collections::HashMap; + use std::convert::TryFrom; + + use crate::events::{collections::all::RoomEvent, EventJson}; + use crate::identifiers::{RoomId, UserId}; + use crate::Room; + + #[test] + fn serialize() { + let id = RoomId::try_from("!roomid:example.com").unwrap(); + let user = UserId::try_from("@example:example.com").unwrap(); + + let mut room = Room::new(&id, &user); + + let json = std::fs::read_to_string("../test_data/events/message_text.json").unwrap(); + let event = serde_json::from_str::>(&json).unwrap(); + + let mut msgs = MessageQueue::new(); + if let Ok(ev) = event.deserialize() { + if let RoomEvent::RoomMessage(msg) = ev { + msgs.push(msg); + } + } + room.messages = msgs; + + let mut joined_rooms = HashMap::new(); + joined_rooms.insert(id, room); + println!("{}", serde_json::to_string_pretty(&joined_rooms).unwrap()); + // this is the correct JSON string changes to `ruma-events` have not been released + // that would fix the doubling of fields + // TODO uncomment when fixed + // assert_eq!( + // r#"{ + // "!roomid:example.com": { + // "room_id": "!roomid:example.com", + // "room_name": { + // "name": null, + // "canonical_alias": null, + // "aliases": [], + // "heroes": [], + // "joined_member_count": null, + // "invited_member_count": null + // }, + // "own_user_id": "@example:example.com", + // "creator": null, + // "members": {}, + // "messages": [ + // { + // "type": "m.room.message", + // "content": { + // "body": "is dancing", + // "format": "org.matrix.custom.html", + // "formatted_body": "is dancing", + // "msgtype": "m.text" + // }, + // "event_id": "$152037280074GZeOm:localhost", + // "origin_server_ts": 1520372800469, + // "sender": "@example:localhost", + // "unsigned": { + // "age": 598971425 + // } + // } + // ], + // "typing_users": [], + // "power_levels": null, + // "encrypted": false, + // "unread_highlight": null, + // "unread_notifications": null, + // "tombstone": null + // } + // }"#, + // serde_json::to_string_pretty(&joined_rooms).unwrap() + // ); + assert_eq!( + r#"{ + "!roomid:example.com": { + "room_id": "!roomid:example.com", + "room_name": { + "name": null, + "canonical_alias": null, + "aliases": [], + "heroes": [], + "joined_member_count": null, + "invited_member_count": null + }, + "own_user_id": "@example:example.com", + "creator": null, + "members": {}, + "messages": [ + { + "content": { + "msgtype": "m.text", + "msgtype": "m.text", + "body": "is dancing", + "format": "org.matrix.custom.html", + "formatted_body": "is dancing" + }, + "event_id": "$152037280074GZeOm:localhost", + "origin_server_ts": 1520372800469, + "sender": "@example:localhost", + "unsigned": { + "age": 598971425 + } + } + ], + "typing_users": [], + "power_levels": null, + "encrypted": false, + "unread_highlight": null, + "unread_notifications": null, + "tombstone": null + } +}"#, + serde_json::to_string_pretty(&joined_rooms).unwrap() + ); + } + + #[test] + fn deserialize() { + let id = RoomId::try_from("!roomid:example.com").unwrap(); + let user = UserId::try_from("@example:example.com").unwrap(); + + let mut room = Room::new(&id, &user); + + let json = std::fs::read_to_string("../test_data/events/message_text.json").unwrap(); + let event = serde_json::from_str::>(&json).unwrap(); + + let mut msgs = MessageQueue::new(); + if let Ok(ev) = event.deserialize() { + if let RoomEvent::RoomMessage(msg) = ev { + msgs.push(msg); + } + } + room.messages = msgs; + + let mut joined_rooms = HashMap::new(); + joined_rooms.insert(id, room.clone()); + + let json = r#"{ + "!roomid:example.com": { + "room_id": "!roomid:example.com", + "room_name": { + "name": null, + "canonical_alias": null, + "aliases": [], + "heroes": [], + "joined_member_count": null, + "invited_member_count": null + }, + "own_user_id": "@example:example.com", + "creator": null, + "members": {}, + "messages": [ + { + "type": "m.room.message", + "content": { + "body": "is dancing", + "format": "org.matrix.custom.html", + "formatted_body": "is dancing", + "msgtype": "m.text" + }, + "event_id": "$152037280074GZeOm:localhost", + "origin_server_ts": 1520372800469, + "sender": "@example:localhost", + "unsigned": { + "age": 598971425 + } + } + ], + "typing_users": [], + "power_levels": null, + "encrypted": false, + "unread_highlight": null, + "unread_notifications": null, + "tombstone": null + } +}"#; + assert_eq!( + joined_rooms, + serde_json::from_str::>(json).unwrap() + ); + } +} diff --git a/matrix_sdk/src/models/mod.rs b/matrix_sdk/src/models/mod.rs index 5e461a32..218cf28b 100644 --- a/matrix_sdk/src/models/mod.rs +++ b/matrix_sdk/src/models/mod.rs @@ -1,9 +1,9 @@ mod event_deser; +#[cfg(feature = "messages")] +#[cfg_attr(docsrs, doc(cfg(feature = "messages")))] +mod message; mod room; mod room_member; pub use room::{Room, RoomName}; pub use room_member::RoomMember; - -#[allow(dead_code)] -pub type Token = String; diff --git a/matrix_sdk/src/models/room.rs b/matrix_sdk/src/models/room.rs index 20d8ccaa..981f5fe3 100644 --- a/matrix_sdk/src/models/room.rs +++ b/matrix_sdk/src/models/room.rs @@ -16,6 +16,8 @@ use std::collections::{BTreeMap, HashMap}; use std::convert::TryFrom; +#[cfg(feature = "messages")] +use super::message::MessageQueue; use super::RoomMember; use crate::api::r0::sync::sync_events::RoomSummary; @@ -32,11 +34,16 @@ use crate::events::room::{ }; use crate::events::stripped::{AnyStrippedStateEvent, StrippedRoomName}; use crate::events::EventType; + +#[cfg(feature = "messages")] +use crate::events::room::message::MessageEvent; + use crate::identifiers::{RoomAliasId, RoomId, UserId}; use crate::js_int::{Int, UInt}; use serde::{Deserialize, Serialize}; #[derive(Debug, Default, PartialEq, Serialize, Deserialize)] +#[cfg_attr(test, derive(Clone))] /// `RoomName` allows the calculation of a text room name. pub struct RoomName { /// The displayed name of the room. @@ -59,6 +66,7 @@ pub struct RoomName { } #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(test, derive(Clone))] pub struct PowerLevels { /// The level required to ban a user. pub ban: Int, @@ -85,6 +93,7 @@ pub struct PowerLevels { } #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(test, derive(Clone))] pub struct Tombstone { /// A server-defined message. body: String, @@ -93,6 +102,7 @@ pub struct Tombstone { } #[derive(Debug, PartialEq, Serialize, Deserialize)] +#[cfg_attr(test, derive(Clone))] /// A Matrix room. pub struct Room { /// The unique id of the room. @@ -105,6 +115,14 @@ pub struct Room { pub creator: Option, /// The map of room members. pub members: HashMap, + /// A queue of messages, holds no more than 10 of the most recent messages. + /// + /// This is helpful when using a `StateStore` to avoid multiple requests + /// to the server for messages. + #[cfg(feature = "messages")] + #[cfg_attr(docsrs, doc(cfg(feature = "messages")))] + #[serde(with = "super::message::ser_deser")] + pub messages: MessageQueue, /// A list of users that are currently typing. pub typing_users: Vec, /// The power level requirements for specific actions in this room @@ -208,6 +226,8 @@ impl Room { own_user_id: own_user_id.clone(), creator: None, members: HashMap::new(), + #[cfg(feature = "messages")] + messages: MessageQueue::new(), typing_users: Vec::new(), power_levels: None, encrypted: false, @@ -218,7 +238,7 @@ impl Room { } /// Return the display name of the room. - pub fn calculate_name(&self) -> String { + pub fn display_name(&self) -> String { self.room_name.calculate_name(&self.members) } @@ -321,6 +341,15 @@ impl Room { } } + /// Handle a room.message event and update the `MessageQueue` if necessary. + /// + /// 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 { + 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. @@ -407,15 +436,17 @@ impl Room { pub fn receive_timeline_event(&mut self, event: &RoomEvent) -> bool { match event { // update to the current members of the room - RoomEvent::RoomMember(m) => self.handle_membership(m), + RoomEvent::RoomMember(member) => self.handle_membership(member), // finds all events related to the name of the room for later use - RoomEvent::RoomName(n) => self.handle_room_name(n), - RoomEvent::RoomCanonicalAlias(ca) => self.handle_canonical(ca), - RoomEvent::RoomAliases(a) => self.handle_room_aliases(a), + 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(p) => self.handle_power_level(p), - RoomEvent::RoomTombstone(t) => self.handle_tombstone(t), - RoomEvent::RoomEncryption(e) => self.handle_encryption_event(e), + 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, } } @@ -429,13 +460,16 @@ impl Room { /// * `event` - The event of the room. pub fn receive_state_event(&mut self, event: &StateEvent) -> bool { match event { - StateEvent::RoomMember(m) => self.handle_membership(m), - StateEvent::RoomName(n) => self.handle_room_name(n), - StateEvent::RoomCanonicalAlias(ca) => self.handle_canonical(ca), - StateEvent::RoomAliases(a) => self.handle_room_aliases(a), - StateEvent::RoomPowerLevels(p) => self.handle_power_level(p), - StateEvent::RoomTombstone(t) => self.handle_tombstone(t), - StateEvent::RoomEncryption(e) => self.handle_encryption_event(e), + // update to the current members of the room + StateEvent::RoomMember(member) => self.handle_membership(member), + // 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), + // 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), _ => false, } } @@ -482,44 +516,42 @@ impl Room { #[cfg(test)] mod test { use super::*; + use crate::api::r0::sync::sync_events::Response as SyncResponse; use crate::events::room::member::MembershipState; use crate::identifiers::UserId; use crate::test_builder::EventBuilder; - use crate::{AsyncClient, Session, SyncSettings}; + use crate::{Client, Session}; - use mockito::{mock, Matcher}; - use url::Url; + use http::Response; use std::convert::TryFrom; + use std::fs::File; + use std::io::Read; use std::ops::Deref; - use std::str::FromStr; - use std::time::Duration; + + fn sync_response(file: &str) -> SyncResponse { + let mut file = File::open(file).unwrap(); + let mut data = vec![]; + file.read_to_end(&mut data).unwrap(); + let response = Response::builder().body(data).unwrap(); + SyncResponse::try_from(response).unwrap() + } #[tokio::test] async fn user_presence() { - let homeserver = Url::from_str(&mockito::server_url()).unwrap(); - let session = Session { access_token: "1234".to_owned(), user_id: UserId::try_from("@example:localhost").unwrap(), device_id: "DEVICEID".to_owned(), }; - let _m = mock( - "GET", - Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_string()), - ) - .with_status(200) - .with_body_from_file("../test_data/sync.json") - .create(); + let mut response = sync_response("../test_data/sync.json"); - let client = AsyncClient::new(homeserver, Some(session)).unwrap(); + let client = Client::new(Some(session)).unwrap(); - let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000)); + client.receive_sync_response(&mut response).await.unwrap(); - let _response = client.sync(sync_settings).await.unwrap(); - - let rooms_lock = &client.base_client.joined_rooms(); + let rooms_lock = &client.joined_rooms(); let rooms = rooms_lock.read().await; let room = &rooms .get(&RoomId::try_from("!SVkFJHzfwvuaIEawgC:localhost").unwrap()) @@ -577,7 +609,7 @@ mod test { let room = bld.to_room(); - assert_eq!("tutorial", room.calculate_name()); + assert_eq!("tutorial", room.display_name()); } #[test] @@ -594,7 +626,7 @@ mod test { let room = bld.to_room(); - assert_eq!("tutorial", room.calculate_name()); + assert_eq!("tutorial", room.display_name()); } #[test] @@ -608,35 +640,26 @@ mod test { let room = bld.to_room(); - assert_eq!("room name", room.calculate_name()); + assert_eq!("room name", room.display_name()); } #[tokio::test] async fn calculate_room_names_from_summary() { - let homeserver = Url::from_str(&mockito::server_url()).unwrap(); - - let mut bld = EventBuilder::default().build_with_response( - // this sync has no room.name or room.alias events so only relies on summary - "../test_data/sync_with_summary.json", - "GET", - Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_string()), - ); + let mut response = sync_response("../test_data/sync_with_summary.json"); let session = Session { access_token: "1234".to_owned(), user_id: UserId::try_from("@example:localhost").unwrap(), device_id: "DEVICEID".to_owned(), }; - let client = AsyncClient::new(homeserver, Some(session)).unwrap(); - let client = bld.set_client(client).to_client().await.unwrap(); + let client = Client::new(Some(session)).unwrap(); + client.receive_sync_response(&mut response).await.unwrap(); - let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000)); - let _response = client.sync(sync_settings).await.unwrap(); - - let mut names = vec![]; - for r in client.joined_rooms().read().await.values() { - names.push(r.read().await.calculate_name()); + let mut room_names = vec![]; + for room in client.joined_rooms().read().await.values() { + room_names.push(room.read().await.display_name()) } - assert_eq!(vec!["example, example2"], names); + + assert_eq!(vec!["example, example2"], room_names); } } diff --git a/matrix_sdk/src/models/room_member.rs b/matrix_sdk/src/models/room_member.rs index 611387ed..eca015b4 100644 --- a/matrix_sdk/src/models/room_member.rs +++ b/matrix_sdk/src/models/room_member.rs @@ -28,6 +28,7 @@ use serde::{Deserialize, Serialize}; // Notes: if Alice invites Bob into a room we will get an event with the sender as Alice and the state key as Bob. #[derive(Debug, Serialize, Deserialize)] +#[cfg_attr(test, derive(Clone))] /// A Matrix room member. /// pub struct RoomMember { diff --git a/matrix_sdk/src/state/mod.rs b/matrix_sdk/src/state/mod.rs index bd201cf0..f0d436d8 100644 --- a/matrix_sdk/src/state/mod.rs +++ b/matrix_sdk/src/state/mod.rs @@ -106,6 +106,8 @@ mod test { let mut joined_rooms = HashMap::new(); joined_rooms.insert(id, room); + + #[cfg(not(feature = "messages"))] assert_eq!( r#"{ "!roomid:example.com": { @@ -128,6 +130,34 @@ mod test { "unread_notifications": null, "tombstone": null } +}"#, + serde_json::to_string_pretty(&joined_rooms).unwrap() + ); + + #[cfg(feature = "messages")] + assert_eq!( + r#"{ + "!roomid:example.com": { + "room_id": "!roomid:example.com", + "room_name": { + "name": null, + "canonical_alias": null, + "aliases": [], + "heroes": [], + "joined_member_count": null, + "invited_member_count": null + }, + "own_user_id": "@example:example.com", + "creator": null, + "members": {}, + "messages": [], + "typing_users": [], + "power_levels": null, + "encrypted": false, + "unread_highlight": null, + "unread_notifications": null, + "tombstone": null + } }"#, serde_json::to_string_pretty(&joined_rooms).unwrap() ); diff --git a/matrix_sdk/tests/async_client_tests.rs b/matrix_sdk/tests/async_client_tests.rs index 04f0bf56..4ed373ea 100644 --- a/matrix_sdk/tests/async_client_tests.rs +++ b/matrix_sdk/tests/async_client_tests.rs @@ -83,7 +83,7 @@ async fn room_names() { let mut names = vec![]; for r in client.joined_rooms().read().await.values() { - names.push(r.read().await.calculate_name()); + names.push(r.read().await.display_name()); } assert_eq!(vec!["tutorial"], names); let room = client @@ -91,5 +91,5 @@ async fn room_names() { .await .unwrap(); - assert_eq!("tutorial".to_string(), room.read().await.calculate_name()); + assert_eq!("tutorial".to_string(), room.read().await.display_name()); } diff --git a/matrix_sdk_types/Cargo.toml b/matrix_sdk_common/Cargo.toml similarity index 83% rename from matrix_sdk_types/Cargo.toml rename to matrix_sdk_common/Cargo.toml index 9f3e192f..4dcfbb16 100644 --- a/matrix_sdk_types/Cargo.toml +++ b/matrix_sdk_common/Cargo.toml @@ -1,11 +1,11 @@ [package] authors = ["Damir Jelić DeviceKeys { let user_id = UserId::try_from("@alice:example.org").unwrap(); diff --git a/matrix_sdk_crypto/src/machine.rs b/matrix_sdk_crypto/src/machine.rs index c3e63c60..2c4dcd48 100644 --- a/matrix_sdk_crypto/src/machine.rs +++ b/matrix_sdk_crypto/src/machine.rs @@ -31,8 +31,8 @@ use super::store::memorystore::MemoryStore; use super::store::sqlite::SqliteStore; use super::{device::Device, store::Result as StoreError, CryptoStore}; -use matrix_sdk_types::api; -use matrix_sdk_types::events::{ +use matrix_sdk_common::api; +use matrix_sdk_common::events::{ collections::all::RoomEvent, room::encrypted::{ CiphertextInfo, EncryptedEvent, EncryptedEventContent, MegolmV1AesSha2Content, @@ -45,7 +45,7 @@ use matrix_sdk_types::events::{ }, Algorithm, EventJson, EventType, }; -use matrix_sdk_types::identifiers::{DeviceId, RoomId, UserId}; +use matrix_sdk_common::identifiers::{DeviceId, RoomId, UserId}; use api::r0::keys; use api::r0::{ @@ -1550,7 +1550,7 @@ mod test { static USER_ID: &str = "@bob:example.org"; static DEVICE_ID: &str = "DEVICEID"; - use matrix_sdk_types::js_int::UInt; + use matrix_sdk_common::js_int::UInt; use std::collections::BTreeMap; use std::convert::TryFrom; use std::fs::File; @@ -1564,10 +1564,10 @@ mod test { use crate::machine::{OlmMachine, OneTimeKeys}; use crate::Device; - use matrix_sdk_types::api::r0::{ + use matrix_sdk_common::api::r0::{ keys, to_device::send_event_to_device::Request as ToDeviceRequest, }; - use matrix_sdk_types::events::{ + use matrix_sdk_common::events::{ collections::all::RoomEvent, room::{ encrypted::{EncryptedEvent, EncryptedEventContent}, @@ -1576,7 +1576,7 @@ mod test { to_device::{AnyToDeviceEvent, ToDeviceEncrypted}, EventJson, EventType, UnsignedData, }; - use matrix_sdk_types::identifiers::{DeviceId, EventId, RoomId, UserId}; + use matrix_sdk_common::identifiers::{DeviceId, EventId, RoomId, UserId}; fn alice_id() -> UserId { UserId::try_from("@alice:example.org").unwrap() diff --git a/matrix_sdk_crypto/src/memory_stores.rs b/matrix_sdk_crypto/src/memory_stores.rs index 2dd20511..0735de30 100644 --- a/matrix_sdk_crypto/src/memory_stores.rs +++ b/matrix_sdk_crypto/src/memory_stores.rs @@ -20,7 +20,7 @@ use tokio::sync::Mutex; use super::device::Device; use super::olm::{InboundGroupSession, Session}; -use matrix_sdk_types::identifiers::{DeviceId, RoomId, UserId}; +use matrix_sdk_common::identifiers::{DeviceId, RoomId, UserId}; /// In-memory store for Olm Sessions. #[derive(Debug, Default)] @@ -215,7 +215,7 @@ mod test { use crate::memory_stores::{DeviceStore, GroupSessionStore, SessionStore}; use crate::olm::test::get_account_and_session; use crate::olm::{InboundGroupSession, OutboundGroupSession}; - use matrix_sdk_types::identifiers::RoomId; + use matrix_sdk_common::identifiers::RoomId; #[tokio::test] async fn test_session_store() { diff --git a/matrix_sdk_crypto/src/olm.rs b/matrix_sdk_crypto/src/olm.rs index c6294177..4df9741f 100644 --- a/matrix_sdk_crypto/src/olm.rs +++ b/matrix_sdk_crypto/src/olm.rs @@ -35,8 +35,8 @@ pub use olm_rs::{ utility::OlmUtility, }; -use matrix_sdk_types::api::r0::keys::SignedKey; -use matrix_sdk_types::identifiers::RoomId; +use matrix_sdk_common::api::r0::keys::SignedKey; +use matrix_sdk_common::identifiers::RoomId; /// Account holding identity keys for which sessions can be created. /// @@ -627,8 +627,8 @@ impl std::fmt::Debug for OutboundGroupSession { #[cfg(test)] pub(crate) mod test { use crate::olm::{Account, InboundGroupSession, OutboundGroupSession, Session}; - use matrix_sdk_types::api::r0::keys::SignedKey; - use matrix_sdk_types::identifiers::RoomId; + use matrix_sdk_common::api::r0::keys::SignedKey; + use matrix_sdk_common::identifiers::RoomId; use olm_rs::session::OlmMessage; use std::collections::BTreeMap; use std::convert::TryFrom; diff --git a/matrix_sdk_crypto/src/store/memorystore.rs b/matrix_sdk_crypto/src/store/memorystore.rs index 3cd422c9..0a921b85 100644 --- a/matrix_sdk_crypto/src/store/memorystore.rs +++ b/matrix_sdk_crypto/src/store/memorystore.rs @@ -21,7 +21,7 @@ use tokio::sync::Mutex; use super::{Account, CryptoStore, InboundGroupSession, Result, Session}; use crate::device::Device; use crate::memory_stores::{DeviceStore, GroupSessionStore, SessionStore, UserDevices}; -use matrix_sdk_types::identifiers::{DeviceId, RoomId, UserId}; +use matrix_sdk_common::identifiers::{DeviceId, RoomId, UserId}; #[derive(Debug)] pub struct MemoryStore { @@ -119,7 +119,7 @@ mod test { use crate::olm::{InboundGroupSession, OutboundGroupSession}; use crate::store::memorystore::MemoryStore; use crate::store::CryptoStore; - use matrix_sdk_types::identifiers::RoomId; + use matrix_sdk_common::identifiers::RoomId; #[tokio::test] async fn test_session_store() { diff --git a/matrix_sdk_crypto/src/store/mod.rs b/matrix_sdk_crypto/src/store/mod.rs index 8d2a7655..36d6c4e4 100644 --- a/matrix_sdk_crypto/src/store/mod.rs +++ b/matrix_sdk_crypto/src/store/mod.rs @@ -26,7 +26,7 @@ use tokio::sync::Mutex; use super::device::Device; use super::memory_stores::UserDevices; use super::olm::{Account, InboundGroupSession, Session}; -use matrix_sdk_types::identifiers::{DeviceId, RoomId, UserId}; +use matrix_sdk_common::identifiers::{DeviceId, RoomId, UserId}; use olm_rs::errors::{OlmAccountError, OlmGroupSessionError, OlmSessionError}; pub mod memorystore; diff --git a/matrix_sdk_crypto/src/store/sqlite.rs b/matrix_sdk_crypto/src/store/sqlite.rs index b7d6fc9a..9d824032 100644 --- a/matrix_sdk_crypto/src/store/sqlite.rs +++ b/matrix_sdk_crypto/src/store/sqlite.rs @@ -30,9 +30,9 @@ use zeroize::Zeroizing; use super::{Account, CryptoStore, CryptoStoreError, InboundGroupSession, Result, Session}; use crate::device::{Device, TrustState}; use crate::memory_stores::{DeviceStore, GroupSessionStore, SessionStore, UserDevices}; -use matrix_sdk_types::api::r0::keys::KeyAlgorithm; -use matrix_sdk_types::events::Algorithm; -use matrix_sdk_types::identifiers::{DeviceId, RoomId, UserId}; +use matrix_sdk_common::api::r0::keys::KeyAlgorithm; +use matrix_sdk_common::events::Algorithm; +use matrix_sdk_common::identifiers::{DeviceId, RoomId, UserId}; /// SQLite based implementation of a `CryptoStore`. pub struct SqliteStore { @@ -694,7 +694,7 @@ impl std::fmt::Debug for SqliteStore { mod test { use crate::device::test::get_device; use crate::olm::GroupSessionKey; - use matrix_sdk_types::api::r0::keys::SignedKey; + use matrix_sdk_common::api::r0::keys::SignedKey; use olm_rs::outbound_group_session::OlmOutboundGroupSession; use std::collections::BTreeMap; use tempfile::tempdir;