magnetar/src/model/mod.rs

143 lines
3.9 KiB
Rust

use crate::model::data::id::BaseId;
use crate::model::processing::PackResult;
use crate::service::MagnetarService;
use either::Either;
use magnetar_model::{ck, CalckeyDbError};
use magnetar_sdk::types::user::UserRelationship;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::Mutex;
pub mod data;
pub mod processing;
#[derive(Clone, Debug)]
pub struct ProcessingLimits {
max_emojis: usize,
}
impl Default for ProcessingLimits {
fn default() -> Self {
ProcessingLimits { max_emojis: 500 }
}
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
struct UserRelationshipLink {
from: String,
to: String,
rel_type: UserRelationship,
}
#[derive(Clone, Debug)]
pub struct PackingContext {
instance_meta: Arc<ck::meta::Model>,
self_user: Option<Arc<ck::user::Model>>,
service: Arc<MagnetarService>,
limits: ProcessingLimits,
relationships: Arc<Mutex<HashMap<UserRelationshipLink, bool>>>,
}
pub trait PackType<I>: 'static {
fn extract(context: &PackingContext, data: I) -> Self;
}
impl PackingContext {
pub async fn new(
service: Arc<MagnetarService>,
self_user: Option<Arc<ck::user::Model>>,
) -> PackResult<PackingContext> {
Ok(Self {
instance_meta: service.instance_meta_cache.get().await?,
self_user,
service,
limits: Default::default(),
relationships: Arc::new(Mutex::new(HashMap::new())),
})
}
fn self_user(&self) -> Option<&ck::user::Model> {
self.self_user.as_deref()
}
fn is_id_self(&self, user_id: &str) -> bool {
self.self_user()
.is_some_and(|self_user| self_user.id == user_id)
}
fn is_self(&self, user: &ck::user::Model) -> bool {
self.is_id_self(&user.id)
}
async fn has_relationship_with(
&self,
user: &ck::user::Model,
rel_type: UserRelationship,
) -> Result<bool, CalckeyDbError> {
let Some(self_user) = self.self_user.as_deref() else {
return Ok(false);
};
self.is_relationship_between(Either::Right(self_user), Either::Right(user), rel_type)
.await
}
async fn is_relationship_between(
&self,
from: Either<&str, &ck::user::Model>,
to: Either<&str, &ck::user::Model>,
rel_type: UserRelationship,
) -> Result<bool, CalckeyDbError> {
let link = UserRelationshipLink {
from: from.left_or_else(ck::user::Model::get_id).to_string(),
to: to.left_or_else(ck::user::Model::get_id).to_string(),
rel_type,
};
let read = self.relationships.lock().await;
if let Some(relationship) = read.get(&link) {
return Ok(*relationship);
}
drop(read);
let relationship = match rel_type {
UserRelationship::Block => self
.service
.db
.get_block_status(&link.from, &link.to)
.await?
.is_some(),
UserRelationship::Follow => self
.service
.db
.get_follower_status(&link.from, &link.to)
.await?
.is_some(),
UserRelationship::FollowRequest => self
.service
.db
.get_follow_request_status(&link.from, &link.to)
.await?
.is_some(),
UserRelationship::Mute => self
.service
.db
.get_mute_status(&link.from, &link.to)
.await?
.is_some(),
UserRelationship::RenoteMute => self
.service
.db
.get_renote_mute_status(&link.from, &link.to)
.await?
.is_some(),
};
let mut write = self.relationships.lock().await;
write.insert(link, relationship);
drop(write);
Ok(relationship)
}
}