]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/voting/mod.rs
add enable_federated_downvotes site option
[lemmy.git] / crates / apub / src / activities / voting / mod.rs
1 use crate::{
2   activities::community::send_activity_in_community,
3   activity_lists::AnnouncableActivities,
4   fetcher::post_or_comment::PostOrComment,
5   objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost},
6   protocol::activities::voting::{
7     undo_vote::UndoVote,
8     vote::{Vote, VoteType},
9   },
10 };
11 use activitypub_federation::{config::Data, fetch::object_id::ObjectId};
12 use lemmy_api_common::context::LemmyContext;
13 use lemmy_db_schema::{
14   newtypes::DbUrl,
15   source::{
16     comment::{CommentLike, CommentLikeForm},
17     community::Community,
18     person::Person,
19     post::{PostLike, PostLikeForm},
20   },
21   traits::Likeable,
22 };
23 use lemmy_utils::error::LemmyError;
24
25 pub mod undo_vote;
26 pub mod vote;
27
28 pub(crate) async fn send_like_activity(
29   object_id: DbUrl,
30   actor: Person,
31   community: Community,
32   score: i16,
33   context: Data<LemmyContext>,
34 ) -> Result<(), LemmyError> {
35   let object_id: ObjectId<PostOrComment> = object_id.try_into()?;
36   let actor: ApubPerson = actor.into();
37   let community: ApubCommunity = community.into();
38
39   // score of 1 means upvote, -1 downvote, 0 undo a previous vote
40   if score != 0 {
41     let vote = Vote::new(object_id, &actor, &community, score.try_into()?, &context)?;
42     let activity = AnnouncableActivities::Vote(vote);
43     send_activity_in_community(activity, &actor, &community, vec![], false, &context).await
44   } else {
45     // Lemmy API doesnt distinguish between Undo/Like and Undo/Dislike, so we hardcode it here.
46     let vote = Vote::new(object_id, &actor, &community, VoteType::Like, &context)?;
47     let undo_vote = UndoVote::new(vote, &actor, &community, &context)?;
48     let activity = AnnouncableActivities::UndoVote(undo_vote);
49     send_activity_in_community(activity, &actor, &community, vec![], false, &context).await
50   }
51 }
52
53 #[tracing::instrument(skip_all)]
54 async fn vote_comment(
55   vote_type: &VoteType,
56   actor: ApubPerson,
57   comment: &ApubComment,
58   context: &Data<LemmyContext>,
59 ) -> Result<(), LemmyError> {
60   let comment_id = comment.id;
61   let like_form = CommentLikeForm {
62     comment_id,
63     post_id: comment.post_id,
64     person_id: actor.id,
65     score: vote_type.into(),
66   };
67   let person_id = actor.id;
68   CommentLike::remove(&mut context.pool(), person_id, comment_id).await?;
69   CommentLike::like(&mut context.pool(), &like_form).await?;
70   Ok(())
71 }
72
73 #[tracing::instrument(skip_all)]
74 async fn vote_post(
75   vote_type: &VoteType,
76   actor: ApubPerson,
77   post: &ApubPost,
78   context: &Data<LemmyContext>,
79 ) -> Result<(), LemmyError> {
80   let post_id = post.id;
81   let like_form = PostLikeForm {
82     post_id: post.id,
83     person_id: actor.id,
84     score: vote_type.into(),
85   };
86   let person_id = actor.id;
87   PostLike::remove(&mut context.pool(), person_id, post_id).await?;
88   PostLike::like(&mut context.pool(), &like_form).await?;
89   Ok(())
90 }
91
92 #[tracing::instrument(skip_all)]
93 async fn undo_vote_comment(
94   actor: ApubPerson,
95   comment: &ApubComment,
96   context: &Data<LemmyContext>,
97 ) -> Result<(), LemmyError> {
98   let comment_id = comment.id;
99   let person_id = actor.id;
100   CommentLike::remove(&mut context.pool(), person_id, comment_id).await?;
101   Ok(())
102 }
103
104 #[tracing::instrument(skip_all)]
105 async fn undo_vote_post(
106   actor: ApubPerson,
107   post: &ApubPost,
108   context: &Data<LemmyContext>,
109 ) -> Result<(), LemmyError> {
110   let post_id = post.id;
111   let person_id = actor.id;
112   PostLike::remove(&mut context.pool(), person_id, post_id).await?;
113   Ok(())
114 }