]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/following/accept.rs
08853c50df77e8c1bd6f897eb0593ee95971d59f
[lemmy.git] / crates / apub / src / activities / following / accept.rs
1 use crate::{
2   activities::{generate_activity_id, send_lemmy_activity},
3   local_instance,
4   protocol::activities::following::{accept::AcceptFollow, follow::Follow},
5   ActorType,
6 };
7 use activitypub_federation::{
8   core::object_id::ObjectId,
9   data::Data,
10   traits::{ActivityHandler, Actor},
11   utils::verify_urls_match,
12 };
13 use activitystreams_kinds::activity::AcceptType;
14 use lemmy_api_common::{
15   community::CommunityResponse,
16   context::LemmyContext,
17   websocket::UserOperation,
18 };
19 use lemmy_db_schema::{
20   source::{actor_language::CommunityLanguage, community::CommunityFollower},
21   traits::Followable,
22 };
23 use lemmy_db_views::structs::LocalUserView;
24 use lemmy_db_views_actor::structs::CommunityView;
25 use lemmy_utils::error::LemmyError;
26 use url::Url;
27
28 impl AcceptFollow {
29   #[tracing::instrument(skip_all)]
30   pub async fn send(
31     follow: Follow,
32     context: &LemmyContext,
33     request_counter: &mut i32,
34   ) -> Result<(), LemmyError> {
35     let user_or_community = follow.object.dereference_local(context).await?;
36     let person = follow
37       .actor
38       .clone()
39       .dereference(context, local_instance(context).await, request_counter)
40       .await?;
41     let accept = AcceptFollow {
42       actor: ObjectId::new(user_or_community.actor_id()),
43       object: follow,
44       kind: AcceptType::Accept,
45       id: generate_activity_id(
46         AcceptType::Accept,
47         &context.settings().get_protocol_and_hostname(),
48       )?,
49     };
50     let inbox = vec![person.shared_inbox_or_inbox()];
51     send_lemmy_activity(context, accept, &user_or_community, inbox, true).await
52   }
53 }
54
55 /// Handle accepted follows
56 #[async_trait::async_trait(?Send)]
57 impl ActivityHandler for AcceptFollow {
58   type DataType = LemmyContext;
59   type Error = LemmyError;
60
61   fn id(&self) -> &Url {
62     &self.id
63   }
64
65   fn actor(&self) -> &Url {
66     self.actor.inner()
67   }
68
69   #[tracing::instrument(skip_all)]
70   async fn verify(
71     &self,
72     context: &Data<LemmyContext>,
73     request_counter: &mut i32,
74   ) -> Result<(), LemmyError> {
75     verify_urls_match(self.actor.inner(), self.object.object.inner())?;
76     self.object.verify(context, request_counter).await?;
77     Ok(())
78   }
79
80   #[tracing::instrument(skip_all)]
81   async fn receive(
82     self,
83     context: &Data<LemmyContext>,
84     request_counter: &mut i32,
85   ) -> Result<(), LemmyError> {
86     let community = self
87       .actor
88       .dereference(context, local_instance(context).await, request_counter)
89       .await?;
90     let person = self
91       .object
92       .actor
93       .dereference(context, local_instance(context).await, request_counter)
94       .await?;
95     // This will throw an error if no follow was requested
96     let community_id = community.id;
97     let person_id = person.id;
98     CommunityFollower::follow_accepted(context.pool(), community_id, person_id).await?;
99
100     // Send the Subscribed message over websocket
101     // Re-read the community_view to get the new SubscribedType
102     let community_view = CommunityView::read(context.pool(), community_id, Some(person_id)).await?;
103
104     // Get the local_user_id
105     let local_recipient_id = LocalUserView::read_person(context.pool(), person_id)
106       .await?
107       .local_user
108       .id;
109     let discussion_languages = CommunityLanguage::read(context.pool(), community_id).await?;
110
111     let response = CommunityResponse {
112       community_view,
113       discussion_languages,
114     };
115
116     context
117       .chat_server()
118       .send_user_room_message(
119         &UserOperation::FollowCommunity,
120         &response,
121         local_recipient_id,
122         None,
123       )
124       .await?;
125
126     Ok(())
127   }
128 }