]> Untitled Git - lemmy.git/blob - crates/apub/src/api/search.rs
Replace Option<bool> with bool for PostQuery and CommentQuery (#3819) (#3857)
[lemmy.git] / crates / apub / src / api / search.rs
1 use crate::{fetcher::resolve_actor_identifier, objects::community::ApubCommunity};
2 use activitypub_federation::config::Data;
3 use actix_web::web::{Json, Query};
4 use lemmy_api_common::{
5   context::LemmyContext,
6   site::{Search, SearchResponse},
7   utils::{check_private_instance, is_admin, local_user_view_from_jwt_opt},
8 };
9 use lemmy_db_schema::{
10   source::{community::Community, local_site::LocalSite},
11   utils::{post_to_comment_sort_type, post_to_person_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;
17
18 #[tracing::instrument(skip(context))]
19 pub async fn search(
20   data: Query<Search>,
21   context: Data<LemmyContext>,
22 ) -> Result<Json<SearchResponse>, LemmyError> {
23   let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), &context).await;
24   let local_site = LocalSite::read(&mut context.pool()).await?;
25
26   check_private_instance(&local_user_view, &local_site)?;
27
28   let is_admin = local_user_view
29     .as_ref()
30     .map(|luv| is_admin(luv).is_ok())
31     .unwrap_or_default();
32
33   let mut posts = Vec::new();
34   let mut comments = Vec::new();
35   let mut communities = Vec::new();
36   let mut users = Vec::new();
37
38   // TODO no clean / non-nsfw searching rn
39
40   let q = data.q.clone();
41   let page = data.page;
42   let limit = data.limit;
43   let sort = data.sort;
44   let listing_type = data.listing_type;
45   let search_type = data.type_.unwrap_or(SearchType::All);
46   let community_id = if let Some(name) = &data.community_name {
47     Some(
48       resolve_actor_identifier::<ApubCommunity, Community>(name, &context, &local_user_view, false)
49         .await?,
50     )
51     .map(|c| c.id)
52   } else {
53     data.community_id
54   };
55   let creator_id = data.creator_id;
56   let local_user = local_user_view.as_ref().map(|l| l.local_user.clone());
57   match search_type {
58     SearchType::Posts => {
59       posts = PostQuery {
60         sort: (sort),
61         listing_type: (listing_type),
62         community_id: (community_id),
63         creator_id: (creator_id),
64         local_user: (local_user_view.as_ref()),
65         search_term: (Some(q)),
66         page: (page),
67         limit: (limit),
68         ..Default::default()
69       }
70       .list(&mut context.pool())
71       .await?;
72     }
73     SearchType::Comments => {
74       comments = CommentQuery {
75         sort: (sort.map(post_to_comment_sort_type)),
76         listing_type: (listing_type),
77         search_term: (Some(q)),
78         community_id: (community_id),
79         creator_id: (creator_id),
80         local_user: (local_user_view.as_ref()),
81         page: (page),
82         limit: (limit),
83         ..Default::default()
84       }
85       .list(&mut context.pool())
86       .await?;
87     }
88     SearchType::Communities => {
89       communities = CommunityQuery {
90         sort: (sort),
91         listing_type: (listing_type),
92         search_term: (Some(q)),
93         local_user: (local_user.as_ref()),
94         is_mod_or_admin: (is_admin),
95         page: (page),
96         limit: (limit),
97         ..Default::default()
98       }
99       .list(&mut context.pool())
100       .await?;
101     }
102     SearchType::Users => {
103       users = PersonQuery {
104         sort: (sort.map(post_to_person_sort_type)),
105         search_term: (Some(q)),
106         page: (page),
107         limit: (limit),
108       }
109       .list(&mut context.pool())
110       .await?;
111     }
112     SearchType::All => {
113       // If the community or creator is included, dont search communities or users
114       let community_or_creator_included =
115         data.community_id.is_some() || data.community_name.is_some() || data.creator_id.is_some();
116
117       let q = data.q.clone();
118
119       posts = PostQuery {
120         sort: (sort),
121         listing_type: (listing_type),
122         community_id: (community_id),
123         creator_id: (creator_id),
124         local_user: (local_user_view.as_ref()),
125         search_term: (Some(q)),
126         page: (page),
127         limit: (limit),
128         ..Default::default()
129       }
130       .list(&mut context.pool())
131       .await?;
132
133       let q = data.q.clone();
134
135       comments = CommentQuery {
136         sort: (sort.map(post_to_comment_sort_type)),
137         listing_type: (listing_type),
138         search_term: (Some(q)),
139         community_id: (community_id),
140         creator_id: (creator_id),
141         local_user: (local_user_view.as_ref()),
142         page: (page),
143         limit: (limit),
144         ..Default::default()
145       }
146       .list(&mut context.pool())
147       .await?;
148
149       let q = data.q.clone();
150
151       communities = if community_or_creator_included {
152         vec![]
153       } else {
154         CommunityQuery {
155           sort: (sort),
156           listing_type: (listing_type),
157           search_term: (Some(q)),
158           local_user: (local_user.as_ref()),
159           is_mod_or_admin: (is_admin),
160           page: (page),
161           limit: (limit),
162           ..Default::default()
163         }
164         .list(&mut context.pool())
165         .await?
166       };
167
168       let q = data.q.clone();
169
170       users = if community_or_creator_included {
171         vec![]
172       } else {
173         PersonQuery {
174           sort: (sort.map(post_to_person_sort_type)),
175           search_term: (Some(q)),
176           page: (page),
177           limit: (limit),
178         }
179         .list(&mut context.pool())
180         .await?
181       };
182     }
183     SearchType::Url => {
184       posts = PostQuery {
185         sort: (sort),
186         listing_type: (listing_type),
187         community_id: (community_id),
188         creator_id: (creator_id),
189         url_search: (Some(q)),
190         page: (page),
191         limit: (limit),
192         ..Default::default()
193       }
194       .list(&mut context.pool())
195       .await?;
196     }
197   };
198
199   // Return the jwt
200   Ok(Json(SearchResponse {
201     type_: search_type,
202     comments,
203     posts,
204     communities,
205     users,
206   }))
207 }