Files
tuwunel/src/service/rooms/user/mod.rs
2025-09-23 05:16:29 +00:00

173 lines
3.8 KiB
Rust

use std::sync::Arc;
use ruma::{RoomId, UserId};
use tuwunel_core::{
Result, implement, trace,
utils::stream::{ReadyExt, TryIgnore},
};
use tuwunel_database::{Database, Deserialized, Interfix, Map};
use crate::rooms::short::ShortStateHash;
pub struct Service {
db: Data,
services: Arc<crate::services::OnceServices>,
}
struct Data {
db: Arc<Database>,
userroomid_notificationcount: Arc<Map>,
userroomid_highlightcount: Arc<Map>,
roomuserid_lastnotificationread: Arc<Map>,
roomsynctoken_shortstatehash: Arc<Map>,
}
impl crate::Service for Service {
fn build(args: &crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
db: Data {
db: args.db.clone(),
userroomid_notificationcount: args.db["userroomid_notificationcount"].clone(),
userroomid_highlightcount: args.db["userroomid_highlightcount"].clone(),
roomuserid_lastnotificationread: args.db["userroomid_highlightcount"].clone(),
roomsynctoken_shortstatehash: args.db["roomsynctoken_shortstatehash"].clone(),
},
services: args.services.clone(),
}))
}
fn name(&self) -> &str { crate::service::make_name(std::module_path!()) }
}
#[implement(Service)]
pub fn reset_notification_counts(&self, user_id: &UserId, room_id: &RoomId) {
let count = self.services.globals.next_count();
let userroom_id = (user_id, room_id);
self.db
.userroomid_highlightcount
.put(userroom_id, 0_u64);
self.db
.userroomid_notificationcount
.put(userroom_id, 0_u64);
let roomuser_id = (room_id, user_id);
self.db
.roomuserid_lastnotificationread
.put(roomuser_id, *count);
}
#[implement(Service)]
pub async fn notification_count(&self, user_id: &UserId, room_id: &RoomId) -> u64 {
let key = (user_id, room_id);
self.db
.userroomid_notificationcount
.qry(&key)
.await
.deserialized()
.unwrap_or(0)
}
#[implement(Service)]
pub async fn highlight_count(&self, user_id: &UserId, room_id: &RoomId) -> u64 {
let key = (user_id, room_id);
self.db
.userroomid_highlightcount
.qry(&key)
.await
.deserialized()
.unwrap_or(0)
}
#[implement(Service)]
pub async fn last_notification_read(&self, user_id: &UserId, room_id: &RoomId) -> u64 {
let key = (room_id, user_id);
self.db
.roomuserid_lastnotificationread
.qry(&key)
.await
.deserialized()
.unwrap_or(0)
}
#[implement(Service)]
pub async fn delete_room_notification_read(&self, room_id: &RoomId) -> Result {
let key = (room_id, Interfix);
self.db
.roomuserid_lastnotificationread
.keys_prefix_raw(&key)
.ignore_err()
.ready_for_each(|key| {
trace!("Removing key: {key:?}");
self.db
.roomuserid_lastnotificationread
.remove(key);
})
.await;
Ok(())
}
#[implement(Service)]
#[tracing::instrument(level = "trace", skip(self))]
pub async fn associate_token_shortstatehash(
&self,
room_id: &RoomId,
token: u64,
shortstatehash: ShortStateHash,
) {
let shortroomid = self
.services
.short
.get_shortroomid(room_id)
.await
.expect("room exists");
let _cork = self.db.db.cork();
let key: &[u64] = &[shortroomid, token];
self.db
.roomsynctoken_shortstatehash
.put(key, shortstatehash);
}
#[implement(Service)]
pub async fn get_token_shortstatehash(
&self,
room_id: &RoomId,
token: u64,
) -> Result<ShortStateHash> {
let shortroomid = self
.services
.short
.get_shortroomid(room_id)
.await?;
let key: &[u64] = &[shortroomid, token];
self.db
.roomsynctoken_shortstatehash
.qry(key)
.await
.deserialized()
}
#[implement(Service)]
pub async fn delete_room_synctokens(&self, room_id: &RoomId) -> Result {
let shortroomid = self
.services
.short
.get_shortroomid(room_id)
.await?;
self.db
.roomsynctoken_shortstatehash
.keys_prefix_raw(&shortroomid)
.ignore_err()
.ready_for_each(|key| {
trace!("Removing key: {key:?}");
self.db.roomsynctoken_shortstatehash.remove(key);
})
.await;
Ok(())
}