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