From 7a176c680459ec77a066476480ff4efb21719777 Mon Sep 17 00:00:00 2001 From: spikecodes <19519553+spikecodes@users.noreply.github.com> Date: Thu, 19 Nov 2020 13:49:32 -0800 Subject: [PATCH] Add pages to subreddits --- src/popular.rs | 30 +++++++++++++++++------ src/post.rs | 2 +- src/subreddit.rs | 53 ++++++++++++++++++++++++++-------------- src/user.rs | 4 +-- src/utils.rs | 17 +++++++------ static/style.css | 8 ++++-- templates/popular.html | 10 ++++++++ templates/subreddit.html | 10 ++++++++ 8 files changed, 95 insertions(+), 39 deletions(-) diff --git a/src/popular.rs b/src/popular.rs index 5181003..08399be 100644 --- a/src/popular.rs +++ b/src/popular.rs @@ -16,21 +16,37 @@ use utils::Params; struct PopularTemplate { posts: Vec, sort: String, + ends: (String, String), } // RENDER -async fn render(sub_name: String, sort: String) -> Result { - let posts: Vec = posts(sub_name, &sort).await?; +async fn render(sub_name: String, sort: Option, ends: (Option, Option)) -> Result { + let sorting = sort.unwrap_or("hot".to_string()); + let before = ends.1.clone().unwrap_or(String::new()); // If there is an after, there must be a before - let s = PopularTemplate { posts: posts, sort: sort }.render().unwrap(); + // Build the Reddit JSON API url + let url = match ends.0 { + Some(val) => format!("https://www.reddit.com/r/{}/{}.json?before={}&count=25", sub_name, sorting, val), + None => match ends.1 { + Some(val) => format!("https://www.reddit.com/r/{}/{}.json?after={}&count=25", sub_name, sorting, val), + None => format!("https://www.reddit.com/r/{}/{}.json", sub_name, sorting), + }, + }; + + let items = posts(url).await?; + + let s = PopularTemplate { + posts: items.0, + sort: sorting, + ends: (before, items.1), + } + .render() + .unwrap(); Ok(HttpResponse::Ok().content_type("text/html").body(s)) } // SERVICES #[get("/")] pub async fn page(params: web::Query) -> Result { - match ¶ms.sort { - Some(sort) => render("popular".to_string(), sort.to_string()).await, - None => render("popular".to_string(), "hot".to_string()).await, - } + render("popular".to_string(), params.sort.clone(), (params.before.clone(), params.after.clone())).await } diff --git a/src/post.rs b/src/post.rs index e902987..20c69f0 100644 --- a/src/post.rs +++ b/src/post.rs @@ -6,7 +6,7 @@ use pulldown_cmark::{html, Options, Parser}; #[path = "utils.rs"] mod utils; -use utils::{val, Comment, Flair, Params, Post, request}; +use utils::{request, val, Comment, Flair, Params, Post}; // STRUCTS #[derive(Template)] diff --git a/src/subreddit.rs b/src/subreddit.rs index d6b3a30..41041a3 100644 --- a/src/subreddit.rs +++ b/src/subreddit.rs @@ -5,7 +5,7 @@ use chrono::{TimeZone, Utc}; #[path = "utils.rs"] mod utils; -pub use utils::{val, Flair, Params, Post, Subreddit, request}; +pub use utils::{request, val, Flair, Params, Post, Subreddit}; // STRUCTS #[derive(Template)] @@ -14,11 +14,31 @@ struct SubredditTemplate { sub: Subreddit, posts: Vec, sort: String, + ends: (String, String), } -async fn render(sub_name: String, sort: String) -> Result { +// SERVICES +#[allow(dead_code)] +#[get("/r/{sub}")] +async fn page(web::Path(sub): web::Path, params: web::Query) -> Result { + render(sub, params.sort.clone(), (params.before.clone(), params.after.clone())).await +} + +pub async fn render(sub_name: String, sort: Option, ends: (Option, Option)) -> Result { + let sorting = sort.unwrap_or("hot".to_string()); + let before = ends.1.clone().unwrap_or(String::new()); // If there is an after, there must be a before + + // Build the Reddit JSON API url + let url = match ends.0 { + Some(val) => format!("https://www.reddit.com/r/{}/{}.json?before={}&count=25", sub_name, sorting, val), + None => match ends.1 { + Some(val) => format!("https://www.reddit.com/r/{}/{}.json?after={}&count=25", sub_name, sorting, val), + None => format!("https://www.reddit.com/r/{}/{}.json", sub_name, sorting), + }, + }; + let mut sub: Subreddit = subreddit(&sub_name).await?; - let posts: Vec = posts(sub_name, &sort).await?; + let items = posts(url).await?; sub.icon = if sub.icon != "" { format!(r#""#, sub.icon) @@ -26,18 +46,15 @@ async fn render(sub_name: String, sort: String) -> Result { String::new() }; - let s = SubredditTemplate { sub: sub, posts: posts, sort: sort }.render().unwrap(); - Ok(HttpResponse::Ok().content_type("text/html").body(s)) -} - -// SERVICES -#[allow(dead_code)] -#[get("/r/{sub}")] -async fn page(web::Path(sub): web::Path, params: web::Query) -> Result { - match ¶ms.sort { - Some(sort) => render(sub, sort.to_string()).await, - None => render(sub, "hot".to_string()).await, + let s = SubredditTemplate { + sub: sub, + posts: items.0, + sort: sorting, + ends: (before, items.1), } + .render() + .unwrap(); + Ok(HttpResponse::Ok().content_type("text/html").body(s)) } // SUBREDDIT @@ -63,10 +80,7 @@ async fn subreddit(sub: &String) -> Result { } // POSTS -pub async fn posts(sub: String, sort: &String) -> Result> { - // Build the Reddit JSON API url - let url: String = format!("https://www.reddit.com/r/{}/{}.json", sub, sort); - +pub async fn posts(url: String) -> Result<(Vec, String)> { // Send a request to the url, receive JSON in response let res = request(url).await; @@ -103,5 +117,6 @@ pub async fn posts(sub: String, sort: &String) -> Result> { ), }); } - Ok(posts) + + Ok((posts, res["data"]["after"].as_str().unwrap_or("").to_string())) } diff --git a/src/user.rs b/src/user.rs index 457e49b..7409475 100644 --- a/src/user.rs +++ b/src/user.rs @@ -5,7 +5,7 @@ use chrono::{TimeZone, Utc}; #[path = "utils.rs"] mod utils; -use utils::{nested_val, val, Flair, Params, Post, User, request}; +use utils::{nested_val, request, val, Flair, Params, Post, User}; // STRUCTS #[derive(Template)] @@ -37,7 +37,7 @@ async fn page(web::Path(username): web::Path, params: web::Query async fn user(name: &String) -> User { // Build the Reddit JSON API url let url: String = format!("https://www.reddit.com/user/{}/about.json", name); - + // Send a request to the url, receive JSON in response let res = request(url).await; diff --git a/src/utils.rs b/src/utils.rs index 7bfa6e6..647cfc9 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -44,6 +44,14 @@ pub struct Subreddit { pub icon: String, } +// Parser for query params, used in sorting (eg. /r/rust/?sort=hot) +#[derive(serde::Deserialize)] +pub struct Params { + pub sort: Option, + pub after: Option, + pub before: Option, +} + #[allow(dead_code)] // val() function used to parse JSON from Reddit APIs pub async fn val(j: &serde_json::Value, k: &str) -> String { @@ -56,16 +64,9 @@ pub async fn nested_val(j: &serde_json::Value, n: &str, k: &str) -> String { String::from(j["data"][n][k].as_str().unwrap()) } -// Parser for query params, used in sorting (eg. /r/rust/?sort=hot) -#[derive(serde::Deserialize)] -pub struct Params { - pub sort: Option, -} - // Make a request to a Reddit API and parse the JSON response #[allow(dead_code)] pub async fn request(url: String) -> serde_json::Value { - // --- actix-web::client --- // let client = actix_web::client::Client::default(); // let res = client @@ -89,6 +90,6 @@ pub async fn request(url: String) -> serde_json::Value { // Parse the response from Reddit as JSON let json: serde_json::Value = serde_json::from_str(resp.as_str()).expect("Failed to parse JSON"); - + json } diff --git a/static/style.css b/static/style.css index 33c6072..96e48dd 100644 --- a/static/style.css +++ b/static/style.css @@ -29,6 +29,11 @@ main { padding: 0px 10px; } +footer { + display: flex; + justify-content: center; +} + button { background: none; border: none; @@ -109,7 +114,7 @@ span { padding: 0px 10px; } -#sort > div { +#sort > div, footer > a { background: #151515; color: lightgrey; border-radius: 5px; @@ -117,7 +122,6 @@ span { padding: 10px 20px; text-align: center; cursor: pointer; - font-weight: bold; } #sort > div:hover { diff --git a/templates/popular.html b/templates/popular.html index ac0b293..57bc8d7 100644 --- a/templates/popular.html +++ b/templates/popular.html @@ -47,6 +47,16 @@
{% endfor %} + +
+ {% if ends.0 != "" %} + PREV + {% endif %} + + {% if ends.1 != "" %} + NEXT + {% endif %} +
\ No newline at end of file diff --git a/templates/subreddit.html b/templates/subreddit.html index b852e7f..a109bd5 100644 --- a/templates/subreddit.html +++ b/templates/subreddit.html @@ -58,6 +58,16 @@
{% endfor %} + + \ No newline at end of file