magnetar/src/model/data/user.rs

185 lines
6.9 KiB
Rust

use magnetar_calckey_model::ck;
use magnetar_calckey_model::ck::sea_orm_active_enums::UserProfileFfvisibilityEnum;
use magnetar_sdk::types::emoji::{EmojiContext, PackEmojiBase};
use magnetar_sdk::types::note::PackNoteFull;
use magnetar_sdk::types::user::{
AvatarDecoration, PackSecurityKeyBase, SecurityKeyBase, SpeechTransform, UserBase,
UserDetailExt, UserProfileExt, UserProfilePinsEx, UserRelationExt, UserSecretsExt,
};
use crate::model::{PackType, PackingContext};
impl PackType<&[PackEmojiBase]> for EmojiContext {
fn extract(_context: &PackingContext, data: &[PackEmojiBase]) -> Self {
EmojiContext(data.to_owned())
}
}
type UserBaseSource<'a> = (
&'a ck::user::Model,
&'a Option<ck::drive_file::Model>,
&'a EmojiContext,
);
impl PackType<UserBaseSource<'_>> for UserBase {
fn extract(_context: &PackingContext, (user, avatar, emoji_context): 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()),
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.as_ref().map(|v| v.url.clone()),
avatar_blurhash: avatar.as_ref().and_then(|v| v.blurhash.clone()),
avatar_color: None,
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(),
}
}
}
type UserProfileExtSource<'a> = (
&'a ck::user::Model,
&'a ck::user_profile::Model,
Option<&'a UserRelationExt>,
);
impl PackType<UserProfileExtSource<'_>> for UserProfileExt {
fn extract(context: &PackingContext, (user, profile, 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(),
location: profile.location.clone(),
birthday: profile
.birthday
.clone()
.and_then(|b| b.parse().map_or_else(|_| None, Some)),
fields: serde_json::from_value(profile.fields.clone()).unwrap_or_else(|_| Vec::new()),
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: None,
banner_color: None,
banner_blurhash: None,
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),
}
}
}
type UserRelationExtSource<'a> = (
Option<&'a ck::following::Model>,
Option<&'a ck::following::Model>,
Option<&'a ck::blocking::Model>,
Option<&'a ck::blocking::Model>,
Option<&'a ck::muting::Model>,
Option<&'a ck::renote_muting::Model>,
);
impl PackType<UserRelationExtSource<'_>> for UserRelationExt {
fn extract(
context: &PackingContext,
(follow_out, follow_in, block_out, block_in, mute, renote_mute): 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
})
}),
}
}
}
impl PackType<&[PackNoteFull]> for UserProfilePinsEx {
fn extract(_context: &PackingContext, pinned_notes: &[PackNoteFull]) -> 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(),
}
}
}