use crate::errors::IssueError; use api::users::UserDto; use auth::Accounts; use models::users::user_notifications::NotificationType; use sea_orm::ConnectionTrait; use std::collections::HashMap; #[derive(Clone)] pub struct Audience { pub(crate) accounts: Accounts, pub(crate) notifications: push::notify::Notifications, mail: Option, pub(crate) default_locale: i18n::UiLocale, } impl Audience { pub fn new( accounts: Accounts, notifications: push::notify::Notifications, mail: Option, default_locale: i18n::UiLocale, ) -> Self { Self { accounts, notifications, mail, default_locale, } } pub async fn load_user_briefs( &self, uids: &[i64], ) -> Result, IssueError> { Ok(auth::users::load_user_briefs(&self.accounts, uids).await?) } pub(crate) async fn recipient_locale(&self, uid: i64) -> i18n::UiLocale { let fallback = self.default_locale; i18n::resolve_user_locale(self.accounts.db().read(), uid, fallback).await } pub(crate) async fn primary_emails( &self, uids: &[i64], ) -> Result, IssueError> { if uids.is_empty() { return Ok(HashMap::new()); } let users = auth::users::load_public_users(&self.accounts, uids).await?; Ok(users .into_iter() .filter(|(_, user)| user.email_verified && !user.email.trim().is_empty()) .map(|(uid, user)| (uid, user.email.to_lowercase())) .collect()) } pub(crate) async fn send_email( &self, to: &str, subject: &str, text: &str, html: &str, ) -> Result<(), IssueError> { let request_id = api::middleware::request_id(); email::send_optional( self.mail.as_ref(), to, subject, text, html, request_id.as_deref(), ) .await .map_err(|error| IssueError::Internal(format!("email send failed: {error}"))) } pub(crate) async fn notify_user( &self, txn: &impl ConnectionTrait, pending: &push::notify::PendingNotifications, recipient: i64, ntype: NotificationType, title: String, body: Option, data: Option, actor_uid: Option, ) -> Result<(), IssueError> { let row = push::notify::insert(txn, recipient, ntype, title, body, data, actor_uid).await?; pending.push(recipient, row.to_event_value()); Ok(()) } }