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