diff --git a/src/api/client_server/mod.rs b/src/api/client_server/mod.rs index 54c99aa0..c50db8d5 100644 --- a/src/api/client_server/mod.rs +++ b/src/api/client_server/mod.rs @@ -11,7 +11,6 @@ mod keys; mod media; mod membership; mod message; -mod presence; mod profile; mod push; mod read_marker; @@ -46,7 +45,6 @@ pub use keys::*; pub use media::*; pub use membership::*; pub use message::*; -pub use presence::*; pub use profile::*; pub use push::*; pub use read_marker::*; diff --git a/src/api/client_server/presence.rs b/src/api/client_server/presence.rs deleted file mode 100644 index e5cd1b8e..00000000 --- a/src/api/client_server/presence.rs +++ /dev/null @@ -1,90 +0,0 @@ -use crate::{services, utils, Error, Result, Ruma}; -use ruma::api::client::{ - error::ErrorKind, - presence::{get_presence, set_presence}, -}; -use std::time::Duration; - -/// # `PUT /_matrix/client/r0/presence/{userId}/status` -/// -/// Sets the presence state of the sender user. -pub async fn set_presence_route( - body: Ruma, -) -> Result { - let sender_user = body.sender_user.as_ref().expect("user is authenticated"); - - for room_id in services().rooms.state_cache.rooms_joined(sender_user) { - let room_id = room_id?; - - services().rooms.edus.presence.update_presence( - sender_user, - &room_id, - ruma::events::presence::PresenceEvent { - content: ruma::events::presence::PresenceEventContent { - avatar_url: services().users.avatar_url(sender_user)?, - currently_active: None, - displayname: services().users.displayname(sender_user)?, - last_active_ago: Some( - utils::millis_since_unix_epoch() - .try_into() - .expect("time is valid"), - ), - presence: body.presence.clone(), - status_msg: body.status_msg.clone(), - }, - sender: sender_user.clone(), - }, - )?; - } - - Ok(set_presence::v3::Response {}) -} - -/// # `GET /_matrix/client/r0/presence/{userId}/status` -/// -/// Gets the presence state of the given user. -/// -/// - Only works if you share a room with the user -pub async fn get_presence_route( - body: Ruma, -) -> Result { - let sender_user = body.sender_user.as_ref().expect("user is authenticated"); - - let mut presence_event = None; - - for room_id in services() - .rooms - .user - .get_shared_rooms(vec![sender_user.clone(), body.user_id.clone()])? - { - let room_id = room_id?; - - if let Some(presence) = services() - .rooms - .edus - .presence - .get_last_presence_event(sender_user, &room_id)? - { - presence_event = Some(presence); - break; - } - } - - if let Some(presence) = presence_event { - Ok(get_presence::v3::Response { - // TODO: Should ruma just use the presenceeventcontent type here? - status_msg: presence.content.status_msg, - currently_active: presence.content.currently_active, - last_active_ago: presence - .content - .last_active_ago - .map(|millis| Duration::from_millis(millis.into())), - presence: presence.content.presence, - }) - } else { - Err(Error::BadRequest( - ErrorKind::NotFound, - "Presence state for this user was not found", - )) - } -} diff --git a/src/api/client_server/profile.rs b/src/api/client_server/profile.rs index cf1db2d7..f1500439 100644 --- a/src/api/client_server/profile.rs +++ b/src/api/client_server/profile.rs @@ -1,4 +1,4 @@ -use crate::{service::pdu::PduBuilder, services, utils, Error, Result, Ruma}; +use crate::{service::pdu::PduBuilder, services, Error, Result, Ruma}; use ruma::{ api::{ client::{ @@ -89,27 +89,6 @@ pub async fn set_displayname_route( .timeline .build_and_append_pdu(pdu_builder, sender_user, &room_id, &state_lock) .await; - - // Presence update - services().rooms.edus.presence.update_presence( - sender_user, - &room_id, - ruma::events::presence::PresenceEvent { - content: ruma::events::presence::PresenceEventContent { - avatar_url: services().users.avatar_url(sender_user)?, - currently_active: None, - displayname: services().users.displayname(sender_user)?, - last_active_ago: Some( - utils::millis_since_unix_epoch() - .try_into() - .expect("time is valid"), - ), - presence: ruma::presence::PresenceState::Online, - status_msg: None, - }, - sender: sender_user.clone(), - }, - )?; } Ok(set_display_name::v3::Response {}) @@ -224,27 +203,6 @@ pub async fn set_avatar_url_route( .timeline .build_and_append_pdu(pdu_builder, sender_user, &room_id, &state_lock) .await; - - // Presence update - services().rooms.edus.presence.update_presence( - sender_user, - &room_id, - ruma::events::presence::PresenceEvent { - content: ruma::events::presence::PresenceEventContent { - avatar_url: services().users.avatar_url(sender_user)?, - currently_active: None, - displayname: services().users.displayname(sender_user)?, - last_active_ago: Some( - utils::millis_since_unix_epoch() - .try_into() - .expect("time is valid"), - ), - presence: ruma::presence::PresenceState::Online, - status_msg: None, - }, - sender: sender_user.clone(), - }, - )?; } Ok(set_avatar_url::v3::Response {}) diff --git a/src/api/client_server/sync.rs b/src/api/client_server/sync.rs index e0c6e0b9..e561c320 100644 --- a/src/api/client_server/sync.rs +++ b/src/api/client_server/sync.rs @@ -21,7 +21,6 @@ use ruma::{ room::member::{MembershipState, RoomMemberEventContent}, StateEventType, TimelineEventType, }, - serde::Raw, uint, DeviceId, EventId, JsOption, OwnedDeviceId, OwnedUserId, RoomId, UInt, UserId, }; use std::{ @@ -174,9 +173,6 @@ async fn sync_helper( body: sync_events::v3::Request, // bool = caching allowed ) -> Result<(sync_events::v3::Response, bool), Error> { - // TODO: match body.set_presence { - services().rooms.edus.presence.ping_presence(&sender_user)?; - // Setup watchers, so if there's no response, we can wait for them let watcher = services().globals.watch(&sender_user, &sender_device); @@ -211,7 +207,6 @@ async fn sync_helper( .unwrap_or(0); let sincecount = PduCount::Normal(since); - let mut presence_updates = HashMap::new(); let mut left_encrypted_users = HashSet::new(); // Users that have left any encrypted rooms the sender was in let mut device_list_updates = HashSet::new(); let mut device_list_left = HashSet::new(); @@ -250,41 +245,6 @@ async fn sync_helper( if !joined_room.is_empty() { joined_rooms.insert(room_id.clone(), joined_room); } - - // Take presence updates from this room - for (user_id, presence) in services() - .rooms - .edus - .presence - .presence_since(&room_id, since)? - { - match presence_updates.entry(user_id) { - Entry::Vacant(v) => { - v.insert(presence); - } - Entry::Occupied(mut o) => { - let p = o.get_mut(); - - // Update existing presence event with more info - p.content.presence = presence.content.presence; - if let Some(status_msg) = presence.content.status_msg { - p.content.status_msg = Some(status_msg); - } - if let Some(last_active_ago) = presence.content.last_active_ago { - p.content.last_active_ago = Some(last_active_ago); - } - if let Some(displayname) = presence.content.displayname { - p.content.displayname = Some(displayname); - } - if let Some(avatar_url) = presence.content.avatar_url { - p.content.avatar_url = Some(avatar_url); - } - if let Some(currently_active) = presence.content.currently_active { - p.content.currently_active = Some(currently_active); - } - } - } - } } } @@ -540,12 +500,7 @@ async fn sync_helper( invite: invited_rooms, knock: BTreeMap::new(), // TODO }, - presence: Presence { - events: presence_updates - .into_values() - .map(|v| Raw::new(&v).expect("PresenceEvent always serializes successfully")) - .collect(), - }, + presence: Presence::default(), account_data: GlobalAccountData { events: services() .account_data diff --git a/src/database/key_value/rooms/edus/mod.rs b/src/database/key_value/rooms/edus/mod.rs index 7abf946f..90f2b24a 100644 --- a/src/database/key_value/rooms/edus/mod.rs +++ b/src/database/key_value/rooms/edus/mod.rs @@ -1,4 +1,3 @@ -mod presence; mod read_receipt; use crate::{database::KeyValueDatabase, service}; diff --git a/src/database/key_value/rooms/edus/presence.rs b/src/database/key_value/rooms/edus/presence.rs deleted file mode 100644 index 904b1c44..00000000 --- a/src/database/key_value/rooms/edus/presence.rs +++ /dev/null @@ -1,152 +0,0 @@ -use std::collections::HashMap; - -use ruma::{ - events::presence::PresenceEvent, presence::PresenceState, OwnedUserId, RoomId, UInt, UserId, -}; - -use crate::{database::KeyValueDatabase, service, services, utils, Error, Result}; - -impl service::rooms::edus::presence::Data for KeyValueDatabase { - fn update_presence( - &self, - user_id: &UserId, - room_id: &RoomId, - presence: PresenceEvent, - ) -> Result<()> { - // TODO: Remove old entry? Or maybe just wipe completely from time to time? - - let count = services().globals.next_count()?.to_be_bytes(); - - let mut presence_id = room_id.as_bytes().to_vec(); - presence_id.push(0xff); - presence_id.extend_from_slice(&count); - presence_id.push(0xff); - presence_id.extend_from_slice(presence.sender.as_bytes()); - - self.presenceid_presence.insert( - &presence_id, - &serde_json::to_vec(&presence).expect("PresenceEvent can be serialized"), - )?; - - self.userid_lastpresenceupdate.insert( - user_id.as_bytes(), - &utils::millis_since_unix_epoch().to_be_bytes(), - )?; - - Ok(()) - } - - fn ping_presence(&self, user_id: &UserId) -> Result<()> { - self.userid_lastpresenceupdate.insert( - user_id.as_bytes(), - &utils::millis_since_unix_epoch().to_be_bytes(), - )?; - - Ok(()) - } - - fn last_presence_update(&self, user_id: &UserId) -> Result> { - self.userid_lastpresenceupdate - .get(user_id.as_bytes())? - .map(|bytes| { - utils::u64_from_bytes(&bytes).map_err(|_| { - Error::bad_database("Invalid timestamp in userid_lastpresenceupdate.") - }) - }) - .transpose() - } - - fn get_presence_event( - &self, - room_id: &RoomId, - user_id: &UserId, - count: u64, - ) -> Result> { - let mut presence_id = room_id.as_bytes().to_vec(); - presence_id.push(0xff); - presence_id.extend_from_slice(&count.to_be_bytes()); - presence_id.push(0xff); - presence_id.extend_from_slice(user_id.as_bytes()); - - self.presenceid_presence - .get(&presence_id)? - .map(|value| parse_presence_event(&value)) - .transpose() - } - - fn presence_since( - &self, - room_id: &RoomId, - since: u64, - ) -> Result> { - let mut prefix = room_id.as_bytes().to_vec(); - prefix.push(0xff); - - let mut first_possible_edu = prefix.clone(); - first_possible_edu.extend_from_slice(&(since + 1).to_be_bytes()); // +1 so we don't send the event at since - let mut hashmap = HashMap::new(); - - for (key, value) in self - .presenceid_presence - .iter_from(&first_possible_edu, false) - .take_while(|(key, _)| key.starts_with(&prefix)) - { - let user_id = UserId::parse( - utils::string_from_bytes( - key.rsplit(|&b| b == 0xff) - .next() - .expect("rsplit always returns an element"), - ) - .map_err(|_| Error::bad_database("Invalid UserId bytes in presenceid_presence."))?, - ) - .map_err(|_| Error::bad_database("Invalid UserId in presenceid_presence."))?; - - let presence = parse_presence_event(&value)?; - - hashmap.insert(user_id, presence); - } - - Ok(hashmap) - } - - /* - fn presence_maintain(&self, db: Arc>) { - // TODO @M0dEx: move this to a timed tasks module - tokio::spawn(async move { - loop { - select! { - Some(user_id) = self.presence_timers.next() { - // TODO @M0dEx: would it be better to acquire the lock outside the loop? - let guard = db.read().await; - - // TODO @M0dEx: add self.presence_timers - // TODO @M0dEx: maintain presence - } - } - } - }); - } - */ -} - -fn parse_presence_event(bytes: &[u8]) -> Result { - let mut presence: PresenceEvent = serde_json::from_slice(bytes) - .map_err(|_| Error::bad_database("Invalid presence event in db."))?; - - let current_timestamp: UInt = utils::millis_since_unix_epoch() - .try_into() - .expect("time is valid"); - - if presence.content.presence == PresenceState::Online { - // Don't set last_active_ago when the user is online - presence.content.last_active_ago = None; - } else { - // Convert from timestamp to duration - presence.content.last_active_ago = presence - .content - .last_active_ago - .map(|timestamp| current_timestamp - timestamp); - } - - Ok(presence) -} diff --git a/src/database/mod.rs b/src/database/mod.rs index eee963d9..4a30465d 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -67,7 +67,11 @@ pub struct KeyValueDatabase { pub(super) readreceiptid_readreceipt: Arc, // ReadReceiptId = RoomId + Count + UserId pub(super) roomuserid_privateread: Arc, // RoomUserId = Room + User, PrivateRead = Count pub(super) roomuserid_lastprivatereadupdate: Arc, // LastPrivateReadUpdate = Count - pub(super) presenceid_presence: Arc, // PresenceId = RoomId + Count + UserId + // This exists in the database already but is currently unused + #[allow(dead_code)] + pub(super) presenceid_presence: Arc, // PresenceId = RoomId + Count + UserId + // This exists in the database already but is currently unused + #[allow(dead_code)] pub(super) userid_lastpresenceupdate: Arc, // LastPresenceUpdate = Count //pub rooms: rooms::Rooms, @@ -929,9 +933,6 @@ impl KeyValueDatabase { ); } - // This data is probably outdated - db.presenceid_presence.clear()?; - services().admin.start_handler(); // Set emergency access for the conduit user diff --git a/src/main.rs b/src/main.rs index 7beeb8ba..938f0d73 100644 --- a/src/main.rs +++ b/src/main.rs @@ -286,8 +286,6 @@ fn routes(config: &Config) -> Router { .ruma_route(client_server::set_avatar_url_route) .ruma_route(client_server::get_avatar_url_route) .ruma_route(client_server::get_profile_route) - .ruma_route(client_server::set_presence_route) - .ruma_route(client_server::get_presence_route) .ruma_route(client_server::upload_keys_route) .ruma_route(client_server::get_keys_route) .ruma_route(client_server::claim_keys_route) diff --git a/src/service/mod.rs b/src/service/mod.rs index 4c11bc18..c96a9041 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -64,7 +64,6 @@ impl Services { auth_chain: rooms::auth_chain::Service { db }, directory: rooms::directory::Service { db }, edus: rooms::edus::Service { - presence: rooms::edus::presence::Service { db }, read_receipt: rooms::edus::read_receipt::Service { db }, typing: rooms::edus::typing::Service { typing: RwLock::new(BTreeMap::new()), diff --git a/src/service/rooms/edus/mod.rs b/src/service/rooms/edus/mod.rs index a6bc3d5b..869865f7 100644 --- a/src/service/rooms/edus/mod.rs +++ b/src/service/rooms/edus/mod.rs @@ -1,11 +1,9 @@ -pub mod presence; pub mod read_receipt; pub mod typing; -pub trait Data: presence::Data + read_receipt::Data + 'static {} +pub trait Data: read_receipt::Data + 'static {} pub struct Service { - pub presence: presence::Service, pub read_receipt: read_receipt::Service, pub typing: typing::Service, } diff --git a/src/service/rooms/edus/presence/data.rs b/src/service/rooms/edus/presence/data.rs deleted file mode 100644 index 53329e08..00000000 --- a/src/service/rooms/edus/presence/data.rs +++ /dev/null @@ -1,38 +0,0 @@ -use std::collections::HashMap; - -use crate::Result; -use ruma::{events::presence::PresenceEvent, OwnedUserId, RoomId, UserId}; - -pub trait Data: Send + Sync { - /// Adds a presence event which will be saved until a new event replaces it. - /// - /// Note: This method takes a RoomId because presence updates are always bound to rooms to - /// make sure users outside these rooms can't see them. - fn update_presence( - &self, - user_id: &UserId, - room_id: &RoomId, - presence: PresenceEvent, - ) -> Result<()>; - - /// Resets the presence timeout, so the user will stay in their current presence state. - fn ping_presence(&self, user_id: &UserId) -> Result<()>; - - /// Returns the timestamp of the last presence update of this user in millis since the unix epoch. - fn last_presence_update(&self, user_id: &UserId) -> Result>; - - /// Returns the presence event with correct last_active_ago. - fn get_presence_event( - &self, - room_id: &RoomId, - user_id: &UserId, - count: u64, - ) -> Result>; - - /// Returns the most recent presence updates that happened after the event with id `since`. - fn presence_since( - &self, - room_id: &RoomId, - since: u64, - ) -> Result>; -} diff --git a/src/service/rooms/edus/presence/mod.rs b/src/service/rooms/edus/presence/mod.rs deleted file mode 100644 index 4b929d28..00000000 --- a/src/service/rooms/edus/presence/mod.rs +++ /dev/null @@ -1,125 +0,0 @@ -mod data; -use std::collections::HashMap; - -pub use data::Data; -use ruma::{events::presence::PresenceEvent, OwnedUserId, RoomId, UserId}; - -use crate::Result; - -pub struct Service { - pub db: &'static dyn Data, -} - -impl Service { - /// Adds a presence event which will be saved until a new event replaces it. - /// - /// Note: This method takes a RoomId because presence updates are always bound to rooms to - /// make sure users outside these rooms can't see them. - pub fn update_presence( - &self, - _user_id: &UserId, - _room_id: &RoomId, - _presence: PresenceEvent, - ) -> Result<()> { - // self.db.update_presence(user_id, room_id, presence) - Ok(()) - } - - /// Resets the presence timeout, so the user will stay in their current presence state. - pub fn ping_presence(&self, _user_id: &UserId) -> Result<()> { - // self.db.ping_presence(user_id) - Ok(()) - } - - pub fn get_last_presence_event( - &self, - _user_id: &UserId, - _room_id: &RoomId, - ) -> Result> { - // let last_update = match self.db.last_presence_update(user_id)? { - // Some(last) => last, - // None => return Ok(None), - // }; - - // self.db.get_presence_event(room_id, user_id, last_update) - Ok(None) - } - - /* TODO - /// Sets all users to offline who have been quiet for too long. - fn _presence_maintain( - &self, - rooms: &super::Rooms, - globals: &super::super::globals::Globals, - ) -> Result<()> { - let current_timestamp = utils::millis_since_unix_epoch(); - - for (user_id_bytes, last_timestamp) in self - .userid_lastpresenceupdate - .iter() - .filter_map(|(k, bytes)| { - Some(( - k, - utils::u64_from_bytes(&bytes) - .map_err(|_| { - Error::bad_database("Invalid timestamp in userid_lastpresenceupdate.") - }) - .ok()?, - )) - }) - .take_while(|(_, timestamp)| current_timestamp.saturating_sub(*timestamp) > 5 * 60_000) - // 5 Minutes - { - // Send new presence events to set the user offline - let count = globals.next_count()?.to_be_bytes(); - let user_id: Box<_> = utils::string_from_bytes(&user_id_bytes) - .map_err(|_| { - Error::bad_database("Invalid UserId bytes in userid_lastpresenceupdate.") - })? - .try_into() - .map_err(|_| Error::bad_database("Invalid UserId in userid_lastpresenceupdate."))?; - for room_id in rooms.rooms_joined(&user_id).filter_map(|r| r.ok()) { - let mut presence_id = room_id.as_bytes().to_vec(); - presence_id.push(0xff); - presence_id.extend_from_slice(&count); - presence_id.push(0xff); - presence_id.extend_from_slice(&user_id_bytes); - - self.presenceid_presence.insert( - &presence_id, - &serde_json::to_vec(&PresenceEvent { - content: PresenceEventContent { - avatar_url: None, - currently_active: None, - displayname: None, - last_active_ago: Some( - last_timestamp.try_into().expect("time is valid"), - ), - presence: PresenceState::Offline, - status_msg: None, - }, - sender: user_id.to_owned(), - }) - .expect("PresenceEvent can be serialized"), - )?; - } - - self.userid_lastpresenceupdate.insert( - user_id.as_bytes(), - &utils::millis_since_unix_epoch().to_be_bytes(), - )?; - } - - Ok(()) - }*/ - - /// Returns the most recent presence updates that happened after the event with id `since`. - pub fn presence_since( - &self, - _room_id: &RoomId, - _since: u64, - ) -> Result> { - // self.db.presence_since(room_id, since) - Ok(HashMap::new()) - } -}