Individually proxy videos

This commit is contained in:
spikecodes 2021-02-18 10:04:59 -08:00
parent 2f4deb221a
commit 58127b17d8
No known key found for this signature in database
GPG Key ID: 004CECFF9B463BCB
5 changed files with 67 additions and 54 deletions

50
Cargo.lock generated
View File

@ -130,9 +130,9 @@ dependencies = [
[[package]] [[package]]
name = "async-channel" name = "async-channel"
version = "1.5.1" version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59740d83946db6a5af71ae25ddf9562c2b176b2ca42cf99a455f09f4a220d6b9" checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319"
dependencies = [ dependencies = [
"concurrent-queue", "concurrent-queue",
"event-listener", "event-listener",
@ -194,7 +194,7 @@ dependencies = [
"httparse", "httparse",
"lazy_static", "lazy_static",
"log", "log",
"pin-project 1.0.5", "pin-project",
] ]
[[package]] [[package]]
@ -395,9 +395,9 @@ dependencies = [
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.6.0" version = "3.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "099e596ef14349721d9016f6b80dd3419ea1bf289ab9b44df8e4dfd3a005d5d9" checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
[[package]] [[package]]
name = "byte-pool" name = "byte-pool"
@ -999,9 +999,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]] [[package]]
name = "idna" name = "idna"
version = "0.2.1" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de910d521f7cc3135c4de8db1cb910e0b5ed1dc6f57c381cd07e8e661ce10094" checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21"
dependencies = [ dependencies = [
"matches", "matches",
"unicode-bidi", "unicode-bidi",
@ -1263,33 +1263,13 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 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]] [[package]]
name = "pin-project" name = "pin-project"
version = "1.0.5" version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96fa8ebb90271c4477f144354485b8068bd8f6b78b428b01ba892ca26caf0b63" checksum = "96fa8ebb90271c4477f144354485b8068bd8f6b78b428b01ba892ca26caf0b63"
dependencies = [ dependencies = [
"pin-project-internal 1.0.5", "pin-project-internal",
]
[[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",
] ]
[[package]] [[package]]
@ -1884,9 +1864,9 @@ dependencies = [
[[package]] [[package]]
name = "tracing" name = "tracing"
version = "0.1.23" version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d40a22fd029e33300d8d89a5cc8ffce18bb7c587662f54629e94c9de5487f3" checksum = "f77d3842f76ca899ff2dbcf231c5c65813dea431301d6eb686279c15c4464f12"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"log", "log",
@ -1897,9 +1877,9 @@ dependencies = [
[[package]] [[package]]
name = "tracing-attributes" name = "tracing-attributes"
version = "0.1.12" version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43f080ea7e4107844ef4766459426fa2d5c1ada2e47edba05dc7fa99d9629f47" checksum = "a8a9bd1db7706f2373a190b0d067146caa39350c486f3d455b0e33b431f94c07"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1917,11 +1897,11 @@ dependencies = [
[[package]] [[package]]
name = "tracing-futures" name = "tracing-futures"
version = "0.2.4" version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c" checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
dependencies = [ dependencies = [
"pin-project 0.4.27", "pin-project",
"tracing", "tracing",
] ]

View File

@ -146,6 +146,8 @@ async fn main() -> tide::Result<()> {
// Proxy media through Libreddit // Proxy media through Libreddit
app.at("/proxy/*url/").get(proxy::handler); 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 // Browse user profile
app.at("/u/:name/").get(user::profile); app.at("/u/:name/").get(user::profile);

View File

@ -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_kind_and_id = val(&comment, "parent_id");
let parent_info = parent_kind_and_id.split("_").collect::<Vec<&str>>(); let parent_info = parent_kind_and_id.split('_').collect::<Vec<&str>>();
let id = val(&comment, "id"); let id = val(&comment, "id");
let highlighted = id == highlighted_comment; let highlighted = id == highlighted_comment;

View File

@ -17,7 +17,6 @@ pub async fn handler(req: Request<()>) -> tide::Result {
"external-preview.redd.it", "external-preview.redd.it",
// MEDIA // MEDIA
"i.redd.it", "i.redd.it",
"v.redd.it",
]; ];
let decoded = decode(req.param("url").unwrap_or_default()).map(|bytes| String::from_utf8(bytes).unwrap_or_default()); 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(media) => match Url::parse(media.as_str()) {
Ok(url) => { Ok(url) => {
if domains.contains(&url.domain().unwrap_or_default()) { if domains.contains(&url.domain().unwrap_or_default()) {
let http = surf::get(url).await.unwrap(); request(url.to_string()).await
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(),
)
} else { } else {
Err(tide::Error::from_str(403, "Resource must be from Reddit")) 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")), 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(),
)
}

View File

@ -186,13 +186,28 @@ pub fn format_url(url: &str) -> String {
if url.is_empty() || url == "self" || url == "default" || url == "nsfw" || url == "spoiler" { if url.is_empty() || url == "self" || url == "default" || url == "nsfw" || url == "spoiler" {
String::new() String::new()
} else { } 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 // Rewrite Reddit links to Libreddit in body of text
pub fn rewrite_urls(text: &str) -> String { 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() 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<GalleryMedia>) { pub async fn media(data: &Value) -> (String, Media, Vec<GalleryMedia>) {
let post_type: &str; let post_type;
let mut gallery = Vec::new(); let mut gallery = Vec::new();
// If post is a video, return the video // If post is a video, return the video
let url = if data["preview"]["reddit_video_preview"]["fallback_url"].is_string() { let url = if data["preview"]["reddit_video_preview"]["fallback_url"].is_string() {
// Return video preview // Return reddit video
post_type = "video"; post_type = "video";
format_url(data["preview"]["reddit_video_preview"]["fallback_url"].as_str().unwrap_or_default()) 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() { } else if data["secure_media"]["reddit_video"]["fallback_url"].is_string() {