async_client/event_emitter: use RoomState to differentiate joined, invited and left rooms when emitting

master
Devin R 2020-05-06 19:45:27 -04:00
parent e0400bd4e6
commit 8afac39611
6 changed files with 472 additions and 461 deletions

View File

@ -1,12 +1,10 @@
use std::sync::Arc;
use std::{env, process::exit}; use std::{env, process::exit};
use matrix_sdk::{ use matrix_sdk::{
self, self,
events::room::message::{MessageEvent, MessageEventContent, TextMessageEventContent}, events::room::message::{MessageEvent, MessageEventContent, TextMessageEventContent},
AsyncClient, AsyncClientConfig, EventEmitter, JsonStore, Room, SyncSettings, AsyncClient, AsyncClientConfig, EventEmitter, JsonStore, RoomState, SyncSettings,
}; };
use tokio::sync::RwLock;
use url::Url; use url::Url;
struct CommandBot { struct CommandBot {
@ -23,37 +21,39 @@ impl CommandBot {
#[async_trait::async_trait] #[async_trait::async_trait]
impl EventEmitter for CommandBot { impl EventEmitter for CommandBot {
async fn on_room_message(&self, room: Arc<RwLock<Room>>, event: &MessageEvent) { async fn on_room_message(&self, room: RoomState, event: &MessageEvent) {
let msg_body = if let MessageEvent { if let RoomState::Joined(room) = room {
content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }), let msg_body = if let MessageEvent {
.. content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }),
} = event ..
{ } = event
msg_body.clone() {
} else { msg_body.clone()
String::new() } else {
}; String::new()
};
if msg_body.contains("!party") { if msg_body.contains("!party") {
let content = MessageEventContent::Text(TextMessageEventContent { let content = MessageEventContent::Text(TextMessageEventContent {
body: "🎉🎊🥳 let's PARTY!! 🥳🎊🎉".to_string(), body: "🎉🎊🥳 let's PARTY!! 🥳🎊🎉".to_string(),
format: None, format: None,
formatted_body: None, formatted_body: None,
relates_to: None, relates_to: None,
}); });
// we clone here to hold the lock for as little time as possible. // we clone here to hold the lock for as little time as possible.
let room_id = room.read().await.room_id.clone(); let room_id = room.read().await.room_id.clone();
println!("sending"); println!("sending");
self.client self.client
// send our message to the room we found the "!party" command in // send our message to the room we found the "!party" command in
// the last parameter is an optional Uuid which we don't care about. // the last parameter is an optional Uuid which we don't care about.
.room_send(&room_id, content, None) .room_send(&room_id, content, None)
.await .await
.unwrap(); .unwrap();
println!("message sent"); println!("message sent");
}
} }
} }
} }

View File

@ -1,37 +1,37 @@
use std::sync::Arc;
use std::{env, process::exit}; use std::{env, process::exit};
use url::Url; use url::Url;
use matrix_sdk::{ use matrix_sdk::{
self, self,
events::room::message::{MessageEvent, MessageEventContent, TextMessageEventContent}, events::room::message::{MessageEvent, MessageEventContent, TextMessageEventContent},
AsyncClient, AsyncClientConfig, EventEmitter, Room, SyncSettings, AsyncClient, AsyncClientConfig, EventEmitter, RoomState, SyncSettings,
}; };
use tokio::sync::RwLock;
struct EventCallback; struct EventCallback;
#[async_trait::async_trait] #[async_trait::async_trait]
impl EventEmitter for EventCallback { impl EventEmitter for EventCallback {
async fn on_room_message(&self, room: Arc<RwLock<Room>>, event: &MessageEvent) { async fn on_room_message(&self, room: RoomState, event: &MessageEvent) {
if let MessageEvent { if let RoomState::Joined(room) = room {
content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }), if let MessageEvent {
sender, content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }),
.. sender,
} = event ..
{ } = event
let name = { {
// any reads should be held for the shortest time possible to let name = {
// avoid dead locks // any reads should be held for the shortest time possible to
let room = room.read().await; // avoid dead locks
let member = room.members.get(&sender).unwrap(); let room = room.read().await;
member let member = room.members.get(&sender).unwrap();
.display_name member
.as_ref() .display_name
.map(ToString::to_string) .as_ref()
.unwrap_or(sender.to_string()) .map(ToString::to_string)
}; .unwrap_or(sender.to_string())
println!("{}: {}", name, msg_body); };
println!("{}: {}", name, msg_body);
}
} }
} }
} }

View File

