magnetar/src/model/processing/user.rs

104 lines
3.3 KiB
Rust

use crate::model::data::user::UserBaseSource;
use crate::model::processing::drive::DriveModel;
use crate::model::processing::emoji::EmojiModel;
use crate::model::processing::{get_mm_token_emoji, PackResult};
use crate::model::{PackType, PackingContext};
use magnetar_calckey_model::ck;
use magnetar_sdk::mmm::Token;
use magnetar_sdk::types::drive::PackDriveFileBase;
use magnetar_sdk::types::emoji::EmojiContext;
use magnetar_sdk::types::instance::InstanceTicker;
use magnetar_sdk::types::user::{PackUserBase, UserBase};
use magnetar_sdk::types::{Id, MmXml};
use magnetar_sdk::{mmm, Packed, Required};
use tracing::warn;
use url::Url;
pub struct UserModel;
impl UserModel {
pub fn tokenize_username(&self, user: &ck::user::Model) -> Token {
mmm::Context::default().parse_ui(user.name.as_deref().unwrap_or(&user.username))
}
pub fn get_effective_avatar_url(
&self,
ctx: &PackingContext,
user: &ck::user::Model,
avatar: Option<&PackDriveFileBase>,
) -> PackResult<Url> {
Ok(avatar
.and_then(
|PackDriveFileBase {
file: Required(base),
..
}| base.thumbnail_url.as_deref(),
)
.map(Url::parse)
.and_then(|r| {
if let Err(e) = r {
warn!("Failed to parse avatar URL: {e}");
}
r.ok().map(Ok)
})
.unwrap_or_else(|| {
Url::parse(&format!(
"{}://{}/identicon/{}",
ctx.service.config.networking.protocol,
ctx.service.config.networking.host,
user.id
))
})?)
}
pub async fn base_from_existing(
&self,
ctx: &PackingContext,
user: &ck::user::Model,
) -> PackResult<PackUserBase> {
let drive_file_pack = DriveModel;
let avatar = match &user.avatar_id {
Some(av_id) => drive_file_pack.get_cached_base(ctx, av_id).await?,
None => None,
};
let avatar_url = &self.get_effective_avatar_url(ctx, user, avatar.as_ref())?;
let username_mm = self.tokenize_username(&user);
let emoji_model = EmojiModel;
let shortcodes = emoji_model.deduplicate_emoji(ctx, get_mm_token_emoji(&username_mm));
let emojis = emoji_model
.fetch_many_emojis(ctx, &shortcodes, user.host.as_deref())
.await?;
let instance = ctx
.service
.remote_instance_cache
.get(
user.host
.as_deref()
.unwrap_or(&ctx.service.config.networking.host),
)
.await?
.map(|i| InstanceTicker::extract(ctx, i.as_ref()));
let emoji_context = EmojiContext(emojis);
let base = UserBase::extract(
ctx,
UserBaseSource {
user,
username_mm: mmm::to_xml_string(&username_mm).map(MmXml).as_ref().ok(),
avatar_url,
avatar: avatar.as_ref(),
emoji_context: &emoji_context,
instance: instance.as_ref(),
},
);
Ok(PackUserBase::pack_from((
Required(Id::from(&user.id)),
Required(base),
)))
}
}