2 activities::{generate_activity_id, send_lemmy_activity, verify_person},
3 fetcher::user_or_community::UserOrCommunity,
5 objects::{community::ApubCommunity, person::ApubPerson},
6 protocol::activities::following::{follow::Follow, undo_follow::UndoFollow},
8 use activitypub_federation::{
10 kinds::activity::UndoType,
11 protocol::verification::verify_urls_match,
12 traits::{ActivityHandler, Actor},
14 use lemmy_api_common::context::LemmyContext;
15 use lemmy_db_schema::{
17 community::{CommunityFollower, CommunityFollowerForm},
18 person::{PersonFollower, PersonFollowerForm},
22 use lemmy_utils::error::LemmyError;
26 #[tracing::instrument(skip_all)]
29 community: &ApubCommunity,
30 context: &Data<LemmyContext>,
31 ) -> Result<(), LemmyError> {
32 let object = Follow::new(actor, community, context)?;
33 let undo = UndoFollow {
34 actor: actor.id().into(),
35 to: Some([community.id().into()]),
38 id: generate_activity_id(
40 &context.settings().get_protocol_and_hostname(),
43 let inbox = vec![community.shared_inbox_or_inbox()];
44 send_lemmy_activity(context, undo, actor, inbox, true).await
48 #[async_trait::async_trait]
49 impl ActivityHandler for UndoFollow {
50 type DataType = LemmyContext;
51 type Error = LemmyError;
53 fn id(&self) -> &Url {
57 fn actor(&self) -> &Url {
61 #[tracing::instrument(skip_all)]
62 async fn verify(&self, context: &Data<LemmyContext>) -> Result<(), LemmyError> {
63 verify_urls_match(self.actor.inner(), self.object.actor.inner())?;
64 verify_person(&self.actor, context).await?;
65 self.object.verify(context).await?;
66 if let Some(to) = &self.to {
67 verify_urls_match(to[0].inner(), self.object.object.inner())?;
72 #[tracing::instrument(skip_all)]
73 async fn receive(self, context: &Data<LemmyContext>) -> Result<(), LemmyError> {
74 insert_activity(&self.id, &self, false, true, context).await?;
75 let person = self.actor.dereference(context).await?;
76 let object = self.object.object.dereference(context).await?;
79 UserOrCommunity::User(u) => {
80 let form = PersonFollowerForm {
82 follower_id: person.id,
85 PersonFollower::unfollow(context.pool(), &form).await?;
87 UserOrCommunity::Community(c) => {
88 let form = CommunityFollowerForm {
93 CommunityFollower::unfollow(context.pool(), &form).await?;