fedimovies/src/activitypub/handlers/like.rs

58 lines
1.7 KiB
Rust

use serde::Deserialize;
use serde_json::Value;
use fedimovies_config::Config;
use fedimovies_models::{
database::{DatabaseClient, DatabaseError},
reactions::queries::create_reaction,
};
use crate::activitypub::{
fetcher::helpers::{get_or_import_profile_by_actor_id, get_post_by_object_id},
receiver::deserialize_into_object_id,
vocabulary::NOTE,
};
use crate::errors::ValidationError;
use crate::media::MediaStorage;
use super::HandlerResult;
#[derive(Deserialize)]
struct Like {
id: String,
actor: String,
#[serde(deserialize_with = "deserialize_into_object_id")]
object: String,
}
pub async fn handle_like(
config: &Config,
db_client: &mut impl DatabaseClient,
activity: Value,
) -> HandlerResult {
let activity: Like = serde_json::from_value(activity.clone()).map_err(|_| {
ValidationError(format!("unexpected Like activity structure: {}", activity))
})?;
let author = get_or_import_profile_by_actor_id(
db_client,
&config.instance(),
&MediaStorage::from(config),
&activity.actor,
)
.await?;
let post_id =
match get_post_by_object_id(db_client, &config.instance_url(), &activity.object).await {
Ok(post) => post.id,
// Ignore like if post is not found locally
Err(DatabaseError::NotFound(_)) => return Ok(None),
Err(other_error) => return Err(other_error.into()),
};
match create_reaction(db_client, &author.id, &post_id, Some(&activity.id)).await {
Ok(_) => (),
// Ignore activity if reaction is already saved
Err(DatabaseError::AlreadyExists(_)) => return Ok(None),
Err(other_error) => return Err(other_error.into()),
};
Ok(Some(NOTE))
}