3 announce_if_community_is_local,
4 get_user_from_activity,
5 receive_unhandled_activity,
11 use activitystreams::{activity::Create, base::AnyBase, object::Note, prelude::*};
12 use actix_web::HttpResponse;
15 comment::{Comment, CommentForm},
16 comment_view::CommentView,
17 post::{Post, PostForm},
20 use lemmy_structs::{blocking, comment::CommentResponse, post::PostResponse, send_local_notifs};
21 use lemmy_utils::{location_info, utils::scrape_text_for_mentions, LemmyError};
22 use lemmy_websocket::{
23 messages::{SendComment, SendPost},
28 pub async fn receive_create(
30 context: &LemmyContext,
31 ) -> Result<HttpResponse, LemmyError> {
32 let create = Create::from_any_base(activity)?.context(location_info!())?;
34 // ensure that create and actor come from the same instance
35 let user = get_user_from_activity(&create, context).await?;
36 create.id(user.actor_id()?.domain().context(location_info!())?)?;
38 match create.object().as_single_kind_str() {
39 Some("Page") => receive_create_post(create, context).await,
40 Some("Note") => receive_create_comment(create, context).await,
41 _ => receive_unhandled_activity(create),
45 async fn receive_create_post(
47 context: &LemmyContext,
48 ) -> Result<HttpResponse, LemmyError> {
49 let user = get_user_from_activity(&create, context).await?;
50 let page = PageExt::from_any_base(create.object().to_owned().one().context(location_info!())?)?
51 .context(location_info!())?;
53 let post = PostForm::from_apub(&page, context, Some(user.actor_id()?)).await?;
55 // Using an upsert, since likes (which fetch the post), sometimes come in before the create
56 // resulting in double posts.
57 let inserted_post = blocking(context.pool(), move |conn| Post::upsert(conn, &post)).await??;
60 let inserted_post_id = inserted_post.id;
61 let post_view = blocking(context.pool(), move |conn| {
62 PostView::read(conn, inserted_post_id, None)
66 let res = PostResponse { post: post_view };
68 context.chat_server().do_send(SendPost {
69 op: UserOperation::CreatePost,
74 announce_if_community_is_local(create, &user, context).await?;
75 Ok(HttpResponse::Ok().finish())
78 async fn receive_create_comment(
80 context: &LemmyContext,
81 ) -> Result<HttpResponse, LemmyError> {
82 let user = get_user_from_activity(&create, context).await?;
83 let note = Note::from_any_base(create.object().to_owned().one().context(location_info!())?)?
84 .context(location_info!())?;
86 let comment = CommentForm::from_apub(¬e, context, Some(user.actor_id()?)).await?;
88 let inserted_comment =
89 blocking(context.pool(), move |conn| Comment::upsert(conn, &comment)).await??;
91 let post_id = inserted_comment.post_id;
92 let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
95 // Although mentions could be gotten from the post tags (they are included there), or the ccs,
96 // Its much easier to scrape them from the comment body, since the API has to do that
98 let mentions = scrape_text_for_mentions(&inserted_comment.content);
99 let recipient_ids = send_local_notifs(
101 inserted_comment.clone(),
110 let comment_view = blocking(context.pool(), move |conn| {
111 CommentView::read(conn, inserted_comment.id, None)
115 let res = CommentResponse {
116 comment: comment_view,
121 context.chat_server().do_send(SendComment {
122 op: UserOperation::CreateComment,
127 announce_if_community_is_local(create, &user, context).await?;
128 Ok(HttpResponse::Ok().finish())