use models::chat::room_user_settings::{self, RoomNotificationLevel}; use sea_orm::{ActiveModelTrait, EntityTrait, Set}; use serde::{Deserialize, Serialize}; use time::OffsetDateTime; use utoipa::ToSchema; use uuid::Uuid; use crate::errors::ChatError; use crate::services::service::ChatService; use crate::share::lookup::require_room_readable; #[derive(Debug, Clone, Serialize, ToSchema)] pub struct RoomSettingDto { pub room_id: Uuid, pub notification_level: RoomNotificationLevel, pub muted: bool, pub mute_until: Option, pub favorite: bool, pub hidden: bool, } #[derive(Debug, Clone, Deserialize, ToSchema)] pub struct UpdateRoomSettingCmd { #[serde(default)] pub notification_level: Option, #[serde(default)] pub muted: Option, #[serde(default)] pub mute_minutes: Option, #[serde(default)] pub favorite: Option, #[serde(default)] pub hidden: Option, } impl From for RoomSettingDto { fn from(s: room_user_settings::Model) -> Self { Self { room_id: s.room_id, notification_level: s.notification_level, muted: s.muted, mute_until: s.mute_until, favorite: s.favorite, hidden: s.hidden, } } } impl ChatService { pub async fn get_room_setting( &self, caller: i64, room_id: Uuid, ) -> Result { let _ctx = require_room_readable(self, room_id, caller).await?; let row = room_user_settings::Entity::find_by_id((caller, room_id)) .one(self.db().read()) .await?; match row { Some(row) => Ok(RoomSettingDto::from(row)), None => Ok(RoomSettingDto { room_id, notification_level: RoomNotificationLevel::Default, muted: false, mute_until: None, favorite: false, hidden: false, }), } } pub async fn update_room_setting( &self, caller: i64, room_id: Uuid, cmd: UpdateRoomSettingCmd, ) -> Result { let _ctx = require_room_readable(self, room_id, caller).await?; let now = OffsetDateTime::now_utc(); let existing = room_user_settings::Entity::find_by_id((caller, room_id)) .one(self.db().write()) .await?; let mut am: room_user_settings::ActiveModel = match existing { Some(row) => row.into(), None => room_user_settings::ActiveModel { user_id: Set(caller), room_id: Set(room_id), notification_level: Set(RoomNotificationLevel::Default), muted: Set(false), mute_until: Set(None), favorite: Set(false), hidden: Set(false), updated_at: Set(now), }, }; if let Some(level) = cmd.notification_level { am.notification_level = Set(level); } if let Some(muted) = cmd.muted { am.muted = Set(muted); if !muted { am.mute_until = Set(None); } } if let Some(minutes) = cmd.mute_minutes { am.mute_until = Set(if minutes > 0 { Some(now + time::Duration::minutes(minutes)) } else { None }); am.muted = Set(minutes > 0); } if let Some(favorite) = cmd.favorite { am.favorite = Set(favorite); } if let Some(hidden) = cmd.hidden { am.hidden = Set(hidden); } am.updated_at = Set(now); am.save(self.db().write()).await?; let row = room_user_settings::Entity::find_by_id((caller, room_id)) .one(self.db().read()) .await? .ok_or(ChatError::Internal("setting vanished".into()))?; Ok(RoomSettingDto::from(row)) } }