]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/send/person.rs
Merge pull request #1678 from LemmyNet/rewrite-post
[lemmy.git] / crates / apub / src / activities / send / person.rs
1 use crate::{
2   activities::generate_activity_id,
3   activity_queue::send_activity_single_dest,
4   extensions::context::lemmy_context,
5   ActorType,
6   UserType,
7 };
8 use activitystreams::{
9   activity::{
10     kind::{FollowType, UndoType},
11     Follow,
12     Undo,
13   },
14   base::{BaseExt, ExtendsExt},
15   object::ObjectExt,
16 };
17 use lemmy_api_common::blocking;
18 use lemmy_db_queries::{ApubObject, Followable};
19 use lemmy_db_schema::source::{
20   community::{Community, CommunityFollower, CommunityFollowerForm},
21   person::Person,
22 };
23 use lemmy_utils::LemmyError;
24 use lemmy_websocket::LemmyContext;
25 use url::Url;
26
27 impl ActorType for Person {
28   fn is_local(&self) -> bool {
29     self.local
30   }
31   fn actor_id(&self) -> Url {
32     self.actor_id.to_owned().into_inner()
33   }
34   fn name(&self) -> String {
35     self.name.clone()
36   }
37
38   fn public_key(&self) -> Option<String> {
39     self.public_key.to_owned()
40   }
41
42   fn private_key(&self) -> Option<String> {
43     self.private_key.to_owned()
44   }
45
46   fn get_shared_inbox_or_inbox_url(&self) -> Url {
47     self
48       .shared_inbox_url
49       .clone()
50       .unwrap_or_else(|| self.inbox_url.to_owned())
51       .into()
52   }
53 }
54
55 #[async_trait::async_trait(?Send)]
56 impl UserType for Person {
57   /// As a given local person, send out a follow request to a remote community.
58   async fn send_follow(
59     &self,
60     follow_actor_id: &Url,
61     context: &LemmyContext,
62   ) -> Result<(), LemmyError> {
63     let follow_actor_id = follow_actor_id.to_owned();
64     let community = blocking(context.pool(), move |conn| {
65       Community::read_from_apub_id(conn, &follow_actor_id.into())
66     })
67     .await??;
68
69     let community_follower_form = CommunityFollowerForm {
70       community_id: community.id,
71       person_id: self.id,
72       pending: true,
73     };
74     blocking(context.pool(), move |conn| {
75       CommunityFollower::follow(conn, &community_follower_form).ok()
76     })
77     .await?;
78
79     let mut follow = Follow::new(self.actor_id(), community.actor_id());
80     follow
81       .set_many_contexts(lemmy_context())
82       .set_id(generate_activity_id(FollowType::Follow)?)
83       .set_to(community.actor_id());
84
85     send_activity_single_dest(follow, self, community.inbox_url.into(), context).await?;
86     Ok(())
87   }
88
89   async fn send_unfollow(
90     &self,
91     follow_actor_id: &Url,
92     context: &LemmyContext,
93   ) -> Result<(), LemmyError> {
94     let follow_actor_id = follow_actor_id.to_owned();
95     let community = blocking(context.pool(), move |conn| {
96       Community::read_from_apub_id(conn, &follow_actor_id.into())
97     })
98     .await??;
99
100     let mut follow = Follow::new(self.actor_id(), community.actor_id());
101     follow
102       .set_many_contexts(lemmy_context())
103       .set_id(generate_activity_id(FollowType::Follow)?)
104       .set_to(community.actor_id());
105
106     // Undo that fake activity
107     let mut undo = Undo::new(
108       self.actor_id.to_owned().into_inner(),
109       follow.into_any_base()?,
110     );
111     undo
112       .set_many_contexts(lemmy_context())
113       .set_id(generate_activity_id(UndoType::Undo)?)
114       .set_to(community.actor_id());
115
116     send_activity_single_dest(undo, self, community.inbox_url.into(), context).await?;
117     Ok(())
118   }
119 }