use db::conn::sea_orm::{ActiveModelTrait, ConnectionTrait, EntityTrait, Set}; use time::OffsetDateTime; use uuid::Uuid; use crate::error::{UserError, UserResult}; use crate::features::UserService; use super::types::{UpdatePreferencesCmd, UserPreferences}; pub async fn get_or_create( svc: &UserService, user_id: Uuid, ) -> UserResult { let db = svc.db.reader(); let pref = db::user::user_preferences::Entity::find_by_id(user_id) .one(&db) .await?; if let Some(m) = pref { return Ok(UserPreferences::from(m)); } let writer = svc.db.writer(); let active: db::user::user_preferences::ActiveModel = db::user::user_preferences::ActiveModel::builder() .set_user_id(user_id) .set_theme_mode(String::from("system")) .set_created_at(OffsetDateTime::now_utc()) .set_updated_at(OffsetDateTime::now_utc()) .into(); let inserted = active.insert(&writer).await?; Ok(UserPreferences::from(inserted)) } pub async fn update( svc: &UserService, user_id: Uuid, cmd: UpdatePreferencesCmd, ) -> UserResult { if let Some(ref mode) = cmd.theme_mode && (mode.is_empty() || mode.len() > 32) { return Err(UserError::BadRequest( "theme_mode length must be 1..=32".into(), )); } let writer = svc.db.writer(); let existing = db::user::user_preferences::Entity::find_by_id(user_id) .one(&writer) .await?; let now = OffsetDateTime::now_utc(); let existing_present = existing.is_some(); let mut active: db::user::user_preferences::ActiveModel = match existing { Some(m) => m.into(), None => db::user::user_preferences::ActiveModel::builder() .set_user_id(user_id) .set_theme_mode(String::from("system")) .set_created_at(now) .set_updated_at(now) .into(), }; if let Some(v) = cmd.theme_mode { active.theme_mode = Set(v); } if let Some(v) = cmd.theme_token { active.theme_token = Set(v); } if let Some(v) = cmd.theme_version { active.theme_version = Set(v); } if let Some(v) = cmd.diff_view_style { active.diff_view_style = Set(v); } if let Some(v) = cmd.in_app_flags { active.in_app_flags = Set(v); } if let Some(v) = cmd.email_flags { active.email_flags = Set(v); } if let Some(v) = cmd.push_flags { active.push_flags = Set(v); } if let Some(v) = cmd.email_digest { active.email_digest = Set(v); } if let Some(v) = cmd.mute_until { if let Some(ts) = v { let parsed = OffsetDateTime::parse( &ts, &time::format_description::well_known::Rfc3339, ) .map_err(|e| UserError::BadRequest(format!("invalid mute_until: {e}")))?; active.mute_until = Set(Some(parsed)); } else { active.mute_until = Set(None); } } if let Some(v) = cmd.allow_dms_from { active.allow_dms_from = Set(v.into()); } if let Some(v) = cmd.allow_mentions_from { active.allow_mentions_from = Set(v.into()); } if let Some(v) = cmd.show_online_status { active.show_online_status = Set(v); } active.updated_at = Set(now); let saved = if existing_present { active.update(&writer).await? } else { active.insert(&writer).await? }; Ok(UserPreferences::from(saved)) } #[allow(dead_code)] fn _connection_bound(_: &C) {}