]> Untitled Git - lemmy.git/blob - src/apub/inbox/activities/update.rs
Fix nginx config for local federation setup (#104)
[lemmy.git] / src / apub / inbox / activities / update.rs
1 use crate::{
2   apub::{
3     fetcher::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post},
4     inbox::shared_inbox::{
5       announce_if_community_is_local,
6       get_user_from_activity,
7       receive_unhandled_activity,
8     },
9     ActorType,
10     FromApub,
11     PageExt,
12   },
13   LemmyContext,
14 };
15 use activitystreams::{activity::Update, base::AnyBase, object::Note, prelude::*};
16 use actix_web::HttpResponse;
17 use anyhow::Context;
18 use lemmy_db::{
19   comment::{Comment, CommentForm},
20   comment_view::CommentView,
21   post::{Post, PostForm},
22   post_view::PostView,
23   Crud,
24 };
25 use lemmy_structs::{
26   blocking,
27   comment::CommentResponse,
28   post::PostResponse,
29   send_local_notifs,
30   websocket::{SendComment, SendPost, UserOperation},
31 };
32 use lemmy_utils::{location_info, utils::scrape_text_for_mentions, LemmyError};
33
34 pub async fn receive_update(
35   activity: AnyBase,
36   context: &LemmyContext,
37 ) -> Result<HttpResponse, LemmyError> {
38   let update = Update::from_any_base(activity)?.context(location_info!())?;
39
40   // ensure that update and actor come from the same instance
41   let user = get_user_from_activity(&update, context).await?;
42   update.id(user.actor_id()?.domain().context(location_info!())?)?;
43
44   match update.object().as_single_kind_str() {
45     Some("Page") => receive_update_post(update, context).await,
46     Some("Note") => receive_update_comment(update, context).await,
47     _ => receive_unhandled_activity(update),
48   }
49 }
50
51 async fn receive_update_post(
52   update: Update,
53   context: &LemmyContext,
54 ) -> Result<HttpResponse, LemmyError> {
55   let user = get_user_from_activity(&update, context).await?;
56   let page = PageExt::from_any_base(update.object().to_owned().one().context(location_info!())?)?
57     .context(location_info!())?;
58
59   let post = PostForm::from_apub(&page, context, Some(user.actor_id()?)).await?;
60
61   let original_post_id = get_or_fetch_and_insert_post(&post.get_ap_id()?, context)
62     .await?
63     .id;
64
65   blocking(context.pool(), move |conn| {
66     Post::update(conn, original_post_id, &post)
67   })
68   .await??;
69
70   // Refetch the view
71   let post_view = blocking(context.pool(), move |conn| {
72     PostView::read(conn, original_post_id, None)
73   })
74   .await??;
75
76   let res = PostResponse { post: post_view };
77
78   context.chat_server().do_send(SendPost {
79     op: UserOperation::EditPost,
80     post: res,
81     websocket_id: None,
82   });
83
84   announce_if_community_is_local(update, &user, context).await?;
85   Ok(HttpResponse::Ok().finish())
86 }
87
88 async fn receive_update_comment(
89   update: Update,
90   context: &LemmyContext,
91 ) -> Result<HttpResponse, LemmyError> {
92   let note = Note::from_any_base(update.object().to_owned().one().context(location_info!())?)?
93     .context(location_info!())?;
94   let user = get_user_from_activity(&update, context).await?;
95
96   let comment = CommentForm::from_apub(&note, context, Some(user.actor_id()?)).await?;
97
98   let original_comment_id = get_or_fetch_and_insert_comment(&comment.get_ap_id()?, context)
99     .await?
100     .id;
101
102   let updated_comment = blocking(context.pool(), move |conn| {
103     Comment::update(conn, original_comment_id, &comment)
104   })
105   .await??;
106
107   let post_id = updated_comment.post_id;
108   let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
109
110   let mentions = scrape_text_for_mentions(&updated_comment.content);
111   let recipient_ids = send_local_notifs(
112     mentions,
113     updated_comment,
114     &user,
115     post,
116     context.pool(),
117     false,
118   )
119   .await?;
120
121   // Refetch the view
122   let comment_view = blocking(context.pool(), move |conn| {
123     CommentView::read(conn, original_comment_id, None)
124   })
125   .await??;
126
127   let res = CommentResponse {
128     comment: comment_view,
129     recipient_ids,
130     form_id: None,
131   };
132
133   context.chat_server().do_send(SendComment {
134     op: UserOperation::EditComment,
135     comment: res,
136     websocket_id: None,
137   });
138
139   announce_if_community_is_local(update, &user, context).await?;
140   Ok(HttpResponse::Ok().finish())
141 }