@ -50,7 +50,7 @@ use crate::models::Room;
use crate::session::Session; use crate::session::Session;
use crate::state::StateStore; use crate::state::StateStore;
use crate::VERSION; use crate::VERSION;
use crate::{Error, EventEmitter, Result}; use crate::{Error, EventEmitter, Result, RoomStateType};
const DEFAULT_SYNC_TIMEOUT: Duration = Duration::from_secs(30); const DEFAULT_SYNC_TIMEOUT: Duration = Duration::from_secs(30);
@ -322,6 +322,9 @@ impl AsyncClient {
/// ///
/// This is a human readable room name. /// This is a human readable room name.
pub async fn get_room_name(&self, room_id: &RoomId) -> Option<String> { pub async fn get_room_name(&self, room_id: &RoomId) -> Option<String> {
// TODO do we want to use the `RoomStateType` enum here or should we have
// 3 seperate `room_name` methods. The other option is to remove this and have
// the user get a `Room` and use `Room::calculate_name` method?
self.base_client self.base_client
.read() .read()
.await .await
@ -336,13 +339,27 @@ impl AsyncClient {
self.base_client.read().await.calculate_room_names().await self.base_client.read().await.calculate_room_names().await
} }
/// Returns the rooms this client knows about. /// Returns the joined rooms this client knows about.
/// ///
/// A `HashMap` of room id to `matrix::models::Room` /// A `HashMap` of room id to `matrix::models::Room`
pub async fn get_rooms(&self) -> HashMap<RoomId, Arc<tokio::sync::RwLock<Room>>> { pub async fn get_joined_rooms(&self) -> HashMap<RoomId, Arc<tokio::sync::RwLock<Room>>> {
self.base_client.read().await.joined_rooms.clone() self.base_client.read().await.joined_rooms.clone()
} }
/// Returns the invited rooms this client knows about.
///
/// A `HashMap` of room id to `matrix::models::Room`
pub async fn get_invited_rooms(&self) -> HashMap<RoomId, Arc<tokio::sync::RwLock<Room>>> {
self.base_client.read().await.invited_rooms.clone()
}
/// Returns the left rooms this client knows about.
///
/// A `HashMap` of room id to `matrix::models::Room`
pub async fn get_left_rooms(&self) -> HashMap<RoomId, Arc<tokio::sync::RwLock<Room>>> {
self.base_client.read().await.lefted_rooms.clone()
}
/// This allows `AsyncClient` to manually sync state with the provided `StateStore`. /// This allows `AsyncClient` to manually sync state with the provided `StateStore`.
/// ///
/// Returns true when a successful `StateStore` sync has completed. /// Returns true when a successful `StateStore` sync has completed.
@ -663,13 +680,12 @@ impl AsyncClient {
Ok(response) Ok(response)
} }
#[inline]
async fn iter_joined_rooms(&self, response: &mut sync_events::Response) -> Result<bool> { async fn iter_joined_rooms(&self, response: &mut sync_events::Response) -> Result<bool> {
let mut updated = false; let mut updated = false;
for (room_id, room) in &mut response.rooms.join { for (room_id, joined_room) in &mut response.rooms.join {
let matrix_room = { let matrix_room = {
let mut client = self.base_client.write().await; let mut client = self.base_client.write().await;
for event in &room.state.events { for event in &joined_room.state.events {
if let Ok(e) = event.deserialize() { if let Ok(e) = event.deserialize() {
if client.receive_joined_state_event(&room_id, &e).await { if client.receive_joined_state_event(&room_id, &e).await {
updated = true; updated = true;
@ -677,21 +693,26 @@ impl AsyncClient {
} }
} }
client.get_or_create_room(&room_id).clone() client.get_or_create_joined_room(&room_id).clone()
}; };
// RoomSummary contains information for calculating room name // RoomSummary contains information for calculating room name
matrix_room.write().await.set_room_summary(&room.summary); matrix_room
.write()
.await
.set_room_summary(&joined_room.summary);
// re looping is not ideal here // re looping is not ideal here
for event in &mut room.state.events { for event in &mut joined_room.state.events {
if let Ok(e) = event.deserialize() { if let Ok(e) = event.deserialize() {
let client = self.base_client.read().await; let client = self.base_client.read().await;
client.emit_state_event(&room_id, &e).await; client
.emit_state_event(&room_id, &e, RoomStateType::Joined)
.await;
} }
} }
for mut event in &mut room.timeline.events { for mut event in &mut joined_room.timeline.events {
let decrypted_event = { let decrypted_event = {
let mut client = self.base_client.write().await; let mut client = self.base_client.write().await;
let (decrypt_ev, timeline_update) = client let (decrypt_ev, timeline_update) = client
@ -709,12 +730,14 @@ impl AsyncClient {
if let Ok(e) = event.deserialize() { if let Ok(e) = event.deserialize() {
let client = self.base_client.read().await; let client = self.base_client.read().await;
client.emit_timeline_event(&room_id, &e).await; client
.emit_timeline_event(&room_id, &e, RoomStateType::Joined)
.await;
} }
} }
// look at AccountData to further cut down users by collecting ignored users // look at AccountData to further cut down users by collecting ignored users
if let Some(account_data) = &room.account_data { if let Some(account_data) = &joined_room.account_data {
for account_data in &account_data.events { for account_data in &account_data.events {
{ {
if let Ok(e) = account_data.deserialize() { if let Ok(e) = account_data.deserialize() {
@ -722,7 +745,9 @@ impl AsyncClient {
if client.receive_account_data_event(&room_id, &e).await { if client.receive_account_data_event(&room_id, &e).await {
updated = true; updated = true;
} }
client.emit_account_data_event(room_id, &e).await; client
.emit_account_data_event(room_id, &e, RoomStateType::Joined)
.await;
} }
} }
} }
@ -739,12 +764,14 @@ impl AsyncClient {
updated = true; updated = true;
} }
client.emit_presence_event(&room_id, &e).await; client
.emit_presence_event(&room_id, &e, RoomStateType::Joined)
.await;
} }
} }
} }
for ephemeral in &mut room.ephemeral.events { for ephemeral in &mut joined_room.ephemeral.events {
{ {
if let Ok(e) = ephemeral.deserialize() { if let Ok(e) = ephemeral.deserialize() {
let mut client = self.base_client.write().await; let mut client = self.base_client.write().await;
@ -752,7 +779,9 @@ impl AsyncClient {
updated = true; updated = true;
} }
client.emit_ephemeral_event(&room_id, &e).await; client
.emit_ephemeral_event(&room_id, &e, RoomStateType::Joined)
.await;
} }
} }
} }
@ -768,16 +797,36 @@ impl AsyncClient {
Ok(updated) Ok(updated)
} }
#[inline]
async fn iter_left_rooms(&self, response: &mut sync_events::Response) -> Result<bool> { async fn iter_left_rooms(&self, response: &mut sync_events::Response) -> Result<bool> {
let mut updated = false; let mut updated = false;
for (room_id, left_room) in &mut response.rooms.leave { for (room_id, left_room) in &mut response.rooms.leave {
let matrix_room = {
let mut client = self.base_client.write().await;
for event in &left_room.state.events {
if let Ok(e) = event.deserialize() {
if client.receive_left_state_event(&room_id, &e).await {
updated = true;
}
}
}
client.get_or_create_left_room(&room_id).clone()
};
for event in &mut left_room.state.events {
if let Ok(e) = event.deserialize() {
let client = self.base_client.read().await;
client
.emit_state_event(&room_id, &e, RoomStateType::Left)
.await;
}
}
for mut event in &mut left_room.timeline.events { for mut event in &mut left_room.timeline.events {
let decrypted_event = { let decrypted_event = {
let mut client = self.base_client.write().await; let mut client = self.base_client.write().await;
let (decrypt_ev, timeline_update) = client let (decrypt_ev, timeline_update) = client
.receive_joined_timeline_event(room_id, &mut event) .receive_left_timeline_event(room_id, &mut event)
.await; .await;
if timeline_update { if timeline_update {
updated = true; updated = true;
@ -791,30 +840,23 @@ impl AsyncClient {
if let Ok(e) = event.deserialize() { if let Ok(e) = event.deserialize() {
let client = self.base_client.read().await; let client = self.base_client.read().await;
client.emit_timeline_event(&room_id, &e).await; client
} .emit_timeline_event(&room_id, &e, RoomStateType::Left)
} .await;
// re looping is not ideal here
for event in &mut left_room.state.events {
if let Ok(e) = event.deserialize() {
let client = self.base_client.read().await;
client.emit_state_event(&room_id, &e).await;
} }
} }
if updated { if updated {
if let Some(store) = self.base_client.read().await.state_store.as_ref() { if let Some(store) = self.base_client.read().await.state_store.as_ref() {
let mut client = self.base_client.write().await; store
let room = client.get_or_create_room(&room_id).clone(); .store_room_state(matrix_room.read().await.deref())
store.store_room_state(room.read().await.deref()).await?; .await?;
} }
} }
} }
Ok(updated) Ok(updated)
} }
#[inline]
async fn iter_invited_rooms(&self, response: &sync_events::Response) -> Result<bool> { async fn iter_invited_rooms(&self, response: &sync_events::Response) -> Result<bool> {
let mut updated = false; let mut updated = false;
for (room_id, invited_room) in &response.rooms.invite { for (room_id, invited_room) in &response.rooms.invite {
@ -828,14 +870,15 @@ impl AsyncClient {
} }
} }
client.get_or_create_room(&room_id).clone() client.get_or_create_left_room(&room_id).clone()
}; };
// re looping is not ideal here
for event in &invited_room.invite_state.events { for event in &invited_room.invite_state.events {
if let Ok(e) = event.deserialize() { if let Ok(e) = event.deserialize() {
let client = self.base_client.read().await; let client = self.base_client.read().await;
client.emit_stripped_state_event(&room_id, &e).await; client
.emit_stripped_state_event(&room_id, &e, RoomStateType::Invited)
.await;
} }
} }

View File

@ -58,6 +58,58 @@ use matrix_sdk_crypto::{OlmMachine, OneTimeKeys};
pub type Token = String; pub type Token = String;
/// Signals to the `BaseClient` which `RoomState` to send to `EventEmitter`.
pub enum RoomStateType {
/// Represents a joined room, the `joined_rooms` HashMap will be used.
Joined,
/// Represents a left room, the `left_rooms` HashMap will be used.
Left,
/// Represents an invited room, the `invited_rooms` HashMap will be used.
Invited,
}
/// An enum that represents the state of the given `Room`.
///
/// If the event came from the `join`, `invite` or `leave` rooms map from the server
/// the variant that holds the corresponding room is used.
pub enum RoomState {
/// A room from the `join` section of a sync response.
Joined(Arc<RwLock<Room>>),
/// A room from the `leave` section of a sync response.
Left(Arc<RwLock<Room>>),
/// A room from the `invite` section of a sync response.
Invited(Arc<RwLock<Room>>),
}
macro_rules! emit_event {
($this:ident, $id:ident, $event:ident, $state:ident, $($variant:path => $meth:ident,)*) => {
match &$event {
$($variant(ev) => {
if let Some(ee) = &$this.event_emitter {
match $state {
RoomStateType::Joined => {
if let Some(room) = $this.get_joined_room(&$id) {
ee.$meth(RoomState::Joined(Arc::clone(&room)), &ev).await;
}
}
RoomStateType::Invited => {
if let Some(room) = $this.get_invited_room(&$id) {
ee.$meth(RoomState::Invited(Arc::clone(&room)), &ev).await;
}
}
RoomStateType::Left => {
if let Some(room) = $this.get_left_room(&$id) {
ee.$meth(RoomState::Left(Arc::clone(&room)), &ev).await;
}
}
}
}
})*
_ => {}
}
}
}
/// A no IO Client implementation. /// A no IO Client implementation.
/// ///
/// This Client is a state machine that receives responses and events and /// This Client is a state machine that receives responses and events and
@ -70,6 +122,10 @@ pub struct Client {
pub sync_token: Option<Token>, pub sync_token: Option<Token>,
/// A map of the rooms our user is joined in. /// A map of the rooms our user is joined in.
pub joined_rooms: HashMap<RoomId, Arc<RwLock<Room>>>, pub joined_rooms: HashMap<RoomId, Arc<RwLock<Room>>>,
/// A map of the rooms our user is invited to.
pub invited_rooms: HashMap<RoomId, Arc<RwLock<Room>>>,
/// A map of the rooms our user has left.
pub lefted_rooms: HashMap<RoomId, Arc<RwLock<Room>>>,
/// A list of ignored users. /// A list of ignored users.
pub ignored_users: Vec<UserId>, pub ignored_users: Vec<UserId>,
/// The push ruleset for the logged in user. /// The push ruleset for the logged in user.
@ -120,6 +176,8 @@ impl Client {
session, session,
sync_token: None, sync_token: None,
joined_rooms: HashMap::new(), joined_rooms: HashMap::new(),
invited_rooms: HashMap::new(),
lefted_rooms: HashMap::new(),
ignored_users: Vec::new(), ignored_users: Vec::new(),
push_ruleset: None, push_ruleset: None,
event_emitter: None, event_emitter: None,
@ -224,7 +282,7 @@ impl Client {
res res
} }
pub(crate) fn get_or_create_room(&mut self, room_id: &RoomId) -> &mut Arc<RwLock<Room>> { pub(crate) fn get_or_create_joined_room(&mut self, room_id: &RoomId) -> &mut Arc<RwLock<Room>> {
#[allow(clippy::or_fun_call)] #[allow(clippy::or_fun_call)]
self.joined_rooms self.joined_rooms
.entry(room_id.clone()) .entry(room_id.clone())
@ -238,10 +296,49 @@ impl Client {
)))) ))))
} }
pub(crate) fn get_room(&self, room_id: &RoomId) -> Option<&Arc<RwLock<Room>>> { pub(crate) fn get_joined_room(&self, room_id: &RoomId) -> Option<&Arc<RwLock<Room>>> {
self.joined_rooms.get(room_id) self.joined_rooms.get(room_id)
} }
pub(crate) fn get_or_create_invited_room(
&mut self,
room_id: &RoomId,
) -> &mut Arc<RwLock<Room>> {
#[allow(clippy::or_fun_call)]
self.invited_rooms
.entry(room_id.clone())
.or_insert(Arc::new(RwLock::new(Room::new(
room_id,
&self
.session
.as_ref()
.expect("Receiving events while not being logged in")
.user_id,
))))
}
pub(crate) fn get_invited_room(&self, room_id: &RoomId) -> Option<&Arc<RwLock<Room>>> {
self.invited_rooms.get(room_id)
}
pub(crate) fn get_or_create_left_room(&mut self, room_id: &RoomId) -> &mut Arc<RwLock<Room>> {
#[allow(clippy::or_fun_call)]
self.lefted_rooms
.entry(room_id.clone())
.or_insert(Arc::new(RwLock::new(Room::new(
room_id,
&self
.session
.as_ref()
.expect("Receiving events while not being logged in")
.user_id,
))))
}
pub(crate) fn get_left_room(&self, room_id: &RoomId) -> Option<&Arc<RwLock<Room>>> {
self.lefted_rooms.get(room_id)
}
/// Handle a m.ignored_user_list event, updating the room state if necessary. /// Handle a m.ignored_user_list event, updating the room state if necessary.
/// ///
/// Returns true if the room name changed, false otherwise. /// Returns true if the room name changed, false otherwise.
@ -308,7 +405,7 @@ impl Client {
} }
} }
let mut room = self.get_or_create_room(&room_id).write().await; let mut room = self.get_or_create_joined_room(&room_id).write().await;
(decrypted_event, room.receive_timeline_event(&e)) (decrypted_event, room.receive_timeline_event(&e))
} }
_ => (None, false), _ => (None, false),
@ -317,7 +414,7 @@ impl Client {
/// Receive a state event for a joined room and update the client state. /// Receive a state event for a joined room and update the client state.
/// ///
/// Returns true if the membership list of the room changed, false /// Returns true if the state of the room changed, false
/// otherwise. /// otherwise.
/// ///
/// # Arguments /// # Arguments
@ -330,7 +427,7 @@ impl Client {
room_id: &RoomId, room_id: &RoomId,
event: &StateEvent, event: &StateEvent,
) -> bool { ) -> bool {
let mut room = self.get_or_create_room(room_id).write().await; let mut room = self.get_or_create_joined_room(room_id).write().await;
room.receive_state_event(event) room.receive_state_event(event)
} }
@ -349,13 +446,70 @@ impl Client {
room_id: &RoomId, room_id: &RoomId,
event: &AnyStrippedStateEvent, event: &AnyStrippedStateEvent,
) -> bool { ) -> bool {
let mut room = self.get_or_create_room(room_id).write().await; let mut room = self.get_or_create_invited_room(room_id).write().await;
room.receive_stripped_state_event(event) room.receive_stripped_state_event(event)
} }
/// Receive a timeline event for a room the user has left and update the client state.
///
/// Returns a tuple of the successfully decrypted event, or None on failure and
/// a bool, true when the `Room` state has been updated.
///
/// # Arguments
///
/// * `room_id` - The unique id of the room the event belongs to.
///
/// * `event` - The event that should be handled by the client.
pub async fn receive_left_timeline_event(
&mut self,
room_id: &RoomId,
event: &mut EventJson<RoomEvent>,
) -> (Option<EventJson<RoomEvent>>, bool) {
match event.deserialize() {
#[allow(unused_mut)]
Ok(mut e) => {
#[cfg(feature = "encryption")]
let mut decrypted_event = None;
#[cfg(not(feature = "encryption"))]
let decrypted_event = None;
#[cfg(feature = "encryption")]
{
if let RoomEvent::RoomEncrypted(ref mut e) = e {
e.room_id = Some(room_id.to_owned());
let mut olm = self.olm.lock().await;
if let Some(o) = &mut *olm {
decrypted_event = o.decrypt_room_event(&e).await.ok();
}
}
}
let mut room = self.get_or_create_left_room(&room_id).write().await;
(decrypted_event, room.receive_timeline_event(&e))
}
_ => (None, false),
}
}
/// Receive a state event for a room the user has left and update the client state.
///
/// Returns true if the state of the room changed, false
/// otherwise.
///
/// # Arguments
///
/// * `room_id` - The unique id of the room the event belongs to.
///
/// * `event` - The event that should be handled by the client.
pub async fn receive_left_state_event(&mut self, room_id: &RoomId, event: &StateEvent) -> bool {
let mut room = self.get_or_create_left_room(room_id).write().await;
room.receive_state_event(event)
}
/// Receive a presence event from a sync response and updates the client state. /// Receive a presence event from a sync response and updates the client state.
/// ///
/// Returns true if the membership list of the room changed, false /// Returns true if the state of the room changed, false
/// otherwise. /// otherwise.
/// ///
/// # Arguments /// # Arguments
@ -369,7 +523,7 @@ impl Client {
event: &PresenceEvent, event: &PresenceEvent,
) -> bool { ) -> bool {
// this should be the room that was just created in the `Client::sync` loop. // this should be the room that was just created in the `Client::sync` loop.
if let Some(room) = self.get_room(room_id) { if let Some(room) = self.get_joined_room(room_id) {
let mut room = room.write().await; let mut room = room.write().await;
room.receive_presence_event(event) room.receive_presence_event(event)
} else { } else {
@ -532,7 +686,7 @@ impl Client {
&self, &self,
room_id: &RoomId, room_id: &RoomId,
) -> Result<Vec<send_event_to_device::Request>> { ) -> Result<Vec<send_event_to_device::Request>> {
let room = self.get_room(room_id).expect("No room found"); let room = self.get_joined_room(room_id).expect("No room found");
let mut olm = self.olm.lock().await; let mut olm = self.olm.lock().await;
match &mut *olm { match &mut *olm {
@ -649,288 +803,117 @@ impl Client {
Ok(()) Ok(())
} }
pub(crate) async fn emit_timeline_event(&self, room_id: &RoomId, event: &RoomEvent) { pub(crate) async fn emit_timeline_event(
match event { &self,
RoomEvent::RoomMember(mem) => { room_id: &RoomId,
if let Some(ee) = &self.event_emitter { event: &RoomEvent,
if let Some(room) = self.get_room(&room_id) { room_state: RoomStateType,
ee.on_room_member(Arc::clone(&room), &mem).await; ) {
} emit_event!(
} self, room_id, event, room_state,
} RoomEvent::RoomMember => on_room_member,
RoomEvent::RoomName(name) => { RoomEvent::RoomName => on_room_name,
if let Some(ee) = &self.event_emitter { RoomEvent::RoomCanonicalAlias => on_room_canonical_alias,
if let Some(room) = self.get_room(&room_id) { RoomEvent::RoomAliases => on_room_aliases,
ee.on_room_name(Arc::clone(&room), &name).await; RoomEvent::RoomAvatar => on_room_avatar,
} RoomEvent::RoomMessage => on_room_message,
} RoomEvent::RoomMessageFeedback => on_room_message_feedback,
} RoomEvent::RoomRedaction => on_room_redaction,
RoomEvent::RoomCanonicalAlias(canonical) => { RoomEvent::RoomPowerLevels => on_room_power_levels,
if let Some(ee) = &self.event_emitter { RoomEvent::RoomTombstone => on_room_tombstone,
if let Some(room) = self.get_room(&room_id) { );
ee.on_room_canonical_alias(Arc::clone(&room), &canonical)
.await;
}
}
}
RoomEvent::RoomAliases(aliases) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_room_aliases(Arc::clone(&room), &aliases).await;
}
}
}
RoomEvent::RoomAvatar(avatar) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_room_avatar(Arc::clone(&room), &avatar).await;
}
}
}
RoomEvent::RoomMessage(msg) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_room_message(Arc::clone(&room), &msg).await;
}
}
}
RoomEvent::RoomMessageFeedback(msg_feedback) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_room_message_feedback(Arc::clone(&room), &msg_feedback)
.await;
}
}
}
RoomEvent::RoomRedaction(redaction) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_room_redaction(Arc::clone(&room), &redaction).await;
}
}
}
RoomEvent::RoomPowerLevels(power) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_room_power_levels(Arc::clone(&room), &power).await;
}
}
}
RoomEvent::RoomTombstone(tomb) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_room_tombstone(Arc::clone(&room), &tomb).await;
}
}
}
_ => {}
}
} }
pub(crate) async fn emit_stripped_state_event( pub(crate) async fn emit_stripped_state_event(
&self, &self,
room_id: &RoomId, room_id: &RoomId,
event: &AnyStrippedStateEvent, event: &AnyStrippedStateEvent,
room_state: RoomStateType,
) { ) {
match event { emit_event!(
AnyStrippedStateEvent::RoomMember(member) => { self, room_id, event, room_state,
if let Some(ee) = &self.event_emitter { AnyStrippedStateEvent::RoomMember => on_stripped_state_member,
if let Some(room) = self.get_room(&room_id) { AnyStrippedStateEvent::RoomName => on_stripped_state_name,
ee.on_stripped_state_member(Arc::clone(&room), &member) AnyStrippedStateEvent::RoomCanonicalAlias => on_stripped_state_canonical_alias,
.await; AnyStrippedStateEvent::RoomAliases => on_stripped_state_aliases,
} AnyStrippedStateEvent::RoomAvatar => on_stripped_state_avatar,
} );
}
AnyStrippedStateEvent::RoomName(name) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_stripped_state_name(Arc::clone(&room), &name).await;
}
}
}
AnyStrippedStateEvent::RoomCanonicalAlias(canonical) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_stripped_state_canonical_alias(Arc::clone(&room), &canonical)
.await;
}
}
}
AnyStrippedStateEvent::RoomAliases(aliases) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_stripped_state_aliases(Arc::clone(&room), &aliases)
.await;
}
}
}
AnyStrippedStateEvent::RoomAvatar(avatar) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_stripped_state_avatar(Arc::clone(&room), &avatar)
.await;
}
}
}
AnyStrippedStateEvent::RoomPowerLevels(power) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_stripped_state_power_levels(Arc::clone(&room), &power)
.await;
}
}
}
AnyStrippedStateEvent::RoomJoinRules(rules) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_stripped_state_join_rules(Arc::clone(&room), &rules)
.await;
}
}
}
_ => {}
}
} }
pub(crate) async fn emit_state_event(&self, room_id: &RoomId, event: &StateEvent) { pub(crate) async fn emit_state_event(
match event { &self,
StateEvent::RoomMember(member) => { room_id: &RoomId,
if let Some(ee) = &self.event_emitter { event: &StateEvent,
if let Some(room) = self.get_room(&room_id) { room_state: RoomStateType,
ee.on_state_member(Arc::clone(&room), &member).await; ) {
} emit_event!(
} self, room_id, event, room_state,
} StateEvent::RoomMember => on_state_member,
StateEvent::RoomName(name) => { StateEvent::RoomName => on_state_name,
if let Some(ee) = &self.event_emitter { StateEvent::RoomCanonicalAlias => on_state_canonical_alias,
if let Some(room) = self.get_room(&room_id) { StateEvent::RoomAliases => on_state_aliases,
ee.on_state_name(Arc::clone(&room), &name).await; StateEvent::RoomAvatar => on_state_avatar,
} StateEvent::RoomPowerLevels => on_state_power_levels,
} StateEvent::RoomTombstone => on_room_tombstone,
} );
StateEvent::RoomCanonicalAlias(canonical) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_state_canonical_alias(Arc::clone(&room), &canonical)
.await;
}
}
}
StateEvent::RoomAliases(aliases) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_state_aliases(Arc::clone(&room), &aliases).await;
}
}
}
StateEvent::RoomAvatar(avatar) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_state_avatar(Arc::clone(&room), &avatar).await;
}
}
}
StateEvent::RoomPowerLevels(power) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_state_power_levels(Arc::clone(&room), &power).await;
}
}
}
StateEvent::RoomJoinRules(rules) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_state_join_rules(Arc::clone(&room), &rules).await;
}
}
}
StateEvent::RoomTombstone(tomb) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_room_tombstone(Arc::clone(&room), &tomb).await;
}
}
}
_ => {}
}
} }
pub(crate) async fn emit_account_data_event(&self, room_id: &RoomId, event: &NonRoomEvent) { pub(crate) async fn emit_account_data_event(
match event { &self,
NonRoomEvent::Presence(presence) => { room_id: &RoomId,
if let Some(ee) = &self.event_emitter { event: &NonRoomEvent,
if let Some(room) = self.get_room(&room_id) { room_state: RoomStateType,
ee.on_account_presence(Arc::clone(&room), &presence).await; ) {
} emit_event!(
} self, room_id, event, room_state,
} NonRoomEvent::Presence => on_account_presence,
NonRoomEvent::IgnoredUserList(ignored) => { NonRoomEvent::IgnoredUserList => on_account_ignored_users,
if let Some(ee) = &self.event_emitter { NonRoomEvent::PushRules => on_account_push_rules,
if let Some(room) = self.get_room(&room_id) { NonRoomEvent::FullyRead => on_account_data_fully_read,
ee.on_account_ignored_users(Arc::clone(&room), &ignored) );
.await;
}
}
}
NonRoomEvent::PushRules(rules) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_account_push_rules(Arc::clone(&room), &rules).await;
}
}
}
NonRoomEvent::FullyRead(full_read) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_account_data_fully_read(Arc::clone(&room), &full_read)
.await;
}
}
}
_ => {}
}
} }
pub(crate) async fn emit_ephemeral_event(&self, room_id: &RoomId, event: &NonRoomEvent) { pub(crate) async fn emit_ephemeral_event(
match event { &self,
NonRoomEvent::Presence(presence) => { room_id: &RoomId,
if let Some(ee) = &self.event_emitter { event: &NonRoomEvent,
if let Some(room) = self.get_room(&room_id) { room_state: RoomStateType,
ee.on_account_presence(Arc::clone(&room), &presence).await; ) {
} emit_event!(
} self, room_id, event, room_state,
} NonRoomEvent::Presence => on_account_presence,
NonRoomEvent::IgnoredUserList(ignored) => { NonRoomEvent::IgnoredUserList => on_account_ignored_users,
if let Some(ee) = &self.event_emitter { NonRoomEvent::PushRules => on_account_push_rules,
if let Some(room) = self.get_room(&room_id) { NonRoomEvent::FullyRead => on_account_data_fully_read,
ee.on_account_ignored_users(Arc::clone(&room), &ignored) );
.await;
}
}
}
NonRoomEvent::PushRules(rules) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_account_push_rules(Arc::clone(&room), &rules).await;
}
}
}
NonRoomEvent::FullyRead(full_read) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_account_data_fully_read(Arc::clone(&room), &full_read)
.await;
}
}
}
_ => {}
}
} }
pub(crate) async fn emit_presence_event(&self, room_id: &RoomId, event: &PresenceEvent) { pub(crate) async fn emit_presence_event(
&self,
room_id: &RoomId,
event: &PresenceEvent,
room_state: RoomStateType,
) {
if let Some(ee) = &self.event_emitter { if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) { match room_state {
ee.on_presence_event(Arc::clone(&room), &event).await; RoomStateType::Invited => {
if let Some(room) = self.get_invited_room(&room_id) {
ee.on_presence_event(RoomState::Invited(Arc::clone(&room)), &event)
.await;
}
}
RoomStateType::Joined => {
if let Some(room) = self.get_joined_room(&room_id) {
ee.on_presence_event(RoomState::Joined(Arc::clone(&room)), &event)
.await;
}
}
RoomStateType::Left => {
if let Some(room) = self.get_left_room(&room_id) {
ee.on_presence_event(RoomState::Left(Arc::clone(&room)), &event)
.await;
}
}
} }
} }
} }

