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},
7 use lemmy_apub::{fetcher::resolve_actor_identifier, objects::community::ApubCommunity};
9 source::community::Community,
10 traits::DeleteableOrRemoveable,
11 utils::post_to_comment_sort_type,
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;
19 #[async_trait::async_trait(?Send)]
20 impl Perform for Search {
21 type Response = SearchResponse;
23 #[tracing::instrument(skip(context, _websocket_id))]
26 context: &Data<LemmyContext>,
27 _websocket_id: Option<ConnectionId>,
28 ) -> Result<SearchResponse, LemmyError> {
29 let data: &Search = self;
32 get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
34 check_private_instance(&local_user_view, context.pool()).await?;
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);
39 let mut posts = Vec::new();
40 let mut comments = Vec::new();
41 let mut communities = Vec::new();
42 let mut users = Vec::new();
44 // TODO no clean / non-nsfw searching rn
46 let q = data.q.to_owned();
48 let limit = data.limit;
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)
61 let creator_id = data.creator_id;
63 SearchType::Posts => {
64 posts = blocking(context.pool(), move |conn| {
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())
81 SearchType::Comments => {
82 comments = blocking(context.pool(), move |conn| {
83 CommentQuery::builder()
85 .sort(sort.map(post_to_comment_sort_type))
86 .listing_type(listing_type)
88 .community_id(community_id)
89 .community_actor_id(community_actor_id)
90 .creator_id(creator_id)
91 .local_user(local_user.as_ref())
99 SearchType::Communities => {
100 communities = blocking(context.pool(), move |conn| {
101 CommunityQuery::builder()
104 .listing_type(listing_type)
105 .search_term(Some(q))
106 .local_user(local_user.as_ref())
114 SearchType::Users => {
115 users = blocking(context.pool(), move |conn| {
116 PersonQuery::builder()
119 .search_term(Some(q))
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();
133 let local_user_ = local_user.clone();
134 posts = blocking(context.pool(), move |conn| {
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))
151 let q = data.q.to_owned();
152 let community_actor_id = community_actor_id.to_owned();
154 let local_user_ = local_user.clone();
155 comments = blocking(context.pool(), move |conn| {
156 CommentQuery::builder()
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())
172 let q = data.q.to_owned();
174 communities = if community_or_creator_included {
177 blocking(context.pool(), move |conn| {
178 CommunityQuery::builder()
181 .listing_type(listing_type)
182 .search_term(Some(q))
183 .local_user(local_user.as_ref())
192 let q = data.q.to_owned();
194 users = if community_or_creator_included {
197 blocking(context.pool(), move |conn| {
198 PersonQuery::builder()
201 .search_term(Some(q))
211 posts = blocking(context.pool(), move |conn| {
215 .listing_type(listing_type)
216 .community_id(community_id)
217 .community_actor_id(community_actor_id)
218 .creator_id(creator_id)
229 // Blank out deleted or removed info for non logged in users
230 if person_id.is_none() {
231 for cv in communities
233 .filter(|cv| cv.community.deleted || cv.community.removed)
235 cv.community = cv.to_owned().community.blank_out_deleted_or_removed_info();
240 .filter(|p| p.post.deleted || p.post.removed)
242 pv.post = pv.to_owned().post.blank_out_deleted_or_removed_info();
247 .filter(|cv| cv.comment.deleted || cv.comment.removed)
249 cv.comment = cv.to_owned().comment.blank_out_deleted_or_removed_info();
255 type_: search_type.to_string(),