3 following::accept::AcceptFollowCommunity,
8 verify_person_in_community,
10 fetcher::object_id::ObjectId,
11 objects::{community::ApubCommunity, person::ApubPerson},
13 use activitystreams::{activity::kind::FollowType, unparsed::Unparsed};
14 use lemmy_api_common::blocking;
17 traits::{ActivityFields, ActivityHandler, ActorType},
18 verify::verify_urls_match,
20 use lemmy_db_schema::{
21 source::community::{CommunityFollower, CommunityFollowerForm},
24 use lemmy_utils::LemmyError;
25 use lemmy_websocket::LemmyContext;
26 use serde::{Deserialize, Serialize};
29 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
30 #[serde(rename_all = "camelCase")]
31 pub struct FollowCommunity {
32 pub(in crate::activities::following) actor: ObjectId<ApubPerson>,
33 pub(in crate::activities::following) to: [ObjectId<ApubCommunity>; 1],
34 pub(in crate::activities::following) object: ObjectId<ApubCommunity>,
35 #[serde(rename = "type")]
42 impl FollowCommunity {
43 pub(in crate::activities::following) fn new(
45 community: &ApubCommunity,
46 context: &LemmyContext,
47 ) -> Result<FollowCommunity, LemmyError> {
49 actor: ObjectId::new(actor.actor_id()),
50 to: [ObjectId::new(community.actor_id())],
51 object: ObjectId::new(community.actor_id()),
52 kind: FollowType::Follow,
53 id: generate_activity_id(
55 &context.settings().get_protocol_and_hostname(),
57 unparsed: Default::default(),
62 community: &ApubCommunity,
63 context: &LemmyContext,
64 ) -> Result<(), LemmyError> {
65 let community_follower_form = CommunityFollowerForm {
66 community_id: community.id,
70 blocking(context.pool(), move |conn| {
71 CommunityFollower::follow(conn, &community_follower_form).ok()
75 let follow = FollowCommunity::new(actor, community, context)?;
76 let inbox = vec![community.inbox_url.clone().into()];
77 send_lemmy_activity(context, &follow, &follow.id, actor, inbox, true).await
81 #[async_trait::async_trait(?Send)]
82 impl ActivityHandler for FollowCommunity {
83 type DataType = LemmyContext;
86 context: &Data<LemmyContext>,
87 request_counter: &mut i32,
88 ) -> Result<(), LemmyError> {
89 verify_activity(self, &context.settings())?;
90 verify_urls_match(self.to[0].inner(), self.object.inner())?;
91 verify_person(&self.actor, context, request_counter).await?;
92 let community = self.to[0].dereference(context, request_counter).await?;
93 verify_person_in_community(&self.actor, &community, context, request_counter).await?;
99 context: &Data<LemmyContext>,
100 request_counter: &mut i32,
101 ) -> Result<(), LemmyError> {
102 let actor = self.actor.dereference(context, request_counter).await?;
103 let community = self.to[0].dereference(context, request_counter).await?;
104 let community_follower_form = CommunityFollowerForm {
105 community_id: community.id,
110 // This will fail if they're already a follower, but ignore the error.
111 blocking(context.pool(), move |conn| {
112 CommunityFollower::follow(conn, &community_follower_form).ok()
116 AcceptFollowCommunity::send(self, context, request_counter).await