From 382ec01bc3b88427e807ffdfdd7992f67907e999 Mon Sep 17 00:00:00 2001 From: Julian Sparber Date: Wed, 17 Mar 2021 11:53:18 +0100 Subject: [PATCH] move matrix_sdk_base::EventHandler to matrix_sdk --- matrix_sdk/examples/autojoin.rs | 7 +- matrix_sdk/examples/command_bot.rs | 22 +++---- matrix_sdk/examples/image_bot.rs | 15 ++--- matrix_sdk/examples/login.rs | 7 +- matrix_sdk/src/client.rs | 23 +++++-- .../src/event_handler/mod.rs | 65 ++++++++++--------- matrix_sdk/src/lib.rs | 6 +- matrix_sdk_base/src/client.rs | 21 ------ matrix_sdk_base/src/lib.rs | 2 - 9 files changed, 82 insertions(+), 86 deletions(-) rename {matrix_sdk_base => matrix_sdk}/src/event_handler/mod.rs (95%) diff --git a/matrix_sdk/examples/autojoin.rs b/matrix_sdk/examples/autojoin.rs index 7d7e3e56..f3f2ade2 100644 --- a/matrix_sdk/examples/autojoin.rs +++ b/matrix_sdk/examples/autojoin.rs @@ -4,7 +4,8 @@ use tokio::time::{sleep, Duration}; use matrix_sdk::{ self, async_trait, events::{room::member::MemberEventContent, StrippedStateEvent}, - room, BaseRoom, Client, ClientConfig, EventHandler, SyncSettings, + room::Room, + Client, ClientConfig, EventHandler, SyncSettings, }; use url::Url; @@ -22,7 +23,7 @@ impl AutoJoinBot { impl EventHandler for AutoJoinBot { async fn on_stripped_state_member( &self, - room: BaseRoom, + room: Room, room_member: &StrippedStateEvent, _: Option, ) { @@ -30,7 +31,7 @@ impl EventHandler for AutoJoinBot { return; } - if let Some(room) = room::Invited::new(self.client.clone(), room) { + if let Room::Invited(room) = room { println!("Autojoining room {}", room.room_id()); let mut delay = 2; diff --git a/matrix_sdk/examples/command_bot.rs b/matrix_sdk/examples/command_bot.rs index e9a29c93..ca5074c4 100644 --- a/matrix_sdk/examples/command_bot.rs +++ b/matrix_sdk/examples/command_bot.rs @@ -6,27 +6,23 @@ use matrix_sdk::{ room::message::{MessageEventContent, MessageType, TextMessageEventContent}, AnyMessageEventContent, SyncMessageEvent, }, - room::Joined, - BaseRoom, Client, ClientConfig, EventHandler, SyncSettings, + room::Room, + Client, ClientConfig, EventHandler, SyncSettings, }; use url::Url; -struct CommandBot { - /// This clone of the `Client` will send requests to the server, - /// while the other keeps us in sync with the server using `sync`. - client: Client, -} +struct CommandBot; impl CommandBot { - pub fn new(client: Client) -> Self { - Self { client } + pub fn new() -> Self { + Self {} } } #[async_trait] impl EventHandler for CommandBot { - async fn on_room_message(&self, room: BaseRoom, event: &SyncMessageEvent) { - if let Some(room) = Joined::new(self.client.clone(), room) { + async fn on_room_message(&self, room: Room, event: &SyncMessageEvent) { + if let Room::Joined(room) = room { let msg_body = if let SyncMessageEvent { content: MessageEventContent { @@ -85,9 +81,7 @@ async fn login_and_sync( client.sync_once(SyncSettings::default()).await.unwrap(); // add our CommandBot to be notified of incoming messages, we do this after the initial // sync to avoid responding to messages before the bot was running. - client - .set_event_handler(Box::new(CommandBot::new(client.clone()))) - .await; + client.set_event_handler(Box::new(CommandBot::new())).await; // since we called `sync_once` before we entered our sync loop we must pass // that sync token to `sync` diff --git a/matrix_sdk/examples/image_bot.rs b/matrix_sdk/examples/image_bot.rs index 7e3c29fc..6e2cb34c 100644 --- a/matrix_sdk/examples/image_bot.rs +++ b/matrix_sdk/examples/image_bot.rs @@ -14,27 +14,26 @@ use matrix_sdk::{ room::message::{MessageEventContent, MessageType, TextMessageEventContent}, SyncMessageEvent, }, - room::Joined, - BaseRoom, Client, EventHandler, SyncSettings, + room::Room, + Client, EventHandler, SyncSettings, }; use url::Url; struct ImageBot { - client: Client, image: Arc>, } impl ImageBot { - pub fn new(client: Client, image: File) -> Self { + pub fn new(image: File) -> Self { let image = Arc::new(Mutex::new(image)); - Self { client, image } + Self { image } } } #[async_trait] impl EventHandler for ImageBot { - async fn on_room_message(&self, room: BaseRoom, event: &SyncMessageEvent) { - if let Some(room) = Joined::new(self.client.clone(), room) { + async fn on_room_message(&self, room: Room, event: &SyncMessageEvent) { + if let Room::Joined(room) = room { let msg_body = if let SyncMessageEvent { content: MessageEventContent { @@ -80,7 +79,7 @@ async fn login_and_sync( client.sync_once(SyncSettings::default()).await.unwrap(); client - .set_event_handler(Box::new(ImageBot::new(client.clone(), image))) + .set_event_handler(Box::new(ImageBot::new(image))) .await; let settings = SyncSettings::default().token(client.sync_token().await.unwrap()); diff --git a/matrix_sdk/examples/login.rs b/matrix_sdk/examples/login.rs index eadfa5d2..2bb10ac4 100644 --- a/matrix_sdk/examples/login.rs +++ b/matrix_sdk/examples/login.rs @@ -7,15 +7,16 @@ use matrix_sdk::{ room::message::{MessageEventContent, MessageType, TextMessageEventContent}, SyncMessageEvent, }, - BaseRoom, Client, EventHandler, RoomType, SyncSettings, + room::Room, + Client, EventHandler, SyncSettings, }; struct EventCallback; #[async_trait] impl EventHandler for EventCallback { - async fn on_room_message(&self, room: BaseRoom, event: &SyncMessageEvent) { - if room.room_type() == RoomType::Joined { + async fn on_room_message(&self, room: Room, event: &SyncMessageEvent) { + if let Room::Joined(room) = room { if let SyncMessageEvent { content: MessageEventContent { diff --git a/matrix_sdk/src/client.rs b/matrix_sdk/src/client.rs index b56f577f..8f7da8f9 100644 --- a/matrix_sdk/src/client.rs +++ b/matrix_sdk/src/client.rs @@ -40,8 +40,7 @@ use tracing::{debug, warn}; use tracing::{error, info, instrument}; use matrix_sdk_base::{ - deserialized_responses::SyncResponse, BaseClient, BaseClientConfig, EventHandler, Session, - Store, + deserialized_responses::SyncResponse, BaseClient, BaseClientConfig, Session, Store, }; #[cfg(feature = "encryption")] @@ -82,6 +81,7 @@ use matrix_sdk_common::{ assign, identifiers::{DeviceIdBox, EventId, RoomId, RoomIdOrAliasId, ServerName, UserId}, instant::{Duration, Instant}, + locks::RwLock, presence::PresenceState, uuid::Uuid, FromHttpResponseError, UInt, @@ -106,9 +106,11 @@ use crate::{ #[cfg(feature = "encryption")] use crate::{ device::{Device, UserDevices}, + event_handler::Handler, identifiers::DeviceId, sas::Sas, verification_request::VerificationRequest, + EventHandler, }; const DEFAULT_SYNC_TIMEOUT: Duration = Duration::from_secs(30); @@ -139,6 +141,9 @@ pub struct Client { key_claim_lock: Arc>, pub(crate) members_request_locks: Arc>>>, pub(crate) typing_notice_times: Arc>, + /// Any implementor of EventHandler will act as the callbacks for various + /// events. + event_handler: Arc>>, } #[cfg(not(tarpaulin_include))] @@ -396,6 +401,7 @@ impl Client { key_claim_lock: Arc::new(Mutex::new(())), members_request_locks: Arc::new(DashMap::new()), typing_notice_times: Arc::new(DashMap::new()), + event_handler: Arc::new(RwLock::new(None)), }) } @@ -541,7 +547,11 @@ impl Client { /// /// The methods of `EventHandler` are called when the respective `RoomEvents` occur. pub async fn set_event_handler(&self, handler: Box) { - self.base_client.set_event_handler(handler).await; + let handler = Handler { + inner: handler, + client: self.clone(), + }; + *self.event_handler.write().await = Some(handler); } /// Get all the rooms the client knows about. @@ -1180,8 +1190,13 @@ impl Client { + SYNC_REQUEST_TIMEOUT; let response = self.send(request, Some(timeout)).await?; + let sync_response = self.base_client.receive_sync_response(response).await?; - Ok(self.base_client.receive_sync_response(response).await?) + if let Some(handler) = self.event_handler.read().await.as_ref() { + handler.handle_sync(&sync_response).await; + } + + Ok(sync_response) } /// Repeatedly call sync to synchronize the client state with the server. diff --git a/matrix_sdk_base/src/event_handler/mod.rs b/matrix_sdk/src/event_handler/mod.rs similarity index 95% rename from matrix_sdk_base/src/event_handler/mod.rs rename to matrix_sdk/src/event_handler/mod.rs index 3a9db97d..fb2b485d 100644 --- a/matrix_sdk_base/src/event_handler/mod.rs +++ b/matrix_sdk/src/event_handler/mod.rs @@ -47,14 +47,14 @@ use crate::{ AnySyncStateEvent, BasicEvent, StrippedStateEvent, SyncEphemeralRoomEvent, SyncMessageEvent, SyncStateEvent, }, - rooms::Room, - Store, + room::Room, + Client, }; use matrix_sdk_common::async_trait; pub(crate) struct Handler { pub(crate) inner: Box, - pub(crate) store: Store, + pub(crate) client: Client, } impl Deref for Handler { @@ -67,7 +67,7 @@ impl Deref for Handler { impl Handler { fn get_room(&self, room_id: &RoomId) -> Option { - self.store.get_room(room_id) + self.client.get_room(room_id) } pub(crate) async fn handle_sync(&self, response: &SyncResponse) { @@ -270,22 +270,23 @@ pub enum CustomEvent<'c> { /// # use std::ops::Deref; /// # use std::sync::Arc; /// # use std::{env, process::exit}; -/// # use matrix_sdk_base::{ -/// # self, +/// # use matrix_sdk::{ +/// # async_trait, +/// # EventHandler, /// # events::{ /// # room::message::{MessageEventContent, MessageType, TextMessageEventContent}, /// # SyncMessageEvent /// # }, -/// # EventHandler, Room, RoomType, +/// # locks::RwLock, +/// # room::Room, /// # }; -/// # use matrix_sdk_common::{async_trait, locks::RwLock}; /// /// struct EventCallback; /// /// #[async_trait] /// impl EventHandler for EventCallback { /// async fn on_room_message(&self, room: Room, event: &SyncMessageEvent) { -/// if room.room_type() == RoomType::Joined { +/// if let Room::Joined(room) = room { /// if let SyncMessageEvent { /// content: /// MessageEventContent { @@ -458,8 +459,9 @@ pub trait EventHandler: Send + Sync { mod test { use super::*; use matrix_sdk_common::{async_trait, locks::Mutex}; - use matrix_sdk_test::{async_test, sync_response, SyncResponseFile}; - use std::sync::Arc; + use matrix_sdk_test::{async_test, test_json}; + use mockito::{mock, Matcher}; + use std::{sync::Arc, time::Duration}; #[cfg(target_arch = "wasm32")] pub use wasm_bindgen_test::*; @@ -667,19 +669,34 @@ mod test { } } - use crate::{identifiers::user_id, BaseClient, Session}; + use crate::{identifiers::user_id, Client, Session, SyncSettings}; - async fn get_client() -> BaseClient { + async fn get_client() -> Client { let session = Session { access_token: "1234".to_owned(), user_id: user_id!("@example:example.com"), device_id: "DEVICEID".into(), }; - let client = BaseClient::new().unwrap(); + let homeserver = url::Url::parse(&mockito::server_url()).unwrap(); + let client = Client::new(homeserver).unwrap(); client.restore_login(session).await.unwrap(); client } + async fn mock_sync(client: Client, response: String) { + let _m = mock( + "GET", + Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_string()), + ) + .with_status(200) + .match_header("authorization", "Bearer 1234") + .with_body(response) + .create(); + + let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000)); + let _response = client.sync_once(sync_settings).await.unwrap(); + } + #[async_test] async fn event_handler_joined() { let vec = Arc::new(Mutex::new(Vec::new())); @@ -688,9 +705,7 @@ mod test { let client = get_client().await; client.set_event_handler(handler).await; - - let response = sync_response(SyncResponseFile::Default); - client.receive_sync_response(response).await.unwrap(); + mock_sync(client, test_json::SYNC.to_string()).await; let v = test_vec.lock().await; assert_eq!( @@ -720,9 +735,7 @@ mod test { let client = get_client().await; client.set_event_handler(handler).await; - - let response = sync_response(SyncResponseFile::Invite); - client.receive_sync_response(response).await.unwrap(); + mock_sync(client, test_json::INVITE_SYNC.to_string()).await; let v = test_vec.lock().await; assert_eq!( @@ -743,9 +756,7 @@ mod test { let client = get_client().await; client.set_event_handler(handler).await; - - let response = sync_response(SyncResponseFile::Leave); - client.receive_sync_response(response).await.unwrap(); + mock_sync(client, test_json::LEAVE_SYNC.to_string()).await; let v = test_vec.lock().await; assert_eq!( @@ -773,9 +784,7 @@ mod test { let client = get_client().await; client.set_event_handler(handler).await; - - let response = sync_response(SyncResponseFile::All); - client.receive_sync_response(response).await.unwrap(); + mock_sync(client, test_json::MORE_SYNC.to_string()).await; let v = test_vec.lock().await; assert_eq!( @@ -798,9 +807,7 @@ mod test { let client = get_client().await; client.set_event_handler(handler).await; - - let response = sync_response(SyncResponseFile::Voip); - client.receive_sync_response(response).await.unwrap(); + mock_sync(client, test_json::VOIP_SYNC.to_string()).await; let v = test_vec.lock().await; assert_eq!( diff --git a/matrix_sdk/src/lib.rs b/matrix_sdk/src/lib.rs index b8f07b90..467c9eaa 100644 --- a/matrix_sdk/src/lib.rs +++ b/matrix_sdk/src/lib.rs @@ -68,8 +68,8 @@ compile_error!("only one of 'native-tls' or 'rustls-tls' features can be enabled #[cfg_attr(feature = "docs", doc(cfg(encryption)))] pub use matrix_sdk_base::crypto::{EncryptionInfo, LocalTrust}; pub use matrix_sdk_base::{ - CustomEvent, Error as BaseError, EventHandler, Room as BaseRoom, RoomInfo, RoomMember, - RoomType, Session, StateChanges, StoreError, + Error as BaseError, Room as BaseRoom, RoomInfo, RoomMember, RoomType, Session, StateChanges, + StoreError, }; pub use matrix_sdk_common::*; @@ -77,6 +77,7 @@ pub use reqwest; mod client; mod error; +mod event_handler; mod http_client; /// High-level room API pub mod room; @@ -93,6 +94,7 @@ pub use client::{Client, ClientConfig, LoopCtrl, SyncSettings}; #[cfg_attr(feature = "docs", doc(cfg(encryption)))] pub use device::Device; pub use error::{Error, HttpError, Result}; +pub use event_handler::{CustomEvent, EventHandler}; pub use http_client::HttpSend; #[cfg(feature = "encryption")] #[cfg_attr(feature = "docs", doc(cfg(encryption)))] diff --git a/matrix_sdk_base/src/client.rs b/matrix_sdk_base/src/client.rs index a5f5b817..da0726e0 100644 --- a/matrix_sdk_base/src/client.rs +++ b/matrix_sdk_base/src/client.rs @@ -62,11 +62,9 @@ use zeroize::Zeroizing; use crate::{ error::Result, - event_handler::Handler, rooms::{Room, RoomInfo, RoomType}, session::Session, store::{ambiguity_map::AmbiguityCache, Result as StoreResult, StateChanges, Store}, - EventHandler, }; pub type Token = String; @@ -172,9 +170,6 @@ pub struct BaseClient { cryptostore: Arc>>>, store_path: Arc>, store_passphrase: Arc>>, - /// Any implementor of EventHandler will act as the callbacks for various - /// events. - event_handler: Arc>>, } #[cfg(not(tarpaulin_include))] @@ -320,7 +315,6 @@ impl BaseClient { cryptostore: Mutex::new(crypto_store).into(), store_path: config.store_path.into(), store_passphrase: config.passphrase.into(), - event_handler: RwLock::new(None).into(), }) } @@ -419,17 +413,6 @@ impl BaseClient { self.sync_token.read().await.clone() } - /// Add `EventHandler` to `Client`. - /// - /// The methods of `EventHandler` are called when the respective `RoomEvents` occur. - pub async fn set_event_handler(&self, handler: Box) { - let handler = Handler { - inner: handler, - store: self.store.clone(), - }; - *self.event_handler.write().await = Some(handler); - } - async fn handle_timeline( &self, room_id: &RoomId, @@ -934,10 +917,6 @@ impl BaseClient { }, }; - if let Some(handler) = self.event_handler.read().await.as_ref() { - handler.handle_sync(&response).await; - } - Ok(response) } diff --git a/matrix_sdk_base/src/lib.rs b/matrix_sdk_base/src/lib.rs index ef1abffa..25f34d9c 100644 --- a/matrix_sdk_base/src/lib.rs +++ b/matrix_sdk_base/src/lib.rs @@ -46,12 +46,10 @@ pub use matrix_sdk_common::*; mod client; mod error; -mod event_handler; mod rooms; mod session; mod store; -pub use event_handler::{CustomEvent, EventHandler}; pub use rooms::{Room, RoomInfo, RoomMember, RoomType}; pub use store::{StateChanges, StateStore, Store, StoreError};