Federated blogging application, thanks to ActivityPub https://joinplu.me
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

85 lines
2.6 KiB

  1. use chrono::offset::Utc;
  2. use rocket::request::Form;
  3. use crate::routes::Page;
  4. use crate::template_utils::{IntoContext, Ructe};
  5. use plume_models::{search::Query, PlumeRocket};
  6. use std::str::FromStr;
  7. #[derive(Default, FromForm)]
  8. pub struct SearchQuery {
  9. q: Option<String>,
  10. title: Option<String>,
  11. subtitle: Option<String>,
  12. content: Option<String>,
  13. instance: Option<String>,
  14. author: Option<String>,
  15. tag: Option<String>,
  16. blog: Option<String>,
  17. lang: Option<String>,
  18. license: Option<String>,
  19. after: Option<String>,
  20. before: Option<String>,
  21. page: Option<Page>,
  22. }
  23. macro_rules! param_to_query {
  24. ( $query:ident, $parsed_query:ident; normal: $($field:ident),*; date: $($date:ident),*) => {
  25. $(
  26. let mut rest = $query.$field.as_ref().map(String::as_str).unwrap_or_default();
  27. while !rest.is_empty() {
  28. let (token, r) = Query::get_first_token(rest);
  29. rest = r;
  30. $parsed_query.$field(token, None);
  31. }
  32. )*
  33. $(
  34. if let Some(ref field) = $query.$date {
  35. let mut rest = field.as_str();
  36. while !rest.is_empty() {
  37. use chrono::naive::NaiveDate;
  38. let (token, r) = Query::get_first_token(rest);
  39. rest = r;
  40. if let Ok(token) = NaiveDate::parse_from_str(token, "%Y-%m-%d") {
  41. $parsed_query.$date(&token);
  42. }
  43. }
  44. }
  45. )*
  46. }
  47. }
  48. #[get("/search?<query..>")]
  49. pub fn search(query: Option<Form<SearchQuery>>, rockets: PlumeRocket) -> Ructe {
  50. let query = query.map(Form::into_inner).unwrap_or_default();
  51. let page = query.page.unwrap_or_default();
  52. let mut parsed_query =
  53. Query::from_str(&query.q.as_ref().map(String::as_str).unwrap_or_default())
  54. .unwrap_or_default();
  55. param_to_query!(query, parsed_query; normal: title, subtitle, content, tag,
  56. instance, author, blog, lang, license;
  57. date: before, after);
  58. let str_query = parsed_query.to_string();
  59. if str_query.is_empty() {
  60. render!(search::index(
  61. &rockets.to_context(),
  62. &format!("{}", Utc::today().format("%Y-%m-d"))
  63. ))
  64. } else {
  65. let res = rockets
  66. .searcher
  67. .search_document(parsed_query, page.limits());
  68. let next_page = if res.is_empty() { 0 } else { page.0 + 1 };
  69. render!(search::result(
  70. &rockets.to_context(),
  71. &str_query,
  72. res,
  73. page.0,
  74. next_page
  75. ))
  76. }
  77. }