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

235 lines
7.9 KiB
Rust

use crate::{
apub::actions::{CreateComment, DeleteComment, DeleteReact, UpdateComment},
Action, Context, Error, Outbound, Required,
};
impl Action for CreateComment {
fn perform(&self, ctx: &Context) -> Result<Option<Box<dyn Outbound + Send>>, Error> {
let submission = ctx
.store
.submissions
.by_id(self.submission_id)?
.req("submission by id")?;
let submissioner_id = submission.profile_id();
ctx.check_block(submissioner_id, self.profile_id)?;
let comment_data = if let Some(comment_id) = self.comment_id {
let commenter_id = ctx
.store
.comments
.by_id(comment_id)?
.req("comment by id")?
.profile_id();
ctx.check_block(commenter_id, self.profile_id)?;
Some(commenter_id)
} else {
None
};
let mut changes =
ctx.store
.comments
.create(ctx, self.submission_id, self.profile_id, self.comment_id);
changes.published(self.published);
if let Some(updated) = self.updated {
changes.updated(updated);
}
if let Some(body) = &self.body {
changes.body(body);
}
if let Some(body_source) = &self.body_source {
changes.body_source(body_source);
}
let comment = changes.save()??;
if let Some(apub_id) = &self.note_apub_id {
ctx.apub.comment(apub_id, comment.id())?;
}
if let Some(commenter_id) = comment_data {
if commenter_id != submissioner_id && commenter_id != self.profile_id {
if let Ok(true) = ctx.is_local(commenter_id) {
ctx.store
.view
.comments
.new(commenter_id, comment.id(), self.published);
}
}
};
if let Ok(true) = ctx.is_local(submissioner_id) {
if submissioner_id != self.profile_id {
ctx.store
.view
.comments
.new(submissioner_id, comment.id(), self.published);
}
}
if !submission.is_local_only() {
if ctx.is_local(self.profile_id)? && ctx.is_local(submissioner_id)? {
return Ok(Some(Box::new(
crate::apub::results::AnnounceCommentCreated {
submissioner_id,
comment_id: comment.id(),
},
)));
} else if ctx.is_local(self.profile_id)? {
return Ok(Some(Box::new(crate::apub::results::CommentCreated {
comment_id: comment.id(),
})));
} else if ctx.is_local(submissioner_id)? {
if let Some(apub_id) = &self.note_apub_id {
return Ok(Some(Box::new(crate::apub::results::RemoteCommentCreated {
note_apub_id: apub_id.clone(),
submissioner_id,
})));
}
}
} else {
return Ok(Some(Box::new(crate::apub::results::LocalCommentCreated {
comment_id: comment.id(),
})));
}
Ok(None)
}
}
impl Action for UpdateComment {
fn perform(&self, ctx: &Context) -> Result<Option<Box<dyn Outbound + Send>>, Error> {
let comment = ctx
.store
.comments
.by_id(self.comment_id)?
.req("comment by id")?;
if comment.deleted() {
return Err(Error::Deleted);
}
let mut changes = comment.update(ctx);
changes.updated(self.updated);
if let Some(body) = &self.body {
changes.body(body);
}
if let Some(body_source) = &self.body_source {
changes.body_source(body_source);
}
let comment = if changes.any_changes() {
changes.save()??
} else {
comment
};
let submission = ctx
.store
.submissions
.by_id(comment.submission_id())?
.req("submission by id")?;
let submissioner_id = submission.profile_id();
let is_local_only = submission.is_local_only();
if !is_local_only {
if ctx.is_local(comment.profile_id())? && ctx.is_local(submissioner_id)? {
return Ok(Some(Box::new(
crate::apub::results::AnnounceCommentUpdated {
submissioner_id,
comment_id: comment.id(),
},
)));
} else if ctx.is_local(comment.profile_id())? {
return Ok(Some(Box::new(crate::apub::results::CommentUpdated {
comment_id: comment.id(),
})));
} else if ctx.is_local(submissioner_id)? {
if let Some(apub_id) = &self.update_apub_id {
return Ok(Some(Box::new(crate::apub::results::RemoteCommentUpdated {
update_apub_id: apub_id.to_owned(),
submissioner_id,
})));
}
}
} else {
return Ok(Some(Box::new(crate::apub::results::LocalCommentUpdated {
comment_id: comment.id(),
})));
}
Ok(None)
}
}
fn delete_react(react_id: uuid::Uuid, ctx: &Context) -> Result<(), Error> {
Action::perform(&DeleteReact { react_id }, ctx)?;
Ok(())
}
impl Action for DeleteComment {
fn perform(&self, ctx: &Context) -> Result<Option<Box<dyn Outbound + Send>>, Error> {
let comment_id = self.comment_id;
let opt = ctx.store.comments.delete(comment_id)?;
if let Some(undo_comment) = opt {
ctx.store.view.comments.remove(comment_id);
let note_apub_id = ctx
.apub
.apub_for_comment(comment_id)?
.req("apub id for comment id")?;
ctx.apub.delete_object(&note_apub_id)?;
let comment_id = undo_comment.0.id();
let ctx_clone = ctx.clone();
ctx.spawn_blocking(move || {
for react_id in ctx_clone.store.reacts.for_comment(comment_id) {
if let Err(e) = delete_react(react_id, &ctx_clone) {
log::error!("Error deleing react {}: {}", react_id, e);
}
}
});
let submissioner_id = ctx
.store
.submissions
.by_id(undo_comment.0.submission_id())?
.req("submission by id")?
.profile_id();
if ctx.is_local(undo_comment.0.profile_id())? && ctx.is_local(submissioner_id)? {
return Ok(Some(Box::new(
crate::apub::results::AnnounceCommentDeleted {
note_apub_id,
submissioner_id,
commenter_id: undo_comment.0.profile_id(),
},
)));
} else if ctx.is_local(undo_comment.0.profile_id())? {
return Ok(Some(Box::new(crate::apub::results::CommentDeleted {
note_apub_id,
commenter_id: undo_comment.0.profile_id(),
submission_id: undo_comment.0.submission_id(),
reply_to_id: undo_comment.0.comment_id(),
})));
} else if ctx.is_local(submissioner_id)? {
if let Some(apub_id) = &self.delete_apub_id {
return Ok(Some(Box::new(crate::apub::results::RemoteCommentDeleted {
delete_apub_id: apub_id.to_owned(),
submissioner_id,
})));
}
}
}
Ok(None)
}
}