]> Untitled Git - lemmy.git/blob - crates/api/src/site/search.rs
Dont show deleted users or communities on profile page. (#2450)
[lemmy.git] / crates / api / src / site / search.rs
1 use crate::Perform;
2 use actix_web::web::Data;
3 use lemmy_api_common::{
4   site::{Search, SearchResponse},
5   utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
6 };
7 use lemmy_apub::{fetcher::resolve_actor_identifier, objects::community::ApubCommunity};
8 use lemmy_db_schema::{
9   source::community::Community,
10   traits::DeleteableOrRemoveable,
11   utils::post_to_comment_sort_type,
12   SearchType,
13 };
14 use lemmy_db_views::{comment_view::CommentQuery, post_view::PostQuery};
15 use lemmy_db_views_actor::{community_view::CommunityQuery, person_view::PersonQuery};
16 use lemmy_utils::{error::LemmyError, ConnectionId};
17 use lemmy_websocket::LemmyContext;
18
19 #[async_trait::async_trait(?Send)]
20 impl Perform for Search {
21   type Response = SearchResponse;
22
23   #[tracing::instrument(skip(context, _websocket_id))]
24   async fn perform(
25     &self,
26     context: &Data<LemmyContext>,
27     _websocket_id: Option<ConnectionId>,
28   ) -> Result<SearchResponse, LemmyError> {
29     let data: &Search = self;
30
31     let local_user_view =
32       get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
33         .await?;
34     check_private_instance(&local_user_view, context.pool()).await?;
35
36     let person_id = local_user_view.as_ref().map(|u| u.person.id);
37     let local_user = local_user_view.map(|l| l.local_user);
38
39     let mut posts = Vec::new();
40     let mut comments = Vec::new();
41     let mut communities = Vec::new();
42     let mut users = Vec::new();
43
44     // TODO no clean / non-nsfw searching rn
45
46     let q = data.q.to_owned();
47     let page = data.page;
48     let limit = data.limit;
49     let sort = data.sort;
50     let listing_type = data.listing_type;
51     let search_type = data.type_.unwrap_or(SearchType::All);
52     let community_id = data.community_id;
53     let community_actor_id = if let Some(name) = &data.community_name {
54       resolve_actor_identifier::<ApubCommunity, Community>(name, context, false)
55         .await
56         .ok()
57         .map(|c| c.actor_id)
58     } else {
59       None
60     };
61     let creator_id = data.creator_id;
62     match search_type {
63       SearchType::Posts => {
64         posts = blocking(context.pool(), move |conn| {
65           PostQuery::builder()
66             .conn(conn)
67             .sort(sort)
68             .listing_type(listing_type)
69             .community_id(community_id)
70             .community_actor_id(community_actor_id)
71             .creator_id(creator_id)
72             .local_user(local_user.as_ref())
73             .search_term(Some(q))
74             .page(page)
75             .limit(limit)
76             .build()
77             .list()
78         })
79         .await??;
80       }
81       SearchType::Comments => {
82         comments = blocking(context.pool(), move |conn| {
83           CommentQuery::builder()
84             .conn(conn)
85             .sort(sort.map(post_to_comment_sort_type))
86             .listing_type(listing_type)
87             .search_term(Some(q))
88             .community_id(community_id)
89             .community_actor_id(community_actor_id)
90             .creator_id(creator_id)
91             .local_user(local_user.as_ref())
92             .page(page)
93             .limit(limit)
94             .build()
95             .list()
96         })
97         .await??;
98       }
99       SearchType::Communities => {
100         communities = blocking(context.pool(), move |conn| {
101           CommunityQuery::builder()
102             .conn(conn)
103             .sort(sort)
104             .listing_type(listing_type)
105             .search_term(Some(q))
106             .local_user(local_user.as_ref())
107             .page(page)
108             .limit(limit)
109             .build()
110             .list()
111         })
112         .await??;
113       }
114       SearchType::Users => {
115         users = blocking(context.pool(), move |conn| {
116           PersonQuery::builder()
117             .conn(conn)
118             .sort(sort)
119             .search_term(Some(q))
120             .page(page)
121             .limit(limit)
122             .build()
123             .list()
124         })
125         .await??;
126       }
127       SearchType::All => {
128         // If the community or creator is included, dont search communities or users
129         let community_or_creator_included =
130           data.community_id.is_some() || data.community_name.is_some() || data.creator_id.is_some();
131         let community_actor_id_2 = community_actor_id.to_owned();
132
133         let local_user_ = local_user.clone();
134         posts = blocking(context.pool(), move |conn| {
135           PostQuery::builder()
136             .conn(conn)
137             .sort(sort)
138             .listing_type(listing_type)
139             .community_id(community_id)
140             .community_actor_id(community_actor_id_2)
141             .creator_id(creator_id)
142             .local_user(local_user_.as_ref())
143             .search_term(Some(q))
144             .page(page)
145             .limit(limit)
146             .build()
147             .list()
148         })
149         .await??;
150
151         let q = data.q.to_owned();
152         let community_actor_id = community_actor_id.to_owned();
153
154         let local_user_ = local_user.clone();
155         comments = blocking(context.pool(), move |conn| {
156           CommentQuery::builder()
157             .conn(conn)
158             .sort(sort.map(post_to_comment_sort_type))
159             .listing_type(listing_type)
160             .search_term(Some(q))
161             .community_id(community_id)
162             .community_actor_id(community_actor_id)
163             .creator_id(creator_id)
164             .local_user(local_user_.as_ref())
165             .page(page)
166             .limit(limit)
167             .build()
168             .list()
169         })
170         .await??;
171
172         let q = data.q.to_owned();
173
174         communities = if community_or_creator_included {
175           vec![]
176         } else {
177           blocking(context.pool(), move |conn| {
178             CommunityQuery::builder()
179               .conn(conn)
180               .sort(sort)
181               .listing_type(listing_type)
182               .search_term(Some(q))
183               .local_user(local_user.as_ref())
184               .page(page)
185               .limit(limit)
186               .build()
187               .list()
188           })
189           .await??
190         };
191
192         let q = data.q.to_owned();
193
194         users = if community_or_creator_included {
195           vec![]
196         } else {
197           blocking(context.pool(), move |conn| {
198             PersonQuery::builder()
199               .conn(conn)
200               .sort(sort)
201               .search_term(Some(q))
202               .page(page)
203               .limit(limit)
204               .build()
205               .list()
206           })
207           .await??
208         };
209       }
210       SearchType::Url => {
211         posts = blocking(context.pool(), move |conn| {
212           PostQuery::builder()
213             .conn(conn)
214             .sort(sort)
215             .listing_type(listing_type)
216             .community_id(community_id)
217             .community_actor_id(community_actor_id)
218             .creator_id(creator_id)
219             .url_search(Some(q))
220             .page(page)
221             .limit(limit)
222             .build()
223             .list()
224         })
225         .await??;
226       }
227     };
228
229     // Blank out deleted or removed info for non logged in users
230     if person_id.is_none() {
231       for cv in communities
232         .iter_mut()
233         .filter(|cv| cv.community.deleted || cv.community.removed)
234       {
235         cv.community = cv.to_owned().community.blank_out_deleted_or_removed_info();
236       }
237
238       for pv in posts
239         .iter_mut()
240         .filter(|p| p.post.deleted || p.post.removed)
241       {
242         pv.post = pv.to_owned().post.blank_out_deleted_or_removed_info();
243       }
244
245       for cv in comments
246         .iter_mut()
247         .filter(|cv| cv.comment.deleted || cv.comment.removed)
248       {
249         cv.comment = cv.to_owned().comment.blank_out_deleted_or_removed_info();
250       }
251     }
252
253     // Return the jwt
254     Ok(SearchResponse {
255       type_: search_type.to_string(),
256       comments,
257       posts,
258       communities,
259       users,
260     })
261   }
262 }