Skip to content
Clone
194c44c
105 lines 3.0 KB Rust
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 uuid::Uuid;
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.redis.clone()).expect("chat realtime client");
Self { state, realtime }
}
pub fn config(&self) -> &AppConfig {
&self.state.config
}
pub fn db(&self) -> &Arc<AppDatabase> {
&self.state.database
}
pub fn storage(&self) -> &AppStorage {
&self.state.storage
}
pub async fn load_user_briefs(
&self,
uids: &[i64],
) -> Result<HashMap<i64, UserDto>, ChatError> {
if uids.is_empty() {
return Ok(HashMap::new());
}
let mut set: Vec<i64> = 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<HashMap<i64, String>, 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 queue_search_message(&self, message_id: Uuid) {
if let Err(error) = search::outbox::enqueue_message(self.db().write(), message_id).await {
tracing::warn!(%message_id, error = %error, "search message enqueue failed");
}
}
pub(crate) async fn send_email(
&self,
to: &str,
subject: &str,
text: &str,
html: &str,
) -> Result<(), ChatError> {
self.state
.email
.send_mail(to, subject, text, html)
.await
.map_err(|error| ChatError::Internal(format!("email send failed: {error}")))
}
}