diff --git a/src/activitypub/builders/delete_note.rs b/src/activitypub/builders/delete_note.rs new file mode 100644 index 0000000..4d7140c --- /dev/null +++ b/src/activitypub/builders/delete_note.rs @@ -0,0 +1,26 @@ +use tokio_postgres::GenericClient; + +use crate::activitypub::activity::create_activity_delete_note as build_delete_note; +use crate::activitypub::deliverer::OutgoingActivity; +use crate::config::Instance; +use crate::errors::DatabaseError; +use crate::mastodon_api::statuses::helpers::get_note_recipients; +use crate::models::posts::types::Post; +use crate::models::users::types::User; + +pub async fn prepare_delete_note( + db_client: &impl GenericClient, + instance: Instance, + author: &User, + post: &Post, +) -> Result { + assert_eq!(author.id, post.author.id); + let activity = build_delete_note(&instance.url(), post); + let recipients = get_note_recipients(db_client, author, post).await?; + Ok(OutgoingActivity { + instance, + sender: author.clone(), + activity, + recipients, + }) +} diff --git a/src/activitypub/builders/mod.rs b/src/activitypub/builders/mod.rs new file mode 100644 index 0000000..26e9756 --- /dev/null +++ b/src/activitypub/builders/mod.rs @@ -0,0 +1 @@ +pub mod delete_note; diff --git a/src/activitypub/deliverer.rs b/src/activitypub/deliverer.rs index 0f66077..ee4ab7c 100644 --- a/src/activitypub/deliverer.rs +++ b/src/activitypub/deliverer.rs @@ -91,6 +91,9 @@ async fn deliver_activity_worker( ACTOR_KEY_SUFFIX, ); let activity_json = serde_json::to_string(&activity)?; + if recipients.is_empty() { + return Ok(()); + }; let mut inboxes: Vec = recipients.into_iter() .map(|actor| actor.inbox) .collect(); @@ -112,25 +115,42 @@ async fn deliver_activity_worker( Ok(()) } +pub struct OutgoingActivity { + pub instance: Instance, + pub sender: User, + pub activity: Activity, + pub recipients: Vec, +} + +impl OutgoingActivity { + pub async fn deliver(self) -> Result<(), DelivererError> { + deliver_activity_worker( + self.instance, + self.sender, + self.activity, + self.recipients, + ).await + } + + pub fn spawn_deliver(self) -> () { + actix_rt::spawn(async move { + self.deliver().await.unwrap_or_else(|err| { + log::error!("{}", err); + }); + }); + } +} + pub fn deliver_activity( config: &Config, sender: &User, activity: Activity, recipients: Vec, ) -> () { - if recipients.is_empty() { - return; - }; - let instance = config.instance(); - let sender = sender.clone(); - actix_rt::spawn(async move { - deliver_activity_worker( - instance, - sender, - activity, - recipients, - ).await.unwrap_or_else(|err| { - log::error!("{}", err); - }); - }); + OutgoingActivity { + instance: config.instance(), + sender: sender.clone(), + activity, + recipients, + }.spawn_deliver(); } diff --git a/src/activitypub/mod.rs b/src/activitypub/mod.rs index d21397a..141d600 100644 --- a/src/activitypub/mod.rs +++ b/src/activitypub/mod.rs @@ -1,5 +1,6 @@ pub mod activity; pub mod actor; +pub mod builders; mod collections; pub mod constants; pub mod deliverer; diff --git a/src/bin/mitractl.rs b/src/bin/mitractl.rs index 5685d89..7fa3a45 100644 --- a/src/bin/mitractl.rs +++ b/src/bin/mitractl.rs @@ -2,6 +2,7 @@ use chrono::{Duration, Utc}; use clap::Parser; use uuid::Uuid; +use mitra::activitypub::builders::delete_note::prepare_delete_note; use mitra::activitypub::fetcher::fetchers::fetch_actor; use mitra::activitypub::handlers::update_person::update_actor; use mitra::config; @@ -11,11 +12,12 @@ use mitra::ethereum::signatures::generate_ecdsa_key; use mitra::ethereum::utils::key_to_ethereum_address; use mitra::logger::configure_logger; use mitra::models::attachments::queries::delete_unused_attachments; -use mitra::models::posts::queries::{delete_post, find_extraneous_posts}; +use mitra::models::posts::queries::{delete_post, find_extraneous_posts, get_post_by_id}; use mitra::models::profiles::queries::delete_profile; use mitra::models::users::queries::{ create_invite_code, get_invite_codes, + get_user_by_id, }; use mitra::utils::crypto::{generate_private_key, serialize_private_key}; @@ -152,8 +154,15 @@ async fn main() { println!("profile deleted"); }, SubCommand::DeletePost(subopts) => { - let deletion_queue = delete_post(db_client, &subopts.id).await.unwrap(); + let post = get_post_by_id(db_client, &subopts.id).await.unwrap(); + let deletion_queue = delete_post(db_client, &post.id).await.unwrap(); deletion_queue.process(&config).await; + if post.author.is_local() { + // Send Delete(Note) activity + let author = get_user_by_id(db_client, &post.author.id).await.unwrap(); + prepare_delete_note(db_client, config.instance(), &author, &post).await.unwrap() + .deliver().await.unwrap(); + }; println!("post deleted"); }, SubCommand::DeleteExtraneousPosts(subopts) => { diff --git a/src/mastodon_api/statuses/views.rs b/src/mastodon_api/statuses/views.rs index c61ee89..bf7fa83 100644 --- a/src/mastodon_api/statuses/views.rs +++ b/src/mastodon_api/statuses/views.rs @@ -11,8 +11,8 @@ use crate::activitypub::activity::{ create_activity_undo_like, create_activity_announce, create_activity_undo_announce, - create_activity_delete_note, }; +use crate::activitypub::builders::delete_note::prepare_delete_note; use crate::activitypub::deliverer::deliver_activity; use crate::config::Config; use crate::database::{Pool, get_database_client}; @@ -175,12 +175,8 @@ async fn delete_status( deletion_queue.process(&config_clone).await; }); - let activity = create_activity_delete_note( - &config.instance_url(), - &post, - ); - let recipients = get_note_recipients(db_client, ¤t_user, &post).await?; - deliver_activity(&config, ¤t_user, activity, recipients); + prepare_delete_note(db_client, config.instance(), ¤t_user, &post).await? + .spawn_deliver(); Ok(HttpResponse::NoContent().finish()) }