157 lines
5.3 KiB
Rust
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(¬e_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)
|
|
}
|
|
}
|