1use std::collections::HashMap;
2
3use reva_axum::Template;
4use axum::extract::Query;
5use axum::response::IntoResponse;
6use axum::{extract::State, response::Html};
7use axum_extra::extract::CookieJar;
8
9use authbeam::model::{Profile, RelationshipStatus};
10
11use super::{SearchHomeQuery, SearchQuery};
12use crate::config::Config;
13use crate::database::Database;
14use crate::model::{DatabaseError, FullResponse, Question};
15use crate::ToHtml;
16
17#[derive(Template)]
18#[template(path = "search/homepage.html")]
19struct HomepageTemplate {
20 config: Config,
21 lang: langbeam::LangFile,
22 profile: Option<Box<Profile>>,
23 unread: usize,
24 notifs: usize,
25 query: String,
26 driver: i8,
27}
28
29pub async fn search_homepage_request(
31 jar: CookieJar,
32 State(database): State<Database>,
33 Query(query): Query<SearchHomeQuery>,
34) -> impl IntoResponse {
35 let auth_user = match jar.get("__Secure-Token") {
36 Some(c) => match database
37 .auth
38 .get_profile_by_unhashed(c.value_trimmed())
39 .await
40 {
41 Ok(ua) => Some(ua),
42 Err(_) => None,
43 },
44 None => None,
45 };
46
47 let unread = if let Some(ref ua) = auth_user {
48 database.get_inbox_count_by_recipient(&ua.id).await
49 } else {
50 0
51 };
52
53 let notifs = if let Some(ref ua) = auth_user {
54 database
55 .auth
56 .get_notification_count_by_recipient(&ua.id)
57 .await
58 } else {
59 0
60 };
61
62 Html(
63 HomepageTemplate {
64 config: database.config.clone(),
65 lang: database.lang(if let Some(c) = jar.get("net.rainbeam.langs.choice") {
66 c.value_trimmed()
67 } else {
68 ""
69 }),
70 profile: auth_user.clone(),
71 unread,
72 notifs,
73 query: String::new(),
74 driver: query.driver,
75 }
76 .render()
77 .unwrap(),
78 )
79}
80
81#[derive(Template)]
82#[template(path = "search/responses.html")]
83struct ResponsesTemplate {
84 config: Config,
85 lang: langbeam::LangFile,
86 profile: Option<Box<Profile>>,
87 unread: usize,
88 notifs: usize,
89 query: String,
90 page: i32,
91 driver: i8,
92 results: Vec<FullResponse>,
94 relationships: HashMap<String, RelationshipStatus>,
95 is_powerful: bool, is_helper: bool, }
98
99pub async fn search_responses_request(
101 jar: CookieJar,
102 State(database): State<Database>,
103 Query(query): Query<SearchQuery>,
104) -> impl IntoResponse {
105 let auth_user = match jar.get("__Secure-Token") {
106 Some(c) => match database
107 .auth
108 .get_profile_by_unhashed(c.value_trimmed())
109 .await
110 {
111 Ok(ua) => Some(ua),
112 Err(_) => None,
113 },
114 None => None,
115 };
116
117 let unread = if let Some(ref ua) = auth_user {
118 database.get_inbox_count_by_recipient(&ua.id).await
119 } else {
120 0
121 };
122
123 let notifs = if let Some(ref ua) = auth_user {
124 database
125 .auth
126 .get_notification_count_by_recipient(&ua.id)
127 .await
128 } else {
129 0
130 };
131
132 let results = if query.tag.is_empty() {
134 match database
135 .get_responses_searched_paginated(query.page, query.q.clone())
136 .await
137 {
138 Ok(responses) => responses,
139 Err(e) => return Html(e.to_html(database)),
140 }
141 } else {
142 match database
143 .get_responses_tagged_paginated(query.tag.clone(), query.page)
144 .await
145 {
146 Ok(responses) => responses,
147 Err(e) => return Html(e.to_html(database)),
148 }
149 };
150
151 let mut is_helper: bool = false;
153 let is_powerful = if let Some(ref ua) = auth_user {
154 let group = match database.auth.get_group_by_id(ua.group).await {
155 Ok(g) => g,
156 Err(_) => return Html(DatabaseError::Other.to_html(database)),
157 };
158
159 is_helper = group.permissions.check_helper();
160 group.permissions.check_manager()
161 } else {
162 false
163 };
164
165 let mut relationships: HashMap<String, RelationshipStatus> = HashMap::new();
167
168 if let Some(ref ua) = auth_user {
169 for response in &results {
170 if relationships.contains_key(&response.1.author.id) {
171 continue;
172 }
173
174 if response.1.author.id == ua.id {
175 relationships.insert(response.1.author.id.clone(), RelationshipStatus::Friends);
177 continue;
178 };
179
180 relationships.insert(
181 response.1.author.id.clone(),
182 database
183 .auth
184 .get_user_relationship(&response.1.author.id, &ua.id)
185 .await
186 .0,
187 );
188 }
189 } else {
190 for response in &results {
191 if relationships.contains_key(&response.1.author.id) {
193 continue;
194 }
195
196 relationships.insert(response.1.author.id.clone(), RelationshipStatus::Unknown);
197 }
198 }
199
200 Html(
202 ResponsesTemplate {
203 config: database.config.clone(),
204 lang: database.lang(if let Some(c) = jar.get("net.rainbeam.langs.choice") {
205 c.value_trimmed()
206 } else {
207 ""
208 }),
209 profile: auth_user.clone(),
210 unread,
211 notifs,
212 query: query.q,
213 page: query.page,
214 driver: if query.tag.is_empty() { 0 } else { 4 },
215 results,
217 relationships,
218 is_powerful,
219 is_helper,
220 }
221 .render()
222 .unwrap(),
223 )
224}
225
226#[derive(Template)]
227#[template(path = "search/questions.html")]
228struct QuestionsTemplate {
229 config: Config,
230 lang: langbeam::LangFile,
231 profile: Option<Box<Profile>>,
232 unread: usize,
233 notifs: usize,
234 query: String,
235 page: i32,
236 driver: i8,
237 results: Vec<(Question, usize, usize)>,
239 relationships: HashMap<String, RelationshipStatus>,
240 is_helper: bool, }
242
243pub async fn search_questions_request(
245 jar: CookieJar,
246 State(database): State<Database>,
247 Query(query): Query<SearchQuery>,
248) -> impl IntoResponse {
249 let auth_user = match jar.get("__Secure-Token") {
250 Some(c) => match database
251 .auth
252 .get_profile_by_unhashed(c.value_trimmed())
253 .await
254 {
255 Ok(ua) => Some(ua),
256 Err(_) => None,
257 },
258 None => None,
259 };
260
261 let unread = if let Some(ref ua) = auth_user {
262 database.get_inbox_count_by_recipient(&ua.id).await
263 } else {
264 0
265 };
266
267 let notifs = if let Some(ref ua) = auth_user {
268 database
269 .auth
270 .get_notification_count_by_recipient(&ua.id)
271 .await
272 } else {
273 0
274 };
275
276 let results = match database
278 .get_global_questions_searched_paginated(query.page, query.q.clone())
279 .await
280 {
281 Ok(responses) => responses,
282 Err(e) => return Html(e.to_html(database)),
283 };
284
285 let mut relationships: HashMap<String, RelationshipStatus> = HashMap::new();
287
288 if let Some(ref ua) = auth_user {
289 for question in &results {
290 if relationships.contains_key(&question.0.author.id) {
291 continue;
292 }
293
294 if question.0.author.id == ua.id {
295 relationships.insert(question.0.author.id.clone(), RelationshipStatus::Friends);
297 continue;
298 };
299
300 relationships.insert(
301 question.0.author.id.clone(),
302 database
303 .auth
304 .get_user_relationship(&question.0.author.id, &ua.id)
305 .await
306 .0,
307 );
308 }
309 } else {
310 for question in &results {
311 if relationships.contains_key(&question.0.author.id) {
313 continue;
314 }
315
316 relationships.insert(question.0.author.id.clone(), RelationshipStatus::Unknown);
317 }
318 }
319
320 let is_helper = if let Some(ref ua) = auth_user {
322 let group = match database.auth.get_group_by_id(ua.group).await {
323 Ok(g) => g,
324 Err(_) => return Html(DatabaseError::Other.to_html(database)),
325 };
326
327 group.permissions.check_helper()
328 } else {
329 false
330 };
331
332 Html(
334 QuestionsTemplate {
335 config: database.config.clone(),
336 lang: database.lang(if let Some(c) = jar.get("net.rainbeam.langs.choice") {
337 c.value_trimmed()
338 } else {
339 ""
340 }),
341 profile: auth_user.clone(),
342 unread,
343 notifs,
344 query: query.q,
345 page: query.page,
346 driver: 1,
347 results,
349 relationships,
350 is_helper,
351 }
352 .render()
353 .unwrap(),
354 )
355}
356
357#[derive(Template)]
358#[template(path = "search/users.html")]
359struct UsersTemplate {
360 config: Config,
361 lang: langbeam::LangFile,
362 profile: Option<Box<Profile>>,
363 unread: usize,
364 notifs: usize,
365 query: String,
366 page: i32,
367 driver: i8,
368 results: Vec<Box<Profile>>,
370}
371
372pub async fn search_users_request(
374 jar: CookieJar,
375 State(database): State<Database>,
376 Query(query): Query<SearchQuery>,
377) -> impl IntoResponse {
378 let auth_user = match jar.get("__Secure-Token") {
379 Some(c) => match database
380 .auth
381 .get_profile_by_unhashed(c.value_trimmed())
382 .await
383 {
384 Ok(ua) => Some(ua),
385 Err(_) => None,
386 },
387 None => None,
388 };
389
390 let unread = if let Some(ref ua) = auth_user {
391 database.get_inbox_count_by_recipient(&ua.id).await
392 } else {
393 0
394 };
395
396 let notifs = if let Some(ref ua) = auth_user {
397 database
398 .auth
399 .get_notification_count_by_recipient(&ua.id)
400 .await
401 } else {
402 0
403 };
404
405 let results = match database
407 .get_profiles_searched_paginated(query.page, query.q.clone())
408 .await
409 {
410 Ok(responses) => responses,
411 Err(e) => return Html(e.to_html(database)),
412 };
413
414 Html(
416 UsersTemplate {
417 config: database.config.clone(),
418 lang: database.lang(if let Some(c) = jar.get("net.rainbeam.langs.choice") {
419 c.value_trimmed()
420 } else {
421 ""
422 }),
423 profile: auth_user.clone(),
424 unread,
425 notifs,
426 query: query.q,
427 page: query.page,
428 driver: 3,
429 results,
431 }
432 .render()
433 .unwrap(),
434 )
435}