3 community::send_activity_in_community,
7 verify_person_in_community,
9 activity_lists::AnnouncableActivities,
11 objects::{community::ApubCommunity, person::ApubPerson, post::ApubPost},
12 protocol::{activities::community::collection_remove::CollectionRemove, InCommunity},
14 use activitypub_federation::{
16 fetch::object_id::ObjectId,
17 kinds::{activity::RemoveType, public},
18 traits::{ActivityHandler, Actor},
20 use lemmy_api_common::{
21 context::LemmyContext,
22 utils::{generate_featured_url, generate_moderators_url},
24 use lemmy_db_schema::{
25 impls::community::CollectionType,
27 community::{Community, CommunityModerator, CommunityModeratorForm},
28 moderator::{ModAddCommunity, ModAddCommunityForm},
29 post::{Post, PostUpdateForm},
31 traits::{Crud, Joinable},
33 use lemmy_utils::error::LemmyError;
36 impl CollectionRemove {
37 #[tracing::instrument(skip_all)]
38 pub async fn send_remove_mod(
39 community: &ApubCommunity,
40 removed_mod: &ApubPerson,
42 context: &Data<LemmyContext>,
43 ) -> Result<(), LemmyError> {
44 let id = generate_activity_id(
46 &context.settings().get_protocol_and_hostname(),
48 let remove = CollectionRemove {
49 actor: actor.id().into(),
51 object: removed_mod.id(),
52 target: generate_moderators_url(&community.actor_id)?.into(),
54 cc: vec![community.id()],
55 kind: RemoveType::Remove,
56 audience: Some(community.id().into()),
59 let activity = AnnouncableActivities::CollectionRemove(remove);
60 let inboxes = vec![removed_mod.shared_inbox_or_inbox()];
61 send_activity_in_community(activity, actor, community, inboxes, true, context).await
64 pub async fn send_remove_featured_post(
65 community: &ApubCommunity,
66 featured_post: &ApubPost,
68 context: &Data<LemmyContext>,
69 ) -> Result<(), LemmyError> {
70 let id = generate_activity_id(
72 &context.settings().get_protocol_and_hostname(),
74 let remove = CollectionRemove {
75 actor: actor.id().into(),
77 object: featured_post.ap_id.clone().into(),
78 target: generate_featured_url(&community.actor_id)?.into(),
79 cc: vec![community.id()],
80 kind: RemoveType::Remove,
82 audience: Some(community.id().into()),
84 let activity = AnnouncableActivities::CollectionRemove(remove);
85 send_activity_in_community(activity, actor, community, vec![], true, context).await
89 #[async_trait::async_trait]
90 impl ActivityHandler for CollectionRemove {
91 type DataType = LemmyContext;
92 type Error = LemmyError;
94 fn id(&self) -> &Url {
98 fn actor(&self) -> &Url {
102 #[tracing::instrument(skip_all)]
103 async fn verify(&self, context: &Data<Self::DataType>) -> Result<(), LemmyError> {
104 verify_is_public(&self.to, &self.cc)?;
105 let community = self.community(context).await?;
106 verify_person_in_community(&self.actor, &community, context).await?;
107 verify_mod_action(&self.actor, &self.object, community.id, context).await?;
111 #[tracing::instrument(skip_all)]
112 async fn receive(self, context: &Data<Self::DataType>) -> Result<(), LemmyError> {
113 insert_activity(&self.id, &self, false, false, context).await?;
114 let (community, collection_type) =
115 Community::get_by_collection_url(&mut context.pool(), &self.target.into()).await?;
116 match collection_type {
117 CollectionType::Moderators => {
118 let remove_mod = ObjectId::<ApubPerson>::from(self.object)
119 .dereference(context)
122 let form = CommunityModeratorForm {
123 community_id: community.id,
124 person_id: remove_mod.id,
126 CommunityModerator::leave(&mut context.pool(), &form).await?;
129 let actor = self.actor.dereference(context).await?;
130 let form = ModAddCommunityForm {
131 mod_person_id: actor.id,
132 other_person_id: remove_mod.id,
133 community_id: community.id,
136 ModAddCommunity::create(&mut context.pool(), &form).await?;
138 // TODO: send websocket notification about removed mod
140 CollectionType::Featured => {
141 let post = ObjectId::<ApubPost>::from(self.object)
142 .dereference(context)
144 let form = PostUpdateForm::builder()
145 .featured_community(Some(false))
147 Post::update(&mut context.pool(), post.id, &form).await?;