Err(_e) => return Err(APIError::err("couldnt_like_comment").into()),
};
+ updated_comment.send_like(&user, &conn)?;
+
let comment_view = CommentView::read(&conn, inserted_comment.id, Some(user_id))?;
let mut res = CommentResponse {
}
// 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());
}
Ok(like) => like,
Err(_e) => return Err(APIError::err("couldnt_like_comment").into()),
};
+
+ if like_form.score == 1 {
+ comment.send_like(&user, &conn)?;
+ } else if like_form.score == -1 {
+ comment.send_dislike(&user, &conn)?;
+ }
+ } else {
+ // TODO tombstone the like
}
// Have to refetch the comment to get the current state
let note = self.to_apub(conn)?;
let post = Post::read(&conn, self.post_id)?;
let community = Community::read(conn, post.community_id)?;
+ let id = format!("{}/create/{}", self.ap_id, uuid::Uuid::new_v4());
+
let mut create = Create::new();
populate_object_props(
&mut create.object_props,
&community.get_followers_url(),
- &self.ap_id,
+ &id,
)?;
create
.create_props
let note = self.to_apub(&conn)?;
let post = Post::read(&conn, self.post_id)?;
let community = Community::read(&conn, post.community_id)?;
+ let id = format!("{}/update/{}", self.ap_id, uuid::Uuid::new_v4());
+
let mut update = Update::new();
populate_object_props(
&mut update.object_props,
&community.get_followers_url(),
- &self.ap_id,
+ &id,
)?;
update
.update_props
Ok(())
}
}
+
+impl ApubLikeableType for Comment {
+ fn send_like(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error> {
+ let note = self.to_apub(&conn)?;
+ let post = Post::read(&conn, self.post_id)?;
+ let community = Community::read(&conn, post.community_id)?;
+ let id = format!("{}/like/{}", self.ap_id, uuid::Uuid::new_v4());
+
+ let mut like = Like::new();
+ populate_object_props(&mut like.object_props, &community.get_followers_url(), &id)?;
+ like
+ .like_props
+ .set_actor_xsd_any_uri(creator.actor_id.to_owned())?
+ .set_object_base_box(note)?;
+
+ // 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 note = self.to_apub(&conn)?;
+ let post = Post::read(&conn, self.post_id)?;
+ let community = Community::read(&conn, post.community_id)?;
+ let id = format!("{}/dislike/{}", self.ap_id, uuid::Uuid::new_v4());
+
+ let mut dislike = Dislike::new();
+ populate_object_props(
+ &mut dislike.object_props,
+ &community.get_followers_url(),
+ &id,
+ )?;
+ dislike
+ .dislike_props
+ .set_actor_xsd_any_uri(creator.actor_id.to_owned())?
+ .set_object_base_box(note)?;
+
+ // 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(())
+ }
+}
.get_actor_xsd_any_uri()
.unwrap()
.to_string();
+ let id = format!("{}/accept/{}", self.actor_id, uuid::Uuid::new_v4());
let mut accept = Accept::new();
- // TODO using a fake accept id
- let id = format!("{}/accept/{}", self.actor_id, uuid::Uuid::new_v4());
- //follow
accept
.object_props
.set_context_xsd_any_uri(context())?
use crate::api::comment::CommentResponse;
use crate::api::post::PostResponse;
use crate::api::site::SearchResponse;
-use crate::db::activity;
-use crate::db::comment::{Comment, CommentForm};
+use crate::db::comment::{Comment, CommentForm, CommentLike, CommentLikeForm};
use crate::db::comment_view::CommentView;
use crate::db::community::{Community, CommunityFollower, CommunityFollowerForm, CommunityForm};
use crate::db::community_view::{CommunityFollowerView, CommunityView};
-use crate::db::post::{Post, PostForm};
+use crate::db::post::{Post, PostForm, PostLike, PostLikeForm};
use crate::db::post_view::PostView;
use crate::db::user::{UserForm, User_};
use crate::db::user_view::UserView;
-use crate::db::{Crud, Followable, SearchType};
+use crate::db::{activity, Crud, Followable, Likeable, SearchType};
use crate::routes::nodeinfo::{NodeInfo, NodeInfoWellKnown};
use crate::routes::{ChatServerParam, DbPoolParam};
use crate::websocket::{
fn send_create(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error> {
let page = self.to_apub(conn)?;
let community = Community::read(conn, self.community_id)?;
+ let id = format!("{}/create/{}", self.ap_id, uuid::Uuid::new_v4());
+
let mut create = Create::new();
populate_object_props(
&mut create.object_props,
&community.get_followers_url(),
- &self.ap_id,
+ &id,
)?;
create
.create_props
fn send_update(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error> {
let page = self.to_apub(conn)?;
let community = Community::read(conn, self.community_id)?;
+ let id = format!("{}/update/{}", self.ap_id, uuid::Uuid::new_v4());
+
let mut update = Update::new();
populate_object_props(
&mut update.object_props,
&community.get_followers_url(),
- &self.ap_id,
+ &id,
)?;
update
.update_props
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 id = format!("{}/like/{}", self.ap_id, uuid::Uuid::new_v4());
+
let mut like = Like::new();
- populate_object_props(
- &mut like.object_props,
- &community.get_followers_url(),
- &self.ap_id,
- )?;
+ populate_object_props(&mut like.object_props, &community.get_followers_url(), &id)?;
like
.like_props
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
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 id = format!("{}/dislike/{}", self.ap_id, uuid::Uuid::new_v4());
+
let mut dislike = Dislike::new();
populate_object_props(
&mut dislike.object_props,
&community.get_followers_url(),
- &self.ap_id,
+ &id,
)?;
dislike
.dislike_props
pub enum SharedAcceptedObjects {
Create(Create),
Update(Update),
+ Like(Like),
+ Dislike(Dislike),
}
impl SharedAcceptedObjects {
match self {
SharedAcceptedObjects::Create(c) => c.create_props.get_object_base_box(),
SharedAcceptedObjects::Update(u) => u.update_props.get_object_base_box(),
+ SharedAcceptedObjects::Like(l) => l.like_props.get_object_base_box(),
+ SharedAcceptedObjects::Dislike(d) => d.dislike_props.get_object_base_box(),
}
}
}
let object = activity.object().cloned().unwrap();
match (activity, object.kind()) {
- (SharedAcceptedObjects::Create(c), Some("Note")) => {
- receive_create_comment(&c, &request, &conn, chat_server)
- }
(SharedAcceptedObjects::Create(c), Some("Page")) => {
receive_create_post(&c, &request, &conn, chat_server)
}
+ (SharedAcceptedObjects::Update(u), Some("Page")) => {
+ receive_update_post(&u, &request, &conn, chat_server)
+ }
+ (SharedAcceptedObjects::Like(l), Some("Page")) => {
+ receive_like_post(&l, &request, &conn, chat_server)
+ }
+ (SharedAcceptedObjects::Dislike(d), Some("Page")) => {
+ receive_dislike_post(&d, &request, &conn, chat_server)
+ }
+ (SharedAcceptedObjects::Create(c), Some("Note")) => {
+ receive_create_comment(&c, &request, &conn, chat_server)
+ }
(SharedAcceptedObjects::Update(u), Some("Note")) => {
receive_update_comment(&u, &request, &conn, chat_server)
}
- (SharedAcceptedObjects::Update(u), Some("Page")) => {
- receive_update_post(&u, &request, &conn, chat_server)
+ (SharedAcceptedObjects::Like(l), Some("Note")) => {
+ receive_like_comment(&l, &request, &conn, chat_server)
+ }
+ (SharedAcceptedObjects::Dislike(d), Some("Note")) => {
+ receive_dislike_comment(&d, &request, &conn, chat_server)
}
_ => Err(format_err!("Unknown incoming activity type.")),
}
Ok(HttpResponse::Ok().finish())
}
+fn receive_like_post(
+ like: &Like,
+ request: &HttpRequest,
+ conn: &PgConnection,
+ chat_server: ChatServerParam,
+) -> Result<HttpResponse, Error> {
+ let page = like
+ .like_props
+ .get_object_base_box()
+ .to_owned()
+ .unwrap()
+ .to_owned()
+ .to_concrete::<Page>()?;
+
+ let user_uri = like.like_props.get_actor_xsd_any_uri().unwrap().to_string();
+
+ let user = get_or_fetch_and_upsert_remote_user(&user_uri, &conn)?;
+ verify(request, &user.public_key.unwrap())?;
+
+ // Insert the received activity into the activity table
+ let activity_form = activity::ActivityForm {
+ user_id: user.id,
+ data: serde_json::to_value(&like)?,
+ local: false,
+ updated: None,
+ };
+ activity::Activity::create(&conn, &activity_form)?;
+
+ let post = PostForm::from_apub(&page, conn)?;
+ let post_id = Post::read_from_apub_id(conn, &post.ap_id)?.id;
+
+ let like_form = PostLikeForm {
+ post_id,
+ user_id: user.id,
+ score: 1,
+ };
+ PostLike::remove(&conn, &like_form)?;
+ PostLike::like(&conn, &like_form)?;
+
+ // Refetch the view
+ let post_view = PostView::read(&conn, post_id, None)?;
+
+ let res = PostResponse { post: post_view };
+
+ chat_server.do_send(SendPost {
+ op: UserOperation::CreatePostLike,
+ post: res,
+ my_id: None,
+ });
+
+ Ok(HttpResponse::Ok().finish())
+}
+
+fn receive_dislike_post(
+ dislike: &Dislike,
+ request: &HttpRequest,
+ conn: &PgConnection,
+ chat_server: ChatServerParam,
+) -> Result<HttpResponse, Error> {
+ let page = dislike
+ .dislike_props
+ .get_object_base_box()
+ .to_owned()
+ .unwrap()
+ .to_owned()
+ .to_concrete::<Page>()?;
+
+ let user_uri = dislike
+ .dislike_props
+ .get_actor_xsd_any_uri()
+ .unwrap()
+ .to_string();
+
+ let user = get_or_fetch_and_upsert_remote_user(&user_uri, &conn)?;
+ verify(request, &user.public_key.unwrap())?;
+
+ // Insert the received activity into the activity table
+ let activity_form = activity::ActivityForm {
+ user_id: user.id,
+ data: serde_json::to_value(&dislike)?,
+ local: false,
+ updated: None,
+ };
+ activity::Activity::create(&conn, &activity_form)?;
+
+ let post = PostForm::from_apub(&page, conn)?;
+ let post_id = Post::read_from_apub_id(conn, &post.ap_id)?.id;
+
+ let like_form = PostLikeForm {
+ post_id,
+ user_id: user.id,
+ score: -1,
+ };
+ PostLike::remove(&conn, &like_form)?;
+ PostLike::like(&conn, &like_form)?;
+
+ // Refetch the view
+ let post_view = PostView::read(&conn, post_id, None)?;
+
+ let res = PostResponse { post: post_view };
+
+ chat_server.do_send(SendPost {
+ op: UserOperation::CreatePostLike,
+ post: res,
+ my_id: None,
+ });
+
+ Ok(HttpResponse::Ok().finish())
+}
+
fn receive_update_comment(
update: &Update,
request: &HttpRequest,
Ok(HttpResponse::Ok().finish())
}
+
+fn receive_like_comment(
+ like: &Like,
+ request: &HttpRequest,
+ conn: &PgConnection,
+ chat_server: ChatServerParam,
+) -> Result<HttpResponse, Error> {
+ let note = like
+ .like_props
+ .get_object_base_box()
+ .to_owned()
+ .unwrap()
+ .to_owned()
+ .to_concrete::<Note>()?;
+
+ let user_uri = like.like_props.get_actor_xsd_any_uri().unwrap().to_string();
+
+ let user = get_or_fetch_and_upsert_remote_user(&user_uri, &conn)?;
+ verify(request, &user.public_key.unwrap())?;
+
+ // Insert the received activity into the activity table
+ let activity_form = activity::ActivityForm {
+ user_id: user.id,
+ data: serde_json::to_value(&like)?,
+ local: false,
+ updated: None,
+ };
+ activity::Activity::create(&conn, &activity_form)?;
+
+ let comment = CommentForm::from_apub(¬e, &conn)?;
+ let comment_id = Comment::read_from_apub_id(conn, &comment.ap_id)?.id;
+ let like_form = CommentLikeForm {
+ comment_id,
+ post_id: comment.post_id,
+ user_id: user.id,
+ score: 1,
+ };
+ CommentLike::remove(&conn, &like_form)?;
+ CommentLike::like(&conn, &like_form)?;
+
+ // Refetch the view
+ let comment_view = CommentView::read(&conn, comment_id, None)?;
+
+ // TODO get those recipient actor ids from somewhere
+ let recipient_ids = vec![];
+ let res = CommentResponse {
+ comment: comment_view,
+ recipient_ids,
+ };
+
+ chat_server.do_send(SendComment {
+ op: UserOperation::CreateCommentLike,
+ comment: res,
+ my_id: None,
+ });
+
+ Ok(HttpResponse::Ok().finish())
+}
+
+fn receive_dislike_comment(
+ dislike: &Dislike,
+ request: &HttpRequest,
+ conn: &PgConnection,
+ chat_server: ChatServerParam,
+) -> Result<HttpResponse, Error> {
+ let note = dislike
+ .dislike_props
+ .get_object_base_box()
+ .to_owned()
+ .unwrap()
+ .to_owned()
+ .to_concrete::<Note>()?;
+
+ let user_uri = dislike
+ .dislike_props
+ .get_actor_xsd_any_uri()
+ .unwrap()
+ .to_string();
+
+ let user = get_or_fetch_and_upsert_remote_user(&user_uri, &conn)?;
+ verify(request, &user.public_key.unwrap())?;
+
+ // Insert the received activity into the activity table
+ let activity_form = activity::ActivityForm {
+ user_id: user.id,
+ data: serde_json::to_value(&dislike)?,
+ local: false,
+ updated: None,
+ };
+ activity::Activity::create(&conn, &activity_form)?;
+
+ let comment = CommentForm::from_apub(¬e, &conn)?;
+ let comment_id = Comment::read_from_apub_id(conn, &comment.ap_id)?.id;
+ let like_form = CommentLikeForm {
+ comment_id,
+ post_id: comment.post_id,
+ user_id: user.id,
+ score: -1,
+ };
+ CommentLike::remove(&conn, &like_form)?;
+ CommentLike::like(&conn, &like_form)?;
+
+ // Refetch the view
+ let comment_view = CommentView::read(&conn, comment_id, None)?;
+
+ // TODO get those recipient actor ids from somewhere
+ let recipient_ids = vec![];
+ let res = CommentResponse {
+ comment: comment_view,
+ recipient_ids,
+ };
+
+ chat_server.do_send(SendComment {
+ op: UserOperation::CreateCommentLike,
+ comment: res,
+ my_id: None,
+ });
+
+ Ok(HttpResponse::Ok().finish())
+}
fn send_follow(&self, follow_actor_id: &str, conn: &PgConnection) -> Result<(), Error> {
let mut follow = Follow::new();
- // TODO using a fake accept id
let id = format!("{}/follow/{}", self.actor_id, uuid::Uuid::new_v4());
follow
expect(createResponse.post.name).toBe(name);
expect(createResponse.post.community_local).toBe(false);
expect(createResponse.post.creator_local).toBe(true);
+ expect(createResponse.post.score).toBe(1);
let getPostUrl = `${lemmyBetaApiUrl}/post?id=2`;
let getPostRes: GetPostResponse = await fetch(getPostUrl, {
expect(getPostRes.post.name).toBe(name);
expect(getPostRes.post.community_local).toBe(true);
expect(getPostRes.post.creator_local).toBe(false);
+ expect(getPostRes.post.score).toBe(1);
});
});
expect(createResponse.comment.content).toBe(content);
expect(createResponse.comment.community_local).toBe(false);
expect(createResponse.comment.creator_local).toBe(true);
+ expect(createResponse.comment.score).toBe(1);
let getPostUrl = `${lemmyBetaApiUrl}/post?id=2`;
let getPostRes: GetPostResponse = await fetch(getPostUrl, {
expect(getPostRes.comments[0].content).toBe(content);
expect(getPostRes.comments[0].community_local).toBe(true);
expect(getPostRes.comments[0].creator_local).toBe(false);
+ expect(getPostRes.comments[0].score).toBe(1);
// Now do beta replying to that comment, as a child comment
let contentBeta = 'A child federated comment from beta';
expect(createResponseBeta.comment.community_local).toBe(true);
expect(createResponseBeta.comment.creator_local).toBe(true);
expect(createResponseBeta.comment.parent_id).toBe(1);
+ expect(createResponseBeta.comment.score).toBe(1);
// Make sure lemmy alpha sees that new child comment from beta
let getPostUrlAlpha = `${lemmyAlphaApiUrl}/post?id=2`;
expect(getPostResAlpha.comments[0].content).toBe(contentBeta);
expect(getPostResAlpha.comments[0].community_local).toBe(false);
expect(getPostResAlpha.comments[0].creator_local).toBe(false);
+ expect(getPostResAlpha.comments[0].score).toBe(1);
});
});