Move matrix-sdk to ruma monorepo

master
Devin R 2020-06-20 17:18:20 -04:00
parent a3441429da
commit eb5949dbc2
19 changed files with 715 additions and 615 deletions

View File

@ -2,7 +2,10 @@ use std::{env, process::exit};
use matrix_sdk::{
self,
events::room::message::{MessageEvent, MessageEventContent, TextMessageEventContent},
events::{
room::message::{MessageEventContent, TextMessageEventContent},
MessageEventStub,
},
Client, ClientConfig, EventEmitter, JsonStore, SyncRoom, SyncSettings,
};
use matrix_sdk_common_macros::async_trait;
@ -22,9 +25,9 @@ impl CommandBot {
#[async_trait]
impl EventEmitter for CommandBot {
async fn on_room_message(&self, room: SyncRoom, event: &MessageEvent) {
async fn on_room_message(&self, room: SyncRoom, event: &MessageEventStub<MessageEventContent>) {
if let SyncRoom::Joined(room) = room {
let msg_body = if let MessageEvent {
let msg_body = if let MessageEventStub {
content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }),
..
} = event
@ -37,8 +40,7 @@ impl EventEmitter for CommandBot {
if msg_body.contains("!party") {
let content = MessageEventContent::Text(TextMessageEventContent {
body: "🎉🎊🥳 let's PARTY!! 🥳🎊🎉".to_string(),
format: None,
formatted_body: None,
formatted: None,
relates_to: None,
});
// we clone here to hold the lock for as little time as possible.

View File

@ -3,7 +3,10 @@ use url::Url;
use matrix_sdk::{
self,
events::room::message::{MessageEvent, MessageEventContent, TextMessageEventContent},
events::{
room::message::{MessageEventContent, TextMessageEventContent},
MessageEventStub,
},
Client, ClientConfig, EventEmitter, SyncRoom, SyncSettings,
};
use matrix_sdk_common_macros::async_trait;
@ -12,9 +15,9 @@ struct EventCallback;
#[async_trait]
impl EventEmitter for EventCallback {
async fn on_room_message(&self, room: SyncRoom, event: &MessageEvent) {
async fn on_room_message(&self, room: SyncRoom, event: &MessageEventStub<MessageEventContent>) {
if let SyncRoom::Joined(room) = room {
if let MessageEvent {
if let MessageEventStub {
content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }),
sender,
..

View File

@ -1,7 +1,7 @@
use matrix_sdk::{
api::r0::sync::sync_events::Response as SyncResponse,
events::collections::all::RoomEvent,
events::room::message::{MessageEvent, MessageEventContent, TextMessageEventContent},
events::room::message::{MessageEventContent, TextMessageEventContent},
events::MessageEventStub,
identifiers::RoomId,
Client, ClientConfig, SyncSettings,
};
@ -12,11 +12,15 @@ use web_sys::console;
struct WasmBot(Client);
impl WasmBot {
async fn on_room_message(&self, room_id: &RoomId, event: RoomEvent) {
let msg_body = if let RoomEvent::RoomMessage(MessageEvent {
async fn on_room_message(
&self,
room_id: &RoomId,
event: MessageEventStub<MessageEventContent>,
) {
let msg_body = if let MessageEventStub {
content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }),
..
}) = event
} = event
{
msg_body.clone()
} else {

View File

@ -773,7 +773,7 @@ impl Client {
///
/// # let homeserver = Url::parse("http://example.com").unwrap();
/// let mut builder = RoomBuilder::default();
/// builder.creation_content(false)
/// builder.creation_content(false, None)
/// .initial_state(vec![])
/// .visibility(Visibility::Public)
/// .name("name")
@ -939,9 +939,9 @@ impl Client {
/// # use matrix_sdk::{Client, SyncSettings};
/// # use url::Url;
/// # use futures::executor::block_on;
/// # use ruma_identifiers::RoomId;
/// # use matrix_sdk::identifiers::RoomId;
/// # use std::convert::TryFrom;
/// use matrix_sdk::events::room::message::{MessageEventContent, TextMessageEventContent};
/// use matrix_sdk::events::room::message::{FormattedBody, MessageEventContent, TextMessageEventContent};
/// # block_on(async {
/// # let homeserver = Url::parse("http://localhost:8080").unwrap();
/// # let mut client = Client::new(homeserver).unwrap();
@ -950,8 +950,7 @@ impl Client {
///
/// let content = MessageEventContent::Text(TextMessageEventContent {
/// body: "Hello world".to_owned(),
/// format: None,
/// formatted_body: None,
/// formatted: None,
/// relates_to: None,
/// });
/// let txn_id = Uuid::new_v4();
@ -1515,8 +1514,9 @@ mod test {
set_read_marker, Invite3pid, MessageEventContent,
};
use super::{Client, ClientConfig, Session, SyncSettings, Url};
use crate::events::collections::all::RoomEvent;
use crate::events::room::member::MembershipState;
use crate::events::room::message::TextMessageEventContent;
use crate::identifiers::{EventId, RoomId, RoomIdOrAliasId, UserId};
use crate::{RegistrationBuilder, RoomListFilterBuilder};
@ -1639,8 +1639,8 @@ mod test {
client.restore_login(session).await.unwrap();
let mut response = EventBuilder::default()
.add_room_event(EventsJson::Member, RoomEvent::RoomMember)
.add_room_event(EventsJson::PowerLevels, RoomEvent::RoomPowerLevels)
.add_state_event(EventsFile::Member)
.add_state_event(EventsFile::PowerLevels)
.build_sync_response();
client
@ -2069,7 +2069,7 @@ mod test {
let homeserver = Url::from_str(&mockito::server_url()).unwrap();
let user_id = UserId::try_from("@example:localhost").unwrap();
let room_id = RoomId::try_from("!testroom:example.org").unwrap();
let event_id = EventId::new("example.org").unwrap();
let event_id = EventId::try_from("$xxxxxx:example.org").unwrap();
let session = Session {
access_token: "1234".to_owned(),
@ -2105,7 +2105,7 @@ mod test {
let homeserver = Url::from_str(&mockito::server_url()).unwrap();
let user_id = UserId::try_from("@example:localhost").unwrap();
let room_id = RoomId::try_from("!testroom:example.org").unwrap();
let event_id = EventId::new("example.org").unwrap();
let event_id = EventId::try_from("$xxxxxx:example.org").unwrap();
let session = Session {
access_token: "1234".to_owned(),
@ -2205,9 +2205,8 @@ mod test {
let content = MessageEventContent::Text(TextMessageEventContent {
body: "Hello world".to_owned(),
format: None,
formatted_body: None,
relates_to: None,
formatted: None,
});
let txn_id = Uuid::new_v4();
let response = client

View File

@ -29,7 +29,7 @@ use matrix_sdk_common::{
/// # let mut rt = tokio::runtime::Runtime::new().unwrap();
/// # rt.block_on(async {
/// let mut builder = RoomBuilder::default();
/// builder.creation_content(false)
/// builder.creation_content(false, None)
/// .initial_state(vec![])
/// .visibility(Visibility::Public)
/// .name("name")
@ -63,9 +63,15 @@ impl RoomBuilder {
/// Set the `CreationContent`.
///
/// Weather users on other servers can join this room.
pub fn creation_content(&mut self, federate: bool) -> &mut Self {
let federate = Some(federate);
self.creation_content = Some(CreationContent { federate });
pub fn creation_content(
&mut self,
federate: bool,
predecessor: Option<PreviousRoom>,
) -> &mut Self {
self.creation_content = Some(CreationContent {
federate,
predecessor,
});
self
}
@ -500,7 +506,7 @@ mod test {
let mut builder = RoomBuilder::new();
builder
.creation_content(false)
.creation_content(false, None)
.initial_state(vec![])
.visibility(Visibility::Public)
.name("room_name")

View File

@ -25,21 +25,22 @@ use std::result::Result as StdResult;
use crate::api::r0 as api;
use crate::error::Result;
use crate::events::collections::all::{RoomEvent, StateEvent};
use crate::events::presence::PresenceEvent;
// `NonRoomEvent` is what it is aliased as
use crate::event_emitter::CustomOrRawEvent;
use crate::events::collections::only::Event as NonRoomEvent;
use crate::events::ignored_user_list::IgnoredUserListEvent;
use crate::events::push_rules::{PushRulesEvent, Ruleset};
use crate::events::push_rules::PushRulesEvent;
use crate::events::room::member::MemberEventContent;
use crate::events::stripped::AnyStrippedStateEvent;
use crate::events::EventJson;
use crate::identifiers::{RoomId, UserId};
use crate::models::Room;
use crate::push::Ruleset;
use crate::session::Session;
use crate::state::{AllRooms, ClientState, StateStore};
use crate::EventEmitter;
use matrix_sdk_common::events::{
AnyBasicEvent, AnyEphemeralRoomEvent, AnyMessageEventStub, AnyRoomEventStub, AnyStateEventStub,
AnyStrippedStateEventStub, EventJson,
};
#[cfg(feature = "encryption")]
use matrix_sdk_common::locks::Mutex;
@ -54,7 +55,9 @@ use crate::api::r0::keys::{
#[cfg(feature = "encryption")]
use crate::api::r0::to_device::send_event_to_device;
#[cfg(feature = "encryption")]
use crate::events::room::{encrypted::EncryptedEventContent, message::MessageEventContent};
use crate::events::room::{
encrypted::EncryptedEventContent, message::MessageEventContent as MsgEventContent,
};
#[cfg(feature = "encryption")]
use crate::identifiers::DeviceId;
#[cfg(not(target_arch = "wasm32"))]
@ -90,7 +93,9 @@ pub struct AdditionalUnsignedData {
///
/// [synapse-bug]: <https://github.com/matrix-org/matrix-doc/issues/684#issuecomment-641182668>
/// [discussion]: <https://github.com/matrix-org/matrix-doc/issues/684#issuecomment-641182668>
fn hoist_room_event_prev_content(event: &mut EventJson<RoomEvent>) -> Option<EventJson<RoomEvent>> {
fn hoist_room_event_prev_content(
event: &EventJson<AnyRoomEventStub>,
) -> Option<EventJson<AnyRoomEventStub>> {
let prev_content = serde_json::from_str::<AdditionalEventData>(event.json().get())
.map(|more_unsigned| more_unsigned.unsigned)
.map(|additional| additional.prev_content)
@ -98,6 +103,7 @@ fn hoist_room_event_prev_content(event: &mut EventJson<RoomEvent>) -> Option<Eve
.flatten()?;
let mut ev = event.deserialize().ok()?;
match &mut ev {
RoomEvent::RoomMember(ref mut member) if member.prev_content.is_none() => {
if let Ok(prev) = prev_content.deserialize() {
@ -113,7 +119,9 @@ fn hoist_room_event_prev_content(event: &mut EventJson<RoomEvent>) -> Option<Eve
/// Transform state event by hoisting `prev_content` field from `unsigned` to the top level.
///
/// See comment of `hoist_room_event_prev_content`.
fn hoist_state_event_prev_content(event: &EventJson<StateEvent>) -> Option<EventJson<StateEvent>> {
fn hoist_state_event_prev_content(
event: &EventJson<AnyStateEventStub>,
) -> Option<EventJson<AnyStateEventStub>> {
let prev_content = serde_json::from_str::<AdditionalEventData>(event.json().get())
.map(|more_unsigned| more_unsigned.unsigned)
.map(|additional| additional.prev_content)
@ -122,11 +130,10 @@ fn hoist_state_event_prev_content(event: &EventJson<StateEvent>) -> Option<Event
let mut ev = event.deserialize().ok()?;
match &mut ev {
StateEvent::RoomMember(ref mut member) if member.prev_content.is_none() => {
if let Ok(prev) = prev_content.deserialize() {
member.prev_content = Some(prev)
}
AnyRoomEventStub::State(AnyStateEventStub::RoomMember(ref mut member))
if member.prev_content.is_none() =>
{
member.prev_content = Some(prev_content.deserialize().ok()?);
Some(EventJson::from(ev))
}
_ => None,
@ -134,7 +141,7 @@ fn hoist_state_event_prev_content(event: &EventJson<StateEvent>) -> Option<Event
}
fn stripped_deserialize_prev_content(
event: &EventJson<AnyStrippedStateEvent>,
event: &EventJson<AnyStrippedStateEventStub>,
) -> Option<AdditionalUnsignedData> {
serde_json::from_str::<AdditionalEventData>(event.json().get())
.map(|more_unsigned| more_unsigned.unsigned)
@ -733,8 +740,8 @@ impl BaseClient {
let room_lock = self.get_or_create_joined_room(&room_id).await?;
let mut room = room_lock.write().await;
if let RoomEvent::RoomMember(mem_event) = &mut e {
let changed = room.handle_membership(mem_event);
if let AnyRoomEventStub::State(AnyStateEventStub::RoomMember(mem_event)) = &mut e {
let changed = room.handle_membership(mem_event, room_id);
// The memberlist of the room changed, invalidate the group session
// of the room.
@ -765,13 +772,13 @@ impl BaseClient {
pub async fn receive_joined_state_event(
&self,
room_id: &RoomId,
event: &StateEvent,
event: &AnyStateEventStub,
) -> Result<bool> {
let room_lock = self.get_or_create_joined_room(room_id).await?;
let mut room = room_lock.write().await;
if let StateEvent::RoomMember(e) = event {
let changed = room.handle_membership(e);
if let AnyStateEventStub::RoomMember(e) = event {
let changed = room.handle_membership(e, room_id);
// The memberlist of the room changed, invalidate the group session
// of the room.
@ -782,7 +789,7 @@ impl BaseClient {
Ok(changed)
} else {
Ok(room.receive_state_event(event))
Ok(room.receive_state_event(event, room_id))
}
}
@ -799,7 +806,7 @@ impl BaseClient {
pub async fn receive_invite_state_event(
&self,
room_id: &RoomId,
event: &AnyStrippedStateEvent,
event: &AnyStrippedStateEventStub,
) -> Result<bool> {
let room_lock = self.get_or_create_invited_room(room_id).await?;
let mut room = room_lock.write().await;
@ -819,13 +826,13 @@ impl BaseClient {
pub async fn receive_left_timeline_event(
&self,
room_id: &RoomId,
event: &EventJson<RoomEvent>,
event: &EventJson<AnyRoomEventStub>,
) -> Result<bool> {
match event.deserialize() {
Ok(e) => {
let room_lock = self.get_or_create_left_room(room_id).await?;
let mut room = room_lock.write().await;
Ok(room.receive_timeline_event(&e))
Ok(room.receive_timeline_event(&e, room_id))
}
_ => Ok(false),
}
@ -844,11 +851,11 @@ impl BaseClient {
pub async fn receive_left_state_event(
&self,
room_id: &RoomId,
event: &StateEvent,
event: &AnyStateEventStub,
) -> Result<bool> {
let room_lock = self.get_or_create_left_room(room_id).await?;
let mut room = room_lock.write().await;
Ok(room.receive_state_event(event))
Ok(room.receive_state_event(event, room_id))
}
/// Receive a presence event from a sync response and updates the client state.
@ -880,11 +887,10 @@ impl BaseClient {
/// * `room_id` - The unique id of the room the event belongs to.
///
/// * `event` - The presence event for a specified room member.
pub async fn receive_account_data_event(&self, room_id: &RoomId, event: &NonRoomEvent) -> bool {
match event {
NonRoomEvent::IgnoredUserList(iu) => self.handle_ignored_users(iu).await,
NonRoomEvent::Presence(p) => self.receive_presence_event(room_id, p).await,
NonRoomEvent::PushRules(pr) => self.handle_push_rules(pr).await,
pub async fn receive_account_data_event(&self, _: &RoomId, event: &AnyBasicEvent) -> bool {
match &event {
AnyBasicEvent::IgnoredUserList(event) => self.handle_ignored_users(&event).await,
AnyBasicEvent::PushRules(event) => self.handle_push_rules(&event).await,
_ => false,
}
}
@ -898,13 +904,18 @@ impl BaseClient {
/// * `room_id` - The unique id of the room the event belongs to.
///
/// * `event` - The presence event for a specified room member.
pub async fn receive_ephemeral_event(&self, room_id: &RoomId, event: &NonRoomEvent) -> bool {
match event {
NonRoomEvent::IgnoredUserList(iu) => self.handle_ignored_users(iu).await,
NonRoomEvent::Presence(p) => self.receive_presence_event(room_id, p).await,
NonRoomEvent::PushRules(pr) => self.handle_push_rules(pr).await,
_ => false,
}
pub async fn receive_ephemeral_event(
&self,
_room_id: &RoomId,
event: &AnyEphemeralRoomEvent,
) -> bool {
match &event {
AnyEphemeralRoomEvent::FullyRead(_) => {}
AnyEphemeralRoomEvent::Receipt(_) => {}
AnyEphemeralRoomEvent::Typing(_) => {}
_ => {}
};
false
}
/// Get the current, if any, sync token of the client.
@ -1055,6 +1066,8 @@ impl BaseClient {
self.emit_account_data_event(room_id, &e, RoomStateType::Joined)
.await;
}
self.emit_account_data_event(room_id, &e, RoomStateType::Joined)
.await;
}
}
}
@ -1190,7 +1203,7 @@ impl BaseClient {
if let Ok(mut e) = event.deserialize() {
// if the event is a m.room.member event the server will sometimes
// send the `prev_content` field as part of the unsigned field.
if let AnyStrippedStateEvent::RoomMember(_) = &mut e {
if let AnyStrippedStateEventStub::RoomMember(_) = &mut e {
if let Some(raw_content) = stripped_deserialize_prev_content(event) {
let prev_content = match raw_content.prev_content {
Some(json) => json.deserialize().ok(),
@ -1313,7 +1326,7 @@ impl BaseClient {
pub async fn encrypt(
&self,
room_id: &RoomId,
content: MessageEventContent,
content: MsgEventContent,
) -> Result<EncryptedEventContent> {
let mut olm = self.olm.lock().await;
@ -1430,7 +1443,7 @@ impl BaseClient {
pub(crate) async fn emit_timeline_event(
&self,
room_id: &RoomId,
event: &RoomEvent,
event: &AnyRoomEventStub,
room_state: RoomStateType,
) {
let lock = self.event_emitter.read().await;
@ -1464,42 +1477,58 @@ impl BaseClient {
}
};
match event {
RoomEvent::RoomMember(mem) => event_emitter.on_room_member(room, &mem).await,
RoomEvent::RoomName(name) => event_emitter.on_room_name(room, &name).await,
RoomEvent::RoomCanonicalAlias(canonical) => {
event_emitter
.on_room_canonical_alias(room, &canonical)
.await
}
RoomEvent::RoomAliases(aliases) => event_emitter.on_room_aliases(room, &aliases).await,
RoomEvent::RoomAvatar(avatar) => event_emitter.on_room_avatar(room, &avatar).await,
RoomEvent::RoomMessage(msg) => event_emitter.on_room_message(room, &msg).await,
RoomEvent::RoomMessageFeedback(msg_feedback) => {
event_emitter
.on_room_message_feedback(room, &msg_feedback)
.await
}
RoomEvent::RoomRedaction(redaction) => {
event_emitter.on_room_redaction(room, &redaction).await
}
RoomEvent::RoomPowerLevels(power) => {
event_emitter.on_room_power_levels(room, &power).await
}
RoomEvent::RoomTombstone(tomb) => event_emitter.on_room_tombstone(room, &tomb).await,
RoomEvent::CustomRoom(custom) => {
event_emitter
.on_unrecognized_event(room, &CustomOrRawEvent::CustomRoom(custom))
.await
}
_ => {}
match &event {
AnyRoomEventStub::State(event) => match &event {
AnyStateEventStub::RoomMember(e) => event_emitter.on_room_member(room, &e).await,
AnyStateEventStub::RoomName(e) => event_emitter.on_room_name(room, &e).await,
AnyStateEventStub::RoomCanonicalAlias(e) => {
event_emitter.on_room_canonical_alias(room, &e).await
}
AnyStateEventStub::RoomAliases(e) => event_emitter.on_room_aliases(room, &e).await,
AnyStateEventStub::RoomAvatar(e) => event_emitter.on_room_avatar(room, &e).await,
AnyStateEventStub::RoomPowerLevels(e) => {
event_emitter.on_room_power_levels(room, &e).await
}
AnyStateEventStub::RoomTombstone(e) => {
event_emitter.on_room_tombstone(room, &e).await
}
AnyStateEventStub::RoomJoinRules(_e) => {
// TODO is this needed ??
// event_emitter
// .on_room_join_rules(room, &e).await
}
AnyStateEventStub::Custom(e) => {
event_emitter
.on_unrecognized_event(room, &CustomOrRawEvent::State(&e))
.await
}
_ => {}
},
AnyRoomEventStub::Message(event) => match &event {
AnyMessageEventStub::RoomMessage(e) => {
event_emitter.on_room_message(room, &e).await
}
AnyMessageEventStub::RoomMessageFeedback(e) => {
event_emitter.on_room_message_feedback(room, &e).await
}
AnyMessageEventStub::RoomRedaction(e) => {
event_emitter.on_room_redaction(room, e).await
}
AnyMessageEventStub::Custom(e) => {
event_emitter
.on_unrecognized_event(room, &CustomOrRawEvent::Message(&e))
.await
}
_ => {}
},
}
}
pub(crate) async fn emit_state_event(
&self,
room_id: &RoomId,
event: &StateEvent,
event: &AnyStateEventStub,
room_state: RoomStateType,
) {
let lock = self.event_emitter.read().await;
@ -1534,27 +1563,34 @@ impl BaseClient {
};
match event {
StateEvent::RoomMember(member) => event_emitter.on_state_member(room, &member).await,
StateEvent::RoomName(name) => event_emitter.on_state_name(room, &name).await,
StateEvent::RoomCanonicalAlias(canonical) => {
AnyStateEventStub::RoomMember(member) => {
event_emitter.on_state_member(room, &member).await
}
AnyStateEventStub::RoomName(name) => event_emitter.on_state_name(room, &name).await,
AnyStateEventStub::RoomCanonicalAlias(canonical) => {
event_emitter
.on_state_canonical_alias(room, &canonical)
.await
}
StateEvent::RoomAliases(aliases) => {
AnyStateEventStub::RoomAliases(aliases) => {
event_emitter.on_state_aliases(room, &aliases).await
}
StateEvent::RoomAvatar(avatar) => event_emitter.on_state_avatar(room, &avatar).await,
StateEvent::RoomPowerLevels(power) => {
AnyStateEventStub::RoomAvatar(avatar) => {
event_emitter.on_state_avatar(room, &avatar).await
}
AnyStateEventStub::RoomPowerLevels(power) => {
event_emitter.on_state_power_levels(room, &power).await
}
StateEvent::RoomJoinRules(rules) => {
AnyStateEventStub::RoomJoinRules(rules) => {
event_emitter.on_state_join_rules(room, &rules).await
}
StateEvent::RoomTombstone(tomb) => event_emitter.on_room_tombstone(room, &tomb).await,
StateEvent::CustomState(custom) => {
AnyStateEventStub::RoomTombstone(tomb) => {
// TODO make `on_state_tombstone` method
event_emitter.on_room_tombstone(room, &tomb).await
}
AnyStateEventStub::Custom(custom) => {
event_emitter
.on_unrecognized_event(room, &CustomOrRawEvent::CustomState(custom))
.on_unrecognized_event(room, &CustomOrRawEvent::State(custom))
.await
}
_ => {}
@ -1564,7 +1600,7 @@ impl BaseClient {
pub(crate) async fn emit_stripped_state_event(
&self,
room_id: &RoomId,
event: &AnyStrippedStateEvent,
event: &AnyStrippedStateEventStub,
prev_content: Option<MemberEventContent>,
room_state: RoomStateType,
) {
@ -1600,33 +1636,33 @@ impl BaseClient {
};
match event {
AnyStrippedStateEvent::RoomMember(member) => {
AnyStrippedStateEventStub::RoomMember(member) => {
event_emitter
.on_stripped_state_member(room, &member, prev_content)
.await
}
AnyStrippedStateEvent::RoomName(name) => {
AnyStrippedStateEventStub::RoomName(name) => {
event_emitter.on_stripped_state_name(room, &name).await
}
AnyStrippedStateEvent::RoomCanonicalAlias(canonical) => {
AnyStrippedStateEventStub::RoomCanonicalAlias(canonical) => {
event_emitter
.on_stripped_state_canonical_alias(room, &canonical)
.await
}
AnyStrippedStateEvent::RoomAliases(aliases) => {
AnyStrippedStateEventStub::RoomAliases(aliases) => {
event_emitter
.on_stripped_state_aliases(room, &aliases)
.await
}
AnyStrippedStateEvent::RoomAvatar(avatar) => {
AnyStrippedStateEventStub::RoomAvatar(avatar) => {
event_emitter.on_stripped_state_avatar(room, &avatar).await
}
AnyStrippedStateEvent::RoomPowerLevels(power) => {
AnyStrippedStateEventStub::RoomPowerLevels(power) => {
event_emitter
.on_stripped_state_power_levels(room, &power)
.await
}
AnyStrippedStateEvent::RoomJoinRules(rules) => {
AnyStrippedStateEventStub::RoomJoinRules(rules) => {
event_emitter
.on_stripped_state_join_rules(room, &rules)
.await
@ -1638,7 +1674,7 @@ impl BaseClient {
pub(crate) async fn emit_account_data_event(
&self,
room_id: &RoomId,
event: &NonRoomEvent,
event: &AnyBasicEvent,
room_state: RoomStateType,
) {
let lock = self.event_emitter.read().await;
@ -1673,21 +1709,17 @@ impl BaseClient {
};
match event {
NonRoomEvent::Presence(presence) => {
AnyBasicEvent::Presence(presence) => {
event_emitter.on_non_room_presence(room, &presence).await
}
NonRoomEvent::IgnoredUserList(ignored) => {
AnyBasicEvent::IgnoredUserList(ignored) => {
event_emitter
.on_non_room_ignored_users(room, &ignored)
.await
}
NonRoomEvent::PushRules(rules) => {
AnyBasicEvent::PushRules(rules) => {
event_emitter.on_non_room_push_rules(room, &rules).await
}
NonRoomEvent::FullyRead(full_read) => {
event_emitter.on_non_room_fully_read(room, &full_read).await
}
NonRoomEvent::Typing(typing) => event_emitter.on_non_room_typing(room, &typing).await,
_ => {}
}
}
@ -1695,7 +1727,7 @@ impl BaseClient {
pub(crate) async fn emit_ephemeral_event(
&self,
room_id: &RoomId,
event: &NonRoomEvent,
event: &AnyEphemeralRoomEvent,
room_state: RoomStateType,
) {
let lock = self.event_emitter.read().await;
@ -1730,21 +1762,15 @@ impl BaseClient {
};
match event {
NonRoomEvent::Presence(presence) => {
event_emitter.on_non_room_presence(room, &presence).await
}
NonRoomEvent::IgnoredUserList(ignored) => {
event_emitter
.on_non_room_ignored_users(room, &ignored)
.await
}
NonRoomEvent::PushRules(rules) => {
event_emitter.on_non_room_push_rules(room, &rules).await
}
NonRoomEvent::FullyRead(full_read) => {
AnyEphemeralRoomEvent::FullyRead(full_read) => {
event_emitter.on_non_room_fully_read(room, &full_read).await
}
NonRoomEvent::Typing(typing) => event_emitter.on_non_room_typing(room, &typing).await,
AnyEphemeralRoomEvent::Typing(typing) => {
event_emitter.on_non_room_typing(room, &typing).await
}
AnyEphemeralRoomEvent::Receipt(receipt) => {
event_emitter.on_non_room_receipt(room, &receipt).await
}
_ => {}
}
}
@ -1822,12 +1848,9 @@ impl BaseClient {
#[cfg(test)]
mod test {
use crate::identifiers::{RoomId, UserId};
use crate::{
events::{collections::all::RoomEvent, stripped::AnyStrippedStateEvent},
BaseClient, Session,
};
use crate::{events::AnyRoomEventStub, BaseClient, Session};
use matrix_sdk_common_macros::async_trait;
use matrix_sdk_test::{async_test, test_json, EventBuilder, EventsJson};
use matrix_sdk_test::{async_test, test_json, EventBuilder, EventsFile};
use serde_json::json;
use std::convert::TryFrom;
@ -1860,14 +1883,14 @@ mod test {
"origin_server_ts": 0,
"sender": "@example:localhost",
"state_key": "@example:localhost",
"type": "m.room.member",
"type": "m.room.member"
})
}
#[async_test]
async fn test_joined_room_creation() {
let mut sync_response = EventBuilder::default()
.add_room_event(EventsJson::Member, RoomEvent::RoomMember)
.add_state_event(EventsFile::Member)
.build_sync_response();
let client = get_client().await;
let room_id = get_room_id();
@ -1887,7 +1910,7 @@ mod test {
assert!(room.is_some());
let mut sync_response = EventBuilder::default()
.add_custom_left_event(&room_id, member_event(), RoomEvent::RoomMember)
.add_custom_left_event(&room_id, member_event(), AnyRoomEventStub::State)
.build_sync_response();
sync_response.next_batch = "Hello".to_owned();
@ -1908,7 +1931,7 @@ mod test {
async fn test_left_room_creation() {
let room_id = RoomId::try_from("!left_room:localhost").unwrap();
let mut sync_response = EventBuilder::default()
.add_custom_left_event(&room_id, member_event(), RoomEvent::RoomMember)
.add_custom_left_event(&room_id, member_event(), AnyRoomEventStub::State)
.build_sync_response();
let client = get_client().await;
@ -1925,7 +1948,7 @@ mod test {
assert!(room.is_some());
let mut sync_response = EventBuilder::default()
.add_custom_joined_event(&room_id, member_event(), RoomEvent::RoomMember)
.add_custom_joined_event(&room_id, member_event(), AnyRoomEventStub::State)
.build_sync_response();
sync_response.next_batch = "Hello".to_owned();
@ -1946,7 +1969,7 @@ mod test {
async fn test_invited_room_creation() {
let room_id = RoomId::try_from("!invited_room:localhost").unwrap();
let mut sync_response = EventBuilder::default()
.add_custom_invited_event(&room_id, member_event(), AnyStrippedStateEvent::RoomMember)
.add_custom_invited_event(&room_id, member_event())
.build_sync_response();
let client = get_client().await;
@ -1963,7 +1986,7 @@ mod test {
assert!(room.is_some());
let mut sync_response = EventBuilder::default()
.add_custom_joined_event(&room_id, member_event(), RoomEvent::RoomMember)
.add_custom_joined_event(&room_id, member_event(), AnyRoomEventStub::State)
.build_sync_response();
sync_response.next_batch = "Hello".to_owned();
@ -1985,7 +2008,10 @@ mod test {
use super::*;
use crate::{EventEmitter, SyncRoom};
use matrix_sdk_common::events::room::member::{MemberEvent, MembershipChange};
use matrix_sdk_common::events::{
room::member::{MemberEventContent, MembershipChange},
StateEventStub,
};
use matrix_sdk_common::locks::RwLock;
use std::sync::{
atomic::{AtomicBool, Ordering},
@ -1995,14 +2021,15 @@ mod test {
struct EE(Arc<AtomicBool>);
#[async_trait]
impl EventEmitter for EE {
async fn on_room_member(&self, room: SyncRoom, event: &MemberEvent) {
async fn on_room_member(
&self,
room: SyncRoom,
event: &StateEventStub<MemberEventContent>,
) {
if let SyncRoom::Joined(_) = room {
match event.membership_change() {
MembershipChange::Joined => {
self.0.swap(true, Ordering::SeqCst);
}
_ => {}
};
if let MembershipChange::Joined = event.membership_change() {
self.0.swap(true, Ordering::SeqCst);
}
}
if event.prev_content.is_none() {
self.0.swap(false, Ordering::SeqCst);
@ -2237,6 +2264,7 @@ mod test {
use super::*;
use crate::{EventEmitter, SyncRoom};
use matrix_sdk_common::api::r0::sync::sync_events;
use matrix_sdk_common::locks::RwLock;
use std::sync::{
atomic::{AtomicBool, Ordering},
@ -2248,9 +2276,9 @@ mod test {
impl EventEmitter for EE {
async fn on_unrecognized_event(&self, room: SyncRoom, event: &CustomOrRawEvent<'_>) {
if let SyncRoom::Joined(_) = room {
if let CustomOrRawEvent::CustomRoom(custom) = event {
if custom.event_type == "m.reaction"
&& custom.content.get("m.relates_to").is_some()
if let CustomOrRawEvent::Message(custom) = event {
if custom.content.event_type == "m.reaction"
&& custom.content.json.get("m.relates_to").is_some()
{
self.0.swap(true, Ordering::SeqCst);
}
@ -2316,8 +2344,7 @@ mod test {
let response = http::Response::builder()
.body(serde_json::to_vec(&body).unwrap())
.unwrap();
let mut sync =
matrix_sdk_common::api::r0::sync::sync_events::Response::try_from(response).unwrap();
let mut sync = sync_events::Response::try_from(response).unwrap();
client.receive_sync_response(&mut sync).await.unwrap();
@ -2331,7 +2358,7 @@ mod test {
let room_id = get_room_id();
let mut sync_response = EventBuilder::default()
.add_room_event(EventsJson::Member, RoomEvent::RoomMember)
.add_state_event(EventsFile::Member)
.build_sync_response();
client

View File

@ -18,29 +18,26 @@ use matrix_sdk_common::locks::RwLock;
use serde_json::value::RawValue as RawJsonValue;
use crate::events::{
fully_read::FullyReadEvent,
ignored_user_list::IgnoredUserListEvent,
custom::CustomEventContent,
fully_read::FullyReadEventContent,
ignored_user_list::IgnoredUserListEventContent,
presence::PresenceEvent,
push_rules::PushRulesEvent,
receipt::ReceiptEvent,
push_rules::PushRulesEventContent,
receipt::ReceiptEventContent,
room::{
aliases::AliasesEvent,
avatar::AvatarEvent,
canonical_alias::CanonicalAliasEvent,
join_rules::JoinRulesEvent,
member::{MemberEvent, MemberEventContent},
message::{feedback::FeedbackEvent, MessageEvent},
name::NameEvent,
power_levels::PowerLevelsEvent,
redaction::RedactionEvent,
tombstone::TombstoneEvent,
aliases::AliasesEventContent,
avatar::AvatarEventContent,
canonical_alias::CanonicalAliasEventContent,
join_rules::JoinRulesEventContent,
member::MemberEventContent,
message::{feedback::FeedbackEventContent, MessageEventContent as MsgEventContent},
name::NameEventContent,
power_levels::PowerLevelsEventContent,
redaction::RedactionEventStub,
tombstone::TombstoneEventContent,
},
stripped::{
StrippedRoomAliases, StrippedRoomAvatar, StrippedRoomCanonicalAlias, StrippedRoomJoinRules,
StrippedRoomMember, StrippedRoomName, StrippedRoomPowerLevels,
},
typing::TypingEvent,
CustomEvent, CustomRoomEvent, CustomStateEvent,
typing::TypingEventContent,
BasicEvent, EphemeralRoomEvent, MessageEventStub, StateEventStub, StrippedStateEventStub,
};
use crate::{Room, RoomState};
use matrix_sdk_common_macros::async_trait;
@ -52,15 +49,17 @@ pub type SyncRoom = RoomState<Arc<RwLock<Room>>>;
#[derive(Clone, Copy, Debug)]
pub enum CustomOrRawEvent<'c> {
/// When an event can not be deserialized by ruma.
///
/// This will be mostly obsolete when ruma-events is updated.
RawJson(&'c RawJsonValue),
/// A custom event.
Custom(&'c CustomEvent),
/// A custom basic event.
Basic(&'c BasicEvent<CustomEventContent>),
/// A custom basic event.
EphemeralRoom(&'c EphemeralRoomEvent<CustomEventContent>),
/// A custom room event.
CustomRoom(&'c CustomRoomEvent),
Message(&'c MessageEventStub<CustomEventContent>),
/// A custom state event.
CustomState(&'c CustomStateEvent),
State(&'c StateEventStub<CustomEventContent>),
/// A custom stripped state event.
StrippedState(&'c StrippedStateEventStub<CustomEventContent>),
}
/// This trait allows any type implementing `EventEmitter` to specify event callbacks for each event.
@ -74,7 +73,8 @@ pub enum CustomOrRawEvent<'c> {
/// # use matrix_sdk_base::{
/// # self,
/// # events::{
/// # room::message::{MessageEvent, MessageEventContent, TextMessageEventContent},
/// # room::message::{MessageEventContent, TextMessageEventContent},
/// # MessageEventStub
/// # },
/// # EventEmitter, SyncRoom
/// # };
@ -85,9 +85,9 @@ pub enum CustomOrRawEvent<'c> {
///
/// #[async_trait]
/// impl EventEmitter for EventCallback {
/// async fn on_room_message(&self, room: SyncRoom, event: &MessageEvent) {
/// async fn on_room_message(&self, room: SyncRoom, event: &MessageEventStub<MessageEventContent>) {
/// if let SyncRoom::Joined(room) = room {
/// if let MessageEvent {
/// if let MessageEventStub {
/// content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }),
/// sender,
/// ..
@ -112,80 +112,140 @@ pub enum CustomOrRawEvent<'c> {
pub trait EventEmitter: Send + Sync {
// ROOM EVENTS from `IncomingTimeline`
/// Fires when `Client` receives a `RoomEvent::RoomMember` event.
async fn on_room_member(&self, _: SyncRoom, _: &MemberEvent) {}
async fn on_room_member(&self, _: SyncRoom, _: &StateEventStub<MemberEventContent>) {}
/// Fires when `Client` receives a `RoomEvent::RoomName` event.
async fn on_room_name(&self, _: SyncRoom, _: &NameEvent) {}
async fn on_room_name(&self, _: SyncRoom, _: &StateEventStub<NameEventContent>) {}
/// Fires when `Client` receives a `RoomEvent::RoomCanonicalAlias` event.
async fn on_room_canonical_alias(&self, _: SyncRoom, _: &CanonicalAliasEvent) {}
async fn on_room_canonical_alias(
&self,
_: SyncRoom,
_: &StateEventStub<CanonicalAliasEventContent>,
) {
}
/// Fires when `Client` receives a `RoomEvent::RoomAliases` event.
async fn on_room_aliases(&self, _: SyncRoom, _: &AliasesEvent) {}
async fn on_room_aliases(&self, _: SyncRoom, _: &StateEventStub<AliasesEventContent>) {}
/// Fires when `Client` receives a `RoomEvent::RoomAvatar` event.
async fn on_room_avatar(&self, _: SyncRoom, _: &AvatarEvent) {}
async fn on_room_avatar(&self, _: SyncRoom, _: &StateEventStub<AvatarEventContent>) {}
/// Fires when `Client` receives a `RoomEvent::RoomMessage` event.
async fn on_room_message(&self, _: SyncRoom, _: &MessageEvent) {}
async fn on_room_message(&self, _: SyncRoom, _: &MessageEventStub<MsgEventContent>) {}
/// Fires when `Client` receives a `RoomEvent::RoomMessageFeedback` event.
async fn on_room_message_feedback(&self, _: SyncRoom, _: &FeedbackEvent) {}
async fn on_room_message_feedback(
&self,
_: SyncRoom,
_: &MessageEventStub<FeedbackEventContent>,
) {
}
/// Fires when `Client` receives a `RoomEvent::RoomRedaction` event.
async fn on_room_redaction(&self, _: SyncRoom, _: &RedactionEvent) {}
async fn on_room_redaction(&self, _: SyncRoom, _: &RedactionEventStub) {}
/// Fires when `Client` receives a `RoomEvent::RoomPowerLevels` event.
async fn on_room_power_levels(&self, _: SyncRoom, _: &PowerLevelsEvent) {}
async fn on_room_power_levels(&self, _: SyncRoom, _: &StateEventStub<PowerLevelsEventContent>) {
}
/// Fires when `Client` receives a `RoomEvent::Tombstone` event.
async fn on_room_tombstone(&self, _: SyncRoom, _: &TombstoneEvent) {}
async fn on_room_tombstone(&self, _: SyncRoom, _: &StateEventStub<TombstoneEventContent>) {}
// `RoomEvent`s from `IncomingState`
/// Fires when `Client` receives a `StateEvent::RoomMember` event.
async fn on_state_member(&self, _: SyncRoom, _: &MemberEvent) {}
async fn on_state_member(&self, _: SyncRoom, _: &StateEventStub<MemberEventContent>) {}
/// Fires when `Client` receives a `StateEvent::RoomName` event.
async fn on_state_name(&self, _: SyncRoom, _: &NameEvent) {}
async fn on_state_name(&self, _: SyncRoom, _: &StateEventStub<NameEventContent>) {}
/// Fires when `Client` receives a `StateEvent::RoomCanonicalAlias` event.
async fn on_state_canonical_alias(&self, _: SyncRoom, _: &CanonicalAliasEvent) {}
async fn on_state_canonical_alias(
&self,
_: SyncRoom,
_: &StateEventStub<CanonicalAliasEventContent>,
) {
}
/// Fires when `Client` receives a `StateEvent::RoomAliases` event.
async fn on_state_aliases(&self, _: SyncRoom, _: &AliasesEvent) {}
async fn on_state_aliases(&self, _: SyncRoom, _: &StateEventStub<AliasesEventContent>) {}
/// Fires when `Client` receives a `StateEvent::RoomAvatar` event.
async fn on_state_avatar(&self, _: SyncRoom, _: &AvatarEvent) {}
async fn on_state_avatar(&self, _: SyncRoom, _: &StateEventStub<AvatarEventContent>) {}
/// Fires when `Client` receives a `StateEvent::RoomPowerLevels` event.
async fn on_state_power_levels(&self, _: SyncRoom, _: &PowerLevelsEvent) {}
async fn on_state_power_levels(
&self,
_: SyncRoom,
_: &StateEventStub<PowerLevelsEventContent>,
) {
}
/// Fires when `Client` receives a `StateEvent::RoomJoinRules` event.
async fn on_state_join_rules(&self, _: SyncRoom, _: &JoinRulesEvent) {}
async fn on_state_join_rules(&self, _: SyncRoom, _: &StateEventStub<JoinRulesEventContent>) {}
// `AnyStrippedStateEvent`s
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomMember` event.
async fn on_stripped_state_member(
&self,
_: SyncRoom,
_: &StrippedRoomMember,
_: &StrippedStateEventStub<MemberEventContent>,
_: Option<MemberEventContent>,
) {
}
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomName` event.
async fn on_stripped_state_name(&self, _: SyncRoom, _: &StrippedRoomName) {}
async fn on_stripped_state_name(
&self,
_: SyncRoom,
_: &StrippedStateEventStub<NameEventContent>,
) {
}
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomCanonicalAlias` event.
async fn on_stripped_state_canonical_alias(&self, _: SyncRoom, _: &StrippedRoomCanonicalAlias) {
async fn on_stripped_state_canonical_alias(
&self,
_: SyncRoom,
_: &StrippedStateEventStub<CanonicalAliasEventContent>,
) {
}
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomAliases` event.
async fn on_stripped_state_aliases(&self, _: SyncRoom, _: &StrippedRoomAliases) {}
async fn on_stripped_state_aliases(
&self,
_: SyncRoom,
_: &StrippedStateEventStub<AliasesEventContent>,
) {
}
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomAvatar` event.
async fn on_stripped_state_avatar(&self, _: SyncRoom, _: &StrippedRoomAvatar) {}
async fn on_stripped_state_avatar(
&self,
_: SyncRoom,
_: &StrippedStateEventStub<AvatarEventContent>,
) {
}
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomPowerLevels` event.
async fn on_stripped_state_power_levels(&self, _: SyncRoom, _: &StrippedRoomPowerLevels) {}
async fn on_stripped_state_power_levels(
&self,
_: SyncRoom,
_: &StrippedStateEventStub<PowerLevelsEventContent>,
) {
}
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomJoinRules` event.
async fn on_stripped_state_join_rules(&self, _: SyncRoom, _: &StrippedRoomJoinRules) {}
async fn on_stripped_state_join_rules(
&self,
_: SyncRoom,
_: &StrippedStateEventStub<JoinRulesEventContent>,
) {
}
// `NonRoomEvent` (this is a type alias from ruma_events)
/// Fires when `Client` receives a `NonRoomEvent::RoomPresence` event.
async fn on_non_room_presence(&self, _: SyncRoom, _: &PresenceEvent) {}
/// Fires when `Client` receives a `NonRoomEvent::RoomName` event.
async fn on_non_room_ignored_users(&self, _: SyncRoom, _: &IgnoredUserListEvent) {}
async fn on_non_room_ignored_users(
&self,
_: SyncRoom,
_: &BasicEvent<IgnoredUserListEventContent>,
) {
}
/// Fires when `Client` receives a `NonRoomEvent::RoomCanonicalAlias` event.
async fn on_non_room_push_rules(&self, _: SyncRoom, _: &PushRulesEvent) {}
async fn on_non_room_push_rules(&self, _: SyncRoom, _: &BasicEvent<PushRulesEventContent>) {}
/// Fires when `Client` receives a `NonRoomEvent::RoomAliases` event.
async fn on_non_room_fully_read(&self, _: SyncRoom, _: &FullyReadEvent) {}
async fn on_non_room_fully_read(
&self,
_: SyncRoom,
_: &EphemeralRoomEvent<FullyReadEventContent>,
) {
}
/// Fires when `Client` receives a `NonRoomEvent::Typing` event.
async fn on_non_room_typing(&self, _: SyncRoom, _: &TypingEvent) {}
async fn on_non_room_typing(&self, _: SyncRoom, _: &EphemeralRoomEvent<TypingEventContent>) {}
/// Fires when `Client` receives a `NonRoomEvent::Receipt` event.
///
/// This is always a read receipt.
async fn on_non_room_receipt(&self, _: SyncRoom, _: &ReceiptEvent) {}
async fn on_non_room_receipt(&self, _: SyncRoom, _: &EphemeralRoomEvent<ReceiptEventContent>) {}
// `PresenceEvent` is a struct so there is only the one method
/// Fires when `Client` receives a `NonRoomEvent::RoomAliases` event.
@ -214,63 +274,89 @@ mod test {
#[async_trait]
impl EventEmitter for EvEmitterTest {
async fn on_room_member(&self, _: SyncRoom, _: &MemberEvent) {
async fn on_room_member(&self, _: SyncRoom, _: &StateEventStub<MemberEventContent>) {
self.0.lock().await.push("member".to_string())
}
async fn on_room_name(&self, _: SyncRoom, _: &NameEvent) {
async fn on_room_name(&self, _: SyncRoom, _: &StateEventStub<NameEventContent>) {
self.0.lock().await.push("name".to_string())
}
async fn on_room_canonical_alias(&self, _: SyncRoom, _: &CanonicalAliasEvent) {
async fn on_room_canonical_alias(
&self,
_: SyncRoom,
_: &StateEventStub<CanonicalAliasEventContent>,
) {
self.0.lock().await.push("canonical".to_string())
}
async fn on_room_aliases(&self, _: SyncRoom, _: &AliasesEvent) {
async fn on_room_aliases(&self, _: SyncRoom, _: &StateEventStub<AliasesEventContent>) {
self.0.lock().await.push("aliases".to_string())
}
async fn on_room_avatar(&self, _: SyncRoom, _: &AvatarEvent) {
async fn on_room_avatar(&self, _: SyncRoom, _: &StateEventStub<AvatarEventContent>) {
self.0.lock().await.push("avatar".to_string())
}
async fn on_room_message(&self, _: SyncRoom, _: &MessageEvent) {
async fn on_room_message(&self, _: SyncRoom, _: &MessageEventStub<MsgEventContent>) {
self.0.lock().await.push("message".to_string())
}
async fn on_room_message_feedback(&self, _: SyncRoom, _: &FeedbackEvent) {
async fn on_room_message_feedback(
&self,
_: SyncRoom,
_: &MessageEventStub<FeedbackEventContent>,
) {
self.0.lock().await.push("feedback".to_string())
}
async fn on_room_redaction(&self, _: SyncRoom, _: &RedactionEvent) {
async fn on_room_redaction(&self, _: SyncRoom, _: &RedactionEventStub) {
self.0.lock().await.push("redaction".to_string())
}
async fn on_room_power_levels(&self, _: SyncRoom, _: &PowerLevelsEvent) {
async fn on_room_power_levels(
&self,
_: SyncRoom,
_: &StateEventStub<PowerLevelsEventContent>,
) {
self.0.lock().await.push("power".to_string())
}
async fn on_room_tombstone(&self, _: SyncRoom, _: &TombstoneEvent) {
async fn on_room_tombstone(&self, _: SyncRoom, _: &StateEventStub<TombstoneEventContent>) {
self.0.lock().await.push("tombstone".to_string())
}
async fn on_state_member(&self, _: SyncRoom, _: &MemberEvent) {
async fn on_state_member(&self, _: SyncRoom, _: &StateEventStub<MemberEventContent>) {
self.0.lock().await.push("state member".to_string())
}
async fn on_state_name(&self, _: SyncRoom, _: &NameEvent) {
async fn on_state_name(&self, _: SyncRoom, _: &StateEventStub<NameEventContent>) {
self.0.lock().await.push("state name".to_string())
}
async fn on_state_canonical_alias(&self, _: SyncRoom, _: &CanonicalAliasEvent) {
async fn on_state_canonical_alias(
&self,
_: SyncRoom,
_: &StateEventStub<CanonicalAliasEventContent>,
) {
self.0.lock().await.push("state canonical".to_string())
}
async fn on_state_aliases(&self, _: SyncRoom, _: &AliasesEvent) {
async fn on_state_aliases(&self, _: SyncRoom, _: &StateEventStub<AliasesEventContent>) {
self.0.lock().await.push("state aliases".to_string())
}
async fn on_state_avatar(&self, _: SyncRoom, _: &AvatarEvent) {
async fn on_state_avatar(&self, _: SyncRoom, _: &StateEventStub<AvatarEventContent>) {
self.0.lock().await.push("state avatar".to_string())
}
async fn on_state_power_levels(&self, _: SyncRoom, _: &PowerLevelsEvent) {
async fn on_state_power_levels(
&self,
_: SyncRoom,
_: &StateEventStub<PowerLevelsEventContent>,
) {
self.0.lock().await.push("state power".to_string())
}
async fn on_state_join_rules(&self, _: SyncRoom, _: &JoinRulesEvent) {
async fn on_state_join_rules(
&self,
_: SyncRoom,
_: &StateEventStub<JoinRulesEventContent>,
) {
self.0.lock().await.push("state rules".to_string())
}
// `AnyStrippedStateEvent`s
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomMember` event.
async fn on_stripped_state_member(
&self,
_: SyncRoom,
_: &StrippedRoomMember,
_: &StrippedStateEventStub<MemberEventContent>,
_: Option<MemberEventContent>,
) {
self.0
@ -278,57 +364,103 @@ mod test {
.await
.push("stripped state member".to_string())
}
async fn on_stripped_state_name(&self, _: SyncRoom, _: &StrippedRoomName) {
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomName` event.
async fn on_stripped_state_name(
&self,
_: SyncRoom,
_: &StrippedStateEventStub<NameEventContent>,
) {
self.0.lock().await.push("stripped state name".to_string())
}
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomCanonicalAlias` event.
async fn on_stripped_state_canonical_alias(
&self,
_: SyncRoom,
_: &StrippedRoomCanonicalAlias,
_: &StrippedStateEventStub<CanonicalAliasEventContent>,
) {
self.0
.lock()
.await
.push("stripped state canonical".to_string())
}
async fn on_stripped_state_aliases(&self, _: SyncRoom, _: &StrippedRoomAliases) {
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomAliases` event.
async fn on_stripped_state_aliases(
&self,
_: SyncRoom,
_: &StrippedStateEventStub<AliasesEventContent>,
) {
self.0
.lock()
.await
.push("stripped state aliases".to_string())
}
async fn on_stripped_state_avatar(&self, _: SyncRoom, _: &StrippedRoomAvatar) {
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomAvatar` event.
async fn on_stripped_state_avatar(
&self,
_: SyncRoom,
_: &StrippedStateEventStub<AvatarEventContent>,
) {
self.0
.lock()
.await
.push("stripped state avatar".to_string())
}
async fn on_stripped_state_power_levels(&self, _: SyncRoom, _: &StrippedRoomPowerLevels) {
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomPowerLevels` event.
async fn on_stripped_state_power_levels(
&self,
_: SyncRoom,
_: &StrippedStateEventStub<PowerLevelsEventContent>,
) {
self.0.lock().await.push("stripped state power".to_string())
}
async fn on_stripped_state_join_rules(&self, _: SyncRoom, _: &StrippedRoomJoinRules) {
/// Fires when `Client` receives a `AnyStrippedStateEvent::StrippedRoomJoinRules` event.
async fn on_stripped_state_join_rules(
&self,
_: SyncRoom,
_: &StrippedStateEventStub<JoinRulesEventContent>,
) {
self.0.lock().await.push("stripped state rules".to_string())
}
async fn on_non_room_presence(&self, _: SyncRoom, _: &PresenceEvent) {
self.0.lock().await.push("account presence".to_string())
self.0.lock().await.push("presence".to_string())
}
async fn on_non_room_ignored_users(&self, _: SyncRoom, _: &IgnoredUserListEvent) {
async fn on_non_room_ignored_users(
&self,
_: SyncRoom,
_: &BasicEvent<IgnoredUserListEventContent>,
) {
self.0.lock().await.push("account ignore".to_string())
}
async fn on_non_room_push_rules(&self, _: SyncRoom, _: &PushRulesEvent) {
async fn on_non_room_push_rules(&self, _: SyncRoom, _: &BasicEvent<PushRulesEventContent>) {
self.0.lock().await.push("account push rules".to_string())
}
async fn on_non_room_fully_read(&self, _: SyncRoom, _: &FullyReadEvent) {
async fn on_non_room_fully_read(
&self,
_: SyncRoom,
_: &EphemeralRoomEvent<FullyReadEventContent>,
) {
self.0.lock().await.push("account read".to_string())
}
async fn on_non_room_typing(&self, _: SyncRoom, _: &TypingEvent) {
async fn on_non_room_typing(
&self,
_: SyncRoom,
_: &EphemeralRoomEvent<TypingEventContent>,
) {
self.0.lock().await.push("typing event".to_string())
}
async fn on_non_room_receipt(
&self,
_: SyncRoom,
_: &EphemeralRoomEvent<ReceiptEventContent>,
) {
self.0.lock().await.push("receipt event".to_string())
}
async fn on_presence_event(&self, _: SyncRoom, _: &PresenceEvent) {
self.0.lock().await.push("presence event".to_string())
}
async fn on_unrecognized_event(&self, _: SyncRoom, _: &CustomOrRawEvent<'_>) {
async fn on_unrecognized_event(&self, _: SyncRoom, event: &CustomOrRawEvent<'_>) {
println!("{:#?}", event);
self.0.lock().await.push("unrecognized event".to_string())
}
}
@ -373,9 +505,10 @@ mod test {
"state member",
"state member",
"message",
"account read",
"account ignore",
"presence event"
"presence event",
"receipt event",
"account read",
],
)
}
@ -448,6 +581,7 @@ mod test {
"redaction",
"unrecognized event",
"unrecognized event",
"receipt event",
"typing event"
],
)

View File

@ -1,55 +0,0 @@
//! De-/serialization functions to and from json strings, allows the type to be used as a query string.
use serde::de::{Deserialize, Deserializer, Error as _};
use crate::events::collections::all::Event;
use crate::events::presence::PresenceEvent;
use crate::events::EventJson;
pub fn deserialize_events<'de, D>(deserializer: D) -> Result<Vec<Event>, D::Error>
where
D: Deserializer<'de>,
{
let mut events = vec![];
let ev = Vec::<EventJson<Event>>::deserialize(deserializer)?;
for event in ev {
events.push(event.deserialize().map_err(D::Error::custom)?);
}
Ok(events)
}
pub fn deserialize_presence<'de, D>(deserializer: D) -> Result<Vec<PresenceEvent>, D::Error>
where
D: Deserializer<'de>,
{
let mut events = vec![];
let ev = Vec::<EventJson<PresenceEvent>>::deserialize(deserializer)?;
for event in ev {
events.push(event.deserialize().map_err(D::Error::custom)?);
}
Ok(events)
}
#[cfg(test)]
mod test {
use crate::events::room::member::MemberEvent;
use crate::events::EventJson;
use crate::models::RoomMember;
use matrix_sdk_test::test_json;
#[test]
fn events_and_presence_deserialization() {
let ev_json = test_json::MEMBER.to_string();
let ev = serde_json::from_str::<EventJson<MemberEvent>>(&ev_json)
.unwrap()
.deserialize()
.unwrap();
let member = RoomMember::new(&ev);
let member_json = serde_json::to_string(&member).unwrap();
let mem = serde_json::from_str::<RoomMember>(&member_json).unwrap();
assert_eq!(member, mem);
}
}

View File

@ -7,11 +7,12 @@ use std::cmp::Ordering;
use std::ops::Deref;
use std::vec::IntoIter;
use crate::events::room::message::MessageEvent;
use crate::events::EventJson;
use crate::events::room::message::MessageEventContent;
use crate::events::MessageEventStub;
use serde::{de, ser, Serialize};
type MessageEvent = MessageEventStub<MessageEventContent>;
/// A queue that holds the 10 most recent messages received from the server.
#[derive(Clone, Debug, Default)]
pub struct MessageQueue {
@ -115,13 +116,10 @@ pub(crate) mod ser_deser {
where
D: de::Deserializer<'de>,
{
use serde::de::Error;
let messages: Vec<EventJson<MessageEvent>> = de::Deserialize::deserialize(deserializer)?;
let messages: Vec<MessageEvent> = de::Deserialize::deserialize(deserializer)?;
let mut msgs = vec![];
for json in messages {
let msg = json.deserialize().map_err(D::Error::custom)?;
for msg in messages {
msgs.push(MessageWrapper(msg));
}
@ -160,17 +158,11 @@ mod test {
let mut room = Room::new(&id, &user);
let json: &serde_json::Value = &test_json::MESSAGE_TEXT;
let event = serde_json::from_value::<EventJson<RoomEvent>>(json.clone()).unwrap();
let msg = serde_json::from_value::<MessageEvent>(json.clone()).unwrap();
let mut msgs = MessageQueue::new();
let message = if let RoomEvent::RoomMessage(msg) = event.deserialize().unwrap() {
msgs.push(msg.clone());
msg
} else {
panic!("this should always be a RoomMessage")
};
room.messages = msgs.clone();
msgs.push(msg.clone());
room.messages = msgs;
let mut joined_rooms = HashMap::new();
joined_rooms.insert(id, room);
@ -191,7 +183,7 @@ mod test {
"creator": null,
"joined_members": {},
"invited_members": {},
"messages": [ message ],
"messages": [ msg ],
"typing_users": [],
"power_levels": null,
"encrypted": null,
@ -212,19 +204,14 @@ mod test {
let mut room = Room::new(&id, &user);
let json: &serde_json::Value = &test_json::MESSAGE_TEXT;
let event = serde_json::from_value::<EventJson<RoomEvent>>(json.clone()).unwrap();
let msg = serde_json::from_value::<MessageEvent>(json.clone()).unwrap();
let mut msgs = MessageQueue::new();
let message = if let RoomEvent::RoomMessage(msg) = event.deserialize().unwrap() {
msgs.push(msg.clone());
msg
} else {
panic!("this should always be a RoomMessage")
};
msgs.push(msg.clone());
room.messages = msgs;
let mut joined_rooms = HashMap::new();
joined_rooms.insert(id, room.clone());
joined_rooms.insert(id, room);
let json = serde_json::json!({
"!roomid:example.com": {
@ -242,7 +229,7 @@ mod test {
"creator": null,
"joined_members": {},
"invited_members": {},
"messages": [ message ],
"messages": [ msg ],
"typing_users": [],
"power_levels": null,
"encrypted": null,

View File

@ -1,4 +1,3 @@
mod event_deser;
#[cfg(feature = "messages")]
#[cfg_attr(docsrs, doc(cfg(feature = "messages")))]
mod message;

View File

@ -22,28 +22,35 @@ use super::message::MessageQueue;
use super::RoomMember;
use crate::api::r0::sync::sync_events::{RoomSummary, UnreadNotificationsCount};
use crate::events::collections::all::{RoomEvent, StateEvent};
use crate::events::presence::PresenceEvent;
use crate::events::room::{
aliases::AliasesEvent,
canonical_alias::CanonicalAliasEvent,
encryption::EncryptionEvent,
member::{MemberEvent, MembershipChange},
name::NameEvent,
power_levels::{NotificationPowerLevels, PowerLevelsEvent, PowerLevelsEventContent},
tombstone::TombstoneEvent,
aliases::AliasesEventContent,
canonical_alias::CanonicalAliasEventContent,
encryption::EncryptionEventContent,
member::{MemberEventContent, MembershipChange},
name::NameEventContent,
power_levels::{NotificationPowerLevels, PowerLevelsEventContent},
tombstone::TombstoneEventContent,
};
use crate::events::{
Algorithm, AnyMessageEventStub, AnyRoomEventStub, AnyStateEventStub, AnyStrippedStateEventStub,
EventType, StateEventStub, StrippedStateEventStub,
};
use crate::events::stripped::{AnyStrippedStateEvent, StrippedRoomName};
use crate::events::{Algorithm, EventType};
#[cfg(feature = "messages")]
use crate::events::room::message::MessageEvent;
use crate::events::{room::message::MessageEventContent as MsgContent, MessageEventStub};
use crate::identifiers::{RoomAliasId, RoomId, UserId};
use crate::js_int::{Int, UInt};
use serde::{Deserialize, Serialize};
#[cfg(feature = "messages")]
type SentMessageEvent = MessageEventStub<MsgContent>;
#[derive(Debug, Default, PartialEq, Serialize, Deserialize, Clone)]
#[cfg_attr(test, derive(Clone))]
/// `RoomName` allows the calculation of a text room name.
pub struct RoomName {
/// The displayed name of the room.
@ -123,8 +130,8 @@ impl EncryptionInfo {
}
}
impl From<&EncryptionEvent> for EncryptionInfo {
fn from(event: &EncryptionEvent) -> Self {
impl From<&StateEventStub<EncryptionEventContent>> for EncryptionInfo {
fn from(event: &StateEventStub<EncryptionEventContent>) -> Self {
EncryptionInfo {
algorithm: event.content.algorithm.clone(),
rotation_period_ms: event
@ -357,29 +364,15 @@ impl Room {
}
}
/// Process the member event of an entering user.
///
/// Returns true if this made a change to the room's state, false otherwise.
fn add_member(&mut self, event: &MemberEvent) -> bool {
let new_member = RoomMember::new(event);
if self.joined_members.contains_key(&new_member.user_id)
|| self.invited_members.contains_key(&new_member.user_id)
fn add_member(&mut self, event: &StateEventStub<MemberEventContent>, room_id: &RoomId) -> bool {
if self
.members
.contains_key(&UserId::try_from(event.state_key.as_str()).unwrap())
{
return false;
}
match event.membership_change() {
MembershipChange::Joined => self
.joined_members
.insert(new_member.user_id.clone(), new_member.clone()),
MembershipChange::Invited => self
.invited_members
.insert(new_member.user_id.clone(), new_member.clone()),
_ => {
panic!("Room::add_member called on an event that is neither a join nor an invite.")
}
};
let member = RoomMember::new(event, room_id);
// Perform display name disambiguations, if necessary.
let disambiguations = self.disambiguation_updates(&new_member, MemberDirection::Entering);
@ -396,7 +389,7 @@ impl Room {
/// Process the member event of a leaving user.
///
/// Returns true if this made a change to the room's state, false otherwise.
fn remove_member(&mut self, event: &MemberEvent) -> bool {
fn remove_member(&mut self, event: &StateEventStub<MemberEventContent>) -> bool {
let leaving_member = RoomMember::new(event);
// Perform display name disambiguations, if necessary.
@ -535,7 +528,7 @@ impl Room {
true
}
fn set_room_power_level(&mut self, event: &PowerLevelsEvent) -> bool {
fn set_room_power_level(&mut self, event: &StateEventStub<PowerLevelsEventContent>) -> bool {
let PowerLevelsEventContent {
ban,
events,
@ -583,7 +576,11 @@ impl Room {
/// Handle a room.member updating the room state if necessary.
///
/// Returns true if the joined member list changed, false otherwise.
pub fn handle_membership(&mut self, event: &MemberEvent) -> bool {
pub fn handle_membership(
&mut self,
event: &StateEventStub<MemberEventContent>,
room_id: &RoomId,
) -> bool {
use MembershipChange::*;
// TODO: This would not be handled correctly as all the MemberEvents have the `prev_content`
@ -594,7 +591,7 @@ impl Room {
self.remove_member(event)
}
ProfileChanged => {
let user_id = if let Ok(id) = UserId::try_from(event.state_key.as_str()) {
let user = if let Ok(id) = UserId::try_from(event.state_key.as_str()) {
id
} else {
return false;
@ -617,14 +614,14 @@ impl Room {
/// Returns true if `MessageQueue` was added to.
#[cfg(feature = "messages")]
#[cfg_attr(docsrs, doc(cfg(feature = "messages")))]
pub fn handle_message(&mut self, event: &MessageEvent) -> bool {
pub fn handle_message(&mut self, event: &SentMessageEvent) -> bool {
self.messages.push(event.clone())
}
/// Handle a room.aliases event, updating the room state if necessary.
///
/// Returns true if the room name changed, false otherwise.
pub fn handle_room_aliases(&mut self, event: &AliasesEvent) -> bool {
pub fn handle_room_aliases(&mut self, event: &StateEventStub<AliasesEventContent>) -> bool {
match event.content.aliases.as_slice() {
[alias] => self.push_room_alias(alias),
[alias, ..] => self.push_room_alias(alias),
@ -635,7 +632,7 @@ impl Room {
/// Handle a room.canonical_alias event, updating the room state if necessary.
///
/// Returns true if the room name changed, false otherwise.
pub fn handle_canonical(&mut self, event: &CanonicalAliasEvent) -> bool {
pub fn handle_canonical(&mut self, event: &StateEventStub<CanonicalAliasEventContent>) -> bool {
match &event.content.alias {
Some(name) => self.canonical_alias(&name),
_ => false,
@ -645,7 +642,7 @@ impl Room {
/// Handle a room.name event, updating the room state if necessary.
///
/// Returns true if the room name changed, false otherwise.
pub fn handle_room_name(&mut self, event: &NameEvent) -> bool {
pub fn handle_room_name(&mut self, event: &StateEventStub<NameEventContent>) -> bool {
match event.content.name() {
Some(name) => self.set_room_name(name),
_ => false,
@ -655,7 +652,10 @@ impl Room {
/// Handle a room.name event, updating the room state if necessary.
///
/// Returns true if the room name changed, false otherwise.
pub fn handle_stripped_room_name(&mut self, event: &StrippedRoomName) -> bool {
pub fn handle_stripped_room_name(
&mut self,
event: &StrippedStateEventStub<NameEventContent>,
) -> bool {
match event.content.name() {
Some(name) => self.set_room_name(name),
_ => false,
@ -665,7 +665,7 @@ impl Room {
/// Handle a room.power_levels event, updating the room state if necessary.
///
/// Returns true if the room name changed, false otherwise.
pub fn handle_power_level(&mut self, event: &PowerLevelsEvent) -> bool {
pub fn handle_power_level(&mut self, event: &StateEventStub<PowerLevelsEventContent>) -> bool {
// NOTE: this is always true, we assume that if we get an event their is an update.
let mut updated = self.set_room_power_level(event);
@ -684,7 +684,7 @@ impl Room {
updated
}
fn handle_tombstone(&mut self, event: &TombstoneEvent) -> bool {
fn handle_tombstone(&mut self, event: &StateEventStub<TombstoneEventContent>) -> bool {
self.tombstone = Some(Tombstone {
body: event.content.body.clone(),
replacement: event.content.replacement_room.clone(),
@ -692,7 +692,7 @@ impl Room {
true
}
fn handle_encryption_event(&mut self, event: &EncryptionEvent) -> bool {
fn handle_encryption_event(&mut self, event: &StateEventStub<EncryptionEventContent>) -> bool {
self.encrypted = Some(event.into());
true
}
@ -704,21 +704,28 @@ impl Room {
/// # Arguments
///
/// * `event` - The event of the room.
pub fn receive_timeline_event(&mut self, event: &RoomEvent) -> bool {
match event {
// update to the current members of the room
RoomEvent::RoomMember(member) => self.handle_membership(member),
// finds all events related to the name of the room for later use
RoomEvent::RoomName(name) => self.handle_room_name(name),
RoomEvent::RoomCanonicalAlias(c_alias) => self.handle_canonical(c_alias),
RoomEvent::RoomAliases(alias) => self.handle_room_aliases(alias),
// power levels of the room members
RoomEvent::RoomPowerLevels(power) => self.handle_power_level(power),
RoomEvent::RoomTombstone(tomb) => self.handle_tombstone(tomb),
RoomEvent::RoomEncryption(encrypt) => self.handle_encryption_event(encrypt),
#[cfg(feature = "messages")]
RoomEvent::RoomMessage(msg) => self.handle_message(msg),
_ => false,
pub fn receive_timeline_event(&mut self, event: &AnyRoomEventStub, room_id: &RoomId) -> bool {
match &event {
AnyRoomEventStub::State(event) => match &event {
// update to the current members of the room
AnyStateEventStub::RoomMember(event) => self.handle_membership(&event, room_id),
// finds all events related to the name of the room for later use
AnyStateEventStub::RoomName(event) => self.handle_room_name(&event),
AnyStateEventStub::RoomCanonicalAlias(event) => self.handle_canonical(&event),
AnyStateEventStub::RoomAliases(event) => self.handle_room_aliases(&event),
// power levels of the room members
AnyStateEventStub::RoomPowerLevels(event) => self.handle_power_level(&event),
AnyStateEventStub::RoomTombstone(event) => self.handle_tombstone(&event),
AnyStateEventStub::RoomEncryption(event) => self.handle_encryption_event(&event),
_ => false,
},
AnyRoomEventStub::Message(event) => match &event {
#[cfg(feature = "messages")]
AnyMessageEventStub::RoomMessage(event) => self.handle_message(&event),
// TODO if a redaction event deletes one of our saved messages delete it?
AnyMessageEventStub::RoomRedaction(_) => false,
_ => false,
},
}
}
@ -729,18 +736,18 @@ impl Room {
/// # Arguments
///
/// * `event` - The event of the room.
pub fn receive_state_event(&mut self, event: &StateEvent) -> bool {
pub fn receive_state_event(&mut self, event: &AnyStateEventStub, room_id: &RoomId) -> bool {
match event {
// update to the current members of the room
StateEvent::RoomMember(member) => self.handle_membership(member),
AnyStateEventStub::RoomMember(member) => self.handle_membership(member, room_id),
// finds all events related to the name of the room for later use
StateEvent::RoomName(name) => self.handle_room_name(name),
StateEvent::RoomCanonicalAlias(c_alias) => self.handle_canonical(c_alias),
StateEvent::RoomAliases(alias) => self.handle_room_aliases(alias),
AnyStateEventStub::RoomName(name) => self.handle_room_name(name),
AnyStateEventStub::RoomCanonicalAlias(c_alias) => self.handle_canonical(c_alias),
AnyStateEventStub::RoomAliases(alias) => self.handle_room_aliases(alias),
// power levels of the room members
StateEvent::RoomPowerLevels(power) => self.handle_power_level(power),
StateEvent::RoomTombstone(tomb) => self.handle_tombstone(tomb),
StateEvent::RoomEncryption(encrypt) => self.handle_encryption_event(encrypt),
AnyStateEventStub::RoomPowerLevels(power) => self.handle_power_level(power),
AnyStateEventStub::RoomTombstone(tomb) => self.handle_tombstone(tomb),
AnyStateEventStub::RoomEncryption(encrypt) => self.handle_encryption_event(encrypt),
_ => false,
}
}
@ -753,9 +760,9 @@ impl Room {
///
/// * `event` - The `AnyStrippedStateEvent` sent by the server for invited but not
/// joined rooms.
pub fn receive_stripped_state_event(&mut self, event: &AnyStrippedStateEvent) -> bool {
match event {
AnyStrippedStateEvent::RoomName(n) => self.handle_stripped_room_name(n),
pub fn receive_stripped_state_event(&mut self, event: &AnyStrippedStateEventStub) -> bool {
match &event {
AnyStrippedStateEventStub::RoomName(event) => self.handle_stripped_room_name(event),
_ => false,
}
}
@ -1025,8 +1032,8 @@ mod test {
let user_id = UserId::try_from("@example:localhost").unwrap();
let mut response = EventBuilder::default()
.add_room_event(EventsJson::Member, RoomEvent::RoomMember)
.add_room_event(EventsJson::PowerLevels, RoomEvent::RoomPowerLevels)
.add_state_event(EventsFile::Member)
.add_state_event(EventsFile::PowerLevels)
.build_sync_response();
client.receive_sync_response(&mut response).await.unwrap();
@ -1054,7 +1061,7 @@ mod test {
let room_id = get_room_id();
let mut response = EventBuilder::default()
.add_state_event(EventsJson::Aliases, StateEvent::RoomAliases)
.add_state_event(EventsFile::Aliases)
.build_sync_response();
client.receive_sync_response(&mut response).await.unwrap();
@ -1072,7 +1079,7 @@ mod test {
let room_id = get_room_id();
let mut response = EventBuilder::default()
.add_state_event(EventsJson::Alias, StateEvent::RoomCanonicalAlias)
.add_state_event(EventsFile::Alias)
.build_sync_response();
client.receive_sync_response(&mut response).await.unwrap();
@ -1090,7 +1097,7 @@ mod test {
let room_id = get_room_id();
let mut response = EventBuilder::default()
.add_state_event(EventsJson::Name, StateEvent::RoomName)
.add_state_event(EventsFile::Name)
.build_sync_response();
client.receive_sync_response(&mut response).await.unwrap();
@ -1125,6 +1132,8 @@ mod test {
#[async_test]
#[cfg(not(target_arch = "wasm32"))]
async fn encryption_info_test() {
let room_id = get_room_id();
let mut response = sync_response(SyncResponseFile::DefaultWithSummary);
let user_id = UserId::try_from("@example:localhost").unwrap();
@ -1137,7 +1146,7 @@ mod test {
client.restore_login(session).await.unwrap();
client.receive_sync_response(&mut response).await.unwrap();
let event = EncryptionEvent {
let event = StateEventStub {
event_id: EventId::try_from("$h29iv0s8:example.com").unwrap(),
origin_server_ts: SystemTime::now(),
sender: user_id,
@ -1149,10 +1158,8 @@ mod test {
rotation_period_msgs: Some(100u32.into()),
},
prev_content: None,
room_id: None,
};
let room_id = get_room_id();
let room = client.get_joined_room(&room_id).await.unwrap();
assert!(!room.read().await.is_encrypted());

View File

@ -15,13 +15,13 @@
use std::convert::TryFrom;
use crate::events::collections::all::Event;
use crate::events::presence::{PresenceEvent, PresenceEventContent, PresenceState};
use crate::events::room::{
member::{MemberEvent, MembershipChange},
power_levels::PowerLevelsEvent,
member::{MemberEventContent, MembershipChange, MembershipState},
power_levels::PowerLevelsEventContent,
};
use crate::identifiers::UserId;
use crate::events::StateEventStub;
use crate::identifiers::{RoomId, UserId};
use crate::js_int::{Int, UInt};
use serde::{Deserialize, Serialize};
@ -29,7 +29,6 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)]
/// A Matrix room member.
///
pub struct RoomMember {
/// The unique MXID of the user.
pub user_id: UserId,
@ -42,7 +41,7 @@ pub struct RoomMember {
/// If the user should be considered active.
pub currently_active: Option<bool>,
/// The unique id of the room.
pub room_id: Option<String>,
pub room_id: Option<RoomId>,
/// If the member is typing.
pub typing: Option<bool>,
/// The presence of the user, if found.
@ -53,13 +52,11 @@ pub struct RoomMember {
pub power_level: Option<Int>,
/// The normalized power level of this `RoomMember` (0-100).
pub power_level_norm: Option<Int>,
/// The `MembershipState` of this `RoomMember`.
pub membership: MembershipState,
/// The human readable name of this room member.
pub name: String,
/// The events that created the state of this room member.
#[serde(deserialize_with = "super::event_deser::deserialize_events")]
pub events: Vec<Event>,
/// The `PresenceEvent`s connected to this user.
#[serde(deserialize_with = "super::event_deser::deserialize_presence")]
pub presence_events: Vec<PresenceEvent>,
}
@ -76,10 +73,10 @@ impl PartialEq for RoomMember {
}
impl RoomMember {
pub fn new(event: &MemberEvent) -> Self {
pub fn new(event: &StateEventStub<MemberEventContent>, room_id: &RoomId) -> Self {
Self {
name: event.state_key.clone(),
room_id: event.room_id.as_ref().map(|id| id.to_string()),
room_id: Some(room_id.clone()),
user_id: UserId::try_from(event.state_key.as_str()).unwrap(),
display_name: event.content.displayname.clone(),
avatar_url: event.content.avatar_url.clone(),
@ -90,8 +87,8 @@ impl RoomMember {
typing: None,
power_level: None,
power_level_norm: None,
presence_events: Vec::default(),
events: vec![Event::RoomMember(event.clone())],
membership: event.content.membership,
presence_events: vec![],
}
}
@ -116,7 +113,7 @@ impl RoomMember {
}
/// Handle profile updates.
pub(crate) fn update_profile(&mut self, event: &MemberEvent) -> bool {
pub(crate) fn update_profile(&mut self, event: &StateEventStub<MemberEventContent>) -> bool {
use MembershipChange::*;
match event.membership_change() {
@ -131,7 +128,11 @@ impl RoomMember {
}
}
pub fn update_power(&mut self, event: &PowerLevelsEvent, max_power: Int) -> bool {
pub fn update_power(
&mut self,
event: &StateEventStub<PowerLevelsEventContent>,
max_power: Int,
) -> bool {
let changed;
if let Some(user_power) = event.content.users.get(&self.user_id) {
changed = self.power_level != Some(*user_power);
@ -211,7 +212,7 @@ impl RoomMember {
mod test {
use matrix_sdk_test::{async_test, EventBuilder, EventsJson};
use crate::events::collections::all::RoomEvent;
use crate::events::room::member::MembershipState;
use crate::identifiers::{RoomId, UserId};
use crate::{BaseClient, Session};
@ -244,8 +245,8 @@ mod test {
let room_id = get_room_id();
let mut response = EventBuilder::default()
.add_room_event(EventsJson::Member, RoomEvent::RoomMember)
.add_room_event(EventsJson::PowerLevels, RoomEvent::RoomPowerLevels)
.add_state_event(EventsFile::Member)
.add_state_event(EventsFile::PowerLevels)
.build_sync_response();
client.receive_sync_response(&mut response).await.unwrap();
@ -267,9 +268,9 @@ mod test {
let room_id = get_room_id();
let mut response = EventBuilder::default()
.add_room_event(EventsJson::Member, RoomEvent::RoomMember)
.add_room_event(EventsJson::PowerLevels, RoomEvent::RoomPowerLevels)
.add_presence_event(EventsJson::Presence)
.add_state_event(EventsFile::Member)
.add_state_event(EventsFile::PowerLevels)
.add_presence_event(EventsFile::Presence)
.build_sync_response();
client.receive_sync_response(&mut response).await.unwrap();

View File

@ -201,6 +201,7 @@ mod test {
use tempfile::tempdir;
use crate::identifiers::{RoomId, UserId};
use crate::push::Ruleset;
use crate::{BaseClient, BaseClientConfig, Session};
use matrix_sdk_test::{sync_response, SyncResponseFile};
@ -221,7 +222,7 @@ mod test {
let state = ClientState {
sync_token: Some("hello".into()),
ignored_users: vec![user],
push_ruleset: None,
push_ruleset: None::<Ruleset>,
};
let mut path_with_user = PathBuf::from(path);

View File

@ -23,8 +23,8 @@ mod json_store;
pub use json_store::JsonStore;
use crate::client::{BaseClient, Token};
use crate::events::push_rules::Ruleset;
use crate::identifiers::{RoomId, UserId};
use crate::push::Ruleset;
use crate::{Result, Room, RoomState, Session};
#[cfg(not(target_arch = "wasm32"))]

View File

@ -1,5 +1,5 @@
[package]
authors = ["Damir Jelić <poljar@termina.org.uk>"]
authors = ["Damir Jelić <poljar@termina.org.uk"]
description = "Collection of common types used in the matrix-sdk"
edition = "2018"
homepage = "https://github.com/matrix-org/matrix-rust-sdk"
@ -11,12 +11,16 @@ repository = "https://github.com/matrix-org/matrix-rust-sdk"
version = "0.1.0"
[dependencies]
js_int = "0.1.8"
ruma-api = "0.16.1"
ruma-client-api = "0.9.0"
ruma-events = "0.21.3"
ruma-identifiers = "0.16.2"
instant = { version = "0.1.6", features = ["wasm-bindgen", "now"] }
js_int = "0.1.5"
# ruma-api = "0.16.1"
# ruma-client-api = "0.9.0"
# ruma-events = "0.21.2"
# ruma-identifiers = "0.16.1"
ruma = { git = "https://github.com/DevinR528/ruma", features = ["client-api", "rand"], branch = "matrix-sdk2"}
# ruma = { path = "../../ruma/ruma", features = ["client-api", "rand"] }
instant = { version = "0.1.4", features = ["wasm-bindgen", "now"] }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
uuid = { version = "0.8.1", features = ["v4"] }

View File

@ -1,12 +1,14 @@
pub use instant;
pub use js_int;
pub use ruma_api::{
error::{FromHttpResponseError, IntoHttpError, ServerError},
Endpoint,
pub use ruma::{
api::{
client as api,
error::{FromHttpRequestError, FromHttpResponseError, IntoHttpError, ServerError},
Endpoint, EndpointError,
},
events, identifiers, push,
};
pub use ruma_client_api as api;
pub use ruma_events as events;
pub use ruma_identifiers as identifiers;
pub use uuid;

View File

@ -13,7 +13,7 @@
// limitations under the License.
use std::collections::{BTreeMap, HashMap, HashSet};
use std::convert::{TryFrom, TryInto};
use std::convert::TryInto;
use std::mem;
#[cfg(feature = "sqlite-cryptostore")]
use std::path::Path;
@ -32,17 +32,16 @@ use super::{device::Device, store::Result as StoreError, CryptoStore};
use matrix_sdk_common::api;
use matrix_sdk_common::events::{
collections::all::RoomEvent,
forwarded_room_key::ForwardedRoomKeyEventContent,
room::encrypted::{
CiphertextInfo, EncryptedEvent, EncryptedEventContent, MegolmV1AesSha2Content,
CiphertextInfo, EncryptedEventContent, MegolmV1AesSha2Content,
OlmV1Curve25519AesSha2Content,
},
room::message::MessageEventContent,
to_device::{
AnyToDeviceEvent as ToDeviceEvent, ToDeviceEncrypted, ToDeviceForwardedRoomKey,
ToDeviceRoomKey, ToDeviceRoomKeyRequest,
},
Algorithm, EventJson, EventType,
room_key::RoomKeyEventContent,
room_key_request::RoomKeyRequestEventContent,
Algorithm, AnyRoomEventStub, AnyToDeviceEvent, EventJson, EventType, MessageEventStub,
ToDeviceEvent,
};
use matrix_sdk_common::identifiers::{DeviceId, RoomId, UserId};
use matrix_sdk_common::uuid::Uuid;
@ -825,7 +824,7 @@ impl OlmMachine {
sender: &UserId,
sender_key: &str,
message: OlmMessage,
) -> OlmResult<(EventJson<ToDeviceEvent>, String)> {
) -> OlmResult<(EventJson<AnyToDeviceEvent>, String)> {
// First try to decrypt using an existing session.
let plaintext = if let Some(p) = self
.try_decrypt_olm_message(sender, sender_key, &message)
@ -894,7 +893,7 @@ impl OlmMachine {
&self,
sender: &UserId,
plaintext: &str,
) -> OlmResult<(EventJson<ToDeviceEvent>, String)> {
) -> OlmResult<(EventJson<AnyToDeviceEvent>, String)> {
// TODO make the errors a bit more specific.
let decrypted_json: Value = serde_json::from_str(&plaintext)?;
@ -939,7 +938,8 @@ impl OlmMachine {
.ok_or(EventError::MissingSigningKey)?;
Ok((
serde_json::from_value::<EventJson<ToDeviceEvent>>(decrypted_json)?,
// FIXME EventJson<Any*Event> fails to deserialize still?
EventJson::from(serde_json::from_value::<AnyToDeviceEvent>(decrypted_json)?),
signing_key.to_owned(),
))
}
@ -954,8 +954,8 @@ impl OlmMachine {
/// * `event` - The to-device event that should be decrypted.
async fn decrypt_to_device_event(
&mut self,
event: &ToDeviceEncrypted,
) -> OlmResult<EventJson<ToDeviceEvent>> {
event: &ToDeviceEvent<EncryptedEventContent>,
) -> OlmResult<EventJson<AnyToDeviceEvent>> {
info!("Decrypting to-device event");
let content = if let EncryptedEventContent::OlmV1Curve25519AesSha2(c) = &event.content {
@ -1018,8 +1018,8 @@ impl OlmMachine {
&mut self,
sender_key: &str,
signing_key: &str,
event: &mut ToDeviceRoomKey,
) -> OlmResult<Option<EventJson<ToDeviceEvent>>> {
event: &mut ToDeviceEvent<RoomKeyEventContent>,
) -> OlmResult<Option<EventJson<AnyToDeviceEvent>>> {
match event.content.algorithm {
Algorithm::MegolmV1AesSha2 => {
let session_key = GroupSessionKey(mem::take(&mut event.content.session_key));
@ -1031,16 +1031,8 @@ impl OlmMachine {
session_key,
)?;
let _ = self.store.save_inbound_group_session(session).await?;
// TODO ideally we would rewrap the event again just like so
// let event = EventJson::from(ToDeviceEvent::RoomKey(event.clone()));
// This saidly lacks a type once it's serialized again, fix
// this in Ruma.
let mut json = serde_json::to_value(event.clone())?;
json.as_object_mut()
.unwrap()
.insert("type".to_owned(), Value::String("m.room_key".to_owned()));
let event = serde_json::from_value::<EventJson<ToDeviceEvent>>(json)?;
let event = EventJson::from(AnyToDeviceEvent::RoomKey(event.clone()));
Ok(Some(event))
}
_ => {
@ -1324,7 +1316,7 @@ impl OlmMachine {
&self,
_sender_key: &str,
_signing_key: &str,
_event: &ToDeviceForwardedRoomKey,
_event: &ToDeviceEvent<ForwardedRoomKeyEventContent>,
) -> OlmResult<()> {
Ok(())
// TODO
@ -1343,8 +1335,8 @@ impl OlmMachine {
&mut self,
sender_key: &str,
signing_key: &str,
event: &EventJson<ToDeviceEvent>,
) -> OlmResult<Option<EventJson<ToDeviceEvent>>> {
event: &EventJson<AnyToDeviceEvent>,
) -> OlmResult<Option<EventJson<AnyToDeviceEvent>>> {
let event = if let Ok(e) = event.deserialize() {
e
} else {
@ -1353,10 +1345,10 @@ impl OlmMachine {
};
match event {
ToDeviceEvent::RoomKey(mut e) => {
AnyToDeviceEvent::RoomKey(mut e) => {
Ok(self.add_room_key(sender_key, signing_key, &mut e).await?)
}
ToDeviceEvent::ForwardedRoomKey(e) => {
AnyToDeviceEvent::ForwardedRoomKey(e) => {
self.add_forwarded_room_key(sender_key, signing_key, &e)?;
Ok(None)
}
@ -1367,11 +1359,11 @@ impl OlmMachine {
}
}
fn handle_room_key_request(&self, _: &ToDeviceRoomKeyRequest) {
fn handle_room_key_request(&self, _: &ToDeviceEvent<RoomKeyRequestEventContent>) {
// TODO handle room key requests here.
}
fn handle_verification_event(&self, _: &ToDeviceEvent) {
fn handle_verification_event(&self, _: &AnyToDeviceEvent) {
// TODO handle to-device verification events here.
}
@ -1394,17 +1386,9 @@ impl OlmMachine {
let count: u64 = one_time_key_count.map_or(0, |c| (*c).into());
self.update_key_count(count);
if let Some(device_list) = &response.device_lists {
for user_id in &device_list.changed {
let user_id = if let Ok(u) = UserId::try_from(user_id.to_owned()) {
u
} else {
continue;
};
if let Err(e) = self.mark_user_as_changed(&user_id).await {
error!("Error marking a tracked user as changed {:?}", e);
}
for user_id in &response.device_lists.changed {
if let Err(e) = self.mark_user_as_changed(&user_id).await {
error!("Error marking a tracked user as changed {:?}", e);
}
}
@ -1420,8 +1404,8 @@ impl OlmMachine {
info!("Received a to-device event {:?}", event);
match &event {
ToDeviceEvent::RoomEncrypted(e) => {
let decrypted_event = match self.decrypt_to_device_event(e).await {
AnyToDeviceEvent::RoomEncrypted(e) => {
let decrypted_event = match self.decrypt_to_device_event(&e).await {
Ok(e) => e,
Err(err) => {
warn!(
@ -1438,13 +1422,15 @@ impl OlmMachine {
// before we replace the result.
*event_result = decrypted_event;
}
ToDeviceEvent::RoomKeyRequest(e) => self.handle_room_key_request(e),
ToDeviceEvent::KeyVerificationAccept(..)
| ToDeviceEvent::KeyVerificationCancel(..)
| ToDeviceEvent::KeyVerificationKey(..)
| ToDeviceEvent::KeyVerificationMac(..)
| ToDeviceEvent::KeyVerificationRequest(..)
| ToDeviceEvent::KeyVerificationStart(..) => self.handle_verification_event(&event),
AnyToDeviceEvent::RoomKeyRequest(e) => self.handle_room_key_request(&e),
AnyToDeviceEvent::KeyVerificationAccept(..)
| AnyToDeviceEvent::KeyVerificationCancel(..)
| AnyToDeviceEvent::KeyVerificationKey(..)
| AnyToDeviceEvent::KeyVerificationMac(..)
| AnyToDeviceEvent::KeyVerificationRequest(..)
| AnyToDeviceEvent::KeyVerificationStart(..) => {
self.handle_verification_event(&event)
}
_ => continue,
}
}
@ -1457,18 +1443,17 @@ impl OlmMachine {
/// * `event` - The event that should be decrypted.
pub async fn decrypt_room_event(
&mut self,
event: &EncryptedEvent,
) -> MegolmResult<EventJson<RoomEvent>> {
event: &MessageEventStub<EncryptedEventContent>,
room_id: &RoomId,
) -> MegolmResult<EventJson<AnyRoomEventStub>> {
let content = match &event.content {
EncryptedEventContent::MegolmV1AesSha2(c) => c,
_ => return Err(EventError::UnsupportedAlgorithm.into()),
};
let room_id = event.room_id.as_ref().unwrap();
let session = self
.store
.get_inbound_group_session(&room_id, &content.sender_key, &content.session_id)
.get_inbound_group_session(room_id, &content.sender_key, &content.session_id)
.await?;
// TODO check if the Olm session is wedged and re-request the key.
let session = session.ok_or(MegolmError::MissingSession)?;
@ -1499,7 +1484,8 @@ impl OlmMachine {
serde_json::to_value(&event.unsigned).unwrap_or_default(),
);
let decrypted_event = serde_json::from_value::<EventJson<RoomEvent>>(decrypted_value)?;
let decrypted_event =
serde_json::from_value::<EventJson<AnyRoomEventStub>>(decrypted_value)?;
trace!("Successfully decrypted Megolm event {:?}", decrypted_event);
// TODO set the encryption info on the event (is it verified, was it
// decrypted, sender key...)
@ -1587,13 +1573,12 @@ mod test {
keys, to_device::send_event_to_device::Request as ToDeviceRequest,
};
use matrix_sdk_common::events::{
collections::all::RoomEvent,
room::{
encrypted::{EncryptedEvent, EncryptedEventContent},
encrypted::EncryptedEventContent,
message::{MessageEventContent, TextMessageEventContent},
},
to_device::{AnyToDeviceEvent, ToDeviceEncrypted},
EventJson, EventType, UnsignedData,
AnyMessageEventStub, AnyRoomEventStub, AnyToDeviceEvent, EventJson, EventType,
MessageEventStub, ToDeviceEvent, UnsignedData,
};
use matrix_sdk_common::identifiers::{DeviceId, EventId, RoomId, UserId};
use matrix_sdk_test::test_json;
@ -1732,7 +1717,7 @@ mod test {
.unwrap()
.unwrap();
let event = ToDeviceEncrypted {
let event = ToDeviceEvent {
sender: alice.user_id.clone(),
content: alice
.olm_encrypt(session, &bob_device, EventType::Dummy, json!({}))
@ -2025,7 +2010,7 @@ mod test {
.unwrap()
.unwrap();
let event = ToDeviceEncrypted {
let event = ToDeviceEvent {
sender: alice.user_id.clone(),
content: alice
.olm_encrypt(session, &bob_device, EventType::Dummy, json!({}))
@ -2033,12 +2018,17 @@ mod test {
.unwrap(),
};
let event = bob.decrypt_to_device_event(&event).await.unwrap();
let event = bob
.decrypt_to_device_event(&event)
.await
.unwrap()
.deserialize()
.unwrap();
if let AnyToDeviceEvent::Dummy(e) = event.deserialize().unwrap() {
if let AnyToDeviceEvent::Dummy(e) = event {
assert_eq!(e.sender, alice.user_id);
} else {
panic!("Event had the wrong type");
panic!("Wrong event type found {:?}", event);
}
}
@ -2053,20 +2043,25 @@ mod test {
.await
.unwrap();
let event = ToDeviceEncrypted {
let event = ToDeviceEvent {
sender: alice.user_id.clone(),
content: to_device_requests_to_content(to_device_requests),
};
let alice_session = alice.outbound_group_sessions.get(&room_id).unwrap();
let event = bob.decrypt_to_device_event(&event).await.unwrap();
let event = bob
.decrypt_to_device_event(&event)
.await
.unwrap()
.deserialize()
.unwrap();
if let AnyToDeviceEvent::RoomKey(e) = event.deserialize().unwrap() {
assert_eq!(e.sender, alice.user_id);
assert!(e.content.session_key.is_empty())
if let AnyToDeviceEvent::RoomKey(event) = event {
assert_eq!(event.sender, alice.user_id);
assert!(event.content.session_key.is_empty());
} else {
panic!("Event had the wrong type");
panic!("expected RoomKeyEvent found {:?}", event);
}
let session = bob
@ -2091,8 +2086,8 @@ mod test {
.await
.unwrap();
let event = ToDeviceEncrypted {
sender: alice.user_id().clone(),
let event = ToDeviceEvent {
sender: alice.user_id.clone(),
content: to_device_requests_to_content(to_device_requests),
};
@ -2104,33 +2099,35 @@ mod test {
let encrypted_content = alice.encrypt(&room_id, content.clone()).await.unwrap();
let event = EncryptedEvent {
event_id: EventId::new("example.org").unwrap(),
let event = MessageEventStub {
event_id: EventId::try_from("$xxxxx:example.org").unwrap(),
origin_server_ts: SystemTime::now(),
room_id: Some(room_id.clone()),
sender: alice.user_id().clone(),
content: encrypted_content,
unsigned: UnsignedData::default(),
};
let decrypted_event = bob
.decrypt_room_event(&event)
.decrypt_room_event(&event, &room_id)
.await
.unwrap()
.deserialize()
.unwrap();
let decrypted_event = match decrypted_event {
RoomEvent::RoomMessage(e) => e,
match decrypted_event {
AnyRoomEventStub::Message(AnyMessageEventStub::RoomMessage(MessageEventStub {
sender,
content,
..
})) => {
assert_eq!(&sender, alice.user_id());
if let MessageEventContent::Text(c) = &content {
assert_eq!(&c.body, plaintext);
} else {
panic!("Decrypted event has a missmatched content");
}
}
_ => panic!("Decrypted room event has the wrong type"),
};
assert_eq!(&decrypted_event.sender, alice.user_id());
assert_eq!(&decrypted_event.room_id, &Some(room_id));
if let MessageEventContent::Text(c) = &decrypted_event.content {
assert_eq!(&c.body, plaintext);
} else {
panic!("Decrypted event has a missmatched content");
}
}
}

View File

@ -16,3 +16,4 @@ http = "0.2.1"
matrix-sdk-common = { version = "0.1.0", path = "../matrix_sdk_common" }
matrix-sdk-test-macros = { version = "0.1.0", path = "../matrix_sdk_test_macros" }
lazy_static = "1.4.0"
serde = "1.0.111"

View File

@ -6,13 +6,8 @@ use http::Response;
use matrix_sdk_common::api::r0::sync::sync_events::Response as SyncResponse;
use matrix_sdk_common::events::{
collections::{
all::{RoomEvent, StateEvent},
only::Event,
},
presence::PresenceEvent,
stripped::AnyStrippedStateEvent,
EventJson, TryFromRaw,
presence::PresenceEvent, AnyBasicEvent, AnyEphemeralRoomEventContent, AnyRoomEventStub,
AnyStateEventStub, EphemeralRoomEventStub,
};
use matrix_sdk_common::identifiers::RoomId;
use serde_json::Value as JsonValue;
@ -22,6 +17,9 @@ pub use matrix_sdk_test_macros::async_test;
pub mod test_json;
/// Static `serde_json::Value`s
type AnyEphemeralRoomEventStub = EphemeralRoomEventStub<AnyEphemeralRoomEventContent>;
/// Embedded event files
#[derive(Debug)]
pub enum EventsJson {
Alias,
@ -51,19 +49,19 @@ pub enum EventsJson {
#[derive(Default)]
pub struct EventBuilder {
/// The events that determine the state of a `Room`.
joined_room_events: HashMap<RoomId, Vec<RoomEvent>>,
joined_room_events: HashMap<RoomId, Vec<AnyRoomEventStub>>,
/// The events that determine the state of a `Room`.
invited_room_events: HashMap<RoomId, Vec<AnyStrippedStateEvent>>,
invited_room_events: HashMap<RoomId, Vec<AnyStateEventStub>>,
/// The events that determine the state of a `Room`.
left_room_events: HashMap<RoomId, Vec<RoomEvent>>,
left_room_events: HashMap<RoomId, Vec<AnyRoomEventStub>>,
/// The presence events that determine the presence state of a `RoomMember`.
presence_events: Vec<PresenceEvent>,
/// The state events that determine the state of a `Room`.
state_events: Vec<StateEvent>,
state_events: Vec<AnyStateEventStub>,
/// The ephemeral room events that determine the state of a `Room`.
ephemeral: Vec<Event>,
ephemeral: Vec<AnyEphemeralRoomEventStub>,
/// The account data events that determine the state of a `Room`.
account_data: Vec<Event>,
account_data: Vec<AnyBasicEvent>,
/// Internal counter to enable the `prev_batch` and `next_batch` of each sync response to vary.
batch_counter: i64,
}
@ -75,11 +73,11 @@ impl EventBuilder {
}
/// Add an event to the room events `Vec`.
pub fn add_ephemeral<Ev: TryFromRaw>(
&mut self,
json: EventsJson,
variant: fn(Ev) -> Event,
) -> &mut Self {
pub fn add_ephemeral<Ev: serde::de::DeserializeOwned>(
mut self,
file: EventsFile,
variant: fn(Ev) -> AnyEphemeralRoomEventStub,
) -> Self {
let val: &JsonValue = match json {
EventsJson::Typing => &test_json::TYPING,
_ => panic!("unknown ephemeral event {:?}", json),
@ -89,6 +87,7 @@ impl EventBuilder {
.unwrap()
.deserialize()
.unwrap();
self.ephemeral.push(variant(event));
self
}
@ -112,77 +111,64 @@ impl EventBuilder {
self
}
/// Add an event to the room events `Vec`.
pub fn add_room_event<Ev: TryFromRaw>(
&mut self,
json: EventsJson,
variant: fn(Ev) -> RoomEvent,
) -> &mut Self {
let val: &JsonValue = match json {
EventsJson::Member => &test_json::MEMBER,
EventsJson::PowerLevels => &test_json::POWER_LEVELS,
_ => panic!("unknown room event json {:?}", json),
};
// /// Add an event to the room events `Vec`.
// pub fn add_room_event<Ev: TryFromRaw>(
// &mut self,
// json: EventsJson,
// variant: fn(Ev) -> AnyRoomEventStub,
// ) -> &mut Self {
// let val: &JsonValue = match json {
// EventsJson::Member => &test_json::MEMBER,
// EventsJson::PowerLevels => &test_json::POWER_LEVELS,
// _ => panic!("unknown room event json {:?}", json),
// };
let event = serde_json::from_value::<EventJson<Ev>>(val.clone())
.unwrap()
.deserialize()
.unwrap();
self.add_joined_event(
&RoomId::try_from("!SVkFJHzfwvuaIEawgC:localhost").unwrap(),
variant(event),
);
self
}
// let event = serde_json::from_value::<EventJson<Ev>>(val.clone())
// .unwrap()
// .deserialize()
// .unwrap();
pub fn add_custom_joined_event<Ev: TryFromRaw>(
&mut self,
// self.add_joined_event(
// &RoomId::try_from("!SVkFJHzfwvuaIEawgC:localhost").unwrap(),
// variant(event),
// );
// self
// }
pub fn add_custom_joined_event<Ev: serde::de::DeserializeOwned>(
mut self,
room_id: &RoomId,
event: serde_json::Value,
variant: fn(Ev) -> RoomEvent,
) -> &mut Self {
let event = serde_json::from_value::<EventJson<Ev>>(event)
.unwrap()
.deserialize()
.unwrap();
variant: fn(Ev) -> AnyRoomEventStub,
) -> Self {
let event = serde_json::from_value::<Ev>(event).unwrap();
self.add_joined_event(room_id, variant(event));
self
}
fn add_joined_event(&mut self, room_id: &RoomId, event: RoomEvent) {
fn add_joined_event(&mut self, room_id: &RoomId, event: AnyRoomEventStub) {
self.joined_room_events
.entry(room_id.clone())
.or_insert_with(Vec::new)
.push(event);
}
pub fn add_custom_invited_event<Ev: TryFromRaw>(
&mut self,
room_id: &RoomId,
event: serde_json::Value,
variant: fn(Ev) -> AnyStrippedStateEvent,
) -> &mut Self {
let event = serde_json::from_value::<EventJson<Ev>>(event)
.unwrap()
.deserialize()
.unwrap();
pub fn add_custom_invited_event(mut self, room_id: &RoomId, event: serde_json::Value) -> Self {
let event = serde_json::from_value::<AnyStateEventStub>(event).unwrap();
self.invited_room_events
.entry(room_id.clone())
.or_insert_with(Vec::new)
.push(variant(event));
.push(event);
self
}
pub fn add_custom_left_event<Ev: TryFromRaw>(
&mut self,
pub fn add_custom_left_event<Ev: serde::de::DeserializeOwned>(
mut self,
room_id: &RoomId,
event: serde_json::Value,
variant: fn(Ev) -> RoomEvent,
) -> &mut Self {
let event = serde_json::from_value::<EventJson<Ev>>(event)
.unwrap()
.deserialize()
.unwrap();
variant: fn(Ev) -> AnyRoomEventStub,
) -> Self {
let event = serde_json::from_value::<Ev>(event).unwrap();
self.left_room_events
.entry(room_id.clone())
.or_insert_with(Vec::new)
@ -194,7 +180,6 @@ impl EventBuilder {
pub fn add_state_event<Ev: TryFromRaw>(
&mut self,
json: EventsJson,
variant: fn(Ev) -> StateEvent,
) -> &mut Self {
let val: &JsonValue = match json {
EventsJson::Alias => &test_json::ALIAS,
@ -203,9 +188,7 @@ impl EventBuilder {
_ => panic!("unknown state event {:?}", json),
};
let event = serde_json::from_value::<EventJson<Ev>>(val.clone())
.unwrap()
.deserialize()
let event = serde_json::from_value::<AnyStateEventStub>(val.clone())
.unwrap();
self.state_events.push(variant(event));
self
@ -218,9 +201,7 @@ impl EventBuilder {
_ => panic!("unknown presence event {:?}", json),
};
let event = serde_json::from_value::<EventJson<PresenceEvent>>(val.clone())
.unwrap()
.deserialize()
let event = serde_json::from_value::<PresenceEvent>(val.clone())
.unwrap();
self.presence_events.push(event);
self