hyaenidae/profiles/src/apub/actions/submission.rs

157 lines
5.3 KiB
Rust

use crate::{
apub::actions::{
AnnounceSubmission, CreateSubmission, DeleteComment, DeleteSubmission, UpdateSubmission,
},
Action, Context, Error, Outbound, Required,
};
use std::collections::HashSet;
impl Action for CreateSubmission {
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Outbound + Send>>, Error> {
let submission =
context
.store
.submissions
.create(self.profile_id, &self.title, self.visibility)?;
let submission_id = submission.id();
let mut changes = submission.update();
changes.publish(Some(self.published));
if let Some(description) = &self.description {
changes.description(description);
}
let submission = context.store.submissions.update(&changes)?;
let mut changes = submission.update_files();
for file in &self.files {
if let Ok(Some(file)) = context.store.files.by_id(*file) {
changes.add_file(&file);
}
}
let submission = context.store.submissions.update_files(&changes)?;
if let Some(apub_id) = &self.note_apub_id {
context.apub.submission(apub_id, submission_id)?;
}
let profile_id = self.profile_id;
let published = submission.published().req()?;
let context_clone = context.clone();
context.spawn_blocking(move || {
for follower_id in context_clone.store.view.follows.forward_iter(profile_id) {
if let Ok(Some(true)) = context_clone.store.profiles.is_local(follower_id) {
context_clone
.store
.view
.submissions
.new(follower_id, submission_id, published);
}
}
});
if context.is_local(submission.profile_id())? {
return Ok(Some(Box::new(crate::apub::results::SubmissionCreated {
submission_id,
})));
}
Ok(None)
}
}
impl Action for AnnounceSubmission {
fn perform(&self, _: &Context) -> Result<Option<Box<dyn Outbound + Send>>, Error> {
Ok(None)
}
}
impl Action for UpdateSubmission {
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Outbound + Send>>, Error> {
let submission_id = self.submission_id;
let submission = context.store.submissions.by_id(submission_id)?.req()?;
let mut changes = submission.update();
if let Some(title) = &self.title {
changes.title(title);
}
if let Some(description) = &self.description {
changes.description(description);
}
let submission = context.store.submissions.update(&changes)?;
let mut original_files = submission.files().iter().cloned().collect::<HashSet<_>>();
let mut changes = submission.update_files();
for file in &self.files {
original_files.remove(file);
if let Ok(Some(file)) = context.store.files.by_id(*file) {
changes.add_file(&file);
}
}
context.store.submissions.update_files(&changes)?;
for file in original_files {
context.spawner.purge_file(file);
}
let profile_id = submission.profile_id();
if context.is_local(profile_id)? {
return Ok(Some(Box::new(crate::apub::results::SubmissionUpdated {
submission_id,
})));
}
Ok(None)
}
}
fn delete_comment(comment_id: uuid::Uuid, context: &Context) -> Result<(), Error> {
let note_apub_id = context.apub.apub_for_comment(comment_id)?.req()?;
Action::perform(
&DeleteComment {
note_apub_id,
comment_id,
},
context,
)?;
Ok(())
}
impl Action for DeleteSubmission {
fn perform(&self, context: &Context) -> Result<Option<Box<dyn Outbound + Send>>, Error> {
let submission_id = self.submission_id;
let opt = context.store.submissions.delete(submission_id)?;
if let Some(undo_submission) = opt {
let note_apub_id = context.apub.apub_for_submission(submission_id)?.req()?;
context.apub.delete_object(&note_apub_id)?;
let context_clone = context.clone();
context.spawn_blocking(move || {
for comment_id in context_clone.store.comments.for_submission(submission_id) {
if let Err(e) = delete_comment(comment_id, &context_clone) {
log::error!("Failed to delete comment {}: {}", comment_id, e);
}
}
});
for file_id in undo_submission.0.files() {
context.spawner.purge_file(*file_id);
}
let context_clone = context.clone();
context.spawn_blocking(move || {
context_clone.store.view.submissions.remove(submission_id);
});
let profile_id = undo_submission.0.profile_id();
if context.is_local(profile_id)? {
return Ok(Some(Box::new(crate::apub::results::SubmissionDeleted {
profile_id,
submission_id,
})));
}
}
Ok(None)
}
}