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