Make a request() utility
This commit is contained in:
@ -24,6 +24,7 @@ async fn favicon() -> HttpResponse {
|
||||
async fn main() -> std::io::Result<()> {
|
||||
// start http server
|
||||
println!("Running Libreddit on 0.0.0.0:8080!");
|
||||
|
||||
HttpServer::new(|| {
|
||||
App::new()
|
||||
// GENERAL SERVICES
|
||||
|
@ -20,7 +20,7 @@ struct PopularTemplate {
|
||||
|
||||
// RENDER
|
||||
async fn render(sub_name: String, sort: String) -> Result<HttpResponse> {
|
||||
let posts: Vec<Post> = posts(sub_name, &sort).await;
|
||||
let posts: Vec<Post> = posts(sub_name, &sort).await?;
|
||||
|
||||
let s = PopularTemplate { posts: posts, sort: sort }.render().unwrap();
|
||||
Ok(HttpResponse::Ok().content_type("text/html").body(s))
|
||||
|
30
src/post.rs
30
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};
|
||||
use utils::{val, Comment, Flair, Params, Post, request};
|
||||
|
||||
// STRUCTS
|
||||
#[derive(Template)]
|
||||
@ -19,8 +19,8 @@ struct PostTemplate {
|
||||
|
||||
async fn render(id: String, sort: String) -> Result<HttpResponse> {
|
||||
println!("id: {}", id);
|
||||
let post: Post = fetch_post(&id).await;
|
||||
let comments: Vec<Comment> = fetch_comments(id, &sort).await.unwrap();
|
||||
let post: Post = fetch_post(&id).await?;
|
||||
let comments: Vec<Comment> = fetch_comments(id, &sort).await?;
|
||||
|
||||
let s = PostTemplate {
|
||||
comments: comments,
|
||||
@ -86,18 +86,19 @@ async fn markdown_to_html(md: &str) -> String {
|
||||
}
|
||||
|
||||
// POSTS
|
||||
async fn fetch_post(id: &String) -> Post {
|
||||
async fn fetch_post(id: &String) -> Result<Post> {
|
||||
// Build the Reddit JSON API url
|
||||
let url: String = format!("https://reddit.com/{}.json", id);
|
||||
let resp: String = reqwest::get(&url).await.unwrap().text().await.unwrap();
|
||||
|
||||
let data: serde_json::Value = serde_json::from_str(resp.as_str()).expect("Failed to parse JSON");
|
||||
// Send a request to the url, receive JSON in response
|
||||
let res = request(url).await;
|
||||
|
||||
let post_data: &serde_json::Value = &data[0]["data"]["children"][0];
|
||||
let post_data: &serde_json::Value = &res[0]["data"]["children"][0];
|
||||
|
||||
let unix_time: i64 = post_data["data"]["created_utc"].as_f64().unwrap().round() as i64;
|
||||
let score = post_data["data"]["score"].as_i64().unwrap();
|
||||
|
||||
Post {
|
||||
let post = Post {
|
||||
title: val(post_data, "title").await,
|
||||
community: val(post_data, "subreddit").await,
|
||||
body: markdown_to_html(post_data["data"]["selftext"].as_str().unwrap()).await,
|
||||
@ -115,17 +116,20 @@ async fn fetch_post(id: &String) -> Post {
|
||||
"white".to_string()
|
||||
},
|
||||
),
|
||||
}
|
||||
};
|
||||
|
||||
Ok(post)
|
||||
}
|
||||
|
||||
// COMMENTS
|
||||
async fn fetch_comments(id: String, sort: &String) -> Result<Vec<Comment>, Box<dyn std::error::Error>> {
|
||||
async fn fetch_comments(id: String, sort: &String) -> Result<Vec<Comment>> {
|
||||
// Build the Reddit JSON API url
|
||||
let url: String = format!("https://reddit.com/{}.json?sort={}", id, sort);
|
||||
let resp: String = reqwest::get(&url).await?.text().await?;
|
||||
|
||||
let data: serde_json::Value = serde_json::from_str(resp.as_str())?;
|
||||
// Send a request to the url, receive JSON in response
|
||||
let res = request(url).await;
|
||||
|
||||
let comment_data = data[1]["data"]["children"].as_array().unwrap();
|
||||
let comment_data = res[1]["data"]["children"].as_array().unwrap();
|
||||
|
||||
let mut comments: Vec<Comment> = Vec::new();
|
||||
|
||||
|
@ -5,7 +5,7 @@ use chrono::{TimeZone, Utc};
|
||||
|
||||
#[path = "utils.rs"]
|
||||
mod utils;
|
||||
pub use utils::{val, Flair, Params, Post, Subreddit};
|
||||
pub use utils::{val, Flair, Params, Post, Subreddit, request};
|
||||
|
||||
// STRUCTS
|
||||
#[derive(Template)]
|
||||
@ -17,8 +17,8 @@ struct SubredditTemplate {
|
||||
}
|
||||
|
||||
async fn render(sub_name: String, sort: String) -> Result<HttpResponse> {
|
||||
let mut sub: Subreddit = subreddit(&sub_name).await;
|
||||
let posts: Vec<Post> = posts(sub_name, &sort).await;
|
||||
let mut sub: Subreddit = subreddit(&sub_name).await?;
|
||||
let posts: Vec<Post> = posts(sub_name, &sort).await?;
|
||||
|
||||
sub.icon = if sub.icon != "" {
|
||||
format!(r#"<img class="subreddit_icon" src="{}">"#, sub.icon)
|
||||
@ -41,35 +41,37 @@ async fn page(web::Path(sub): web::Path<String>, params: web::Query<Params>) ->
|
||||
}
|
||||
|
||||
// SUBREDDIT
|
||||
async fn subreddit(sub: &String) -> Subreddit {
|
||||
// Make a GET request to the Reddit's JSON API for the metadata of this subreddit
|
||||
async fn subreddit(sub: &String) -> Result<Subreddit> {
|
||||
// Build the Reddit JSON API url
|
||||
let url: String = format!("https://www.reddit.com/r/{}/about.json", sub);
|
||||
let resp: String = reqwest::get(&url).await.unwrap().text().await.unwrap();
|
||||
|
||||
// Parse the response from Reddit as JSON
|
||||
let data: serde_json::Value = serde_json::from_str(resp.as_str()).expect("Failed to parse JSON");
|
||||
// Send a request to the url, receive JSON in response
|
||||
let res = request(url).await;
|
||||
|
||||
let icon: String = String::from(data["data"]["community_icon"].as_str().unwrap()); //val(&data, "community_icon");
|
||||
let icon: String = String::from(res["data"]["community_icon"].as_str().unwrap()); //val(&data, "community_icon");
|
||||
let icon_split: std::str::Split<&str> = icon.split("?");
|
||||
let icon_parts: Vec<&str> = icon_split.collect();
|
||||
|
||||
Subreddit {
|
||||
name: val(&data, "display_name").await,
|
||||
title: val(&data, "title").await,
|
||||
description: val(&data, "public_description").await,
|
||||
let sub = Subreddit {
|
||||
name: val(&res, "display_name").await,
|
||||
title: val(&res, "title").await,
|
||||
description: val(&res, "public_description").await,
|
||||
icon: String::from(icon_parts[0]),
|
||||
}
|
||||
};
|
||||
|
||||
Ok(sub)
|
||||
}
|
||||
|
||||
// POSTS
|
||||
pub async fn posts(sub: String, sort: &String) -> Vec<Post> {
|
||||
// Make a GET request to the Reddit's JSON API for the content of this subreddit
|
||||
pub async fn posts(sub: String, sort: &String) -> Result<Vec<Post>> {
|
||||
// Build the Reddit JSON API url
|
||||
let url: String = format!("https://www.reddit.com/r/{}/{}.json", sub, sort);
|
||||
let resp: String = reqwest::get(&url).await.unwrap().text().await.unwrap();
|
||||
|
||||
// Parse the response from Reddit as JSON
|
||||
let popular: serde_json::Value = serde_json::from_str(resp.as_str()).expect("Failed to parse JSON");
|
||||
let post_list = popular["data"]["children"].as_array().unwrap();
|
||||
// Send a request to the url, receive JSON in response
|
||||
let res = request(url).await;
|
||||
|
||||
// Fetch the list of posts from the JSON response
|
||||
let post_list = res["data"]["children"].as_array().unwrap();
|
||||
|
||||
let mut posts: Vec<Post> = Vec::new();
|
||||
|
||||
@ -101,5 +103,5 @@ pub async fn posts(sub: String, sort: &String) -> Vec<Post> {
|
||||
),
|
||||
});
|
||||
}
|
||||
posts
|
||||
Ok(posts)
|
||||
}
|
||||
|
25
src/user.rs
25
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};
|
||||
use utils::{nested_val, val, Flair, Params, Post, User, request};
|
||||
|
||||
// STRUCTS
|
||||
#[derive(Template)]
|
||||
@ -35,27 +35,30 @@ async fn page(web::Path(username): web::Path<String>, params: web::Query<Params>
|
||||
|
||||
// USER
|
||||
async fn user(name: &String) -> User {
|
||||
// Build the Reddit JSON API url
|
||||
let url: String = format!("https://www.reddit.com/user/{}/about.json", name);
|
||||
let resp: String = reqwest::get(&url).await.unwrap().text().await.unwrap();
|
||||
|
||||
let data: serde_json::Value = serde_json::from_str(resp.as_str()).expect("Failed to parse JSON");
|
||||
|
||||
// Send a request to the url, receive JSON in response
|
||||
let res = request(url).await;
|
||||
|
||||
User {
|
||||
name: name.to_string(),
|
||||
icon: nested_val(&data, "subreddit", "icon_img").await,
|
||||
karma: data["data"]["total_karma"].as_i64().unwrap(),
|
||||
banner: nested_val(&data, "subreddit", "banner_img").await,
|
||||
description: nested_val(&data, "subreddit", "public_description").await,
|
||||
icon: nested_val(&res, "subreddit", "icon_img").await,
|
||||
karma: res["data"]["total_karma"].as_i64().unwrap(),
|
||||
banner: nested_val(&res, "subreddit", "banner_img").await,
|
||||
description: nested_val(&res, "subreddit", "public_description").await,
|
||||
}
|
||||
}
|
||||
|
||||
// POSTS
|
||||
async fn posts(sub: String, sort: &String) -> Vec<Post> {
|
||||
// Build the Reddit JSON API url
|
||||
let url: String = format!("https://www.reddit.com/u/{}/.json?sort={}", sub, sort);
|
||||
let resp: String = reqwest::get(&url).await.unwrap().text().await.unwrap();
|
||||
|
||||
let popular: serde_json::Value = serde_json::from_str(resp.as_str()).expect("Failed to parse JSON");
|
||||
let post_list = popular["data"]["children"].as_array().unwrap();
|
||||
// Send a request to the url, receive JSON in response
|
||||
let res = request(url).await;
|
||||
|
||||
let post_list = res["data"]["children"].as_array().unwrap();
|
||||
|
||||
let mut posts: Vec<Post> = Vec::new();
|
||||
|
||||
|
31
src/utils.rs
31
src/utils.rs
@ -61,3 +61,34 @@ pub async fn nested_val(j: &serde_json::Value, n: &str, k: &str) -> String {
|
||||
pub struct Params {
|
||||
pub sort: Option<String>,
|
||||
}
|
||||
|
||||
// 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
|
||||
// .get(url)
|
||||
// .send()
|
||||
// .await?
|
||||
// .body()
|
||||
// .limit(1000000)
|
||||
// .await?;
|
||||
|
||||
// let body = std::str::from_utf8(res.as_ref())?; // .as_ref converts Bytes to [u8]
|
||||
|
||||
// --- surf ---
|
||||
// let req = surf::get(url);
|
||||
// let client = surf::client().with(surf::middleware::Redirect::new(5));
|
||||
// let mut res = client.send(req).await.unwrap();
|
||||
// let body = res.body_string().await.unwrap();
|
||||
|
||||
// --- reqwest ---
|
||||
let resp: String = reqwest::get(&url).await.unwrap().text().await.unwrap();
|
||||
|
||||
// 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
|
||||
}
|
||||
|
Reference in New Issue
Block a user