143 lines
3.9 KiB
Rust
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)
|
|
}
|
|
}
|