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())?,
40 unparsed: Default::default(),
44 #[tracing::instrument(skip_all)]
46 object: &PostOrComment,
48 community_id: CommunityId,
50 context: &LemmyContext,
51 ) -> Result<(), LemmyError> {
52 let community = Community::read(context.pool(), community_id).await?.into();
53 let vote = Vote::new(object, actor, kind, context)?;
55 let activity = AnnouncableActivities::Vote(vote);
56 send_activity_in_community(activity, actor, &community, vec![], context).await
60 #[async_trait::async_trait(?Send)]
61 impl ActivityHandler for Vote {
62 type DataType = LemmyContext;
63 type Error = LemmyError;
65 fn id(&self) -> &Url {
69 fn actor(&self) -> &Url {
73 #[tracing::instrument(skip_all)]
76 context: &Data<LemmyContext>,
77 request_counter: &mut i32,
78 ) -> Result<(), LemmyError> {
79 let community = self.get_community(context, request_counter).await?;
80 verify_person_in_community(&self.actor, &community, context, request_counter).await?;
81 let enable_downvotes = LocalSite::read(context.pool())
83 .map(|l| l.enable_downvotes)
85 if self.kind == VoteType::Dislike && !enable_downvotes {
86 return Err(anyhow!("Downvotes disabled").into());
91 #[tracing::instrument(skip_all)]
94 context: &Data<LemmyContext>,
95 request_counter: &mut i32,
96 ) -> Result<(), LemmyError> {
99 .dereference(context, local_instance(context).await, request_counter)
103 .dereference(context, local_instance(context).await, request_counter)
106 PostOrComment::Post(p) => vote_post(&self.kind, actor, &p, context).await,
107 PostOrComment::Comment(c) => vote_comment(&self.kind, actor, &c, context).await,
112 #[async_trait::async_trait(?Send)]
113 impl GetCommunity for Vote {
114 #[tracing::instrument(skip_all)]
115 async fn get_community(
117 context: &LemmyContext,
118 request_counter: &mut i32,
119 ) -> Result<ApubCommunity, LemmyError> {
122 .dereference(context, local_instance(context).await, request_counter)
124 let cid = match object {
125 PostOrComment::Post(p) => p.community_id,
126 PostOrComment::Comment(c) => Post::read(context.pool(), c.post_id).await?.community_id,
128 let community = Community::read(context.pool(), cid).await?;