mirror of
https://gitlab.computer.surgery/matrix/grapevine.git
synced 2025-12-17 07:41:23 +01:00
remove half-baked presence implementation
But I'm leaving behind the database state for now in case we want it back later, so we won't need to do a migration or whatever.
This commit is contained in:
parent
c765a1634d
commit
f27941d510
12 changed files with 8 additions and 507 deletions
|
|
@ -11,7 +11,6 @@ mod keys;
|
||||||
mod media;
|
mod media;
|
||||||
mod membership;
|
mod membership;
|
||||||
mod message;
|
mod message;
|
||||||
mod presence;
|
|
||||||
mod profile;
|
mod profile;
|
||||||
mod push;
|
mod push;
|
||||||
mod read_marker;
|
mod read_marker;
|
||||||
|
|
@ -46,7 +45,6 @@ pub use keys::*;
|
||||||
pub use media::*;
|
pub use media::*;
|
||||||
pub use membership::*;
|
pub use membership::*;
|
||||||
pub use message::*;
|
pub use message::*;
|
||||||
pub use presence::*;
|
|
||||||
pub use profile::*;
|
pub use profile::*;
|
||||||
pub use push::*;
|
pub use push::*;
|
||||||
pub use read_marker::*;
|
pub use read_marker::*;
|
||||||
|
|
|
||||||
|
|
@ -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<set_presence::v3::Request>,
|
|
||||||
) -> Result<set_presence::v3::Response> {
|
|
||||||
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<get_presence::v3::Request>,
|
|
||||||
) -> Result<get_presence::v3::Response> {
|
|
||||||
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",
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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::{
|
use ruma::{
|
||||||
api::{
|
api::{
|
||||||
client::{
|
client::{
|
||||||
|
|
@ -89,27 +89,6 @@ pub async fn set_displayname_route(
|
||||||
.timeline
|
.timeline
|
||||||
.build_and_append_pdu(pdu_builder, sender_user, &room_id, &state_lock)
|
.build_and_append_pdu(pdu_builder, sender_user, &room_id, &state_lock)
|
||||||
.await;
|
.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 {})
|
Ok(set_display_name::v3::Response {})
|
||||||
|
|
@ -224,27 +203,6 @@ pub async fn set_avatar_url_route(
|
||||||
.timeline
|
.timeline
|
||||||
.build_and_append_pdu(pdu_builder, sender_user, &room_id, &state_lock)
|
.build_and_append_pdu(pdu_builder, sender_user, &room_id, &state_lock)
|
||||||
.await;
|
.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 {})
|
Ok(set_avatar_url::v3::Response {})
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ use ruma::{
|
||||||
room::member::{MembershipState, RoomMemberEventContent},
|
room::member::{MembershipState, RoomMemberEventContent},
|
||||||
StateEventType, TimelineEventType,
|
StateEventType, TimelineEventType,
|
||||||
},
|
},
|
||||||
serde::Raw,
|
|
||||||
uint, DeviceId, EventId, JsOption, OwnedDeviceId, OwnedUserId, RoomId, UInt, UserId,
|
uint, DeviceId, EventId, JsOption, OwnedDeviceId, OwnedUserId, RoomId, UInt, UserId,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
|
|
@ -174,9 +173,6 @@ async fn sync_helper(
|
||||||
body: sync_events::v3::Request,
|
body: sync_events::v3::Request,
|
||||||
// bool = caching allowed
|
// bool = caching allowed
|
||||||
) -> Result<(sync_events::v3::Response, bool), Error> {
|
) -> 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
|
// Setup watchers, so if there's no response, we can wait for them
|
||||||
let watcher = services().globals.watch(&sender_user, &sender_device);
|
let watcher = services().globals.watch(&sender_user, &sender_device);
|
||||||
|
|
||||||
|
|
@ -211,7 +207,6 @@ async fn sync_helper(
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
let sincecount = PduCount::Normal(since);
|
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 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_updates = HashSet::new();
|
||||||
let mut device_list_left = HashSet::new();
|
let mut device_list_left = HashSet::new();
|
||||||
|
|
@ -250,41 +245,6 @@ async fn sync_helper(
|
||||||
if !joined_room.is_empty() {
|
if !joined_room.is_empty() {
|
||||||
joined_rooms.insert(room_id.clone(), joined_room);
|
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,
|
invite: invited_rooms,
|
||||||
knock: BTreeMap::new(), // TODO
|
knock: BTreeMap::new(), // TODO
|
||||||
},
|
},
|
||||||
presence: Presence {
|
presence: Presence::default(),
|
||||||
events: presence_updates
|
|
||||||
.into_values()
|
|
||||||
.map(|v| Raw::new(&v).expect("PresenceEvent always serializes successfully"))
|
|
||||||
.collect(),
|
|
||||||
},
|
|
||||||
account_data: GlobalAccountData {
|
account_data: GlobalAccountData {
|
||||||
events: services()
|
events: services()
|
||||||
.account_data
|
.account_data
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
mod presence;
|
|
||||||
mod read_receipt;
|
mod read_receipt;
|
||||||
|
|
||||||
use crate::{database::KeyValueDatabase, service};
|
use crate::{database::KeyValueDatabase, service};
|
||||||
|
|
|
||||||
|
|
@ -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<Option<u64>> {
|
|
||||||
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<Option<PresenceEvent>> {
|
|
||||||
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<HashMap<OwnedUserId, PresenceEvent>> {
|
|
||||||
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<TokioRwLock<Database>>) {
|
|
||||||
// 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<PresenceEvent> {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
@ -67,7 +67,11 @@ pub struct KeyValueDatabase {
|
||||||
pub(super) readreceiptid_readreceipt: Arc<dyn KvTree>, // ReadReceiptId = RoomId + Count + UserId
|
pub(super) readreceiptid_readreceipt: Arc<dyn KvTree>, // ReadReceiptId = RoomId + Count + UserId
|
||||||
pub(super) roomuserid_privateread: Arc<dyn KvTree>, // RoomUserId = Room + User, PrivateRead = Count
|
pub(super) roomuserid_privateread: Arc<dyn KvTree>, // RoomUserId = Room + User, PrivateRead = Count
|
||||||
pub(super) roomuserid_lastprivatereadupdate: Arc<dyn KvTree>, // LastPrivateReadUpdate = Count
|
pub(super) roomuserid_lastprivatereadupdate: Arc<dyn KvTree>, // LastPrivateReadUpdate = Count
|
||||||
pub(super) presenceid_presence: Arc<dyn KvTree>, // PresenceId = RoomId + Count + UserId
|
// This exists in the database already but is currently unused
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub(super) presenceid_presence: Arc<dyn KvTree>, // PresenceId = RoomId + Count + UserId
|
||||||
|
// This exists in the database already but is currently unused
|
||||||
|
#[allow(dead_code)]
|
||||||
pub(super) userid_lastpresenceupdate: Arc<dyn KvTree>, // LastPresenceUpdate = Count
|
pub(super) userid_lastpresenceupdate: Arc<dyn KvTree>, // LastPresenceUpdate = Count
|
||||||
|
|
||||||
//pub rooms: rooms::Rooms,
|
//pub rooms: rooms::Rooms,
|
||||||
|
|
@ -929,9 +933,6 @@ impl KeyValueDatabase {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This data is probably outdated
|
|
||||||
db.presenceid_presence.clear()?;
|
|
||||||
|
|
||||||
services().admin.start_handler();
|
services().admin.start_handler();
|
||||||
|
|
||||||
// Set emergency access for the conduit user
|
// Set emergency access for the conduit user
|
||||||
|
|
|
||||||
|
|
@ -286,8 +286,6 @@ fn routes(config: &Config) -> Router {
|
||||||
.ruma_route(client_server::set_avatar_url_route)
|
.ruma_route(client_server::set_avatar_url_route)
|
||||||
.ruma_route(client_server::get_avatar_url_route)
|
.ruma_route(client_server::get_avatar_url_route)
|
||||||
.ruma_route(client_server::get_profile_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::upload_keys_route)
|
||||||
.ruma_route(client_server::get_keys_route)
|
.ruma_route(client_server::get_keys_route)
|
||||||
.ruma_route(client_server::claim_keys_route)
|
.ruma_route(client_server::claim_keys_route)
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,6 @@ impl Services {
|
||||||
auth_chain: rooms::auth_chain::Service { db },
|
auth_chain: rooms::auth_chain::Service { db },
|
||||||
directory: rooms::directory::Service { db },
|
directory: rooms::directory::Service { db },
|
||||||
edus: rooms::edus::Service {
|
edus: rooms::edus::Service {
|
||||||
presence: rooms::edus::presence::Service { db },
|
|
||||||
read_receipt: rooms::edus::read_receipt::Service { db },
|
read_receipt: rooms::edus::read_receipt::Service { db },
|
||||||
typing: rooms::edus::typing::Service {
|
typing: rooms::edus::typing::Service {
|
||||||
typing: RwLock::new(BTreeMap::new()),
|
typing: RwLock::new(BTreeMap::new()),
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
pub mod presence;
|
|
||||||
pub mod read_receipt;
|
pub mod read_receipt;
|
||||||
pub mod typing;
|
pub mod typing;
|
||||||
|
|
||||||
pub trait Data: presence::Data + read_receipt::Data + 'static {}
|
pub trait Data: read_receipt::Data + 'static {}
|
||||||
|
|
||||||
pub struct Service {
|
pub struct Service {
|
||||||
pub presence: presence::Service,
|
|
||||||
pub read_receipt: read_receipt::Service,
|
pub read_receipt: read_receipt::Service,
|
||||||
pub typing: typing::Service,
|
pub typing: typing::Service,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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<Option<u64>>;
|
|
||||||
|
|
||||||
/// Returns the presence event with correct last_active_ago.
|
|
||||||
fn get_presence_event(
|
|
||||||
&self,
|
|
||||||
room_id: &RoomId,
|
|
||||||
user_id: &UserId,
|
|
||||||
count: u64,
|
|
||||||
) -> Result<Option<PresenceEvent>>;
|
|
||||||
|
|
||||||
/// Returns the most recent presence updates that happened after the event with id `since`.
|
|
||||||
fn presence_since(
|
|
||||||
&self,
|
|
||||||
room_id: &RoomId,
|
|
||||||
since: u64,
|
|
||||||
) -> Result<HashMap<OwnedUserId, PresenceEvent>>;
|
|
||||||
}
|
|
||||||
|
|
@ -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<Option<PresenceEvent>> {
|
|
||||||
// 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<HashMap<OwnedUserId, PresenceEvent>> {
|
|
||||||
// self.db.presence_since(room_id, since)
|
|
||||||
Ok(HashMap::new())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue