]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/voting/undo_vote.rs
Move @context out of object/activity definitions
[lemmy.git] / crates / apub / src / activities / voting / undo_vote.rs
1 use crate::{
2   activities::{
3     community::{
4       announce::{AnnouncableActivities, GetCommunity},
5       send_to_community,
6     },
7     generate_activity_id,
8     verify_activity,
9     verify_is_public,
10     verify_person_in_community,
11     voting::{
12       undo_vote_comment,
13       undo_vote_post,
14       vote::{Vote, VoteType},
15     },
16   },
17   fetcher::object_id::ObjectId,
18   objects::{community::ApubCommunity, person::ApubPerson},
19   PostOrComment,
20 };
21 use activitystreams::{activity::kind::UndoType, public, unparsed::Unparsed};
22 use lemmy_api_common::blocking;
23 use lemmy_apub_lib::{
24   data::Data,
25   traits::{ActivityFields, ActivityHandler, ActorType},
26   verify::verify_urls_match,
27 };
28 use lemmy_db_schema::{newtypes::CommunityId, source::community::Community, traits::Crud};
29 use lemmy_utils::LemmyError;
30 use lemmy_websocket::LemmyContext;
31 use serde::{Deserialize, Serialize};
32 use std::ops::Deref;
33 use url::Url;
34
35 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
36 #[serde(rename_all = "camelCase")]
37 pub struct UndoVote {
38   actor: ObjectId<ApubPerson>,
39   to: Vec<Url>,
40   object: Vote,
41   cc: Vec<Url>,
42   #[serde(rename = "type")]
43   kind: UndoType,
44   id: Url,
45   #[serde(flatten)]
46   unparsed: Unparsed,
47 }
48
49 impl UndoVote {
50   pub async fn send(
51     object: &PostOrComment,
52     actor: &ApubPerson,
53     community_id: CommunityId,
54     kind: VoteType,
55     context: &LemmyContext,
56   ) -> Result<(), LemmyError> {
57     let community: ApubCommunity = blocking(context.pool(), move |conn| {
58       Community::read(conn, community_id)
59     })
60     .await??
61     .into();
62
63     let object = Vote::new(object, actor, &community, kind.clone(), context)?;
64     let id = generate_activity_id(
65       UndoType::Undo,
66       &context.settings().get_protocol_and_hostname(),
67     )?;
68     let undo_vote = UndoVote {
69       actor: ObjectId::new(actor.actor_id()),
70       to: vec![public()],
71       object,
72       cc: vec![community.actor_id()],
73       kind: UndoType::Undo,
74       id: id.clone(),
75       unparsed: Default::default(),
76     };
77     let activity = AnnouncableActivities::UndoVote(undo_vote);
78     send_to_community(activity, &id, actor, &community, vec![], context).await
79   }
80 }
81
82 #[async_trait::async_trait(?Send)]
83 impl ActivityHandler for UndoVote {
84   type DataType = LemmyContext;
85   async fn verify(
86     &self,
87     context: &Data<LemmyContext>,
88     request_counter: &mut i32,
89   ) -> Result<(), LemmyError> {
90     verify_is_public(&self.to)?;
91     verify_activity(self, &context.settings())?;
92     let community = self.get_community(context, request_counter).await?;
93     verify_person_in_community(&self.actor, &community, context, request_counter).await?;
94     verify_urls_match(self.actor(), self.object.actor())?;
95     self.object.verify(context, request_counter).await?;
96     Ok(())
97   }
98
99   async fn receive(
100     self,
101     context: &Data<LemmyContext>,
102     request_counter: &mut i32,
103   ) -> Result<(), LemmyError> {
104     let actor = self.actor.dereference(context, request_counter).await?;
105     let object = self
106       .object
107       .object
108       .dereference(context, request_counter)
109       .await?;
110     match object {
111       PostOrComment::Post(p) => undo_vote_post(actor, p.deref(), context).await,
112       PostOrComment::Comment(c) => undo_vote_comment(actor, &c, context).await,
113     }
114   }
115 }
116
117 #[async_trait::async_trait(?Send)]
118 impl GetCommunity for UndoVote {
119   async fn get_community(
120     &self,
121     context: &LemmyContext,
122     request_counter: &mut i32,
123   ) -> Result<ApubCommunity, LemmyError> {
124     self.object.get_community(context, request_counter).await
125   }
126 }