View File

@ -12,7 +12,6 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::sync::Arc;
use crate::events::{ use crate::events::{
fully_read::FullyReadEvent, fully_read::FullyReadEvent,
@ -36,8 +35,7 @@ use crate::events::{
StrippedRoomMember, StrippedRoomName, StrippedRoomPowerLevels, StrippedRoomMember, StrippedRoomName, StrippedRoomPowerLevels,
}, },
}; };
use crate::models::Room; use crate::RoomState;
use tokio::sync::RwLock;
/// This trait allows any type implementing `EventEmitter` to specify event callbacks for each event. /// This trait allows any type implementing `EventEmitter` to specify event callbacks for each event.
/// The `AsyncClient` calls each method when the corresponding event is received. /// The `AsyncClient` calls each method when the corresponding event is received.
@ -53,7 +51,7 @@ use tokio::sync::RwLock;
/// events::{ /// events::{
/// room::message::{MessageEvent, MessageEventContent, TextMessageEventContent}, /// room::message::{MessageEvent, MessageEventContent, TextMessageEventContent},
/// }, /// },
/// AsyncClient, AsyncClientConfig, EventEmitter, Room, SyncSettings, /// AsyncClient, AsyncClientConfig, EventEmitter, RoomState, SyncSettings,
/// }; /// };
/// use tokio::sync::RwLock; /// use tokio::sync::RwLock;
/// ///
@ -61,23 +59,25 @@ use tokio::sync::RwLock;
/// ///
/// #[async_trait::async_trait] /// #[async_trait::async_trait]
/// impl EventEmitter for EventCallback { /// impl EventEmitter for EventCallback {
/// async fn on_room_message(&self, room: Arc<RwLock<Room>>, event: &MessageEvent) { /// async fn on_room_message(&self, room: RoomState, event: &MessageEvent) {
/// if let MessageEvent { /// if let RoomState::Joined(room) = room {
/// content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }), /// if let MessageEvent {
/// sender, /// content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }),
/// .. /// sender,
/// } = event /// ..
/// { /// } = event
/// let name = { /// {
/// let room = room.read().await; /// let name = {
/// let member = room.members.get(&sender).unwrap(); /// let room = room.read().await;
/// member /// let member = room.members.get(&sender).unwrap();
/// .display_name /// member
/// .as_ref() /// .display_name
/// .map(ToString::to_string) /// .as_ref()
/// .unwrap_or(sender.to_string()) /// .map(ToString::to_string)
/// }; /// .unwrap_or(sender.to_string())
/// println!("{}: {}", name, msg_body); /// };
/// println!("{}: {}", name, msg_body);
/// }
/// } /// }
/// } /// }
/// } /// }
@ -86,81 +86,76 @@ use tokio::sync::RwLock;
pub trait EventEmitter: Send + Sync { pub trait EventEmitter: Send + Sync {
// ROOM EVENTS from `IncomingTimeline` // ROOM EVENTS from `IncomingTimeline`
/// Fires when `AsyncClient` receives a `RoomEvent::RoomMember` event. /// Fires when `AsyncClient` receives a `RoomEvent::RoomMember` event.
async fn on_room_member(&self, _: Arc<RwLock<Room>>, _: &MemberEvent) {} async fn on_room_member(&self, _: RoomState, _: &MemberEvent) {}
/// Fires when `AsyncClient` receives a `RoomEvent::RoomName` event. /// Fires when `AsyncClient` receives a `RoomEvent::RoomName` event.
async fn on_room_name(&self, _: Arc<RwLock<Room>>, _: &NameEvent) {} async fn on_room_name(&self, _: RoomState, _: &NameEvent) {}
/// Fires when `AsyncClient` receives a `RoomEvent::RoomCanonicalAlias` event. /// Fires when `AsyncClient` receives a `RoomEvent::RoomCanonicalAlias` event.
async fn on_room_canonical_alias(&self, _: Arc<RwLock<Room>>, _: &CanonicalAliasEvent) {} async fn on_room_canonical_alias(&self, _: RoomState, _: &CanonicalAliasEvent) {}
/// Fires when `AsyncClient` receives a `RoomEvent::RoomAliases` event. /// Fires when `AsyncClient` receives a `RoomEvent::RoomAliases` event.
async fn on_room_aliases(&self, _: Arc<RwLock<Room>>, _: &AliasesEvent) {} async fn on_room_aliases(&self, _: RoomState, _: &AliasesEvent) {}
/// Fires when `AsyncClient` receives a `RoomEvent::RoomAvatar` event. /// Fires when `AsyncClient` receives a `RoomEvent::RoomAvatar` event.
async fn on_room_avatar(&self, _: Arc<RwLock<Room>>, _: &AvatarEvent) {} async fn on_room_avatar(&self, _: RoomState, _: &AvatarEvent) {}
/// Fires when `AsyncClient` receives a `RoomEvent::RoomMessage` event. /// Fires when `AsyncClient` receives a `RoomEvent::RoomMessage` event.
async fn on_room_message(&self, _: Arc<RwLock<Room>>, _: &MessageEvent) {} async fn on_room_message(&self, _: RoomState, _: &MessageEvent) {}
/// Fires when `AsyncClient` receives a `RoomEvent::RoomMessageFeedback` event. /// Fires when `AsyncClient` receives a `RoomEvent::RoomMessageFeedback` event.
async fn on_room_message_feedback(&self, _: Arc<RwLock<Room>>, _: &FeedbackEvent) {} async fn on_room_message_feedback(&self, _: RoomState, _: &FeedbackEvent) {}
/// Fires when `AsyncClient` receives a `RoomEvent::RoomRedaction` event. /// Fires when `AsyncClient` receives a `RoomEvent::RoomRedaction` event.
async fn on_room_redaction(&self, _: Arc<RwLock<Room>>, _: &RedactionEvent) {} async fn on_room_redaction(&self, _: RoomState, _: &RedactionEvent) {}
/// Fires when `AsyncClient` receives a `RoomEvent::RoomPowerLevels` event. /// Fires when `AsyncClient` receives a `RoomEvent::RoomPowerLevels` event.
async fn on_room_power_levels(&self, _: Arc<RwLock<Room>>, _: &PowerLevelsEvent) {} async fn on_room_power_levels(&self, _: RoomState, _: &PowerLevelsEvent) {}
/// Fires when `AsyncClient` receives a `RoomEvent::Tombstone` event. /// Fires when `AsyncClient` receives a `RoomEvent::Tombstone` event.
async fn on_room_tombstone(&self, _: Arc<RwLock<Room>>, _: &TombstoneEvent) {} async fn on_room_tombstone(&self, _: RoomState, _: &TombstoneEvent) {}
// `RoomEvent`s from `IncomingState` // `RoomEvent`s from `IncomingState`
/// Fires when `AsyncClient` receives a `StateEvent::RoomMember` event. /// Fires when `AsyncClient` receives a `StateEvent::RoomMember` event.
async fn on_state_member(&self, _: Arc<RwLock<Room>>, _: &MemberEvent) {} async fn on_state_member(&self, _: RoomState, _: &MemberEvent) {}
/// Fires when `AsyncClient` receives a `StateEvent::RoomName` event. /// Fires when `AsyncClient` receives a `StateEvent::RoomName` event.
async fn on_state_name(&self, _: Arc<RwLock<Room>>, _: &NameEvent) {} async fn on_state_name(&self, _: RoomState, _: &NameEvent) {}
/// Fires when `AsyncClient` receives a `StateEvent::RoomCanonicalAlias` event. /// Fires when `AsyncClient` receives a `StateEvent::RoomCanonicalAlias` event.
async fn on_state_canonical_alias(&self, _: Arc<RwLock<Room>>, _: &CanonicalAliasEvent) {} async fn on_state_canonical_alias(&self, _: RoomState, _: &CanonicalAliasEvent) {}
/// Fires when `AsyncClient` receives a `StateEvent::RoomAliases` event. /// Fires when `AsyncClient` receives a `StateEvent::RoomAliases` event.
async fn on_state_aliases(&self, _: Arc<RwLock<Room>>, _: &AliasesEvent) {} async fn on_state_aliases(&self, _: RoomState, _: &AliasesEvent) {}
/// Fires when `AsyncClient` receives a `StateEvent::RoomAvatar` event. /// Fires when `AsyncClient` receives a `StateEvent::RoomAvatar` event.
async fn on_state_avatar(&self, _: Arc<RwLock<Room>>, _: &AvatarEvent) {} async fn on_state_avatar(&self, _: RoomState, _: &AvatarEvent) {}
/// Fires when `AsyncClient` receives a `StateEvent::RoomPowerLevels` event. /// Fires when `AsyncClient` receives a `StateEvent::RoomPowerLevels` event.
async fn on_state_power_levels(&self, _: Arc<RwLock<Room>>, _: &PowerLevelsEvent) {} async fn on_state_power_levels(&self, _: RoomState, _: &PowerLevelsEvent) {}
/// Fires when `AsyncClient` receives a `StateEvent::RoomJoinRules` event. /// Fires when `AsyncClient` receives a `StateEvent::RoomJoinRules` event.
async fn on_state_join_rules(&self, _: Arc<RwLock<Room>>, _: &JoinRulesEvent) {} async fn on_state_join_rules(&self, _: RoomState, _: &JoinRulesEvent) {}
// `AnyStrippedStateEvent`s // `AnyStrippedStateEvent`s
/// Fires when `AsyncClient` receives a `AnyStrippedStateEvent::StrippedRoomMember` event. /// Fires when `AsyncClient` receives a `AnyStrippedStateEvent::StrippedRoomMember` event.
async fn on_stripped_state_member(&self, _: Arc<RwLock<Room>>, _: &StrippedRoomMember) {} async fn on_stripped_state_member(&self, _: RoomState, _: &StrippedRoomMember) {}
/// Fires when `AsyncClient` receives a `AnyStrippedStateEvent::StrippedRoomName` event. /// Fires when `AsyncClient` receives a `AnyStrippedStateEvent::StrippedRoomName` event.
async fn on_stripped_state_name(&self, _: Arc<RwLock<Room>>, _: &StrippedRoomName) {} async fn on_stripped_state_name(&self, _: RoomState, _: &StrippedRoomName) {}
/// Fires when `AsyncClient` receives a `AnyStrippedStateEvent::StrippedRoomCanonicalAlias` event. /// Fires when `AsyncClient` receives a `AnyStrippedStateEvent::StrippedRoomCanonicalAlias` event.
async fn on_stripped_state_canonical_alias( async fn on_stripped_state_canonical_alias(
&self, &self,
_: Arc<RwLock<Room>>, _: RoomState,
_: &StrippedRoomCanonicalAlias, _: &StrippedRoomCanonicalAlias,
) { ) {
} }
/// Fires when `AsyncClient` receives a `AnyStrippedStateEvent::StrippedRoomAliases` event. /// Fires when `AsyncClient` receives a `AnyStrippedStateEvent::StrippedRoomAliases` event.
async fn on_stripped_state_aliases(&self, _: Arc<RwLock<Room>>, _: &StrippedRoomAliases) {} async fn on_stripped_state_aliases(&self, _: RoomState, _: &StrippedRoomAliases) {}
/// Fires when `AsyncClient` receives a `AnyStrippedStateEvent::StrippedRoomAvatar` event. /// Fires when `AsyncClient` receives a `AnyStrippedStateEvent::StrippedRoomAvatar` event.
async fn on_stripped_state_avatar(&self, _: Arc<RwLock<Room>>, _: &StrippedRoomAvatar) {} async fn on_stripped_state_avatar(&self, _: RoomState, _: &StrippedRoomAvatar) {}
/// Fires when `AsyncClient` receives a `AnyStrippedStateEvent::StrippedRoomPowerLevels` event. /// Fires when `AsyncClient` receives a `AnyStrippedStateEvent::StrippedRoomPowerLevels` event.
async fn on_stripped_state_power_levels( async fn on_stripped_state_power_levels(&self, _: RoomState, _: &StrippedRoomPowerLevels) {}
&self,
_: Arc<RwLock<Room>>,
_: &StrippedRoomPowerLevels,
) {
}
/// Fires when `AsyncClient` receives a `AnyStrippedStateEvent::StrippedRoomJoinRules` event. /// Fires when `AsyncClient` receives a `AnyStrippedStateEvent::StrippedRoomJoinRules` event.
async fn on_stripped_state_join_rules(&self, _: Arc<RwLock<Room>>, _: &StrippedRoomJoinRules) {} async fn on_stripped_state_join_rules(&self, _: RoomState, _: &StrippedRoomJoinRules) {}
// `NonRoomEvent` (this is a type alias from ruma_events) from `IncomingAccountData` // `NonRoomEvent` (this is a type alias from ruma_events) from `IncomingAccountData`
/// Fires when `AsyncClient` receives a `NonRoomEvent::RoomMember` event. /// Fires when `AsyncClient` receives a `NonRoomEvent::RoomMember` event.
async fn on_account_presence(&self, _: Arc<RwLock<Room>>, _: &PresenceEvent) {} async fn on_account_presence(&self, _: RoomState, _: &PresenceEvent) {}
/// Fires when `AsyncClient` receives a `NonRoomEvent::RoomName` event. /// Fires when `AsyncClient` receives a `NonRoomEvent::RoomName` event.
async fn on_account_ignored_users(&self, _: Arc<RwLock<Room>>, _: &IgnoredUserListEvent) {} async fn on_account_ignored_users(&self, _: RoomState, _: &IgnoredUserListEvent) {}
/// Fires when `AsyncClient` receives a `NonRoomEvent::RoomCanonicalAlias` event. /// Fires when `AsyncClient` receives a `NonRoomEvent::RoomCanonicalAlias` event.
async fn on_account_push_rules(&self, _: Arc<RwLock<Room>>, _: &PushRulesEvent) {} async fn on_account_push_rules(&self, _: RoomState, _: &PushRulesEvent) {}
/// Fires when `AsyncClient` receives a `NonRoomEvent::RoomAliases` event. /// Fires when `AsyncClient` receives a `NonRoomEvent::RoomAliases` event.
async fn on_account_data_fully_read(&self, _: Arc<RwLock<Room>>, _: &FullyReadEvent) {} async fn on_account_data_fully_read(&self, _: RoomState, _: &FullyReadEvent) {}
// `PresenceEvent` is a struct so there is only the one method // `PresenceEvent` is a struct so there is only the one method
/// Fires when `AsyncClient` receives a `NonRoomEvent::RoomAliases` event. /// Fires when `AsyncClient` receives a `NonRoomEvent::RoomAliases` event.
async fn on_presence_event(&self, _: Arc<RwLock<Room>>, _: &PresenceEvent) {} async fn on_presence_event(&self, _: RoomState, _: &PresenceEvent) {}
} }
#[cfg(test)] #[cfg(test)]
@ -173,71 +168,71 @@ mod test {
#[async_trait::async_trait] #[async_trait::async_trait]
impl EventEmitter for EvEmitterTest { impl EventEmitter for EvEmitterTest {
async fn on_room_member(&self, _: Arc<RwLock<Room>>, _: &MemberEvent) { async fn on_room_member(&self, _: RoomState, _: &MemberEvent) {
self.0.lock().await.push("member".to_string()) self.0.lock().await.push("member".to_string())
} }
async fn on_room_name(&self, _: Arc<RwLock<Room>>, _: &NameEvent) { async fn on_room_name(&self, _: RoomState, _: &NameEvent) {
self.0.lock().await.push("name".to_string()) self.0.lock().await.push("name".to_string())
} }
async fn on_room_canonical_alias(&self, _: Arc<RwLock<Room>>, _: &CanonicalAliasEvent) { async fn on_room_canonical_alias(&self, _: RoomState, _: &CanonicalAliasEvent) {
self.0.lock().await.push("canonical".to_string()) self.0.lock().await.push("canonical".to_string())
} }
async fn on_room_aliases(&self, _: Arc<RwLock<Room>>, _: &AliasesEvent) { async fn on_room_aliases(&self, _: RoomState, _: &AliasesEvent) {
self.0.lock().await.push("aliases".to_string()) self.0.lock().await.push("aliases".to_string())
} }
async fn on_room_avatar(&self, _: Arc<RwLock<Room>>, _: &AvatarEvent) { async fn on_room_avatar(&self, _: RoomState, _: &AvatarEvent) {
self.0.lock().await.push("avatar".to_string()) self.0.lock().await.push("avatar".to_string())
} }
async fn on_room_message(&self, _: Arc<RwLock<Room>>, _: &MessageEvent) { async fn on_room_message(&self, _: RoomState, _: &MessageEvent) {
self.0.lock().await.push("message".to_string()) self.0.lock().await.push("message".to_string())
} }
async fn on_room_message_feedback(&self, _: Arc<RwLock<Room>>, _: &FeedbackEvent) { async fn on_room_message_feedback(&self, _: RoomState, _: &FeedbackEvent) {
self.0.lock().await.push("feedback".to_string()) self.0.lock().await.push("feedback".to_string())
} }
async fn on_room_redaction(&self, _: Arc<RwLock<Room>>, _: &RedactionEvent) { async fn on_room_redaction(&self, _: RoomState, _: &RedactionEvent) {
self.0.lock().await.push("redaction".to_string()) self.0.lock().await.push("redaction".to_string())
} }
async fn on_room_power_levels(&self, _: Arc<RwLock<Room>>, _: &PowerLevelsEvent) { async fn on_room_power_levels(&self, _: RoomState, _: &PowerLevelsEvent) {
self.0.lock().await.push("power".to_string()) self.0.lock().await.push("power".to_string())
} }
async fn on_room_tombstone(&self, _: Arc<RwLock<Room>>, _: &TombstoneEvent) { async fn on_room_tombstone(&self, _: RoomState, _: &TombstoneEvent) {
self.0.lock().await.push("tombstone".to_string()) self.0.lock().await.push("tombstone".to_string())
} }
async fn on_state_member(&self, _: Arc<RwLock<Room>>, _: &MemberEvent) { async fn on_state_member(&self, _: RoomState, _: &MemberEvent) {
self.0.lock().await.push("state member".to_string()) self.0.lock().await.push("state member".to_string())
} }
async fn on_state_name(&self, _: Arc<RwLock<Room>>, _: &NameEvent) { async fn on_state_name(&self, _: RoomState, _: &NameEvent) {
self.0.lock().await.push("state name".to_string()) self.0.lock().await.push("state name".to_string())
} }
async fn on_state_canonical_alias(&self, _: Arc<RwLock<Room>>, _: &CanonicalAliasEvent) { async fn on_state_canonical_alias(&self, _: RoomState, _: &CanonicalAliasEvent) {
self.0.lock().await.push("state canonical".to_string()) self.0.lock().await.push("state canonical".to_string())
} }
async fn on_state_aliases(&self, _: Arc<RwLock<Room>>, _: &AliasesEvent) { async fn on_state_aliases(&self, _: RoomState, _: &AliasesEvent) {
self.0.lock().await.push("state aliases".to_string()) self.0.lock().await.push("state aliases".to_string())
} }
async fn on_state_avatar(&self, _: Arc<RwLock<Room>>, _: &AvatarEvent) { async fn on_state_avatar(&self, _: RoomState, _: &AvatarEvent) {
self.0.lock().await.push("state avatar".to_string()) self.0.lock().await.push("state avatar".to_string())
} }
async fn on_state_power_levels(&self, _: Arc<RwLock<Room>>, _: &PowerLevelsEvent) { async fn on_state_power_levels(&self, _: RoomState, _: &PowerLevelsEvent) {
self.0.lock().await.push("state power".to_string()) self.0.lock().await.push("state power".to_string())
} }
async fn on_state_join_rules(&self, _: Arc<RwLock<Room>>, _: &JoinRulesEvent) { async fn on_state_join_rules(&self, _: RoomState, _: &JoinRulesEvent) {
self.0.lock().await.push("state rules".to_string()) self.0.lock().await.push("state rules".to_string())
} }
async fn on_stripped_state_member(&self, _: Arc<RwLock<Room>>, _: &StrippedRoomMember) { async fn on_stripped_state_member(&self, _: RoomState, _: &StrippedRoomMember) {
self.0 self.0
.lock() .lock()
.await .await
.push("stripped state member".to_string()) .push("stripped state member".to_string())
} }
async fn on_stripped_state_name(&self, _: Arc<RwLock<Room>>, _: &StrippedRoomName) { async fn on_stripped_state_name(&self, _: RoomState, _: &StrippedRoomName) {
self.0.lock().await.push("stripped state name".to_string()) self.0.lock().await.push("stripped state name".to_string())
} }
async fn on_stripped_state_canonical_alias( async fn on_stripped_state_canonical_alias(
&self, &self,
_: Arc<RwLock<Room>>, _: RoomState,
_: &StrippedRoomCanonicalAlias, _: &StrippedRoomCanonicalAlias,
) { ) {
self.0 self.0
@ -245,46 +240,38 @@ mod test {
.await .await
.push("stripped state canonical".to_string()) .push("stripped state canonical".to_string())
} }
async fn on_stripped_state_aliases(&self, _: Arc<RwLock<Room>>, _: &StrippedRoomAliases) { async fn on_stripped_state_aliases(&self, _: RoomState, _: &StrippedRoomAliases) {
self.0 self.0
.lock() .lock()
.await .await
.push("stripped state aliases".to_string()) .push("stripped state aliases".to_string())
} }
async fn on_stripped_state_avatar(&self, _: Arc<RwLock<Room>>, _: &StrippedRoomAvatar) { async fn on_stripped_state_avatar(&self, _: RoomState, _: &StrippedRoomAvatar) {
self.0 self.0
.lock() .lock()
.await .await
.push("stripped state avatar".to_string()) .push("stripped state avatar".to_string())
} }
async fn on_stripped_state_power_levels( async fn on_stripped_state_power_levels(&self, _: RoomState, _: &StrippedRoomPowerLevels) {
&self,
_: Arc<RwLock<Room>>,
_: &StrippedRoomPowerLevels,
) {
self.0.lock().await.push("stripped state power".to_string()) self.0.lock().await.push("stripped state power".to_string())
} }
async fn on_stripped_state_join_rules( async fn on_stripped_state_join_rules(&self, _: RoomState, _: &StrippedRoomJoinRules) {
&self,
_: Arc<RwLock<Room>>,
_: &StrippedRoomJoinRules,
) {
self.0.lock().await.push("stripped state rules".to_string()) self.0.lock().await.push("stripped state rules".to_string())
} }
async fn on_account_presence(&self, _: Arc<RwLock<Room>>, _: &PresenceEvent) { async fn on_account_presence(&self, _: RoomState, _: &PresenceEvent) {
self.0.lock().await.push("account presence".to_string()) self.0.lock().await.push("account presence".to_string())
} }
async fn on_account_ignored_users(&self, _: Arc<RwLock<Room>>, _: &IgnoredUserListEvent) { async fn on_account_ignored_users(&self, _: RoomState, _: &IgnoredUserListEvent) {
self.0.lock().await.push("account ignore".to_string()) self.0.lock().await.push("account ignore".to_string())
} }
async fn on_account_push_rules(&self, _: Arc<RwLock<Room>>, _: &PushRulesEvent) { async fn on_account_push_rules(&self, _: RoomState, _: &PushRulesEvent) {
self.0.lock().await.push("".to_string()) self.0.lock().await.push("".to_string())
} }
async fn on_account_data_fully_read(&self, _: Arc<RwLock<Room>>, _: &FullyReadEvent) { async fn on_account_data_fully_read(&self, _: RoomState, _: &FullyReadEvent) {
self.0.lock().await.push("account read".to_string()) self.0.lock().await.push("account read".to_string())
} }
async fn on_presence_event(&self, _: Arc<RwLock<Room>>, _: &PresenceEvent) { async fn on_presence_event(&self, _: RoomState, _: &PresenceEvent) {
self.0.lock().await.push("presence event".to_string()) self.0.lock().await.push("presence event".to_string())
} }
} }
@ -330,7 +317,6 @@ mod test {
assert_eq!( assert_eq!(
v.as_slice(), v.as_slice(),
[ [
"state rules",
"state member", "state member",
"state aliases", "state aliases",
"state power", "state power",
@ -340,7 +326,7 @@ mod test {
"message", "message",
"account read", "account read",
"account ignore", "account ignore",
"presence event", "presence event"
], ],
) )
} }
@ -410,14 +396,13 @@ mod test {
assert_eq!( assert_eq!(
v.as_slice(), v.as_slice(),
[ [
"message",
"state rules",
"state member", "state member",
"state aliases", "state aliases",
"state power", "state power",
"state canonical", "state canonical",
"state member", "state member",
"state member" "state member",
"message"
], ],
) )
} }

View File

@ -43,7 +43,7 @@ mod state;
pub mod test_builder; pub mod test_builder;
pub use async_client::{AsyncClient, AsyncClientConfig, SyncSettings}; pub use async_client::{AsyncClient, AsyncClientConfig, SyncSettings};
pub use base_client::Client; pub use base_client::{Client, RoomState, RoomStateType};
pub use event_emitter::EventEmitter; pub use event_emitter::EventEmitter;
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
pub use matrix_sdk_crypto::{Device, TrustState}; pub use matrix_sdk_crypto::{Device, TrustState};