]> Untitled Git - lemmy.git/blob - crates/api_crud/src/post/read.rs
Don't drop error context when adding a message to errors (#1958)
[lemmy.git] / crates / api_crud / src / post / read.rs
1 use crate::PerformCrud;
2 use actix_web::web::Data;
3 use lemmy_api_common::{blocking, get_local_user_view_from_jwt_opt, mark_post_as_read, post::*};
4 use lemmy_apub::{
5   fetcher::webfinger::webfinger_resolve,
6   objects::community::ApubCommunity,
7   EndpointType,
8 };
9 use lemmy_db_schema::{
10   from_opt_str_to_opt_enum,
11   traits::DeleteableOrRemoveable,
12   ListingType,
13   SortType,
14 };
15 use lemmy_db_views::{
16   comment_view::CommentQueryBuilder,
17   post_view::{PostQueryBuilder, PostView},
18 };
19 use lemmy_db_views_actor::{
20   community_moderator_view::CommunityModeratorView,
21   community_view::CommunityView,
22 };
23 use lemmy_utils::{ConnectionId, LemmyError};
24 use lemmy_websocket::{messages::GetPostUsersOnline, LemmyContext};
25
26 #[async_trait::async_trait(?Send)]
27 impl PerformCrud for GetPost {
28   type Response = GetPostResponse;
29
30   #[tracing::instrument(skip(context, _websocket_id))]
31   async fn perform(
32     &self,
33     context: &Data<LemmyContext>,
34     _websocket_id: Option<ConnectionId>,
35   ) -> Result<GetPostResponse, LemmyError> {
36     let data: &GetPost = self;
37     let local_user_view =
38       get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
39         .await?;
40
41     let show_bot_accounts = local_user_view
42       .as_ref()
43       .map(|t| t.local_user.show_bot_accounts);
44     let person_id = local_user_view.map(|u| u.person.id);
45
46     let id = data.id;
47     let mut post_view = blocking(context.pool(), move |conn| {
48       PostView::read(conn, id, person_id)
49     })
50     .await?
51     .map_err(LemmyError::from)
52     .map_err(|e| e.with_message("couldnt_find_post"))?;
53
54     // Mark the post as read
55     if let Some(person_id) = person_id {
56       mark_post_as_read(person_id, id, context.pool()).await?;
57     }
58
59     let id = data.id;
60     let mut comments = blocking(context.pool(), move |conn| {
61       CommentQueryBuilder::create(conn)
62         .my_person_id(person_id)
63         .show_bot_accounts(show_bot_accounts)
64         .post_id(id)
65         .limit(9999)
66         .list()
67     })
68     .await??;
69
70     // Necessary for the sidebar
71     let community_id = post_view.community.id;
72     let mut community_view = blocking(context.pool(), move |conn| {
73       CommunityView::read(conn, community_id, person_id)
74     })
75     .await?
76     .map_err(LemmyError::from)
77     .map_err(|e| e.with_message("couldnt_find_community"))?;
78
79     // Blank out deleted or removed info for non-logged in users
80     if person_id.is_none() {
81       if post_view.post.deleted || post_view.post.removed {
82         post_view.post = post_view.post.blank_out_deleted_or_removed_info();
83       }
84
85       for cv in comments
86         .iter_mut()
87         .filter(|cv| cv.comment.deleted || cv.comment.removed)
88       {
89         cv.comment = cv.to_owned().comment.blank_out_deleted_or_removed_info();
90       }
91       if community_view.community.deleted || community_view.community.removed {
92         community_view.community = community_view.community.blank_out_deleted_or_removed_info();
93       }
94     }
95
96     let moderators = blocking(context.pool(), move |conn| {
97       CommunityModeratorView::for_community(conn, community_id)
98     })
99     .await??;
100
101     let online = context
102       .chat_server()
103       .send(GetPostUsersOnline { post_id: data.id })
104       .await
105       .unwrap_or(1);
106
107     // Return the jwt
108     Ok(GetPostResponse {
109       post_view,
110       community_view,
111       comments,
112       moderators,
113       online,
114     })
115   }
116 }
117
118 #[async_trait::async_trait(?Send)]
119 impl PerformCrud for GetPosts {
120   type Response = GetPostsResponse;
121
122   #[tracing::instrument(skip(context, _websocket_id))]
123   async fn perform(
124     &self,
125     context: &Data<LemmyContext>,
126     _websocket_id: Option<ConnectionId>,
127   ) -> Result<GetPostsResponse, LemmyError> {
128     let data: &GetPosts = self;
129     let local_user_view =
130       get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
131         .await?;
132
133     let person_id = local_user_view.to_owned().map(|l| l.person.id);
134
135     let show_nsfw = local_user_view.as_ref().map(|t| t.local_user.show_nsfw);
136     let show_bot_accounts = local_user_view
137       .as_ref()
138       .map(|t| t.local_user.show_bot_accounts);
139     let show_read_posts = local_user_view
140       .as_ref()
141       .map(|t| t.local_user.show_read_posts);
142
143     let sort: Option<SortType> = from_opt_str_to_opt_enum(&data.sort);
144     let listing_type: Option<ListingType> = from_opt_str_to_opt_enum(&data.type_);
145
146     let page = data.page;
147     let limit = data.limit;
148     let community_id = data.community_id;
149     let community_actor_id = if let Some(name) = &data.community_name {
150       webfinger_resolve::<ApubCommunity>(name, EndpointType::Community, context, &mut 0)
151         .await
152         .ok()
153     } else {
154       None
155     };
156     let saved_only = data.saved_only;
157
158     let mut posts = blocking(context.pool(), move |conn| {
159       PostQueryBuilder::create(conn)
160         .listing_type(listing_type)
161         .sort(sort)
162         .show_nsfw(show_nsfw)
163         .show_bot_accounts(show_bot_accounts)
164         .show_read_posts(show_read_posts)
165         .community_id(community_id)
166         .community_actor_id(community_actor_id)
167         .saved_only(saved_only)
168         .my_person_id(person_id)
169         .page(page)
170         .limit(limit)
171         .list()
172     })
173     .await?
174     .map_err(LemmyError::from)
175     .map_err(|e| e.with_message("couldnt_get_posts"))?;
176
177     // Blank out deleted or removed info for non-logged in users
178     if person_id.is_none() {
179       for pv in posts
180         .iter_mut()
181         .filter(|p| p.post.deleted || p.post.removed)
182       {
183         pv.post = pv.to_owned().post.blank_out_deleted_or_removed_info();
184       }
185
186       for pv in posts
187         .iter_mut()
188         .filter(|p| p.community.deleted || p.community.removed)
189       {
190         pv.community = pv.to_owned().community.blank_out_deleted_or_removed_info();
191       }
192     }
193
194     Ok(GetPostsResponse { posts })
195   }
196 }