mirror of https://github.com/LemmyNet/lemmy
Rewrite delete activities (#1699)
* Limit type/method visibility in apub code * Simplify db_queries traits by removing generics * Simplify delete activity implementation * Rewrite delete activities * Implement helper functions for websocket message sending * When receiving delete reason as empty string, change to nonepull/1710/head
parent
6fbf6a684c
commit
28d6370c35
@ -1,2 +1,209 @@
|
||||
use crate::{
|
||||
activities::{
|
||||
deletion::{delete::Delete, undo_delete::UndoDelete},
|
||||
verify_mod_action,
|
||||
verify_person_in_community,
|
||||
},
|
||||
fetcher::person::get_or_fetch_and_upsert_person,
|
||||
ActorType,
|
||||
};
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields};
|
||||
use lemmy_db_queries::{
|
||||
source::{comment::Comment_, community::Community_, post::Post_},
|
||||
ApubObject,
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{comment::Comment, community::Community, person::Person, post::Post},
|
||||
DbUrl,
|
||||
};
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::{
|
||||
send::{send_comment_ws_message_simple, send_community_ws_message, send_post_ws_message},
|
||||
LemmyContext,
|
||||
UserOperationCrud,
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
pub mod delete;
|
||||
pub mod undo_delete;
|
||||
|
||||
pub async fn send_apub_delete(
|
||||
actor: &Person,
|
||||
community: &Community,
|
||||
object_id: Url,
|
||||
deleted: bool,
|
||||
context: &LemmyContext,
|
||||
) -> Result<(), LemmyError> {
|
||||
if deleted {
|
||||
Delete::send(actor, community, object_id, None, context).await
|
||||
} else {
|
||||
UndoDelete::send(actor, community, object_id, None, context).await
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove reason is actually optional in lemmy. we set an empty string in that case, but its
|
||||
// ugly
|
||||
pub async fn send_apub_remove(
|
||||
actor: &Person,
|
||||
community: &Community,
|
||||
object_id: Url,
|
||||
reason: String,
|
||||
removed: bool,
|
||||
context: &LemmyContext,
|
||||
) -> Result<(), LemmyError> {
|
||||
if removed {
|
||||
Delete::send(actor, community, object_id, Some(reason), context).await
|
||||
} else {
|
||||
UndoDelete::send(actor, community, object_id, Some(reason), context).await
|
||||
}
|
||||
}
|
||||
|
||||
pub enum DeletableObjects {
|
||||
Community(Box<Community>),
|
||||
Comment(Box<Comment>),
|
||||
Post(Box<Post>),
|
||||
}
|
||||
|
||||
impl DeletableObjects {
|
||||
pub(crate) async fn read_from_db(
|
||||
ap_id: &Url,
|
||||
context: &LemmyContext,
|
||||
) -> Result<DeletableObjects, LemmyError> {
|
||||
let id: DbUrl = ap_id.clone().into();
|
||||
|
||||
if let Some(c) = DeletableObjects::read_type_from_db::<Community>(id.clone(), context).await? {
|
||||
return Ok(DeletableObjects::Community(Box::new(c)));
|
||||
}
|
||||
if let Some(p) = DeletableObjects::read_type_from_db::<Post>(id.clone(), context).await? {
|
||||
return Ok(DeletableObjects::Post(Box::new(p)));
|
||||
}
|
||||
if let Some(c) = DeletableObjects::read_type_from_db::<Comment>(id.clone(), context).await? {
|
||||
return Ok(DeletableObjects::Comment(Box::new(c)));
|
||||
}
|
||||
Err(diesel::NotFound.into())
|
||||
}
|
||||
|
||||
// TODO: a method like this should be provided by fetcher module
|
||||
async fn read_type_from_db<Type: ApubObject + Send + 'static>(
|
||||
ap_id: DbUrl,
|
||||
context: &LemmyContext,
|
||||
) -> Result<Option<Type>, LemmyError> {
|
||||
blocking(context.pool(), move |conn| {
|
||||
Type::read_from_apub_id(conn, &ap_id).ok()
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
pub(in crate::activities) async fn verify_delete_activity(
|
||||
object: &Url,
|
||||
cc: &Url,
|
||||
common: &ActivityCommonFields,
|
||||
is_mod_action: bool,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
let object = DeletableObjects::read_from_db(object, context).await?;
|
||||
match object {
|
||||
DeletableObjects::Community(c) => {
|
||||
if c.local {
|
||||
// can only do this check for local community, in remote case it would try to fetch the
|
||||
// deleted community (which fails)
|
||||
verify_person_in_community(&common.actor, cc, context, request_counter).await?;
|
||||
}
|
||||
// community deletion is always a mod (or admin) action
|
||||
verify_mod_action(&common.actor, c.actor_id(), context).await?;
|
||||
}
|
||||
DeletableObjects::Post(p) => {
|
||||
verify_delete_activity_post_or_comment(
|
||||
cc,
|
||||
common,
|
||||
&p.ap_id.into(),
|
||||
is_mod_action,
|
||||
context,
|
||||
request_counter,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
DeletableObjects::Comment(c) => {
|
||||
verify_delete_activity_post_or_comment(
|
||||
cc,
|
||||
common,
|
||||
&c.ap_id.into(),
|
||||
is_mod_action,
|
||||
context,
|
||||
request_counter,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn verify_delete_activity_post_or_comment(
|
||||
cc: &Url,
|
||||
common: &ActivityCommonFields,
|
||||
object_id: &Url,
|
||||
is_mod_action: bool,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
verify_person_in_community(&common.actor, cc, context, request_counter).await?;
|
||||
if is_mod_action {
|
||||
verify_mod_action(&common.actor, cc.clone(), context).await?;
|
||||
} else {
|
||||
// domain of post ap_id and post.creator ap_id are identical, so we just check the former
|
||||
verify_domains_match(&common.actor, object_id)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct WebsocketMessages {
|
||||
community: UserOperationCrud,
|
||||
post: UserOperationCrud,
|
||||
comment: UserOperationCrud,
|
||||
}
|
||||
|
||||
/// Write deletion or restoring of an object to the database, and send websocket message.
|
||||
/// TODO: we should do something similar for receive_remove_action(), but its much more complicated
|
||||
/// because of the mod log
|
||||
async fn receive_delete_action(
|
||||
object: &Url,
|
||||
actor: &Url,
|
||||
ws_messages: WebsocketMessages,
|
||||
deleted: bool,
|
||||
context: &LemmyContext,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<(), LemmyError> {
|
||||
match DeletableObjects::read_from_db(object, context).await? {
|
||||
DeletableObjects::Community(community) => {
|
||||
if community.local {
|
||||
let mod_ = get_or_fetch_and_upsert_person(actor, context, request_counter).await?;
|
||||
let object = community.actor_id();
|
||||
send_apub_delete(&mod_, &community.clone(), object, true, context).await?;
|
||||
}
|
||||
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
Community::update_deleted(conn, community.id, deleted)
|
||||
})
|
||||
.await??;
|
||||
send_community_ws_message(community.id, ws_messages.community, None, None, context).await?;
|
||||
}
|
||||
DeletableObjects::Post(post) => {
|
||||
let deleted_post = blocking(context.pool(), move |conn| {
|
||||
Post::update_deleted(conn, post.id, deleted)
|
||||
})
|
||||
.await??;
|
||||
send_post_ws_message(deleted_post.id, ws_messages.post, None, None, context).await?;
|
||||
}
|
||||
DeletableObjects::Comment(comment) => {
|
||||
let deleted_comment = blocking(context.pool(), move |conn| {
|
||||
Comment::update_deleted(conn, comment.id, deleted)
|
||||
})
|
||||
.await??;
|
||||
send_comment_ws_message_simple(deleted_comment.id, ws_messages.comment, context).await?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,153 +0,0 @@
|
||||
use crate::{
|
||||
activities::generate_activity_id,
|
||||
activity_queue::send_to_community,
|
||||
extensions::context::lemmy_context,
|
||||
ActorType,
|
||||
ApubObjectType,
|
||||
};
|
||||
use activitystreams::{
|
||||
activity::{
|
||||
kind::{DeleteType, RemoveType, UndoType},
|
||||
Delete,
|
||||
Remove,
|
||||
Undo,
|
||||
},
|
||||
prelude::*,
|
||||
public,
|
||||
};
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_db_queries::Crud;
|
||||
use lemmy_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post};
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ApubObjectType for Comment {
|
||||
async fn send_delete(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||
let post_id = self.post_id;
|
||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||
|
||||
let community_id = post.community_id;
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
Community::read(conn, community_id)
|
||||
})
|
||||
.await??;
|
||||
|
||||
let mut delete = Delete::new(
|
||||
creator.actor_id.to_owned().into_inner(),
|
||||
self.ap_id.to_owned().into_inner(),
|
||||
);
|
||||
delete
|
||||
.set_many_contexts(lemmy_context())
|
||||
.set_id(generate_activity_id(DeleteType::Delete)?)
|
||||
.set_to(public())
|
||||
.set_many_ccs(vec![community.actor_id()]);
|
||||
|
||||
send_to_community(delete, creator, &community, None, context).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn send_undo_delete(
|
||||
&self,
|
||||
creator: &Person,
|
||||
context: &LemmyContext,
|
||||
) -> Result<(), LemmyError> {
|
||||
let post_id = self.post_id;
|
||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||
|
||||
let community_id = post.community_id;
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
Community::read(conn, community_id)
|
||||
})
|
||||
.await??;
|
||||
|
||||
// Generate a fake delete activity, with the correct object
|
||||
let mut delete = Delete::new(
|
||||
creator.actor_id.to_owned().into_inner(),
|
||||
self.ap_id.to_owned().into_inner(),
|
||||
);
|
||||
delete
|
||||
.set_many_contexts(lemmy_context())
|
||||
.set_id(generate_activity_id(DeleteType::Delete)?)
|
||||
.set_to(public())
|
||||
.set_many_ccs(vec![community.actor_id()]);
|
||||
|
||||
// Undo that fake activity
|
||||
let mut undo = Undo::new(
|
||||
creator.actor_id.to_owned().into_inner(),
|
||||
delete.into_any_base()?,
|
||||
);
|
||||
undo
|
||||
.set_many_contexts(lemmy_context())
|
||||
.set_id(generate_activity_id(UndoType::Undo)?)
|
||||
.set_to(public())
|
||||
.set_many_ccs(vec![community.actor_id()]);
|
||||
|
||||
send_to_community(undo, creator, &community, None, context).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn send_remove(&self, mod_: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||
let post_id = self.post_id;
|
||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||
|
||||
let community_id = post.community_id;
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
Community::read(conn, community_id)
|
||||
})
|
||||
.await??;
|
||||
|
||||
let mut remove = Remove::new(
|
||||
mod_.actor_id.to_owned().into_inner(),
|
||||
self.ap_id.to_owned().into_inner(),
|
||||
);
|
||||
remove
|
||||
.set_many_contexts(lemmy_context())
|
||||
.set_id(generate_activity_id(RemoveType::Remove)?)
|
||||
.set_to(public())
|
||||
.set_many_ccs(vec![community.actor_id()]);
|
||||
|
||||
send_to_community(remove, mod_, &community, None, context).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn send_undo_remove(
|
||||
&self,
|
||||
mod_: &Person,
|
||||
context: &LemmyContext,
|
||||
) -> Result<(), LemmyError> {
|
||||
let post_id = self.post_id;
|
||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||
|
||||
let community_id = post.community_id;
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
Community::read(conn, community_id)
|
||||
})
|
||||
.await??;
|
||||
|
||||
// Generate a fake delete activity, with the correct object
|
||||
let mut remove = Remove::new(
|
||||
mod_.actor_id.to_owned().into_inner(),
|
||||
self.ap_id.to_owned().into_inner(),
|
||||
);
|
||||
remove
|
||||
.set_many_contexts(lemmy_context())
|
||||
.set_id(generate_activity_id(RemoveType::Remove)?)
|
||||
.set_to(public())
|
||||
.set_many_ccs(vec![community.actor_id()]);
|
||||
|
||||
// Undo that fake activity
|
||||
let mut undo = Undo::new(
|
||||
mod_.actor_id.to_owned().into_inner(),
|
||||
remove.into_any_base()?,
|
||||
);
|
||||
undo
|
||||
.set_many_contexts(lemmy_context())
|
||||
.set_id(generate_activity_id(UndoType::Undo)?)
|
||||
.set_to(public())
|
||||
.set_many_ccs(vec![community.actor_id()]);
|
||||
|
||||
send_to_community(undo, mod_, &community, None, context).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -1,139 +0,0 @@
|
||||
use crate::{
|
||||
activities::generate_activity_id,
|
||||
activity_queue::send_to_community,
|
||||
extensions::context::lemmy_context,
|
||||
ActorType,
|
||||
ApubObjectType,
|
||||
};
|
||||
use activitystreams::{
|
||||
activity::{
|
||||
kind::{DeleteType, RemoveType, UndoType},
|
||||
Delete,
|
||||
Remove,
|
||||
Undo,
|
||||
},
|
||||
prelude::*,
|
||||
public,
|
||||
};
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_db_queries::Crud;
|
||||
use lemmy_db_schema::source::{community::Community, person::Person, post::Post};
|
||||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ApubObjectType for Post {
|
||||
async fn send_delete(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||
let community_id = self.community_id;
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
Community::read(conn, community_id)
|
||||
})
|
||||
.await??;
|
||||
|
||||
let mut delete = Delete::new(
|
||||
creator.actor_id.to_owned().into_inner(),
|
||||
self.ap_id.to_owned().into_inner(),
|
||||
);
|
||||
delete
|
||||
.set_many_contexts(lemmy_context())
|
||||
.set_id(generate_activity_id(DeleteType::Delete)?)
|
||||
.set_to(public())
|
||||
.set_many_ccs(vec![community.actor_id()]);
|
||||
|
||||
send_to_community(delete, creator, &community, None, context).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn send_undo_delete(
|
||||
&self,
|
||||
creator: &Person,
|
||||
context: &LemmyContext,
|
||||
) -> Result<(), LemmyError> {
|
||||
let community_id = self.community_id;
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
Community::read(conn, community_id)
|
||||
})
|
||||
.await??;
|
||||
|
||||
let mut delete = Delete::new(
|
||||
creator.actor_id.to_owned().into_inner(),
|
||||
self.ap_id.to_owned().into_inner(),
|
||||
);
|
||||
delete
|
||||
.set_many_contexts(lemmy_context())
|
||||
.set_id(generate_activity_id(DeleteType::Delete)?)
|
||||
.set_to(public())
|
||||
.set_many_ccs(vec![community.actor_id()]);
|
||||
|
||||
// Undo that fake activity
|
||||
let mut undo = Undo::new(
|
||||
creator.actor_id.to_owned().into_inner(),
|
||||
delete.into_any_base()?,
|
||||
);
|
||||
undo
|
||||
.set_many_contexts(lemmy_context())
|
||||
.set_id(generate_activity_id(UndoType::Undo)?)
|
||||
.set_to(public())
|
||||
.set_many_ccs(vec![community.actor_id()]);
|
||||
|
||||
send_to_community(undo, creator, &community, None, context).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn send_remove(&self, mod_: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||
let community_id = self.community_id;
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
Community::read(conn, community_id)
|
||||
})
|
||||
.await??;
|
||||
|
||||
let mut remove = Remove::new(
|
||||
mod_.actor_id.to_owned().into_inner(),
|
||||
self.ap_id.to_owned().into_inner(),
|
||||
);
|
||||
remove
|
||||
.set_many_contexts(lemmy_context())
|
||||
.set_id(generate_activity_id(RemoveType::Remove)?)
|
||||
.set_to(public())
|
||||
.set_many_ccs(vec![community.actor_id()]);
|
||||
|
||||
send_to_community(remove, mod_, &community, None, context).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn send_undo_remove(
|
||||
&self,
|
||||
mod_: &Person,
|
||||
context: &LemmyContext,
|
||||
) -> Result<(), LemmyError> {
|
||||
let community_id = self.community_id;
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
Community::read(conn, community_id)
|
||||
})
|
||||
.await??;
|
||||
|
||||
let mut remove = Remove::new(
|
||||
mod_.actor_id.to_owned().into_inner(),
|
||||
self.ap_id.to_owned().into_inner(),
|
||||
);
|
||||
remove
|
||||
.set_many_contexts(lemmy_context())
|
||||
.set_id(generate_activity_id(RemoveType::Remove)?)
|
||||
.set_to(public())
|
||||
.set_many_ccs(vec![community.actor_id()]);
|
||||
|
||||
// Undo that fake activity
|
||||
let mut undo = Undo::new(
|
||||
mod_.actor_id.to_owned().into_inner(),
|
||||
remove.into_any_base()?,
|
||||
);
|
||||
undo
|
||||
.set_many_contexts(lemmy_context())
|
||||
.set_id(generate_activity_id(UndoType::Undo)?)
|
||||
.set_to(public())
|
||||
.set_many_ccs(vec![community.actor_id()]);
|
||||
|
||||
send_to_community(undo, mod_, &community, None, context).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -0,0 +1,162 @@
|
||||
use crate::{
|
||||
messages::{SendComment, SendCommunityRoomMessage, SendPost, SendUserRoomMessage},
|
||||
LemmyContext,
|
||||
OperationType,
|
||||
};
|
||||
use lemmy_api_common::{
|
||||
blocking,
|
||||
comment::CommentResponse,
|
||||
community::CommunityResponse,
|
||||
person::PrivateMessageResponse,
|
||||
post::PostResponse,
|
||||
};
|
||||
use lemmy_db_queries::DeleteableOrRemoveable;
|
||||
use lemmy_db_schema::{CommentId, CommunityId, LocalUserId, PersonId, PostId, PrivateMessageId};
|
||||
use lemmy_db_views::{
|
||||
comment_view::CommentView,
|
||||
local_user_view::LocalUserView,
|
||||
post_view::PostView,
|
||||
private_message_view::PrivateMessageView,
|
||||
};
|
||||
use lemmy_db_views_actor::community_view::CommunityView;
|
||||
use lemmy_utils::{ConnectionId, LemmyError};
|
||||
|
||||
pub async fn send_post_ws_message<OP: ToString + Send + OperationType + 'static>(
|
||||
post_id: PostId,
|
||||
op: OP,
|
||||
websocket_id: Option<ConnectionId>,
|
||||
person_id: Option<PersonId>,
|
||||
context: &LemmyContext,
|
||||
) -> Result<PostResponse, LemmyError> {
|
||||
let mut post_view = blocking(context.pool(), move |conn| {
|
||||
PostView::read(conn, post_id, person_id)
|
||||
})
|
||||
.await??;
|
||||
|
||||
if post_view.post.deleted || post_view.post.removed {
|
||||
post_view.post = post_view.post.blank_out_deleted_or_removed_info();
|
||||
}
|
||||
|
||||
let res = PostResponse { post_view };
|
||||
|
||||
context.chat_server().do_send(SendPost {
|
||||
op,
|
||||
post: res.clone(),
|
||||
websocket_id,
|
||||
});
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
// TODO: in many call sites in apub crate, we are setting an empty vec for recipient_ids,
|
||||
// we should get the actual recipient actors from somewhere
|
||||
pub async fn send_comment_ws_message_simple<OP: ToString + Send + OperationType + 'static>(
|
||||
comment_id: CommentId,
|
||||
op: OP,
|
||||
context: &LemmyContext,
|
||||
) -> Result<CommentResponse, LemmyError> {
|
||||
send_comment_ws_message(comment_id, op, None, None, None, vec![], context).await
|
||||
}
|
||||
|
||||
pub async fn send_comment_ws_message<OP: ToString + Send + OperationType + 'static>(
|
||||
comment_id: CommentId,
|
||||
op: OP,
|
||||
websocket_id: Option<ConnectionId>,
|
||||
form_id: Option<String>,
|
||||
person_id: Option<PersonId>,
|
||||
recipient_ids: Vec<LocalUserId>,
|
||||
context: &LemmyContext,
|
||||
) -> Result<CommentResponse, LemmyError> {
|
||||
let mut view = blocking(context.pool(), move |conn| {
|
||||
CommentView::read(conn, comment_id, person_id)
|
||||
})
|
||||
.await??;
|
||||
|
||||
if view.comment.deleted || view.comment.removed {
|
||||
view.comment = view.comment.blank_out_deleted_or_removed_info();
|
||||
}
|
||||
|
||||
let res = CommentResponse {
|
||||
comment_view: view,
|
||||
recipient_ids,
|
||||
form_id,
|
||||
};
|
||||
|
||||
context.chat_server().do_send(SendComment {
|
||||
op,
|
||||
comment: res.clone(),
|
||||
websocket_id,
|
||||
});
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub async fn send_community_ws_message<OP: ToString + Send + OperationType + 'static>(
|
||||
community_id: CommunityId,
|
||||
op: OP,
|
||||
websocket_id: Option<ConnectionId>,
|
||||
person_id: Option<PersonId>,
|
||||
context: &LemmyContext,
|
||||
) -> Result<CommunityResponse, LemmyError> {
|
||||
let mut community_view = blocking(context.pool(), move |conn| {
|
||||
CommunityView::read(conn, community_id, person_id)
|
||||
})
|
||||
.await??;
|
||||
// Blank out deleted or removed info
|
||||
if community_view.community.deleted || community_view.community.removed {
|
||||
community_view.community = community_view.community.blank_out_deleted_or_removed_info();
|
||||
}
|
||||
|
||||
let res = CommunityResponse { community_view };
|
||||
|
||||
// Strip out the person id and subscribed when sending to others
|
||||
let mut res_mut = res.clone();
|
||||
res_mut.community_view.subscribed = false;
|
||||
|
||||
context.chat_server().do_send(SendCommunityRoomMessage {
|
||||
op,
|
||||
response: res_mut,
|
||||
community_id: res.community_view.community.id,
|
||||
websocket_id,
|
||||
});
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub async fn send_pm_ws_message<OP: ToString + Send + OperationType + 'static>(
|
||||
private_message_id: PrivateMessageId,
|
||||
op: OP,
|
||||
websocket_id: Option<ConnectionId>,
|
||||
context: &LemmyContext,
|
||||
) -> Result<PrivateMessageResponse, LemmyError> {
|
||||
let mut view = blocking(context.pool(), move |conn| {
|
||||
PrivateMessageView::read(conn, private_message_id)
|
||||
})
|
||||
.await??;
|
||||
|
||||
// Blank out deleted or removed info
|
||||
if view.private_message.deleted {
|
||||
view.private_message = view.private_message.blank_out_deleted_or_removed_info();
|
||||
}
|
||||
|
||||
let res = PrivateMessageResponse {
|
||||
private_message_view: view,
|
||||
};
|
||||
|
||||
// Send notifications to the local recipient, if one exists
|
||||
if res.private_message_view.recipient.local {
|
||||
let recipient_id = res.private_message_view.recipient.id;
|
||||
let local_recipient = blocking(context.pool(), move |conn| {
|
||||
LocalUserView::read_person(conn, recipient_id)
|
||||
})
|
||||
.await??;
|
||||
context.chat_server().do_send(SendUserRoomMessage {
|
||||
op,
|
||||
response: res.clone(),
|
||||
local_recipient_id: local_recipient.local_user.id,
|
||||
websocket_id,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
}
|
Loading…
Reference in New Issue