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

122 lines
4.1 KiB
Rust
Raw Normal View History

2021-01-04 17:34:31 +00:00
use crate::{
2021-01-04 17:41:34 +00:00
apub::actions::{
2021-01-04 17:34:31 +00:00
AnnounceSubmission, CreateSubmission, DeleteComment, DeleteSubmission, UpdateSubmission,
},
Action, Context, Error, Required,
};
use std::collections::HashSet;
impl Action for CreateSubmission {
fn perform(&self, context: &Context) -> Result<(), Error> {
let submission =
context
.store
.submissions
.create(self.profile_id, &self.title, self.visibility)?;
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)?;
context.apub.submission(&self.apub_id, submission.id())?;
let submission_id = submission.id();
let profile_id = self.profile_id;
let published = submission.published().req()?;
let context_clone = context.clone();
context.arbiter.send(Box::pin(async move {
let _ = actix_web::web::block(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,
);
}
}
Ok(()) as Result<(), ()>
})
.await;
}));
Ok(())
}
}
impl Action for AnnounceSubmission {
fn perform(&self, _: &Context) -> Result<(), Error> {
Ok(())
}
}
impl Action for UpdateSubmission {
fn perform(&self, context: &Context) -> Result<(), Error> {
let submission = context.store.submissions.by_id(self.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);
}
Ok(())
}
}
impl Action for DeleteSubmission {
fn perform(&self, context: &Context) -> Result<(), Error> {
let opt = context.store.submissions.delete(self.submission_id)?;
if let Some(undo_submission) = opt {
for comment_id in context.store.comments.for_submission(self.submission_id) {
if let Err(e) = Action::perform(&DeleteComment { comment_id }, context) {
log::error!("Failed to delete comment {}: {}", comment_id, e);
}
}
for file_id in undo_submission.0.files() {
context.spawner.purge_file(*file_id);
}
let submission_id = self.submission_id;
let context_clone = context.clone();
context.arbiter.send(Box::pin(async move {
let _ = actix_web::web::block(move || {
context_clone.store.view.submissions.remove(submission_id);
Ok(()) as Result<(), ()>
})
.await;
}));
}
Ok(())
}
}