merged add-events, fix a few type changes and merge fails

master
Devin R 2020-03-28 08:58:02 -04:00
parent b1027796c8
commit 9ee8a2d011
11 changed files with 102 additions and 289 deletions

View File

@ -28,7 +28,11 @@ async fn async_cb(room: Arc<RwLock<Room>>, event: Arc<EventResult<RoomEvent>>) {
let member = room.members.get(&sender.to_string()).unwrap(); let member = room.members.get(&sender.to_string()).unwrap();
println!( println!(
"{}: {}", "{}: {}",
member.user.display_name.as_ref().unwrap_or(&sender.to_string()), member
.user
.display_name
.as_ref()
.unwrap_or(&sender.to_string()),
msg_body msg_body
); );
} }

View File

@ -38,7 +38,6 @@ use ruma_identifiers::RoomId;
use crate::api; use crate::api;
use crate::base_client::Client as BaseClient; use crate::base_client::Client as BaseClient;
use crate::models::Room; use crate::models::Room;
use crate::error::{Error, InnerError};
use crate::session::Session; use crate::session::Session;
use crate::VERSION; use crate::VERSION;
use crate::{Error, Result}; use crate::{Error, Result};
@ -266,7 +265,7 @@ impl AsyncClient {
pub fn base_client(&self) -> Arc<RwLock<BaseClient>> { pub fn base_client(&self) -> Arc<RwLock<BaseClient>> {
Arc::clone(&self.base_client) Arc::clone(&self.base_client)
} }
/// Calculate the room name from a `RoomId`, returning a string. /// Calculate the room name from a `RoomId`, returning a string.
pub async fn get_room_name(&self, room_id: &str) -> Option<String> { pub async fn get_room_name(&self, room_id: &str) -> Option<String> {
self.base_client.read().await.calculate_room_name(room_id) self.base_client.read().await.calculate_room_name(room_id)
@ -424,16 +423,14 @@ impl AsyncClient {
if let Some(e) = decrypted_event { if let Some(e) = decrypted_event {
*event = e; *event = e;
} }
for presence in &response.presence.events { for presence in &response.presence.events {
let mut client = self.base_client.write().await; let mut client = self.base_client.write().await;
if let EventResult::Ok(e) = presence { if let EventResult::Ok(e) = presence {
client.receive_presence_event(&room_id, e); client.receive_presence_event(&room_id_string, e);
} }
} }
let event = Arc::new(event.clone());
let callbacks = { let callbacks = {
let mut cb_futures = self.event_callbacks.lock().unwrap(); let mut cb_futures = self.event_callbacks.lock().unwrap();
@ -446,7 +443,7 @@ impl AsyncClient {
let mut callbacks = Vec::new(); let mut callbacks = Vec::new();
for cb in &mut cb_futures.iter_mut() { for cb in &mut cb_futures.iter_mut() {
callbacks.push(cb(matrix_room.clone(), event.clone())); callbacks.push(cb(matrix_room.clone(), Arc::clone(&event)));
} }
callbacks callbacks

View File

@ -21,17 +21,17 @@ use std::result::Result as StdResult;
use crate::api::r0 as api; use crate::api::r0 as api;
use crate::error::Result; use crate::error::Result;
use crate::events::collections::all::{RoomEvent, StateEvent}; use crate::events::collections::all::{RoomEvent, StateEvent};
use crate::events::presence::PresenceEvent;
use crate::events::room::{ use crate::events::room::{
aliases::AliasesEvent, aliases::AliasesEvent,
canonical_alias::CanonicalAliasEvent, canonical_alias::CanonicalAliasEvent,
member::{MemberEvent, MembershipState}, member::{MemberEvent, MembershipState},
name::NameEvent, name::NameEvent,
}; };
use crate::events::presence::PresenceEvent;
use crate::events::EventResult; use crate::events::EventResult;
use crate::identifiers::RoomAliasId; use crate::identifiers::RoomAliasId;
use crate::models::Room;
use crate::session::Session; use crate::session::Session;
use crate::models::{Room};
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]

View File

@ -13,32 +13,35 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::collections::HashMap; use crate::events::collections::all::RoomEvent;
use std::sync::{Arc, RwLock};
use crate::api::r0 as api;
use crate::events::collections::all::{Event, RoomEvent, StateEvent};
use crate::events::room::{
aliases::AliasesEvent,
canonical_alias::CanonicalAliasEvent,
member::{MemberEvent, MemberEventContent, MembershipState},
name::NameEvent,
};
use crate::events::EventResult;
use crate::identifiers::RoomAliasId;
use crate::session::Session;
use crate::models::Room; use crate::models::Room;
use js_int::{Int, UInt}; // JUST AN IDEA
#[cfg(feature = "encryption")] //
use tokio::sync::Mutex;
#[cfg(feature = "encryption")]
use crate::crypto::{OlmMachine, OneTimeKeys};
#[cfg(feature = "encryption")]
use ruma_client_api::r0::keys::{upload_keys::Response as KeysUploadResponse, DeviceKeys};
/// This is just a thought I had. Making users impl a trait instead of writing callbacks for events
/// could give the chance for really good documentation for each event?
/// It would look something like this
///
/// ```rust,ignore
/// use matrix-sdk::{AsyncClient, EventEmitter};
///
/// struct MyAppClient;
///
/// impl EventEmitter for MyAppClient {
/// fn on_room_member(&mut self, room: &Room, event: &RoomEvent) { ... }
/// }
/// async fn main() {
/// let cl = AsyncClient::with_emitter(MyAppClient);
/// }
/// ```
///
/// And in `AsyncClient::sync` there could be a switch case that calls the corresponding method on
/// the `Box<dyn EventEmitter>
pub trait EventEmitter { pub trait EventEmitter {
fn on_room_name(&mut self, _: &Room) {} fn on_room_name(&mut self, _: &Room, _: &RoomEvent) {}
fn on_room_member(&mut self, _: &Room) {} /// Any event that alters the state of the room's members
fn on_room_member(&mut self, _: &Room, _: &RoomEvent) {}
} }

View File

@ -35,9 +35,9 @@ pub use ruma_identifiers as identifiers;
mod async_client; mod async_client;
mod base_client; mod base_client;
mod error; mod error;
mod event_emitter;
mod models; mod models;
mod session; mod session;
mod event_emitter;
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
mod crypto; mod crypto;

View File

@ -1,51 +1,6 @@
use crate::events::{ mod room;
call::{
answer::AnswerEvent, candidates::CandidatesEvent, hangup::HangupEvent, invite::InviteEvent,
},
direct::DirectEvent,
dummy::DummyEvent,
forwarded_room_key::ForwardedRoomKeyEvent,
fully_read::FullyReadEvent,
ignored_user_list::IgnoredUserListEvent,
key::verification::{
accept::AcceptEvent, cancel::CancelEvent, key::KeyEvent, mac::MacEvent,
request::RequestEvent, start::StartEvent,
},
presence::PresenceEvent,
push_rules::PushRulesEvent,
receipt::ReceiptEvent,
room::{
aliases::AliasesEvent,
avatar::AvatarEvent,
canonical_alias::CanonicalAliasEvent,
create::CreateEvent,
encrypted::EncryptedEvent,
encryption::EncryptionEvent,
guest_access::GuestAccessEvent,
history_visibility::HistoryVisibilityEvent,
join_rules::JoinRulesEvent,
member::MemberEvent,
message::{feedback::FeedbackEvent, MessageEvent},
name::NameEvent,
pinned_events::PinnedEventsEvent,
power_levels::PowerLevelsEvent,
redaction::RedactionEvent,
server_acl::ServerAclEvent,
third_party_invite::ThirdPartyInviteEvent,
tombstone::TombstoneEvent,
topic::TopicEvent,
},
room_key::RoomKeyEvent,
room_key_request::RoomKeyRequestEvent,
sticker::StickerEvent,
tag::TagEvent,
typing::TypingEvent,
CustomEvent, CustomRoomEvent, CustomStateEvent,
};
mod room_member; mod room_member;
mod room_state; mod room_state;
mod room;
mod user; mod user;
pub use room::{Room, RoomName}; pub use room::{Room, RoomName};
@ -53,145 +8,4 @@ pub use room_member::RoomMember;
pub use user::User; pub use user::User;
pub type Token = String; pub type Token = String;
pub type RoomId = String;
pub type UserId = String; pub type UserId = String;
pub enum EventWrapper<'ev> {
/// m.call.answer
CallAnswer(&'ev AnswerEvent),
/// m.call.candidates
CallCandidates(&'ev CandidatesEvent),
/// m.call.hangup
CallHangup(&'ev HangupEvent),
/// m.call.invite
CallInvite(&'ev InviteEvent),
/// m.direct
Direct(&'ev DirectEvent),
/// m.dummy
Dummy(&'ev DummyEvent),
/// m.forwarded_room_key
ForwardedRoomKey(&'ev ForwardedRoomKeyEvent),
/// m.fully_read
FullyRead(&'ev FullyReadEvent),
/// m.ignored_user_list
IgnoredUserList(&'ev IgnoredUserListEvent),
/// m.key.verification.accept
KeyVerificationAccept(&'ev AcceptEvent),
/// m.key.verification.cancel
KeyVerificationCancel(&'ev CancelEvent),
/// m.key.verification.key
KeyVerificationKey(&'ev KeyEvent),
/// m.key.verification.mac
KeyVerificationMac(&'ev MacEvent),
/// m.key.verification.request
KeyVerificationRequest(&'ev RequestEvent),
/// m.key.verification.start
KeyVerificationStart(&'ev StartEvent),
/// m.presence
Presence(&'ev PresenceEvent),
/// m.push_rules
PushRules(&'ev PushRulesEvent),
/// m.receipt
Receipt(&'ev ReceiptEvent),
/// m.room.aliases
RoomAliases(&'ev AliasesEvent),
/// m.room.avatar
RoomAvatar(&'ev AvatarEvent),
/// m.room.canonical_alias
RoomCanonicalAlias(&'ev CanonicalAliasEvent),
/// m.room.create
RoomCreate(&'ev CreateEvent),
/// m.room.encrypted
RoomEncrypted(&'ev EncryptedEvent),
/// m.room.encryption
RoomEncryption(&'ev EncryptionEvent),
/// m.room.guest_access
RoomGuestAccess(&'ev GuestAccessEvent),
/// m.room.history_visibility
RoomHistoryVisibility(&'ev HistoryVisibilityEvent),
/// m.room.join_rules
RoomJoinRules(&'ev JoinRulesEvent),
/// m.room.member
RoomMember(&'ev MemberEvent),
/// m.room.message
RoomMessage(&'ev MessageEvent),
/// m.room.message.feedback
RoomMessageFeedback(&'ev FeedbackEvent),
/// m.room.name
RoomName(&'ev NameEvent),
/// m.room.pinned_events
RoomPinnedEvents(&'ev PinnedEventsEvent),
/// m.room.power_levels
RoomPowerLevels(&'ev PowerLevelsEvent),
/// m.room.redaction
RoomRedaction(&'ev RedactionEvent),
/// m.room.server_acl
RoomServerAcl(&'ev ServerAclEvent),
/// m.room.third_party_invite
RoomThirdPartyInvite(&'ev ThirdPartyInviteEvent),
/// m.room.tombstone
RoomTombstone(&'ev TombstoneEvent),
/// m.room.topic
RoomTopic(&'ev TopicEvent),
/// m.room_key
RoomKey(&'ev RoomKeyEvent),
/// m.room_key_request
RoomKeyRequest(&'ev RoomKeyRequestEvent),
/// m.sticker
Sticker(&'ev StickerEvent),
/// m.tag
Tag(&'ev TagEvent),
/// m.typing
Typing(&'ev TypingEvent),
/// Any basic event that is not part of the specification.
Custom(&'ev CustomEvent),
/// Any room event that is not part of the specification.
CustomRoom(&'ev CustomRoomEvent),
/// Any state event that is not part of the specification.
CustomState(&'ev CustomStateEvent),
}

View File

@ -16,6 +16,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use super::{RoomMember, User, UserId};
use crate::api::r0 as api; use crate::api::r0 as api;
use crate::events::collections::all::{RoomEvent, StateEvent}; use crate::events::collections::all::{RoomEvent, StateEvent};
use crate::events::room::{ use crate::events::room::{
@ -24,10 +25,12 @@ use crate::events::room::{
member::{MemberEvent, MembershipState}, member::{MemberEvent, MembershipState},
name::NameEvent, name::NameEvent,
}; };
use crate::events::{presence::{PresenceEvent, PresenceEventContent}, EventResult}; use crate::events::{
presence::{PresenceEvent, PresenceEventContent},
EventResult,
};
use crate::identifiers::RoomAliasId; use crate::identifiers::RoomAliasId;
use crate::session::Session; use crate::session::Session;
use super::{RoomId, UserId, RoomMember, User};
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
use tokio::sync::Mutex; use tokio::sync::Mutex;
@ -52,7 +55,7 @@ pub struct RoomName {
/// A Matrix rooom. /// A Matrix rooom.
pub struct Room { pub struct Room {
/// The unique id of the room. /// The unique id of the room.
pub room_id: RoomId, pub room_id: String,
/// The name of the room, clients use this to represent a room. /// The name of the room, clients use this to represent a room.
pub room_name: RoomName, pub room_name: RoomName,
/// The mxid of our own user. /// The mxid of our own user.
@ -175,11 +178,11 @@ impl Room {
// } // }
// fn handle_leave(&mut self, event: &MemberEvent) -> bool { // fn handle_leave(&mut self, event: &MemberEvent) -> bool {
// } // }
/// Handle a room.member updating the room state if necessary. /// Handle a room.member updating the room state if necessary.
/// ///
/// Returns true if the joined member list changed, false otherwise. /// 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: &MemberEvent) -> bool {
match &event.content.membership { match &event.content.membership {
@ -214,7 +217,7 @@ impl Room {
} }
/// Handle a room.aliases event, updating the room state if necessary. /// Handle a room.aliases event, updating the room state if necessary.
/// ///
/// Returns true if the room name changed, false otherwise. /// Returns true if the room name changed, false otherwise.
pub fn handle_room_aliases(&mut self, event: &AliasesEvent) -> bool { pub fn handle_room_aliases(&mut self, event: &AliasesEvent) -> bool {
match event.content.aliases.as_slice() { match event.content.aliases.as_slice() {
@ -225,7 +228,7 @@ impl Room {
} }
/// Handle a room.canonical_alias event, updating the room state if necessary. /// Handle a room.canonical_alias event, updating the room state if necessary.
/// ///
/// Returns true if the room name changed, false otherwise. /// Returns true if the room name changed, false otherwise.
pub fn handle_canonical(&mut self, event: &CanonicalAliasEvent) -> bool { pub fn handle_canonical(&mut self, event: &CanonicalAliasEvent) -> bool {
match &event.content.alias { match &event.content.alias {
@ -235,7 +238,7 @@ impl Room {
} }
/// Handle a room.name event, updating the room state if necessary. /// Handle a room.name event, updating the room state if necessary.
/// ///
/// Returns true if the room name changed, false otherwise. /// Returns true if the room name changed, false otherwise.
pub fn handle_room_name(&mut self, event: &NameEvent) -> bool { pub fn handle_room_name(&mut self, event: &NameEvent) -> bool {
match event.content.name() { match event.content.name() {
@ -291,21 +294,29 @@ impl Room {
/// * `event` - The event of the room. /// * `event` - The event of the room.
pub fn receive_presence_event(&mut self, event: &PresenceEvent) -> bool { pub fn receive_presence_event(&mut self, event: &PresenceEvent) -> bool {
let PresenceEvent { let PresenceEvent {
content: PresenceEventContent { content:
avatar_url, PresenceEventContent {
currently_active, avatar_url,
displayname, currently_active,
last_active_ago, displayname,
presence, last_active_ago,
status_msg, presence,
}, status_msg,
},
sender, sender,
} = event; } = event;
if let Some(user) = self.members.get_mut(&sender.to_string()).map(|m| &mut m.user) { if let Some(user) = self
if user.display_name == *displayname && user.avatar_url == *avatar_url .members
&& user.presence.as_ref() == Some(presence) && user.status_msg == *status_msg .get_mut(&sender.to_string())
&& user.last_active_ago == *last_active_ago && user.currently_active == *currently_active .map(|m| &mut m.user)
{
if user.display_name == *displayname
&& user.avatar_url == *avatar_url
&& user.presence.as_ref() == Some(presence)
&& user.status_msg == *status_msg
&& user.last_active_ago == *last_active_ago
&& user.currently_active == *currently_active
{ {
false false
} else { } else {

View File

@ -16,6 +16,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use super::{User, UserId};
use crate::api::r0 as api; use crate::api::r0 as api;
use crate::events::collections::all::{Event, RoomEvent, StateEvent}; use crate::events::collections::all::{Event, RoomEvent, StateEvent};
use crate::events::room::{ use crate::events::room::{
@ -27,7 +28,6 @@ use crate::events::room::{
use crate::events::EventResult; use crate::events::EventResult;
use crate::identifiers::RoomAliasId; use crate::identifiers::RoomAliasId;
use crate::session::Session; use crate::session::Session;
use super::{UserId, RoomId, User};
use js_int::{Int, UInt}; use js_int::{Int, UInt};
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
@ -44,7 +44,7 @@ pub struct RoomMember {
/// The unique mxid of the user. /// The unique mxid of the user.
pub user_id: UserId, pub user_id: UserId,
/// The unique id of the room. /// The unique id of the room.
pub room_id: Option<RoomId>, pub room_id: Option<String>,
/// If the member is typing. /// If the member is typing.
pub typing: Option<bool>, pub typing: Option<bool>,
/// The user data for this room member. /// The user data for this room member.
@ -58,7 +58,7 @@ pub struct RoomMember {
/// The human readable name of this room member. /// The human readable name of this room member.
pub name: String, pub name: String,
/// The events that created the state of this room member. /// The events that created the state of this room member.
pub events: Vec<Event> pub events: Vec<Event>,
} }
impl RoomMember { impl RoomMember {
@ -73,26 +73,30 @@ impl RoomMember {
power_level_norm: None, power_level_norm: None,
membership: event.content.membership, membership: event.content.membership,
name: event.state_key.clone(), name: event.state_key.clone(),
events: vec![Event::RoomMember(event.clone())] events: vec![Event::RoomMember(event.clone())],
} }
} }
pub fn update(&mut self, event: &MemberEvent) { pub fn update(&mut self, event: &MemberEvent) {
let MemberEvent { let MemberEvent {
content: MemberEventContent { content: MemberEventContent { membership, .. },
membership,
..
},
room_id, room_id,
state_key, state_key,
.. ..
} = event; } = event;
let mut events = Vec::new(); let mut events = Vec::new();
events.extend(self.events.drain(..).chain(Some(Event::RoomMember(event.clone())))); events.extend(
self.events
.drain(..)
.chain(Some(Event::RoomMember(event.clone()))),
);
*self = Self { *self = Self {
room_id: room_id.as_ref().map(|id| id.to_string()).or(self.room_id.take()), room_id: room_id
.as_ref()
.map(|id| id.to_string())
.or(self.room_id.take()),
user_id: state_key.clone(), user_id: state_key.clone(),
typing: None, typing: None,
user: User::new(event), user: User::new(event),

View File

@ -0,0 +1,15 @@
// Copyright 2020 Damir Jelić
// Copyright 2020 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// 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.

View File

@ -16,19 +16,19 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use super::UserId;
use crate::api::r0 as api; use crate::api::r0 as api;
use crate::events::collections::all::{Event, RoomEvent, StateEvent}; use crate::events::collections::all::{Event, RoomEvent, StateEvent};
use crate::events::presence::{PresenceEvent, PresenceState};
use crate::events::room::{ use crate::events::room::{
aliases::AliasesEvent, aliases::AliasesEvent,
canonical_alias::CanonicalAliasEvent, canonical_alias::CanonicalAliasEvent,
member::{MemberEvent, MembershipState}, member::{MemberEvent, MembershipState},
name::NameEvent, name::NameEvent,
}; };
use crate::events::presence::{PresenceEvent, PresenceState};
use crate::events::EventResult; use crate::events::EventResult;
use crate::identifiers::RoomAliasId; use crate::identifiers::RoomAliasId;
use crate::session::Session; use crate::session::Session;
use super::{UserId, RoomId};
use js_int::UInt; use js_int::UInt;
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]

View File

@ -90,38 +90,3 @@ async fn timeline() {
println!("{:#?}", &client.base_client().read().await.joined_rooms); println!("{:#?}", &client.base_client().read().await.joined_rooms);
} }
#[test]
fn timeline() {
let mut rt = Runtime::new().unwrap();
let homeserver = Url::from_str(&mockito::server_url()).unwrap();
let session = Session {
access_token: "1234".to_owned(),
user_id: UserId::try_from("@example:example.com").unwrap(),
device_id: "DEVICEID".to_owned(),
};
let _m = mock(
"GET",
Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_string()),
)
.with_status(200)
.with_body_from_file("tests/data/sync.json")
.create();
let mut client = AsyncClient::new(homeserver, Some(session)).unwrap();
let sync_settings = SyncSettings::new().timeout(3000).unwrap();
let _response = rt.block_on(client.sync(sync_settings)).unwrap();
assert_eq!(vec!["tutorial"], rt.block_on(client.get_room_names()));
assert_eq!(
Some("tutorial".into()),
rt.block_on(client.get_room_name("!SVkFJHzfwvuaIEawgC:localhost"))
);
rt.block_on(async { println!("{:#?}", &client.base_client().read().await.joined_rooms ) });
}