NSFW Support
This commit is contained in:
parent
3516404a5f
commit
0957f2e339
14
src/post.rs
14
src/post.rs
@ -28,7 +28,7 @@ async fn render(id: String, sort: Option<String>, comment_id: Option<String>) ->
|
|||||||
// Build the Reddit JSON API url
|
// Build the Reddit JSON API url
|
||||||
let url: String = match comment_id {
|
let url: String = match comment_id {
|
||||||
None => format!("{}.json?sort={}", id, sorting),
|
None => format!("{}.json?sort={}", id, sorting),
|
||||||
Some(val) => format!("{}.json?sort={}&comment={}", id, sorting, val)
|
Some(val) => format!("{}.json?sort={}&comment={}", id, sorting, val),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Send a request to the url, receive JSON in response
|
// Send a request to the url, receive JSON in response
|
||||||
@ -111,13 +111,18 @@ async fn markdown_to_html(md: &str) -> String {
|
|||||||
|
|
||||||
// POSTS
|
// POSTS
|
||||||
async fn parse_post(json: serde_json::Value) -> Result<Post, &'static str> {
|
async fn parse_post(json: serde_json::Value) -> Result<Post, &'static str> {
|
||||||
|
// Retrieve post (as opposed to comments) from JSON
|
||||||
let post_data: &serde_json::Value = &json["data"]["children"][0];
|
let post_data: &serde_json::Value = &json["data"]["children"][0];
|
||||||
|
|
||||||
|
// Grab UTC time as unix timestamp
|
||||||
let unix_time: i64 = post_data["data"]["created_utc"].as_f64().unwrap().round() as i64;
|
let unix_time: i64 = post_data["data"]["created_utc"].as_f64().unwrap().round() as i64;
|
||||||
|
// Parse post score
|
||||||
let score = post_data["data"]["score"].as_i64().unwrap();
|
let score = post_data["data"]["score"].as_i64().unwrap();
|
||||||
|
|
||||||
|
// Determine the type of media along with the media URL
|
||||||
let media = media(&post_data["data"]).await;
|
let media = media(&post_data["data"]).await;
|
||||||
|
|
||||||
|
// Build a post using data parsed from Reddit post API
|
||||||
let post = Post {
|
let post = Post {
|
||||||
title: val(post_data, "title").await,
|
title: val(post_data, "title").await,
|
||||||
community: val(post_data, "subreddit").await,
|
community: val(post_data, "subreddit").await,
|
||||||
@ -131,8 +136,6 @@ async fn parse_post(json: serde_json::Value) -> Result<Post, &'static str> {
|
|||||||
url: val(post_data, "permalink").await,
|
url: val(post_data, "permalink").await,
|
||||||
score: format_num(score),
|
score: format_num(score),
|
||||||
post_type: media.0,
|
post_type: media.0,
|
||||||
media: media.1,
|
|
||||||
time: Utc.timestamp(unix_time, 0).format("%b %e %Y %H:%M UTC").to_string(),
|
|
||||||
flair: Flair(
|
flair: Flair(
|
||||||
val(post_data, "link_flair_text").await,
|
val(post_data, "link_flair_text").await,
|
||||||
val(post_data, "link_flair_background_color").await,
|
val(post_data, "link_flair_background_color").await,
|
||||||
@ -142,6 +145,9 @@ async fn parse_post(json: serde_json::Value) -> Result<Post, &'static str> {
|
|||||||
"white".to_string()
|
"white".to_string()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
nsfw: post_data["data"]["over_18"].as_bool().unwrap_or(false),
|
||||||
|
media: media.1,
|
||||||
|
time: Utc.timestamp(unix_time, 0).format("%b %e %Y %H:%M UTC").to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(post)
|
Ok(post)
|
||||||
@ -156,7 +162,7 @@ async fn parse_comments(json: serde_json::Value) -> Result<Vec<Comment>, &'stati
|
|||||||
let mut comments: Vec<Comment> = Vec::new();
|
let mut comments: Vec<Comment> = Vec::new();
|
||||||
|
|
||||||
// For each comment, retrieve the values to build a Comment object
|
// For each comment, retrieve the values to build a Comment object
|
||||||
for comment in comment_data.iter() {
|
for comment in comment_data {
|
||||||
let unix_time: i64 = comment["data"]["created_utc"].as_f64().unwrap_or(0.0).round() as i64;
|
let unix_time: i64 = comment["data"]["created_utc"].as_f64().unwrap_or(0.0).round() as i64;
|
||||||
if unix_time == 0 {
|
if unix_time == 0 {
|
||||||
continue;
|
continue;
|
||||||
|
19
src/utils.rs
19
src/utils.rs
@ -11,11 +11,9 @@ use base64::encode;
|
|||||||
//
|
//
|
||||||
// STRUCTS
|
// STRUCTS
|
||||||
//
|
//
|
||||||
#[allow(dead_code)]
|
|
||||||
// Post flair with text, background color and foreground color
|
// Post flair with text, background color and foreground color
|
||||||
pub struct Flair(pub String, pub String, pub String);
|
pub struct Flair(pub String, pub String, pub String);
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
// Post containing content, metadata and media
|
// Post containing content, metadata and media
|
||||||
pub struct Post {
|
pub struct Post {
|
||||||
pub title: String,
|
pub title: String,
|
||||||
@ -26,12 +24,12 @@ pub struct Post {
|
|||||||
pub url: String,
|
pub url: String,
|
||||||
pub score: String,
|
pub score: String,
|
||||||
pub post_type: String,
|
pub post_type: String,
|
||||||
|
pub flair: Flair,
|
||||||
|
pub nsfw: bool,
|
||||||
pub media: String,
|
pub media: String,
|
||||||
pub time: String,
|
pub time: String,
|
||||||
pub flair: Flair,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
// Comment with content, post, score and data/time that it was posted
|
// Comment with content, post, score and data/time that it was posted
|
||||||
pub struct Comment {
|
pub struct Comment {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
@ -43,7 +41,6 @@ pub struct Comment {
|
|||||||
pub replies: Vec<Comment>,
|
pub replies: Vec<Comment>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
// User struct containing metadata about user
|
// User struct containing metadata about user
|
||||||
pub struct User {
|
pub struct User {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -53,7 +50,6 @@ pub struct User {
|
|||||||
pub description: String,
|
pub description: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
// Subreddit struct containing metadata about community
|
// Subreddit struct containing metadata about community
|
||||||
pub struct Subreddit {
|
pub struct Subreddit {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -105,19 +101,16 @@ pub fn format_num(num: i64) -> String {
|
|||||||
// JSON PARSING
|
// JSON PARSING
|
||||||
//
|
//
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
// val() function used to parse JSON from Reddit APIs
|
// val() function used to parse JSON from Reddit APIs
|
||||||
pub async fn val(j: &serde_json::Value, k: &str) -> String {
|
pub async fn val(j: &serde_json::Value, k: &str) -> String {
|
||||||
String::from(j["data"][k].as_str().unwrap_or(""))
|
String::from(j["data"][k].as_str().unwrap_or(""))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
// nested_val() function used to parse JSON from Reddit APIs
|
// nested_val() function used to parse JSON from Reddit APIs
|
||||||
pub async fn nested_val(j: &serde_json::Value, n: &str, k: &str) -> String {
|
pub async fn nested_val(j: &serde_json::Value, n: &str, k: &str) -> String {
|
||||||
String::from(j["data"][n][k].as_str().unwrap())
|
String::from(j["data"][n][k].as_str().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub async fn fetch_posts(url: String, fallback_title: String) -> Result<(Vec<Post>, String), &'static str> {
|
pub async fn fetch_posts(url: String, fallback_title: String) -> Result<(Vec<Post>, String), &'static str> {
|
||||||
// Send a request to the url, receive JSON in response
|
// Send a request to the url, receive JSON in response
|
||||||
let req = request(url).await;
|
let req = request(url).await;
|
||||||
@ -135,7 +128,7 @@ pub async fn fetch_posts(url: String, fallback_title: String) -> Result<(Vec<Pos
|
|||||||
|
|
||||||
let mut posts: Vec<Post> = Vec::new();
|
let mut posts: Vec<Post> = Vec::new();
|
||||||
|
|
||||||
for post in post_list.iter() {
|
for post in post_list {
|
||||||
let img = if val(post, "thumbnail").await.starts_with("https:/") {
|
let img = if val(post, "thumbnail").await.starts_with("https:/") {
|
||||||
format_url(val(post, "thumbnail").await.as_str()).await
|
format_url(val(post, "thumbnail").await.as_str()).await
|
||||||
} else {
|
} else {
|
||||||
@ -158,8 +151,6 @@ pub async fn fetch_posts(url: String, fallback_title: String) -> Result<(Vec<Pos
|
|||||||
score: format_num(score),
|
score: format_num(score),
|
||||||
post_type: "link".to_string(),
|
post_type: "link".to_string(),
|
||||||
media: img,
|
media: img,
|
||||||
url: val(post, "permalink").await,
|
|
||||||
time: Utc.timestamp(unix_time, 0).format("%b %e '%y").to_string(),
|
|
||||||
flair: Flair(
|
flair: Flair(
|
||||||
val(post, "link_flair_text").await,
|
val(post, "link_flair_text").await,
|
||||||
val(post, "link_flair_background_color").await,
|
val(post, "link_flair_background_color").await,
|
||||||
@ -169,6 +160,9 @@ pub async fn fetch_posts(url: String, fallback_title: String) -> Result<(Vec<Pos
|
|||||||
"white".to_string()
|
"white".to_string()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
nsfw: post["data"]["over_18"].as_bool().unwrap_or(false),
|
||||||
|
url: val(post, "permalink").await,
|
||||||
|
time: Utc.timestamp(unix_time, 0).format("%b %e '%y").to_string(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,7 +174,6 @@ pub async fn fetch_posts(url: String, fallback_title: String) -> Result<(Vec<Pos
|
|||||||
//
|
//
|
||||||
|
|
||||||
// Make a request to a Reddit API and parse the JSON response
|
// Make a request to a Reddit API and parse the JSON response
|
||||||
#[allow(dead_code)]
|
|
||||||
pub async fn request(mut url: String) -> Result<serde_json::Value, &'static str> {
|
pub async fn request(mut url: String) -> Result<serde_json::Value, &'static str> {
|
||||||
url = format!("https://www.reddit.com/{}", url);
|
url = format!("https://www.reddit.com/{}", url);
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ main {
|
|||||||
footer {
|
footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
@ -199,6 +200,21 @@ a:not(.post_right):hover {
|
|||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.post_score {
|
||||||
|
margin-top: 20px;
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nsfw {
|
||||||
|
color: #FF5C5D;
|
||||||
|
margin-top: 20px;
|
||||||
|
border: 1px solid #FF5C5D;
|
||||||
|
padding: 5px;
|
||||||
|
font-size: 12px;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
.post_subreddit {
|
.post_subreddit {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
@ -207,11 +223,6 @@ a:not(.post_right):hover {
|
|||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post_score {
|
|
||||||
margin-top: 20px;
|
|
||||||
color: var(--accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
.post_right {
|
.post_right {
|
||||||
padding: 20px 25px;
|
padding: 20px 25px;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
<div class="post">
|
<div class="post">
|
||||||
<div class="post_left">
|
<div class="post_left">
|
||||||
<h3 class="post_score">{{ post.score }}</h3>
|
<h3 class="post_score">{{ post.score }}</h3>
|
||||||
|
{% if post.nsfw %}<div class="nsfw">NSFW</div>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="post_right">
|
<div class="post_right">
|
||||||
<h4>
|
<h4>
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
<div class="post highlighted">
|
<div class="post highlighted">
|
||||||
<div class="post_left">
|
<div class="post_left">
|
||||||
<h3 class="post_score">{{ post.score }}</h3>
|
<h3 class="post_score">{{ post.score }}</h3>
|
||||||
|
{% if post.nsfw %}<div class="nsfw">NSFW</div>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="post_right">
|
<div class="post_right">
|
||||||
<h4>
|
<h4>
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
<div class="post">
|
<div class="post">
|
||||||
<div class="post_left">
|
<div class="post_left">
|
||||||
<h3 class="post_score">{{ post.score }}</h3>
|
<h3 class="post_score">{{ post.score }}</h3>
|
||||||
|
{% if post.nsfw %}<div class="nsfw">NSFW</div>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="post_right">
|
<div class="post_right">
|
||||||
<h4>
|
<h4>
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
<div class='post'>
|
<div class='post'>
|
||||||
<div class="post_left">
|
<div class="post_left">
|
||||||
<h3 class="post_score">{{ post.score }}</h3>
|
<h3 class="post_score">{{ post.score }}</h3>
|
||||||
|
{% if post.nsfw %}<div class="nsfw">NSFW</div>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="post_right">
|
<div class="post_right">
|
||||||
<h4>
|
<h4>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user