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 matrix_sdk::{
self,
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;
struct CommandBot {
@ -23,37 +21,39 @@ impl CommandBot {
#[async_trait::async_trait]
impl EventEmitter for CommandBot {
async fn on_room_message(&self, room: Arc<RwLock<Room>>, event: &MessageEvent) {
let msg_body = if let MessageEvent {
content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }),
..
} = event
{
msg_body.clone()
} else {
String::new()
};
async fn on_room_message(&self, room: RoomState, event: &MessageEvent) {
if let RoomState::Joined(room) = room {
let msg_body = if let MessageEvent {
content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }),
..
} = event
{
msg_body.clone()
} else {
String::new()
};
if msg_body.contains("!party") {
let content = MessageEventContent::Text(TextMessageEventContent {
body: "🎉🎊🥳 let's PARTY!! 🥳🎊🎉".to_string(),
format: None,
formatted_body: None,
relates_to: None,
});
// we clone here to hold the lock for as little time as possible.
let room_id = room.read().await.room_id.clone();
if msg_body.contains("!party") {
let content = MessageEventContent::Text(TextMessageEventContent {
body: "🎉🎊🥳 let's PARTY!! 🥳🎊🎉".to_string(),
format: None,
formatted_body: None,
relates_to: None,
});
// we clone here to hold the lock for as little time as possible.
let room_id = room.read().await.room_id.clone();
println!("sending");
println!("sending");
self.client
// 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.
.room_send(&room_id, content, None)
.await
.unwrap();
self.client
// 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.
.room_send(&room_id, content, None)
.await
.unwrap();
println!("message sent");
println!("message sent");
}
}
}
}

View File

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

View File

@ -50,7 +50,7 @@ use crate::models::Room;
use crate::session::Session;
use crate::state::StateStore;
use crate::VERSION;
use crate::{Error, EventEmitter, Result};
use crate::{Error, EventEmitter, Result, RoomStateType};
const DEFAULT_SYNC_TIMEOUT: Duration = Duration::from_secs(30);
@ -322,6 +322,9 @@ impl AsyncClient {
///
/// This is a human readable room name.
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
.read()
.await
@ -336,13 +339,27 @@ impl AsyncClient {
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`
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()
}
/// 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`.
///
/// Returns true when a successful `StateStore` sync has completed.
@ -663,13 +680,12 @@ impl AsyncClient {
Ok(response)
}
#[inline]
async fn iter_joined_rooms(&self, response: &mut sync_events::Response) -> Result<bool> {
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 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 client.receive_joined_state_event(&room_id, &e).await {
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
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
for event in &mut room.state.events {
for event in &mut joined_room.state.events {
if let Ok(e) = event.deserialize() {
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 mut client = self.base_client.write().await;
let (decrypt_ev, timeline_update) = client
@ -709,12 +730,14 @@ impl AsyncClient {
if let Ok(e) = event.deserialize() {
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
if let Some(account_data) = &room.account_data {
if let Some(account_data) = &joined_room.account_data {
for account_data in &account_data.events {
{
if let Ok(e) = account_data.deserialize() {
@ -722,7 +745,9 @@ impl AsyncClient {
if client.receive_account_data_event(&room_id, &e).await {
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;
}
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() {
let mut client = self.base_client.write().await;
@ -752,7 +779,9 @@ impl AsyncClient {
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)
}
#[inline]
async fn iter_left_rooms(&self, response: &mut sync_events::Response) -> Result<bool> {
let mut updated = false;
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 {
let decrypted_event = {
let mut client = self.base_client.write().await;
let (decrypt_ev, timeline_update) = client
.receive_joined_timeline_event(room_id, &mut event)
.receive_left_timeline_event(room_id, &mut event)
.await;
if timeline_update {
updated = true;
@ -791,30 +840,23 @@ impl AsyncClient {
if let Ok(e) = event.deserialize() {
let client = self.base_client.read().await;
client.emit_timeline_event(&room_id, &e).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;
client
.emit_timeline_event(&room_id, &e, RoomStateType::Left)
.await;
}
}
if updated {
if let Some(store) = self.base_client.read().await.state_store.as_ref() {
let mut client = self.base_client.write().await;
let room = client.get_or_create_room(&room_id).clone();
store.store_room_state(room.read().await.deref()).await?;
store
.store_room_state(matrix_room.read().await.deref())
.await?;
}
}
}
Ok(updated)
}
#[inline]
async fn iter_invited_rooms(&self, response: &sync_events::Response) -> Result<bool> {
let mut updated = false;
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 {
if let Ok(e) = event.deserialize() {
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;
/// 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.
///
/// This Client is a state machine that receives responses and events and
@ -70,6 +122,10 @@ pub struct Client {
pub sync_token: Option<Token>,
/// A map of the rooms our user is joined in.
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.
pub ignored_users: Vec<UserId>,
/// The push ruleset for the logged in user.
@ -120,6 +176,8 @@ impl Client {
session,
sync_token: None,
joined_rooms: HashMap::new(),
invited_rooms: HashMap::new(),
lefted_rooms: HashMap::new(),
ignored_users: Vec::new(),
push_ruleset: None,
event_emitter: None,
@ -224,7 +282,7 @@ impl Client {
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)]
self.joined_rooms
.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)
}
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.
///
/// 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))
}
_ => (None, false),
@ -317,7 +414,7 @@ impl Client {
/// 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.
///
/// # Arguments
@ -330,7 +427,7 @@ impl Client {
room_id: &RoomId,
event: &StateEvent,
) -> 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)
}
@ -349,13 +446,70 @@ impl Client {
room_id: &RoomId,
event: &AnyStrippedStateEvent,
) -> 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)
}
/// 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.
///
/// Returns true if the membership list of the room changed, false
/// Returns true if the state of the room changed, false
/// otherwise.
///
/// # Arguments
@ -369,7 +523,7 @@ impl Client {
event: &PresenceEvent,
) -> bool {
// 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;
room.receive_presence_event(event)
} else {
@ -532,7 +686,7 @@ impl Client {
&self,
room_id: &RoomId,
) -> 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;
match &mut *olm {
@ -649,288 +803,117 @@ impl Client {
Ok(())
}
pub(crate) async fn emit_timeline_event(&self, room_id: &RoomId, event: &RoomEvent) {
match event {
RoomEvent::RoomMember(mem) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_room_member(Arc::clone(&room), &mem).await;
}
}
}
RoomEvent::RoomName(name) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_room_name(Arc::clone(&room), &name).await;
}
}
}
RoomEvent::RoomCanonicalAlias(canonical) => {
if let Some(ee) = &self.event_emitter {
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_timeline_event(
&self,
room_id: &RoomId,
event: &RoomEvent,
room_state: RoomStateType,
) {
emit_event!(
self, room_id, event, room_state,
RoomEvent::RoomMember => on_room_member,
RoomEvent::RoomName => on_room_name,
RoomEvent::RoomCanonicalAlias => on_room_canonical_alias,
RoomEvent::RoomAliases => on_room_aliases,
RoomEvent::RoomAvatar => on_room_avatar,
RoomEvent::RoomMessage => on_room_message,
RoomEvent::RoomMessageFeedback => on_room_message_feedback,
RoomEvent::RoomRedaction => on_room_redaction,
RoomEvent::RoomPowerLevels => on_room_power_levels,
RoomEvent::RoomTombstone => on_room_tombstone,
);
}
pub(crate) async fn emit_stripped_state_event(
&self,
room_id: &RoomId,
event: &AnyStrippedStateEvent,
room_state: RoomStateType,
) {
match event {
AnyStrippedStateEvent::RoomMember(member) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_stripped_state_member(Arc::clone(&room), &member)
.await;
}
}
}
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;
}
}
}
_ => {}
}
emit_event!(
self, room_id, event, room_state,
AnyStrippedStateEvent::RoomMember => on_stripped_state_member,
AnyStrippedStateEvent::RoomName => on_stripped_state_name,
AnyStrippedStateEvent::RoomCanonicalAlias => on_stripped_state_canonical_alias,
AnyStrippedStateEvent::RoomAliases => on_stripped_state_aliases,
AnyStrippedStateEvent::RoomAvatar => on_stripped_state_avatar,
);
}
pub(crate) async fn emit_state_event(&self, room_id: &RoomId, event: &StateEvent) {
match event {
StateEvent::RoomMember(member) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_state_member(Arc::clone(&room), &member).await;
}
}
}
StateEvent::RoomName(name) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_state_name(Arc::clone(&room), &name).await;
}
}
}
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_state_event(
&self,
room_id: &RoomId,
event: &StateEvent,
room_state: RoomStateType,
) {
emit_event!(
self, room_id, event, room_state,
StateEvent::RoomMember => on_state_member,
StateEvent::RoomName => on_state_name,
StateEvent::RoomCanonicalAlias => on_state_canonical_alias,
StateEvent::RoomAliases => on_state_aliases,
StateEvent::RoomAvatar => on_state_avatar,
StateEvent::RoomPowerLevels => on_state_power_levels,
StateEvent::RoomTombstone => on_room_tombstone,
);
}
pub(crate) async fn emit_account_data_event(&self, room_id: &RoomId, event: &NonRoomEvent) {
match event {
NonRoomEvent::Presence(presence) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_account_presence(Arc::clone(&room), &presence).await;
}
}
}
NonRoomEvent::IgnoredUserList(ignored) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
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_account_data_event(
&self,
room_id: &RoomId,
event: &NonRoomEvent,
room_state: RoomStateType,
) {
emit_event!(
self, room_id, event, room_state,
NonRoomEvent::Presence => on_account_presence,
NonRoomEvent::IgnoredUserList => on_account_ignored_users,
NonRoomEvent::PushRules => on_account_push_rules,
NonRoomEvent::FullyRead => on_account_data_fully_read,
);
}
pub(crate) async fn emit_ephemeral_event(&self, room_id: &RoomId, event: &NonRoomEvent) {
match event {
NonRoomEvent::Presence(presence) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
ee.on_account_presence(Arc::clone(&room), &presence).await;
}
}
}
NonRoomEvent::IgnoredUserList(ignored) => {
if let Some(ee) = &self.event_emitter {
if let Some(room) = self.get_room(&room_id) {
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,
room_state: RoomStateType,
) {
emit_event!(
self, room_id, event, room_state,
NonRoomEvent::Presence => on_account_presence,
NonRoomEvent::IgnoredUserList => on_account_ignored_users,
NonRoomEvent::PushRules => on_account_push_rules,
NonRoomEvent::FullyRead => on_account_data_fully_read,
);
}
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(room) = self.get_room(&room_id) {
ee.on_presence_event(Arc::clone(&room), &event).await;
match room_state {
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.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::sync::Arc;
use crate::events::{
fully_read::FullyReadEvent,
@ -36,8 +35,7 @@ use crate::events::{
StrippedRoomMember, StrippedRoomName, StrippedRoomPowerLevels,
},
};
use crate::models::Room;
use tokio::sync::RwLock;
use crate::RoomState;
/// 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.
@ -53,7 +51,7 @@ use tokio::sync::RwLock;
/// events::{
/// room::message::{MessageEvent, MessageEventContent, TextMessageEventContent},
/// },
/// AsyncClient, AsyncClientConfig, EventEmitter, Room, SyncSettings,
/// AsyncClient, AsyncClientConfig, EventEmitter, RoomState, SyncSettings,
/// };
/// use tokio::sync::RwLock;
///
@ -61,23 +59,25 @@ use tokio::sync::RwLock;
///
/// #[async_trait::async_trait]
/// impl EventEmitter for EventCallback {
/// async fn on_room_message(&self, room: Arc<RwLock<Room>>, event: &MessageEvent) {
/// if let MessageEvent {
/// content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }),
/// sender,
/// ..
/// } = event
/// {
/// let name = {
/// let room = room.read().await;
/// let member = room.members.get(&sender).unwrap();
/// member
/// .display_name
/// .as_ref()
/// .map(ToString::to_string)
/// .unwrap_or(sender.to_string())
/// };
/// println!("{}: {}", name, msg_body);
/// async fn on_room_message(&self, room: RoomState, event: &MessageEvent) {
/// if let RoomState::Joined(room) = room {
/// if let MessageEvent {
/// content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }),
/// sender,
/// ..
/// } = event
/// {
/// let name = {
/// let room = room.read().await;
/// let member = room.members.get(&sender).unwrap();
/// member
/// .display_name
/// .as_ref()
/// .map(ToString::to_string)
/// .unwrap_or(sender.to_string())
/// };
/// println!("{}: {}", name, msg_body);
/// }
/// }
/// }
/// }
@ -86,81 +86,76 @@ use tokio::sync::RwLock;
pub trait EventEmitter: Send + Sync {
// ROOM EVENTS from `IncomingTimeline`
/// 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.
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.
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.
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.
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.
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.
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.
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.
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.
async fn on_room_tombstone(&self, _: Arc<RwLock<Room>>, _: &TombstoneEvent) {}
async fn on_room_tombstone(&self, _: RoomState, _: &TombstoneEvent) {}
// `RoomEvent`s from `IncomingState`
/// 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.
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.
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.
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.
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.
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.
async fn on_state_join_rules(&self, _: Arc<RwLock<Room>>, _: &JoinRulesEvent) {}
async fn on_state_join_rules(&self, _: RoomState, _: &JoinRulesEvent) {}
// `AnyStrippedStateEvent`s
/// 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.
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.
async fn on_stripped_state_canonical_alias(
&self,
_: Arc<RwLock<Room>>,
_: RoomState,
_: &StrippedRoomCanonicalAlias,
) {
}
/// 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.
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.
async fn on_stripped_state_power_levels(
&self,
_: Arc<RwLock<Room>>,
_: &StrippedRoomPowerLevels,
) {
}
async fn on_stripped_state_power_levels(&self, _: RoomState, _: &StrippedRoomPowerLevels) {}
/// 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`
/// 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.
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.
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.
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
/// 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)]
@ -173,71 +168,71 @@ mod test {
#[async_trait::async_trait]
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())
}
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())
}
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())
}
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())
}
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())
}
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())
}
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())
}
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())
}
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())
}
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())
}
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())
}
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())
}
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())
}
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())
}
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())
}
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())
}
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())
}
async fn on_stripped_state_member(&self, _: Arc<RwLock<Room>>, _: &StrippedRoomMember) {
async fn on_stripped_state_member(&self, _: RoomState, _: &StrippedRoomMember) {
self.0
.lock()
.await
.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())
}
async fn on_stripped_state_canonical_alias(
&self,
_: Arc<RwLock<Room>>,
_: RoomState,
_: &StrippedRoomCanonicalAlias,
) {
self.0
@ -245,46 +240,38 @@ mod test {
.await
.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
.lock()
.await
.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
.lock()
.await
.push("stripped state avatar".to_string())
}
async fn on_stripped_state_power_levels(
&self,
_: Arc<RwLock<Room>>,
_: &StrippedRoomPowerLevels,
) {
async fn on_stripped_state_power_levels(&self, _: RoomState, _: &StrippedRoomPowerLevels) {
self.0.lock().await.push("stripped state power".to_string())
}
async fn on_stripped_state_join_rules(
&self,
_: Arc<RwLock<Room>>,
_: &StrippedRoomJoinRules,
) {
async fn on_stripped_state_join_rules(&self, _: RoomState, _: &StrippedRoomJoinRules) {
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())
}
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())
}
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())
}
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())
}
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())
}
}
@ -330,7 +317,6 @@ mod test {
assert_eq!(
v.as_slice(),
[
"state rules",
"state member",
"state aliases",
"state power",
@ -340,7 +326,7 @@ mod test {
"message",
"account read",
"account ignore",
"presence event",
"presence event"
],
)
}
@ -410,14 +396,13 @@ mod test {
assert_eq!(
v.as_slice(),
[
"message",
"state rules",
"state member",
"state aliases",
"state power",
"state canonical",
"state member",
"state member"
"state member",
"message"
],
)
}

View File

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