magnetar/src/model/data/user.rs

241 lines
8.8 KiB
Rust

use magnetar_calckey_model::ck;
use magnetar_calckey_model::ck::sea_orm_active_enums::UserProfileFfvisibilityEnum;
use magnetar_sdk::types::drive::PackDriveFileBase;
use magnetar_sdk::types::emoji::{EmojiContext, PackEmojiBase};
use magnetar_sdk::types::instance::InstanceTicker;
use magnetar_sdk::types::note::PackNoteMaybeFull;
use magnetar_sdk::types::user::{
AvatarDecoration, PackSecurityKeyBase, ProfileField, SecurityKeyBase, SpeechTransform,
UserBase, UserDetailExt, UserProfileExt, UserProfilePinsEx, UserRelationExt, UserSecretsExt,
};
use magnetar_sdk::types::MmXml;
use url::Url;
use crate::model::{PackType, PackingContext};
impl PackType<&[PackEmojiBase]> for EmojiContext {
fn extract(_context: &PackingContext, data: &[PackEmojiBase]) -> Self {
EmojiContext(data.to_owned())
}
}
pub struct UserBaseSource<'a> {
pub user: &'a ck::user::Model,
pub username_mm: Option<&'a MmXml>,
pub avatar_url: &'a Url,
pub avatar: Option<&'a PackDriveFileBase>,
pub emoji_context: &'a EmojiContext,
pub instance: Option<&'a InstanceTicker>,
}
impl PackType<UserBaseSource<'_>> for UserBase {
fn extract(
_context: &PackingContext,
UserBaseSource {
user,
username_mm,
avatar_url,
avatar,
emoji_context,
instance,
}: UserBaseSource,
) -> Self {
UserBase {
acct: user
.host
.as_ref()
.map(|host| format!("@{}@{}", user.username, host))
.unwrap_or_else(|| format!("@{}", user.username)),
username: user.username.clone(),
display_name: user.name.clone().unwrap_or_else(|| user.username.clone()),
display_name_mm: username_mm.cloned(),
host: user.host.clone(),
speech_transform: if user.is_cat && user.speak_as_cat {
SpeechTransform::Cat
} else {
SpeechTransform::None
},
created_at: user.created_at.into(),
avatar_url: avatar_url.to_string(),
avatar_blurhash: avatar.and_then(|v| v.file.0.blurhash.clone()),
avatar_decoration: if user.is_cat {
AvatarDecoration::CatEars
} else {
AvatarDecoration::None
},
is_admin: user.is_admin,
is_moderator: user.is_moderator,
is_bot: user.is_bot,
emojis: emoji_context.clone(),
instance: instance.map(|i| i.clone()),
}
}
}
pub struct UserProfileExtSource<'a> {
pub user: &'a ck::user::Model,
pub profile: &'a ck::user_profile::Model,
pub profile_fields: &'a Vec<ProfileField>,
pub banner_url: Option<&'a Url>,
pub banner: Option<&'a ck::drive_file::Model>,
pub description_mm: Option<&'a MmXml>,
pub relation: Option<&'a UserRelationExt>,
}
impl PackType<UserProfileExtSource<'_>> for UserProfileExt {
fn extract(
context: &PackingContext,
UserProfileExtSource {
user,
profile,
profile_fields,
banner_url,
banner,
description_mm,
relation,
}: UserProfileExtSource,
) -> Self {
let follow_visibility = match profile.ff_visibility {
UserProfileFfvisibilityEnum::Public => true,
UserProfileFfvisibilityEnum::Followers => relation.is_some_and(|r| r.follows_you),
UserProfileFfvisibilityEnum::Private => false,
} || context.is_self(user);
UserProfileExt {
is_locked: user.is_locked,
is_silenced: user.is_silenced,
is_suspended: user.is_suspended,
description: profile.description.clone(),
description_mm: description_mm.cloned(),
location: profile.location.clone(),
birthday: profile
.birthday
.clone()
.and_then(|b| b.parse().map_or_else(|_| None, Some)),
fields: profile_fields.clone(),
follower_count: follow_visibility.then_some(user.followers_count as u64),
following_count: follow_visibility.then_some(user.following_count as u64),
note_count: Some(user.notes_count as u64),
url: profile.url.clone(),
moved_to_uri: user.moved_to_uri.clone(),
also_known_as: user.also_known_as.clone(),
banner_url: banner_url.map(Url::to_string),
banner_blurhash: banner.and_then(|b| b.blurhash.clone()),
has_public_reactions: profile.public_reactions,
}
}
}
impl PackType<&ck::user::Model> for UserDetailExt {
fn extract(_context: &PackingContext, user: &ck::user::Model) -> Self {
UserDetailExt {
last_fetched_at: user.last_fetched_at.map(Into::into),
uri: user.uri.clone(),
updated_at: user.updated_at.map(Into::into),
}
}
}
struct UserRelationExtSource<'a> {
pub follow_out: Option<&'a ck::following::Model>,
pub follow_in: Option<&'a ck::following::Model>,
pub block_out: Option<&'a ck::blocking::Model>,
pub block_in: Option<&'a ck::blocking::Model>,
pub mute: Option<&'a ck::muting::Model>,
pub renote_mute: Option<&'a ck::renote_muting::Model>,
pub follow_request_out: Option<&'a ck::follow_request::Model>,
pub follow_request_in: Option<&'a ck::follow_request::Model>,
}
impl PackType<UserRelationExtSource<'_>> for UserRelationExt {
fn extract(
context: &PackingContext,
UserRelationExtSource {
follow_out,
follow_in,
block_out,
block_in,
mute,
renote_mute,
follow_request_in,
follow_request_out,
}: UserRelationExtSource,
) -> Self {
let self_user = context.self_user();
UserRelationExt {
follows_you: self_user.is_some_and(|self_user| {
follow_in.is_some_and(|follow_in| {
self_user.id == follow_in.followee_id && self_user.id != follow_in.follower_id
})
}),
you_follow: self_user.is_some_and(|self_user| {
follow_out.is_some_and(|follow_out| {
self_user.id == follow_out.follower_id && self_user.id != follow_out.followee_id
})
}),
blocks_you: self_user.is_some_and(|self_user| {
block_in.is_some_and(|block_in| {
self_user.id == block_in.blockee_id && self_user.id != block_in.blocker_id
})
}),
you_block: self_user.is_some_and(|self_user| {
block_out.is_some_and(|block_out| {
self_user.id == block_out.blocker_id && self_user.id != block_out.blockee_id
})
}),
mute: self_user.is_some_and(|self_user| {
mute.is_some_and(|mute| {
self_user.id == mute.muter_id && self_user.id != mute.mutee_id
})
}),
mute_renotes: self_user.is_some_and(|self_user| {
renote_mute.is_some_and(|renote_mute| {
self_user.id == renote_mute.muter_id && self_user.id != renote_mute.mutee_id
})
}),
you_request_follow: self_user.is_some_and(|self_user| {
follow_request_in.is_some_and(|follow_req_in| {
self_user.id == follow_req_in.followee_id
&& self_user.id != follow_req_in.follower_id
})
}),
they_request_follow: self_user.is_some_and(|self_user| {
follow_request_out.is_some_and(|follow_req_out| {
self_user.id == follow_req_out.follower_id
&& self_user.id != follow_req_out.followee_id
})
}),
}
}
}
impl PackType<&[PackNoteMaybeFull]> for UserProfilePinsEx {
fn extract(_context: &PackingContext, pinned_notes: &[PackNoteMaybeFull]) -> Self {
UserProfilePinsEx {
pinned_notes: pinned_notes.to_owned(),
}
}
}
impl PackType<ck::user_security_key::Model> for SecurityKeyBase {
fn extract(_context: &PackingContext, key: ck::user_security_key::Model) -> Self {
SecurityKeyBase {
name: key.name.clone(),
last_used_at: Some(key.last_used.into()),
}
}
}
type UserSecretsExtSource<'a> = (&'a ck::user_profile::Model, &'a [PackSecurityKeyBase]);
impl PackType<UserSecretsExtSource<'_>> for UserSecretsExt {
fn extract(_context: &PackingContext, (profile, keys): UserSecretsExtSource) -> Self {
UserSecretsExt {
email: profile.email.clone(),
email_verified: profile.email_verified,
security_keys: keys.to_owned(),
}
}
}