3 community::{announce::GetCommunity, send_activity_in_community},
5 verify_person_in_community,
6 voting::{vote_comment, vote_post},
8 activity_lists::AnnouncableActivities,
10 objects::{community::ApubCommunity, person::ApubPerson},
11 protocol::activities::voting::vote::{Vote, VoteType},
15 use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler};
17 use lemmy_db_schema::{
18 newtypes::CommunityId,
19 source::{community::Community, local_site::LocalSite, post::Post},
22 use lemmy_utils::error::LemmyError;
23 use lemmy_websocket::LemmyContext;
26 /// Vote has as:Public value in cc field, unlike other activities. This indicates to other software
27 /// (like GNU social, or presumably Mastodon), that the like actor should not be disclosed.
29 pub(in crate::activities::voting) fn new(
30 object: &PostOrComment,
33 context: &LemmyContext,
34 ) -> Result<Vote, LemmyError> {
36 actor: ObjectId::new(actor.actor_id()),
37 object: ObjectId::new(object.ap_id()),
39 id: generate_activity_id(kind, &context.settings().get_protocol_and_hostname())?,
43 #[tracing::instrument(skip_all)]
45 object: &PostOrComment,
47 community_id: CommunityId,
49 context: &LemmyContext,
50 ) -> Result<(), LemmyError> {
51 let community = Community::read(context.pool(), community_id).await?.into();
52 let vote = Vote::new(object, actor, kind, context)?;
54 let activity = AnnouncableActivities::Vote(vote);
55 send_activity_in_community(activity, actor, &community, vec![], context).await
59 #[async_trait::async_trait(?Send)]
60 impl ActivityHandler for Vote {
61 type DataType = LemmyContext;
62 type Error = LemmyError;
64 fn id(&self) -> &Url {
68 fn actor(&self) -> &Url {
72 #[tracing::instrument(skip_all)]
75 context: &Data<LemmyContext>,
76 request_counter: &mut i32,
77 ) -> Result<(), LemmyError> {
78 let community = self.get_community(context, request_counter).await?;
79 verify_person_in_community(&self.actor, &community, context, request_counter).await?;
80 let enable_downvotes = LocalSite::read(context.pool())
82 .map(|l| l.enable_downvotes)
84 if self.kind == VoteType::Dislike && !enable_downvotes {
85 return Err(anyhow!("Downvotes disabled").into());
90 #[tracing::instrument(skip_all)]
93 context: &Data<LemmyContext>,
94 request_counter: &mut i32,
95 ) -> Result<(), LemmyError> {
98 .dereference(context, local_instance(context).await, request_counter)
102 .dereference(context, local_instance(context).await, request_counter)
105 PostOrComment::Post(p) => vote_post(&self.kind, actor, &p, context).await,
106 PostOrComment::Comment(c) => vote_comment(&self.kind, actor, &c, context).await,
111 #[async_trait::async_trait(?Send)]
112 impl GetCommunity for Vote {
113 #[tracing::instrument(skip_all)]
114 async fn get_community(
116 context: &LemmyContext,
117 request_counter: &mut i32,
118 ) -> Result<ApubCommunity, LemmyError> {
121 .dereference(context, local_instance(context).await, request_counter)
123 let cid = match object {
124 PostOrComment::Post(p) => p.community_id,
125 PostOrComment::Comment(c) => Post::read(context.pool(), c.post_id).await?.community_id,
127 let community = Community::read(context.pool(), cid).await?;