4 announce_if_community_is_local,
5 get_user_from_activity,
6 receive_unhandled_activity,
14 use activitystreams::{activity::Create, base::AnyBase, object::Note, prelude::*};
15 use actix_web::HttpResponse;
18 comment::{Comment, CommentForm},
19 comment_view::CommentView,
20 post::{Post, PostForm},
25 comment::CommentResponse,
28 websocket::{SendComment, SendPost, UserOperation},
30 use lemmy_utils::{location_info, utils::scrape_text_for_mentions, LemmyError};
32 pub async fn receive_create(
34 context: &LemmyContext,
35 ) -> Result<HttpResponse, LemmyError> {
36 let create = Create::from_any_base(activity)?.context(location_info!())?;
38 // ensure that create and actor come from the same instance
39 let user = get_user_from_activity(&create, context).await?;
40 create.id(user.actor_id()?.domain().context(location_info!())?)?;
42 match create.object().as_single_kind_str() {
43 Some("Page") => receive_create_post(create, context).await,
44 Some("Note") => receive_create_comment(create, context).await,
45 _ => receive_unhandled_activity(create),
49 async fn receive_create_post(
51 context: &LemmyContext,
52 ) -> Result<HttpResponse, LemmyError> {
53 let user = get_user_from_activity(&create, context).await?;
54 let page = PageExt::from_any_base(create.object().to_owned().one().context(location_info!())?)?
55 .context(location_info!())?;
57 let post = PostForm::from_apub(&page, context, Some(user.actor_id()?)).await?;
59 // Using an upsert, since likes (which fetch the post), sometimes come in before the create
60 // resulting in double posts.
61 let inserted_post = blocking(context.pool(), move |conn| Post::upsert(conn, &post)).await??;
64 let inserted_post_id = inserted_post.id;
65 let post_view = blocking(context.pool(), move |conn| {
66 PostView::read(conn, inserted_post_id, None)
70 let res = PostResponse { post: post_view };
72 context.chat_server().do_send(SendPost {
73 op: UserOperation::CreatePost,
78 announce_if_community_is_local(create, &user, context).await?;
79 Ok(HttpResponse::Ok().finish())
82 async fn receive_create_comment(
84 context: &LemmyContext,
85 ) -> Result<HttpResponse, LemmyError> {
86 let user = get_user_from_activity(&create, context).await?;
87 let note = Note::from_any_base(create.object().to_owned().one().context(location_info!())?)?
88 .context(location_info!())?;
90 let comment = CommentForm::from_apub(¬e, context, Some(user.actor_id()?)).await?;
92 let inserted_comment =
93 blocking(context.pool(), move |conn| Comment::upsert(conn, &comment)).await??;
95 let post_id = inserted_comment.post_id;
96 let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
99 // Although mentions could be gotten from the post tags (they are included there), or the ccs,
100 // Its much easier to scrape them from the comment body, since the API has to do that
102 let mentions = scrape_text_for_mentions(&inserted_comment.content);
103 let recipient_ids = send_local_notifs(
105 inserted_comment.clone(),
114 let comment_view = blocking(context.pool(), move |conn| {
115 CommentView::read(conn, inserted_comment.id, None)
119 let res = CommentResponse {
120 comment: comment_view,
125 context.chat_server().do_send(SendComment {
126 op: UserOperation::CreateComment,
131 announce_if_community_is_local(create, &user, context).await?;
132 Ok(HttpResponse::Ok().finish())