3 comment::send_websocket_message as send_comment_message,
4 community::send_websocket_message as send_community_message,
5 post::send_websocket_message as send_post_message,
7 verify_add_remove_moderator_target,
9 verify_person_in_community,
12 community::get_or_fetch_and_upsert_community,
13 objects::get_or_fetch_and_insert_post_or_comment,
14 person::get_or_fetch_and_upsert_person,
19 use activitystreams::{activity::kind::RemoveType, base::AnyBase};
21 use lemmy_api_common::blocking;
22 use lemmy_apub_lib::{values::PublicUrl, ActivityCommonFields, ActivityHandler};
23 use lemmy_db_queries::{
24 source::{comment::Comment_, community::Community_, post::Post_},
27 use lemmy_db_schema::source::{
29 community::{Community, CommunityModerator, CommunityModeratorForm},
32 use lemmy_utils::LemmyError;
33 use lemmy_websocket::{LemmyContext, UserOperationCrud};
36 // TODO: we can probably deduplicate a bunch of code between this and DeletePostCommentOrCommunity
37 #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
38 #[serde(rename_all = "camelCase")]
39 pub struct RemovePostCommentCommunityOrMod {
41 pub(in crate::activities::removal) object: Url,
43 #[serde(rename = "type")]
45 // if target is set, this is means remove mod from community
48 common: ActivityCommonFields,
51 #[async_trait::async_trait(?Send)]
52 impl ActivityHandler for RemovePostCommentCommunityOrMod {
55 context: &LemmyContext,
56 request_counter: &mut i32,
57 ) -> Result<(), LemmyError> {
58 verify_activity(self.common())?;
59 let object_community =
60 get_or_fetch_and_upsert_community(&self.object, context, request_counter).await;
61 // removing a community
62 if object_community.is_ok() {
63 verify_mod_action(&self.common.actor, self.object.clone(), context).await?;
65 // removing community mod
66 else if let Some(target) = &self.target {
67 verify_person_in_community(&self.common.actor, &self.cc[0], context, request_counter).await?;
68 verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
69 verify_add_remove_moderator_target(target, self.cc[0].clone())?;
71 // removing a post or comment
73 verify_person_in_community(&self.common.actor, &self.cc[0], context, request_counter).await?;
74 verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
81 context: &LemmyContext,
82 request_counter: &mut i32,
83 ) -> Result<(), LemmyError> {
84 let object_community =
85 get_or_fetch_and_upsert_community(&self.object, context, request_counter).await;
86 // removing a community
87 if let Ok(community) = object_community {
89 return Err(anyhow!("Only local admin can remove community").into());
91 let deleted_community = blocking(context.pool(), move |conn| {
92 Community::update_removed(conn, community.id, true)
96 send_community_message(
98 UserOperationCrud::RemoveCommunity,
103 // removing community mod
104 else if self.target.is_some() {
106 get_or_fetch_and_upsert_community(&self.cc[0], context, request_counter).await?;
108 get_or_fetch_and_upsert_person(&self.object, context, request_counter).await?;
110 let form = CommunityModeratorForm {
111 community_id: community.id,
112 person_id: remove_mod.id,
114 blocking(context.pool(), move |conn| {
115 CommunityModerator::leave(conn, &form)
118 let anybase = AnyBase::from_arbitrary_json(serde_json::to_string(&self)?)?;
120 .send_announce(anybase, Some(self.object.clone()), context)
122 // TODO: send websocket notification about removed mod
125 // removing a post or comment
127 match get_or_fetch_and_insert_post_or_comment(&self.object, context, request_counter).await? {
128 PostOrComment::Post(post) => {
129 let removed_post = blocking(context.pool(), move |conn| {
130 Post::update_removed(conn, post.id, true)
133 send_post_message(removed_post.id, UserOperationCrud::EditPost, context).await
135 PostOrComment::Comment(comment) => {
136 let removed_comment = blocking(context.pool(), move |conn| {
137 Comment::update_removed(conn, comment.id, true)
140 send_comment_message(
143 UserOperationCrud::EditComment,
152 fn common(&self) -> &ActivityCommonFields {