3 deletion::{receive_delete_action, verify_delete_activity, DeletableObjects},
7 objects::person::ApubPerson,
8 protocol::{activities::deletion::delete::Delete, IdOrNestedObject},
10 use activitypub_federation::{config::Data, kinds::activity::DeleteType, traits::ActivityHandler};
11 use lemmy_api_common::{
12 context::LemmyContext,
14 send::{send_comment_ws_message_simple, send_community_ws_message, send_post_ws_message},
18 use lemmy_db_schema::{
20 comment::{Comment, CommentUpdateForm},
21 community::{Community, CommunityUpdateForm},
26 ModRemoveCommunityForm,
30 post::{Post, PostUpdateForm},
34 use lemmy_utils::error::LemmyError;
37 #[async_trait::async_trait]
38 impl ActivityHandler for Delete {
39 type DataType = LemmyContext;
40 type Error = LemmyError;
42 fn id(&self) -> &Url {
46 fn actor(&self) -> &Url {
50 #[tracing::instrument(skip_all)]
51 async fn verify(&self, context: &Data<Self::DataType>) -> Result<(), LemmyError> {
52 verify_delete_activity(self, self.summary.is_some(), context).await?;
56 #[tracing::instrument(skip_all)]
57 async fn receive(self, context: &Data<LemmyContext>) -> Result<(), LemmyError> {
58 insert_activity(&self.id, &self, false, false, context).await?;
59 if let Some(reason) = self.summary {
60 // We set reason to empty string if it doesn't exist, to distinguish between delete and
61 // remove. Here we change it back to option, so we don't write it to db.
62 let reason = if reason.is_empty() {
67 receive_remove_action(
68 &self.actor.dereference(context).await?,
75 receive_delete_action(self.object.id(), &self.actor, true, context).await
81 pub(in crate::activities::deletion) fn new(
83 object: DeletableObjects,
85 community: Option<&Community>,
86 summary: Option<String>,
87 context: &Data<LemmyContext>,
88 ) -> Result<Delete, LemmyError> {
89 let id = generate_activity_id(
91 &context.settings().get_protocol_and_hostname(),
93 let cc: Option<Url> = community.map(|c| c.actor_id.clone().into());
95 actor: actor.actor_id.clone().into(),
97 object: IdOrNestedObject::Id(object.id()),
98 cc: cc.into_iter().collect(),
99 kind: DeleteType::Delete,
102 audience: community.map(|c| c.actor_id.clone().into()),
107 #[tracing::instrument(skip_all)]
108 pub(in crate::activities) async fn receive_remove_action(
111 reason: Option<String>,
112 context: &Data<LemmyContext>,
113 ) -> Result<(), LemmyError> {
114 use UserOperationCrud::*;
115 match DeletableObjects::read_from_db(object, context).await? {
116 DeletableObjects::Community(community) => {
118 return Err(LemmyError::from_message(
119 "Only local admin can remove community",
122 let form = ModRemoveCommunityForm {
123 mod_person_id: actor.id,
124 community_id: community.id,
129 ModRemoveCommunity::create(context.pool(), &form).await?;
130 let deleted_community = Community::update(
133 &CommunityUpdateForm::builder().removed(Some(true)).build(),
137 send_community_ws_message(deleted_community.id, RemoveCommunity, None, None, context).await?;
139 DeletableObjects::Post(post) => {
140 let form = ModRemovePostForm {
141 mod_person_id: actor.id,
146 ModRemovePost::create(context.pool(), &form).await?;
147 let removed_post = Post::update(
150 &PostUpdateForm::builder().removed(Some(true)).build(),
154 send_post_ws_message(removed_post.id, RemovePost, None, None, context).await?;
156 DeletableObjects::Comment(comment) => {
157 let form = ModRemoveCommentForm {
158 mod_person_id: actor.id,
159 comment_id: comment.id,
163 ModRemoveComment::create(context.pool(), &form).await?;
164 let removed_comment = Comment::update(
167 &CommentUpdateForm::builder().removed(Some(true)).build(),
171 send_comment_ws_message_simple(removed_comment.id, RemoveComment, context).await?;
173 DeletableObjects::PrivateMessage(_) => unimplemented!(),