From 14ecf3cf604c8b351940e3b923f15eff525ebd3a Mon Sep 17 00:00:00 2001 From: spikecodes <19519553+spikecodes@users.noreply.github.com> Date: Sun, 14 Feb 2021 14:53:09 -0800 Subject: [PATCH] Edit indicator --- src/post.rs | 31 +++++++++++++-------- src/utils.rs | 62 ++++++++++++++++++++++++++---------------- static/style.css | 6 ++++ templates/comment.html | 1 + 4 files changed, 66 insertions(+), 34 deletions(-) diff --git a/src/post.rs b/src/post.rs index 90caeaf..2e3d53d 100644 --- a/src/post.rs +++ b/src/post.rs @@ -86,7 +86,7 @@ async fn parse_post(json: &serde_json::Value) -> Post { name: val(post, "author"), flair: Flair { flair_parts: parse_rich_flair( - val(post, "author_flair_type"), + post["data"]["author_flair_type"].as_str().unwrap_or_default(), post["data"]["author_flair_richtext"].as_array(), post["data"]["author_flair_text"].as_str(), ), @@ -108,7 +108,7 @@ async fn parse_post(json: &serde_json::Value) -> Post { }, flair: Flair { flair_parts: parse_rich_flair( - val(post, "link_flair_type"), + post["data"]["link_flair_type"].as_str().unwrap_or_default(), post["data"]["link_flair_richtext"].as_array(), post["data"]["link_flair_text"].as_str(), ), @@ -144,14 +144,22 @@ async fn parse_comments(json: &serde_json::Value, post_link: &str, post_author: // For each comment, retrieve the values to build a Comment object for comment in comment_data { - let unix_time = comment["data"]["created_utc"].as_f64().unwrap_or_default(); + let kind = comment["kind"].as_str().unwrap_or_default().to_string(); + let data = &comment["data"]; + + let unix_time = data["created_utc"].as_f64().unwrap_or_default(); let (rel_time, created) = time(unix_time); - let score = comment["data"]["score"].as_i64().unwrap_or(0); + let edited = match data["edited"].as_f64() { + Some(stamp) => time(stamp), + None => (String::new(), String::new()), + }; + + let score = data["score"].as_i64().unwrap_or(0); let body = rewrite_urls(&val(&comment, "body_html")); - let replies: Vec = if comment["data"]["replies"].is_object() { - parse_comments(&comment["data"]["replies"], post_link, post_author, highlighted_comment).await + let replies: Vec = if data["replies"].is_object() { + parse_comments(&data["replies"], post_link, post_author, highlighted_comment).await } else { Vec::new() }; @@ -164,7 +172,7 @@ async fn parse_comments(json: &serde_json::Value, post_link: &str, post_author: comments.push(Comment { id, - kind: comment["kind"].as_str().unwrap_or_default().to_string(), + kind, parent_id: parent_info[1].to_string(), parent_kind: parent_info[0].to_string(), post_link: post_link.to_string(), @@ -174,22 +182,23 @@ async fn parse_comments(json: &serde_json::Value, post_link: &str, post_author: name: val(&comment, "author"), flair: Flair { flair_parts: parse_rich_flair( - val(&comment, "author_flair_type"), - comment["data"]["author_flair_richtext"].as_array(), - comment["data"]["author_flair_text"].as_str(), + data["author_flair_type"].as_str().unwrap_or_default(), + data["author_flair_richtext"].as_array(), + data["author_flair_text"].as_str(), ), background_color: val(&comment, "author_flair_background_color"), foreground_color: val(&comment, "author_flair_text_color"), }, distinguished: val(&comment, "distinguished"), }, - score: if comment["data"]["score_hidden"].as_bool().unwrap_or_default() { + score: if data["score_hidden"].as_bool().unwrap_or_default() { "•".to_string() } else { format_num(score) }, rel_time, created, + edited, replies, highlighted, }); diff --git a/src/utils.rs b/src/utils.rs index 555f0cf..3a97adf 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -91,6 +91,7 @@ pub struct Comment { pub score: String, pub rel_time: String, pub created: String, + pub edited: (String, String), pub replies: Vec, pub highlighted: bool, } @@ -209,17 +210,21 @@ pub fn format_num(num: i64) -> String { pub async fn media(data: &Value) -> (String, Media, Vec) { let post_type: &str; let mut gallery = Vec::new(); + // If post is a video, return the video let url = if data["preview"]["reddit_video_preview"]["fallback_url"].is_string() { + // Return video preview post_type = "video"; format_url(data["preview"]["reddit_video_preview"]["fallback_url"].as_str().unwrap_or_default()) } else if data["secure_media"]["reddit_video"]["fallback_url"].is_string() { + // Return reddit video post_type = "video"; format_url(data["secure_media"]["reddit_video"]["fallback_url"].as_str().unwrap_or_default()) } else if data["post_hint"].as_str().unwrap_or("") == "image" { // Handle images, whether GIFs or pics - let preview = data["preview"]["images"][0].clone(); + let preview = &data["preview"]["images"][0]; let mp4 = &preview["variants"]["mp4"]; + if mp4.is_object() { // Return the mp4 if the media is a gif post_type = "gif"; @@ -230,17 +235,22 @@ pub async fn media(data: &Value) -> (String, Media, Vec) { format_url(preview["source"]["url"].as_str().unwrap_or_default()) } } else if data["is_self"].as_bool().unwrap_or_default() { + // If type is self, return permalink post_type = "self"; data["permalink"].as_str().unwrap_or_default().to_string() } else if data["is_gallery"].as_bool().unwrap_or_default() { + // If this post contains a gallery of images post_type = "gallery"; gallery = data["gallery_data"]["items"] .as_array() .unwrap_or(&Vec::::new()) .iter() .map(|item| { + // For each image in gallery let media_id = item["media_id"].as_str().unwrap_or_default(); let image = &data["media_metadata"][media_id]["s"]; + + // Construct gallery items GalleryMedia { url: format_url(image["u"].as_str().unwrap_or_default()), width: image["x"].as_i64().unwrap_or_default(), @@ -250,27 +260,31 @@ pub async fn media(data: &Value) -> (String, Media, Vec) { } }) .collect::>(); + data["url"].as_str().unwrap_or_default().to_string() } else { + // If type can't be determined, return url post_type = "link"; data["url"].as_str().unwrap_or_default().to_string() }; + let source = &data["preview"]["images"][0]["source"]; + ( post_type.to_string(), Media { url, - width: data["preview"]["images"][0]["source"]["width"].as_i64().unwrap_or_default(), - height: data["preview"]["images"][0]["source"]["height"].as_i64().unwrap_or_default(), - poster: format_url(data["preview"]["images"][0]["source"]["url"].as_str().unwrap_or_default()), + width: source["width"].as_i64().unwrap_or_default(), + height: source["height"].as_i64().unwrap_or_default(), + poster: format_url(source["url"].as_str().unwrap_or_default()), }, gallery, ) } -pub fn parse_rich_flair(flair_type: String, rich_flair: Option<&Vec>, text_flair: Option<&str>) -> Vec { +pub fn parse_rich_flair(flair_type: &str, rich_flair: Option<&Vec>, text_flair: Option<&str>) -> Vec { // Parse type of flair - match flair_type.as_str() { + match flair_type { // If flair contains emojis and text "richtext" => match rich_flair { Some(rich) => rich @@ -318,7 +332,7 @@ pub fn time(created: f64) -> (String, String) { format!("{}m ago", time_delta.whole_minutes()) }; - (rel_time, time.format("%b %d %Y, %H:%M UTC")) + (rel_time, time.format("%b %d %Y, %H:%M:%S UTC")) } // @@ -355,13 +369,15 @@ pub async fn fetch_posts(path: &str, fallback_title: String) -> Result<(Vec Result<(Vec Result<(Vec Result<(Vec{% call utils::render_flair(author.flair.flair_parts) %} {% endif %} {{ rel_time }} + {% if edited.0 != "".to_string() %}edited {{ edited.0 }}{% endif %}
{{ body }}
{% for c in replies -%}{{ c.render().unwrap() }}{%- endfor %}