move matrix_sdk_base::EventHandler to matrix_sdk

This commit is contained in:
Julian Sparber 2021-03-17 11:53:18 +01:00
parent e9dff24ba7
commit 382ec01bc3
9 changed files with 82 additions and 86 deletions

View file

@ -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<MemberEventContent>,
_: Option<MemberEventContent>,
) {
@ -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;

View file

@ -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<MessageEventContent>) {
if let Some(room) = Joined::new(self.client.clone(), room) {
async fn on_room_message(&self, room: Room, event: &SyncMessageEvent<MessageEventContent>) {
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`

View file

@ -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<Mutex<File>>,
}
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<MessageEventContent>) {
if let Some(room) = Joined::new(self.client.clone(), room) {
async fn on_room_message(&self, room: Room, event: &SyncMessageEvent<MessageEventContent>) {
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());

View file

@ -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<MessageEventContent>) {
if room.room_type() == RoomType::Joined {
async fn on_room_message(&self, room: Room, event: &SyncMessageEvent<MessageEventContent>) {
if let Room::Joined(room) = room {
if let SyncMessageEvent {
content:
MessageEventContent {

View file

@ -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<Mutex<()>>,
pub(crate) members_request_locks: Arc<DashMap<RoomId, Arc<Mutex<()>>>>,
pub(crate) typing_notice_times: Arc<DashMap<RoomId, Instant>>,
/// Any implementor of EventHandler will act as the callbacks for various
/// events.
event_handler: Arc<RwLock<Option<Handler>>>,
}
#[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<dyn EventHandler>) {
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.

View file

@ -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<dyn EventHandler>,
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<Room> {
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<MessageEventContent>) {
/// 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!(

View file

@ -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)))]

View file

@ -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<Mutex<Option<Box<dyn CryptoStore>>>>,
store_path: Arc<Option<PathBuf>>,
store_passphrase: Arc<Option<Zeroizing<String>>>,
/// Any implementor of EventHandler will act as the callbacks for various
/// events.
event_handler: Arc<RwLock<Option<Handler>>>,
}
#[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<dyn EventHandler>) {
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)
}

View file

@ -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};