diff --git a/server/Cargo.lock b/server/Cargo.lock index e6bac637..56e81b47 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -2814,18 +2814,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b3d3d2ff68104100ab257bb6bb0cb26c901abe4bd4ba15961f3bf867924012" +checksum = "d12a1dae4add0f0d568eebc7bf142f145ba1aa2544cafb195c76f0f409091b60" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca972988113b7715266f91250ddb98070d033c62a011fa0fcc57434a649310dd" +checksum = "3f34e0c1caaa462fd840ec6b768946ea1e7842620d94fe29d5b847138f521269" dependencies = [ "proc-macro2", "quote", diff --git a/server/src/api/mod.rs b/server/src/api/mod.rs index 70ff2bfe..8bc03fee 100644 --- a/server/src/api/mod.rs +++ b/server/src/api/mod.rs @@ -25,7 +25,7 @@ use crate::{ use crate::apub::{ fetcher::search_by_apub_id, signatures::generate_actor_keypair, - {make_apub_endpoint, ActorType, ApubObjectType, EndpointType}, + {make_apub_endpoint, ActorType, ApubLikeableType, ApubObjectType, EndpointType}, }; use crate::settings::Settings; use crate::websocket::{ diff --git a/server/src/api/post.rs b/server/src/api/post.rs index 5be227d8..306365fa 100644 --- a/server/src/api/post.rs +++ b/server/src/api/post.rs @@ -169,12 +169,13 @@ impl Perform for Oper { score: 1, }; - // Only add the like if the score isnt 0 let _inserted_like = match PostLike::like(&conn, &like_form) { Ok(like) => like, Err(_e) => return Err(APIError::err("couldnt_like_post").into()), }; + updated_post.send_like(&user, &conn)?; + // Refetch the view let post_view = match PostView::read(&conn, inserted_post.id, Some(user_id)) { Ok(post) => post, @@ -368,7 +369,8 @@ impl Perform for Oper { } // Check for a site ban - if UserView::read(&conn, user_id)?.banned { + let user = User_::read(&conn, user_id)?; + if user.banned { return Err(APIError::err("site_ban").into()); } @@ -388,6 +390,14 @@ impl Perform for Oper { Ok(like) => like, Err(_e) => return Err(APIError::err("couldnt_like_post").into()), }; + + if like_form.score == 1 { + post.send_like(&user, &conn)?; + } else if like_form.score == -1 { + post.send_dislike(&user, &conn)?; + } + } else { + // TODO tombstone the post like } let post_view = match PostView::read(&conn, data.post_id, Some(user_id)) { diff --git a/server/src/apub/mod.rs b/server/src/apub/mod.rs index 77d42b82..f56a8344 100644 --- a/server/src/apub/mod.rs +++ b/server/src/apub/mod.rs @@ -10,7 +10,7 @@ pub mod user; pub mod user_inbox; use activitystreams::{ - activity::{Accept, Create, Follow, Update}, + activity::{Accept, Create, Dislike, Follow, Like, Update}, actor::{properties::ApActorProperties, Actor, Group, Person}, collection::UnorderedCollection, context, @@ -161,6 +161,11 @@ pub trait ApubObjectType { fn send_update(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error>; } +pub trait ApubLikeableType { + fn send_like(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error>; + fn send_dislike(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error>; +} + pub fn get_shared_inbox(actor_id: &str) -> String { let url = Url::parse(actor_id).unwrap(); format!( diff --git a/server/src/apub/post.rs b/server/src/apub/post.rs index 4164eca7..505ab98a 100644 --- a/server/src/apub/post.rs +++ b/server/src/apub/post.rs @@ -160,3 +160,69 @@ impl ApubObjectType for Post { Ok(()) } } + +impl ApubLikeableType for Post { + fn send_like(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error> { + let page = self.to_apub(conn)?; + let community = Community::read(conn, self.community_id)?; + let mut like = Like::new(); + populate_object_props( + &mut like.object_props, + &community.get_followers_url(), + &self.ap_id, + )?; + like + .like_props + .set_actor_xsd_any_uri(creator.actor_id.to_owned())? + .set_object_base_box(page)?; + + // Insert the sent activity into the activity table + let activity_form = activity::ActivityForm { + user_id: creator.id, + data: serde_json::to_value(&like)?, + local: true, + updated: None, + }; + activity::Activity::create(&conn, &activity_form)?; + + send_activity( + &like, + &creator.private_key.as_ref().unwrap(), + &creator.actor_id, + community.get_follower_inboxes(&conn)?, + )?; + Ok(()) + } + + fn send_dislike(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error> { + let page = self.to_apub(conn)?; + let community = Community::read(conn, self.community_id)?; + let mut dislike = Dislike::new(); + populate_object_props( + &mut dislike.object_props, + &community.get_followers_url(), + &self.ap_id, + )?; + dislike + .dislike_props + .set_actor_xsd_any_uri(creator.actor_id.to_owned())? + .set_object_base_box(page)?; + + // Insert the sent activity into the activity table + let activity_form = activity::ActivityForm { + user_id: creator.id, + data: serde_json::to_value(&dislike)?, + local: true, + updated: None, + }; + activity::Activity::create(&conn, &activity_form)?; + + send_activity( + &dislike, + &creator.private_key.as_ref().unwrap(), + &creator.actor_id, + community.get_follower_inboxes(&conn)?, + )?; + Ok(()) + } +}