diff --git a/Cargo.lock b/Cargo.lock index a6a07de..aee8fe5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -130,9 +130,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "1.5.1" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59740d83946db6a5af71ae25ddf9562c2b176b2ca42cf99a455f09f4a220d6b9" +checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" dependencies = [ "concurrent-queue", "event-listener", @@ -194,7 +194,7 @@ dependencies = [ "httparse", "lazy_static", "log", - "pin-project 1.0.5", + "pin-project", ] [[package]] @@ -395,9 +395,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.6.0" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099e596ef14349721d9016f6b80dd3419ea1bf289ab9b44df8e4dfd3a005d5d9" +checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" [[package]] name = "byte-pool" @@ -999,9 +999,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de910d521f7cc3135c4de8db1cb910e0b5ed1dc6f57c381cd07e8e661ce10094" +checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21" dependencies = [ "matches", "unicode-bidi", @@ -1263,33 +1263,13 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" -[[package]] -name = "pin-project" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffbc8e94b38ea3d2d8ba92aea2983b503cd75d0888d75b86bb37970b5698e15" -dependencies = [ - "pin-project-internal 0.4.27", -] - [[package]] name = "pin-project" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96fa8ebb90271c4477f144354485b8068bd8f6b78b428b01ba892ca26caf0b63" dependencies = [ - "pin-project-internal 1.0.5", -] - -[[package]] -name = "pin-project-internal" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "pin-project-internal", ] [[package]] @@ -1884,9 +1864,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d40a22fd029e33300d8d89a5cc8ffce18bb7c587662f54629e94c9de5487f3" +checksum = "f77d3842f76ca899ff2dbcf231c5c65813dea431301d6eb686279c15c4464f12" dependencies = [ "cfg-if 1.0.0", "log", @@ -1897,9 +1877,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f080ea7e4107844ef4766459426fa2d5c1ada2e47edba05dc7fa99d9629f47" +checksum = "a8a9bd1db7706f2373a190b0d067146caa39350c486f3d455b0e33b431f94c07" dependencies = [ "proc-macro2", "quote", @@ -1917,11 +1897,11 @@ dependencies = [ [[package]] name = "tracing-futures" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ - "pin-project 0.4.27", + "pin-project", "tracing", ] diff --git a/src/main.rs b/src/main.rs index 15a19d6..44b0b2b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -146,6 +146,8 @@ async fn main() -> tide::Result<()> { // Proxy media through Libreddit app.at("/proxy/*url/").get(proxy::handler); + app.at("/vid/:id/:size/").get(proxy::video); + app.at("/img/:id/").get(proxy::image); // Browse user profile app.at("/u/:name/").get(user::profile); diff --git a/src/post.rs b/src/post.rs index 2e3d53d..397f1ac 100644 --- a/src/post.rs +++ b/src/post.rs @@ -165,7 +165,7 @@ async fn parse_comments(json: &serde_json::Value, post_link: &str, post_author: }; let parent_kind_and_id = val(&comment, "parent_id"); - let parent_info = parent_kind_and_id.split("_").collect::>(); + let parent_info = parent_kind_and_id.split('_').collect::>(); let id = val(&comment, "id"); let highlighted = id == highlighted_comment; diff --git a/src/proxy.rs b/src/proxy.rs index 31300de..3fd656e 100644 --- a/src/proxy.rs +++ b/src/proxy.rs @@ -17,7 +17,6 @@ pub async fn handler(req: Request<()>) -> tide::Result { "external-preview.redd.it", // MEDIA "i.redd.it", - "v.redd.it", ]; let decoded = decode(req.param("url").unwrap_or_default()).map(|bytes| String::from_utf8(bytes).unwrap_or_default()); @@ -26,19 +25,7 @@ pub async fn handler(req: Request<()>) -> tide::Result { Ok(media) => match Url::parse(media.as_str()) { Ok(url) => { if domains.contains(&url.domain().unwrap_or_default()) { - let http = surf::get(url).await.unwrap(); - - let content_length = http.header("Content-Length").map(|v| v.to_string()).unwrap_or_default(); - let content_type = http.content_type().map(|m| m.to_string()).unwrap_or_default(); - - Ok( - Response::builder(http.status()) - .body(Body::from_reader(http, None)) - .header("Cache-Control", "public, max-age=1209600, s-maxage=86400") - .header("Content-Length", content_length) - .header("Content-Type", content_type) - .build(), - ) + request(url.to_string()).await } else { Err(tide::Error::from_str(403, "Resource must be from Reddit")) } @@ -48,3 +35,32 @@ pub async fn handler(req: Request<()>) -> tide::Result { Err(_) => Err(tide::Error::from_str(400, "Can't decode base64")), } } + +pub async fn video(req: Request<()>) -> tide::Result { + let id = req.param("id").unwrap_or_default(); + let size = req.param("size").unwrap_or("720.mp4"); + let url = format!("https://v.redd.it/{}/DASH_{}", id, size); + request(url).await +} + +pub async fn image(req: Request<()>) -> tide::Result { + let id = req.param("id").unwrap_or_default(); + let url = format!("https://i.redd.it/{}", id); + request(url).await +} + +async fn request(url: String) -> tide::Result { + let http = surf::get(url).await.unwrap(); + + let content_length = http.header("Content-Length").map(|v| v.to_string()).unwrap_or_default(); + let content_type = http.content_type().map(|m| m.to_string()).unwrap_or_default(); + + Ok( + Response::builder(http.status()) + .body(Body::from_reader(http, None)) + .header("Cache-Control", "public, max-age=1209600, s-maxage=86400") + .header("Content-Length", content_length) + .header("Content-Type", content_type) + .build(), + ) +} diff --git a/src/utils.rs b/src/utils.rs index 3a97adf..922f9ef 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -186,13 +186,28 @@ pub fn format_url(url: &str) -> String { if url.is_empty() || url == "self" || url == "default" || url == "nsfw" || url == "spoiler" { String::new() } else { - format!("/proxy/{}/", encode(url).as_str()) + let domain = Url::parse(url).map(|f| f.domain().unwrap_or_default().to_owned()).unwrap_or_default(); + + match domain.as_str() { + "v.redd.it" => { + let re = Regex::new(r"https://v\.redd\.it/(.*)/DASH_([0-9]{2,4}(\.mp4|$))").unwrap(); + + match re.captures(url) { + Some(caps) => format!("/vid/{}/{}", &caps[1], &caps[2]), + None => { + dbg!(url); + String::new() + } + } + } + _ => format!("/proxy/{}/", encode(url).as_str()), + } } } // Rewrite Reddit links to Libreddit in body of text pub fn rewrite_urls(text: &str) -> String { - let re = Regex::new(r#"href="(https://|http://|)(www.|old.|np.|)(reddit).(com)/"#).unwrap(); + let re = Regex::new(r#"href="(https|http|)://(www.|old.|np.|)(reddit).(com)/"#).unwrap(); re.replace_all(text, r#"href="/"#).to_string() } @@ -208,12 +223,12 @@ pub fn format_num(num: i64) -> String { } pub async fn media(data: &Value) -> (String, Media, Vec) { - let post_type: &str; + let post_type; 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 + // Return reddit video 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() {