Send and receive Like activities

This commit is contained in:
silverpill 2021-10-29 19:21:26 +00:00
parent 371be9836e
commit d41d85548d
4 changed files with 83 additions and 7 deletions

View file

@ -163,6 +163,27 @@ pub fn create_activity_note(
activity
}
pub fn create_activity_like(
instance_url: &str,
actor_profile: &DbActorProfile,
object_id: &str,
) -> Activity {
let object = Object {
context: Some(json!(AP_CONTEXT)),
id: object_id.to_string(),
object_type: NOTE.to_string(),
..Default::default()
};
let activity = create_activity(
instance_url,
&actor_profile.username,
LIKE,
None,
serde_json::to_value(object).unwrap(),
);
activity
}
pub fn create_activity_follow(
instance_url: &str,
actor_profile: &DbActorProfile,

View file

@ -22,6 +22,7 @@ use crate::models::profiles::queries::{
update_profile,
};
use crate::models::profiles::types::{DbActorProfile, ProfileUpdateData};
use crate::models::reactions::queries::create_reaction;
use crate::models::relationships::queries::{
follow_request_accepted,
follow_request_rejected,
@ -216,6 +217,23 @@ pub async fn receive_activity(
create_post(db_client, &author.id, post_data).await?;
}
},
(LIKE, _) => {
let author = get_or_fetch_profile_by_actor_id(
db_client,
&activity.actor,
&config.media_dir(),
).await?;
let object_id = match activity.object.as_str() {
Some(object_id) => object_id.to_owned(),
None => {
let object: Object = serde_json::from_value(activity.object)
.map_err(|_| ValidationError("invalid object"))?;
object.id
},
};
let post_id = parse_object_id(&config.instance_url(), &object_id)?;
create_reaction(db_client, &author.id, &post_id).await?;
},
(FOLLOW, _) => {
let source_profile = get_or_fetch_profile_by_actor_id(
db_client,
@ -225,8 +243,14 @@ pub async fn receive_activity(
let source_actor_value = source_profile.actor_json.ok_or(HttpError::InternalError)?;
let source_actor: Actor = serde_json::from_value(source_actor_value)
.map_err(|_| HttpError::InternalError)?;
let target_actor_id = activity.object.as_str()
.ok_or(ValidationError("invalid object"))?;
let target_actor_id = match activity.object.as_str() {
Some(object_id) => object_id.to_owned(),
None => {
let object: Object = serde_json::from_value(activity.object)
.map_err(|_| ValidationError("invalid object"))?;
object.id
},
};
let target_username = parse_actor_id(&config.instance_url(), &target_actor_id)?;
let target_profile = get_profile_by_acct(db_client, &target_username).await?;
// Create and send 'Accept' activity

View file

@ -2,6 +2,7 @@
pub const ACCEPT: &str = "Accept";
pub const CREATE: &str = "Create";
pub const FOLLOW: &str = "Follow";
pub const LIKE: &str = "Like";
pub const REJECT: &str = "Reject";
pub const UNDO: &str = "Undo";
pub const UPDATE: &str = "Update";

View file

@ -4,7 +4,10 @@ use actix_web_httpauth::extractors::bearer::BearerAuth;
use serde::Serialize;
use uuid::Uuid;
use crate::activitypub::activity::create_activity_note;
use crate::activitypub::activity::{
create_activity_note,
create_activity_like,
};
use crate::activitypub::actor::Actor;
use crate::activitypub::deliverer::deliver_activity;
use crate::config::Config;
@ -137,12 +140,39 @@ async fn favourite(
) -> Result<HttpResponse, HttpError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
match create_reaction(db_client, &current_user.id, &status_id).await {
Err(DatabaseError::AlreadyExists(_)) => (), // post already favourited
other_result => other_result?,
}
let reaction_created = match create_reaction(
db_client, &current_user.id, &status_id,
).await {
Ok(_) => true,
Err(DatabaseError::AlreadyExists(_)) => false, // post already favourited
Err(other_error) => return Err(other_error.into()),
};
let mut post = get_post_by_id(db_client, &status_id).await?;
get_actions_for_post(db_client, &current_user.id, &mut post).await?;
if reaction_created {
if let Some(actor_value) = &post.author.actor_json {
// Federate
let object_id = post.object_id.as_ref().ok_or(HttpError::InternalError)?;
let activity = create_activity_like(
&config.instance_url(),
&current_user.profile,
&object_id,
);
let recipient: Actor = serde_json::from_value(actor_value.clone())
.map_err(|_| HttpError::InternalError)?;
let config_clone = config.clone();
actix_rt::spawn(async move {
deliver_activity(
&config_clone,
&current_user,
activity,
vec![recipient],
).await;
});
}
}
let status = Status::from_post(post, &config.instance_url());
Ok(HttpResponse::Ok().json(status))
}