use std::collections::HashMap; use std::sync::Arc; use config::AppConfig; use export::AppState; use export::database::AppDatabase; use export::storage::AppStorage; use models::users::user; use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; use space::services::spaces::UserDto; use crate::errors::ChatError; use crate::share::realtime::Realtime; #[derive(Clone)] pub struct ChatService { pub state: AppState, pub realtime: Realtime, } impl ChatService { pub fn new(state: AppState) -> Self { let realtime = Realtime::new(state.database.write().clone(), state.events_enabled); Self { state, realtime } } pub fn config(&self) -> &AppConfig { &self.state.config } pub fn db(&self) -> &Arc { &self.state.database } pub fn storage(&self) -> &AppStorage { &self.state.storage } pub async fn load_user_briefs(&self, uids: &[i64]) -> Result, ChatError> { if uids.is_empty() { return Ok(HashMap::new()); } let mut set: Vec = uids.to_vec(); set.sort(); set.dedup(); let users = user::Entity::find() .filter(user::Column::Uid.is_in(set)) .all(self.db().read()) .await?; let map = users .into_iter() .map(|u| (u.uid, UserDto::from(u))) .collect(); Ok(map) } /// Language for one recipient's notification/e-mail text. /// /// Account preference only: a fan-out event has no single ambient request /// language, and writing one language for every recipient is the bug this /// replaces. pub(crate) async fn recipient_locale(&self, uid: i64) -> i18n::UiLocale { let fallback = i18n::config_fallback(self.config().email.default_locale()); i18n::resolve_user_locale(self.db().read(), uid, fallback).await } pub(crate) async fn primary_emails( &self, uids: &[i64], ) -> Result, ChatError> { if uids.is_empty() { return Ok(HashMap::new()); } models::users::queries::primary_emails(self.db().read(), uids) .await .map_err(ChatError::from) } pub(crate) async fn send_email( &self, to: &str, subject: &str, text: &str, html: &str, ) -> Result<(), ChatError> { let Some(client) = self.state.email_rpc.as_ref() else { tracing::warn!(to, "email rpc disabled; skipping chat mail"); return Ok(()); }; client .send_mail(to, subject, text, html) .await .map_err(|error| ChatError::Internal(format!("email send failed: {error}"))) } }