libreddit/src/search.rs

98 lines
2.4 KiB
Rust
Raw Normal View History

2021-01-01 00:54:13 +01:00
// CRATES
2021-03-17 23:30:33 +01:00
use crate::utils::{cookie, error, param, template, val, Post, Preferences};
use crate::{client::json, RequestExt};
2021-01-01 00:54:13 +01:00
use askama::Template;
2021-03-17 23:30:33 +01:00
use hyper::{Body, Request, Response};
2021-01-01 00:54:13 +01:00
// STRUCTS
2021-01-03 07:37:54 +01:00
struct SearchParams {
q: String,
sort: String,
t: String,
before: String,
after: String,
restrict_sr: String,
}
2021-01-14 19:22:50 +01:00
// STRUCTS
struct Subreddit {
name: String,
url: String,
description: String,
subscribers: i64,
}
2021-01-01 00:54:13 +01:00
#[derive(Template)]
#[template(path = "search.html", escape = "none")]
struct SearchTemplate {
posts: Vec<Post>,
2021-01-14 19:22:50 +01:00
subreddits: Vec<Subreddit>,
2021-01-01 00:54:13 +01:00
sub: String,
2021-01-03 07:37:54 +01:00
params: SearchParams,
2021-01-09 02:35:04 +01:00
prefs: Preferences,
2021-01-01 00:54:13 +01:00
}
// SERVICES
2021-03-17 23:30:33 +01:00
pub async fn find(req: Request<Body>) -> Result<Response<Body>, String> {
2021-01-31 06:43:46 +01:00
let nsfw_results = if cookie(&req, "show_nsfw") == "on" { "&include_over_18=on" } else { "" };
2021-03-17 23:30:33 +01:00
let path = format!("{}.json?{}{}", req.uri().path(), req.uri().query().unwrap_or_default(), nsfw_results);
let sub = req.param("sub").unwrap_or_default();
2021-02-20 22:59:16 +01:00
let query = param(&path, "q");
2021-01-14 20:45:04 +01:00
2021-01-01 21:33:57 +01:00
let sort = if param(&path, "sort").is_empty() {
2021-01-01 00:54:13 +01:00
"relevance".to_string()
} else {
2021-01-01 21:33:57 +01:00
param(&path, "sort")
2021-01-01 00:54:13 +01:00
};
2021-01-14 19:22:50 +01:00
2021-01-14 20:45:04 +01:00
let subreddits = if param(&path, "restrict_sr").is_empty() {
2021-02-20 22:59:16 +01:00
search_subreddits(&query).await
2021-01-14 20:45:04 +01:00
} else {
Vec::new()
};
2021-01-01 00:54:13 +01:00
2021-02-25 06:29:23 +01:00
match Post::fetch(&path, String::new()).await {
Ok((posts, after)) => template(SearchTemplate {
posts,
subreddits,
sub,
params: SearchParams {
2021-02-20 22:59:16 +01:00
q: query.replace('"', "&quot;"),
sort,
t: param(&path, "t"),
before: param(&path, "after"),
after,
restrict_sr: param(&path, "restrict_sr"),
},
2021-02-25 06:29:23 +01:00
prefs: Preferences::new(req),
}),
2021-02-21 03:36:30 +01:00
Err(msg) => error(req, msg).await,
2021-01-01 00:54:13 +01:00
}
}
2021-01-14 20:45:04 +01:00
2021-02-20 22:59:16 +01:00
async fn search_subreddits(q: &str) -> Vec<Subreddit> {
2021-01-14 20:45:04 +01:00
let subreddit_search_path = format!("/subreddits/search.json?q={}&limit=3", q.replace(' ', "+"));
// Send a request to the url
2021-03-17 23:30:33 +01:00
match json(subreddit_search_path).await {
2021-01-14 20:45:04 +01:00
// If success, receive JSON in response
Ok(response) => {
match response["data"]["children"].as_array() {
// For each subreddit from subreddit list
Some(list) => list
.iter()
.map(|subreddit| Subreddit {
name: val(subreddit, "display_name_prefixed"),
url: val(subreddit, "url"),
description: val(subreddit, "public_description"),
2021-03-09 16:22:17 +01:00
subscribers: subreddit["data"]["subscribers"].as_f64().unwrap_or_default() as i64,
2021-01-14 20:45:04 +01:00
})
.collect::<Vec<Subreddit>>(),
_ => Vec::new(),
}
}
// If the Reddit API returns an error, exit this function
_ => Vec::new(),
}
}