]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/send/person.rs
9560c2fbcef957a96be00340971f146a34681c2f
[lemmy.git] / crates / apub / src / activities / send / person.rs
1 use crate::{
2   activities::send::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_structs::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 #[async_trait::async_trait(?Send)]
28 impl ActorType for Person {
29   fn is_local(&self) -> bool {
30     self.local
31   }
32   fn actor_id(&self) -> Url {
33     self.actor_id.to_owned().into_inner()
34   }
35
36   fn public_key(&self) -> Option<String> {
37     self.public_key.to_owned()
38   }
39
40   fn private_key(&self) -> Option<String> {
41     self.private_key.to_owned()
42   }
43
44   fn get_shared_inbox_or_inbox_url(&self) -> Url {
45     self
46       .shared_inbox_url
47       .clone()
48       .unwrap_or_else(|| self.inbox_url.to_owned())
49       .into()
50   }
51 }
52
53 #[async_trait::async_trait(?Send)]
54 impl UserType for Person {
55   /// As a given local person, send out a follow request to a remote community.
56   async fn send_follow(
57     &self,
58     follow_actor_id: &Url,
59     context: &LemmyContext,
60   ) -> Result<(), LemmyError> {
61     let follow_actor_id = follow_actor_id.to_owned();
62     let community = blocking(context.pool(), move |conn| {
63       Community::read_from_apub_id(conn, &follow_actor_id.into())
64     })
65     .await??;
66
67     let community_follower_form = CommunityFollowerForm {
68       community_id: community.id,
69       person_id: self.id,
70       pending: true,
71     };
72     blocking(&context.pool(), move |conn| {
73       CommunityFollower::follow(conn, &community_follower_form).ok()
74     })
75     .await?;
76
77     let mut follow = Follow::new(self.actor_id.to_owned().into_inner(), community.actor_id());
78     follow
79       .set_many_contexts(lemmy_context()?)
80       .set_id(generate_activity_id(FollowType::Follow)?)
81       .set_to(community.actor_id());
82
83     send_activity_single_dest(follow, self, community.inbox_url.into(), context).await?;
84     Ok(())
85   }
86
87   async fn send_unfollow(
88     &self,
89     follow_actor_id: &Url,
90     context: &LemmyContext,
91   ) -> Result<(), LemmyError> {
92     let follow_actor_id = follow_actor_id.to_owned();
93     let community = blocking(context.pool(), move |conn| {
94       Community::read_from_apub_id(conn, &follow_actor_id.into())
95     })
96     .await??;
97
98     let mut follow = Follow::new(self.actor_id.to_owned().into_inner(), community.actor_id());
99     follow
100       .set_many_contexts(lemmy_context()?)
101       .set_id(generate_activity_id(FollowType::Follow)?)
102       .set_to(community.actor_id());
103
104     // Undo that fake activity
105     let mut undo = Undo::new(
106       self.actor_id.to_owned().into_inner(),
107       follow.into_any_base()?,
108     );
109     undo
110       .set_many_contexts(lemmy_context()?)
111       .set_id(generate_activity_id(UndoType::Undo)?)
112       .set_to(community.actor_id());
113
114     send_activity_single_dest(undo, self, community.inbox_url.into(), context).await?;
115     Ok(())
116   }
117 }