2 activities::{generate_activity_id, send_lemmy_activity},
6 protocol::activities::following::{accept::AcceptFollowCommunity, follow::FollowCommunity},
9 use activitypub_federation::{
10 core::object_id::ObjectId,
12 traits::{ActivityHandler, Actor},
13 utils::verify_urls_match,
15 use activitystreams_kinds::activity::AcceptType;
16 use lemmy_api_common::{community::CommunityResponse, utils::blocking};
17 use lemmy_db_schema::{source::community::CommunityFollower, traits::Followable};
18 use lemmy_db_views::structs::LocalUserView;
19 use lemmy_db_views_actor::structs::CommunityView;
20 use lemmy_utils::error::LemmyError;
21 use lemmy_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperation};
24 impl AcceptFollowCommunity {
25 #[tracing::instrument(skip_all)]
27 follow: FollowCommunity,
28 context: &LemmyContext,
29 request_counter: &mut i32,
30 ) -> Result<(), LemmyError> {
31 let community = follow.object.dereference_local(context).await?;
35 .dereference(context, local_instance(context), request_counter)
37 let accept = AcceptFollowCommunity {
38 actor: ObjectId::new(community.actor_id()),
40 kind: AcceptType::Accept,
41 id: generate_activity_id(
43 &context.settings().get_protocol_and_hostname(),
45 unparsed: Default::default(),
47 let inbox = vec![person.shared_inbox_or_inbox()];
48 send_lemmy_activity(context, accept, &community, inbox, true).await
52 /// Handle accepted follows
53 #[async_trait::async_trait(?Send)]
54 impl ActivityHandler for AcceptFollowCommunity {
55 type DataType = LemmyContext;
56 type Error = LemmyError;
58 fn id(&self) -> &Url {
62 fn actor(&self) -> &Url {
66 #[tracing::instrument(skip_all)]
69 context: &Data<LemmyContext>,
70 request_counter: &mut i32,
71 ) -> Result<(), LemmyError> {
72 let local_site_data = blocking(context.pool(), fetch_local_site_data).await??;
73 check_apub_id_valid(self.id(), &local_site_data, context.settings())
74 .map_err(LemmyError::from_message)?;
76 verify_urls_match(self.actor.inner(), self.object.object.inner())?;
77 self.object.verify(context, request_counter).await?;
81 #[tracing::instrument(skip_all)]
84 context: &Data<LemmyContext>,
85 request_counter: &mut i32,
86 ) -> Result<(), LemmyError> {
89 .dereference(context, local_instance(context), request_counter)
94 .dereference(context, local_instance(context), request_counter)
96 // This will throw an error if no follow was requested
97 let community_id = community.id;
98 let person_id = person.id;
99 blocking(context.pool(), move |conn| {
100 CommunityFollower::follow_accepted(conn, community_id, person_id)
104 // Send the Subscribed message over websocket
105 // Re-read the community_view to get the new SubscribedType
106 let community_view = blocking(context.pool(), move |conn| {
107 CommunityView::read(conn, community_id, Some(person_id))
111 // Get the local_user_id
112 let local_recipient_id = blocking(context.pool(), move |conn| {
113 LocalUserView::read_person(conn, person_id)
119 let response = CommunityResponse { community_view };
121 context.chat_server().do_send(SendUserRoomMessage {
122 op: UserOperation::FollowCommunity,