Parse video data from cross_post_parent_list as vanilla Reddit does.

introduce testdata directory for testing JSON parsing functions.

refactor Media::parse for slightly more readability.

Add various test cases.
This commit is contained in:
mikupls 2021-11-21 15:50:28 +01:00
parent 67d3be06e1
commit 1e9ca3cb55
4 changed files with 77 additions and 11 deletions

View File

@ -113,6 +113,9 @@ pub async fn json(path: String, quarantine: bool) -> Result<Value, String> {
// Build Reddit url from path
let url = format!("https://www.reddit.com{}", path);
#[cfg(debug_assertions)]
println!("{}", url);
// Closure to quickly build errors
let err = |msg: &str, e: String| -> Result<Value, String> {
// eprintln!("{} - {}: {}", url, msg, e);

View File

@ -229,3 +229,38 @@ fn parse_comments(json: &serde_json::Value, post_link: &str, post_author: &str,
})
.collect()
}
#[cfg(test)]
mod tests {
use std::fs::File;
use super::parse_post;
#[tokio::test]
async fn parse_post_works() {
// https://www.reddit.com/r/antiwork/comments/qybiul.json?&sort=confidence&raw_json=1
let testdata = File::open("testdata/cross_post_parent_list.json")
.expect("error reading file");
let post_json: serde_json::Value = serde_json::from_reader(testdata)
.expect("error parsing JSON");
let post = parse_post(&post_json[0]).await;
println!("{:?}", post.media);
assert_eq!(
post.post_type,
"video"
);
assert_ne!(
post.media.url,
""
);
assert_ne!(
post.media.alt_url,
""
);
assert_ne!(
post.media.poster,
""
);
}
}

View File

@ -73,6 +73,7 @@ pub struct Flags {
pub stickied: bool,
}
#[derive(Debug)]
pub struct Media {
pub url: String,
pub alt_url: String,
@ -85,28 +86,41 @@ impl Media {
pub async fn parse(data: &Value) -> (String, Self, Vec<GalleryMedia>) {
let mut gallery = Vec::new();
// Define the various known places that Reddit might put video URLs.
let data_preview = &data["preview"]["reddit_video_preview"];
let secure_media = &data["secure_media"]["reddit_video"];
let crosspost_parent_media = &data["crosspost_parent_list"][0]["secure_media"]["reddit_video"];
// If post is a video, return the video
let (post_type, url_val, alt_url_val) = if data["preview"]["reddit_video_preview"]["fallback_url"].is_string() {
// Return reddit video
let (post_type, url_val, alt_url_val) = if data_preview["fallback_url"].is_string() {
(
if data["preview"]["reddit_video_preview"]["is_gif"].as_bool().unwrap_or(false) {
if data_preview["is_gif"].as_bool().unwrap_or(false) {
"gif"
} else {
"video"
},
&data["preview"]["reddit_video_preview"]["fallback_url"],
Some(&data["preview"]["reddit_video_preview"]["hls_url"]),
&data_preview["fallback_url"],
Some(&data_preview["hls_url"]),
)
} else if data["secure_media"]["reddit_video"]["fallback_url"].is_string() {
// Return reddit video
} else if secure_media["fallback_url"].is_string() {
(
if data["preview"]["reddit_video_preview"]["is_gif"].as_bool().unwrap_or(false) {
if secure_media["is_gif"].as_bool().unwrap_or(false) {
"gif"
} else {
"video"
},
&data["secure_media"]["reddit_video"]["fallback_url"],
Some(&data["secure_media"]["reddit_video"]["hls_url"]),
&secure_media["fallback_url"],
Some(&secure_media["hls_url"]),
)
} else if crosspost_parent_media["fallback_url"].is_string() {
(
if crosspost_parent_media["is_gif"].as_bool().unwrap_or(false) {
"gif"
} else {
"video"
},
&crosspost_parent_media["fallback_url"],
Some(&crosspost_parent_media["hls_url"]),
)
} else if data["post_hint"].as_str().unwrap_or("") == "image" {
// Handle images, whether GIFs or pics
@ -512,7 +526,7 @@ pub fn format_url(url: &str) -> String {
match domain {
"v.redd.it" => chain!(
capture(r"https://v\.redd\.it/(.*)/DASH_([0-9]{2,4}(\.mp4|$))", "/vid/", 2),
capture(r"https://v\.redd\.it/(.*)/DASH_([0-9]{2,4}(\.mp4|$|\?source=fallback))", "/vid/", 2),
capture(r"https://v\.redd\.it/(.+)/(HLSPlaylist\.m3u8.*)$", "/hls/", 2)
),
"i.redd.it" => capture(r"https://i\.redd\.it/(.*)", "/img/", 1),
@ -634,6 +648,7 @@ pub async fn error(req: Request<Body>, msg: String) -> Result<Response<Body>, St
#[cfg(test)]
mod tests {
use super::format_num;
use super::format_url;
#[test]
fn format_num_works() {
@ -658,4 +673,16 @@ mod tests {
("2.0m".to_string(), "1999999".to_string())
);
}
#[test]
fn format_url_works() {
assert_eq!(
format_url("https://v.redd.it/test123/DASH_480?source=fallback"),
"/vid/test123/480?source=fallback"
);
assert_eq!(
format_url("https://v.redd.it/test123/DASH_720.mp4?source=fallback"),
"/vid/test123/720.mp4"
);
}
}

1
testdata/cross_post_parent_list.json vendored Normal file

File diff suppressed because one or more lines are too long