]> Untitled Git - lemmy.git/blob - crates/api_crud/src/post/read.rs
Moving settings to Database. (#2492)
[lemmy.git] / crates / api_crud / src / post / read.rs
1 use crate::PerformCrud;
2 use actix_web::web::Data;
3 use lemmy_api_common::{
4   post::{GetPost, GetPostResponse},
5   utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt, mark_post_as_read},
6 };
7 use lemmy_db_schema::{
8   aggregates::structs::{PersonPostAggregates, PersonPostAggregatesForm},
9   source::{comment::Comment, local_site::LocalSite},
10   traits::{Crud, DeleteableOrRemoveable},
11 };
12 use lemmy_db_views::structs::PostView;
13 use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView};
14 use lemmy_utils::{error::LemmyError, ConnectionId};
15 use lemmy_websocket::{messages::GetPostUsersOnline, LemmyContext};
16
17 #[async_trait::async_trait(?Send)]
18 impl PerformCrud for GetPost {
19   type Response = GetPostResponse;
20
21   #[tracing::instrument(skip(context, _websocket_id))]
22   async fn perform(
23     &self,
24     context: &Data<LemmyContext>,
25     _websocket_id: Option<ConnectionId>,
26   ) -> Result<GetPostResponse, LemmyError> {
27     let data: &GetPost = self;
28     let local_user_view =
29       get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
30         .await?;
31     let local_site = blocking(context.pool(), LocalSite::read).await??;
32
33     check_private_instance(&local_user_view, &local_site)?;
34
35     let person_id = local_user_view.map(|u| u.person.id);
36
37     // I'd prefer fetching the post_view by a comment join, but it adds a lot of boilerplate
38     let post_id = if let Some(id) = data.id {
39       id
40     } else if let Some(comment_id) = data.comment_id {
41       blocking(context.pool(), move |conn| Comment::read(conn, comment_id))
42         .await?
43         .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_post"))?
44         .post_id
45     } else {
46       Err(LemmyError::from_message("couldnt_find_post"))?
47     };
48
49     let mut post_view = blocking(context.pool(), move |conn| {
50       PostView::read(conn, post_id, person_id)
51     })
52     .await?
53     .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_post"))?;
54
55     // Mark the post as read
56     let post_id = post_view.post.id;
57     if let Some(person_id) = person_id {
58       mark_post_as_read(person_id, post_id, context.pool()).await?;
59     }
60
61     // Necessary for the sidebar subscribed
62     let community_id = post_view.community.id;
63     let mut community_view = blocking(context.pool(), move |conn| {
64       CommunityView::read(conn, community_id, person_id)
65     })
66     .await?
67     .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_community"))?;
68
69     // Insert into PersonPostAggregates
70     // to update the read_comments count
71     if let Some(person_id) = person_id {
72       let read_comments = post_view.counts.comments;
73       let person_post_agg_form = PersonPostAggregatesForm {
74         person_id,
75         post_id,
76         read_comments,
77         ..PersonPostAggregatesForm::default()
78       };
79       blocking(context.pool(), move |conn| {
80         PersonPostAggregates::upsert(conn, &person_post_agg_form)
81       })
82       .await?
83       .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_post"))?;
84     }
85
86     // Blank out deleted or removed info for non-logged in users
87     if person_id.is_none() {
88       if post_view.post.deleted || post_view.post.removed {
89         post_view.post = post_view.post.blank_out_deleted_or_removed_info();
90       }
91
92       if community_view.community.deleted || community_view.community.removed {
93         community_view.community = community_view.community.blank_out_deleted_or_removed_info();
94       }
95     }
96
97     let moderators = blocking(context.pool(), move |conn| {
98       CommunityModeratorView::for_community(conn, community_id)
99     })
100     .await??;
101
102     let online = context
103       .chat_server()
104       .send(GetPostUsersOnline { post_id })
105       .await
106       .unwrap_or(1);
107
108     // Return the jwt
109     Ok(GetPostResponse {
110       post_view,
111       community_view,
112       moderators,
113       online,
114     })
115   }
116 }