This commit is contained in:
Simon
2026-03-23 11:32:22 +00:00
parent 9021521c00
commit 90ce9c684b
4 changed files with 350 additions and 14 deletions

View File

@@ -1,7 +1,8 @@
use crate::DbPool;
use crate::api::ClientVersion;
use crate::providers::{
Provider, report_provider_error, report_provider_error_background, requester_or_default,
Provider, build_proxy_url, report_provider_error, report_provider_error_background,
requester_or_default, strip_url_scheme,
};
use crate::status::*;
use crate::util::cache::VideoCache;
@@ -395,6 +396,39 @@ impl Pornhd3xProvider {
.map(|value| value.id.clone())
}
fn is_allowed_detail_url(&self, value: &str) -> bool {
let normalized = self.normalize_url(value);
let Some(url) = Url::parse(&normalized).ok() else {
return false;
};
if url.scheme() != "https" {
return false;
}
let Some(host) = url.host_str() else {
return false;
};
(host == "www.pornhd3x.tv" || host == "pornhd3x.tv") && url.path().starts_with("/movies/")
}
fn proxied_video(
&self,
options: &ServerOptions,
detail_url: &str,
quality: Option<&str>,
) -> String {
if detail_url.is_empty() || !self.is_allowed_detail_url(detail_url) {
return detail_url.to_string();
}
let mut target = strip_url_scheme(detail_url);
if let Some(quality) = quality.map(str::trim).filter(|quality| !quality.is_empty()) {
target.push_str("/__quality__/");
target.push_str(&quality.replace(' ', "%20"));
}
build_proxy_url(options, CHANNEL_ID, &target)
}
fn filters_need_refresh(&self) -> bool {
let categories_len = self
.categories
@@ -967,7 +1001,12 @@ impl Pornhd3xProvider {
Ok(serde_json::from_str::<Value>(&response)?)
}
fn build_formats(&self, value: &Value) -> Vec<VideoFormat> {
fn build_formats(
&self,
value: &Value,
options: &ServerOptions,
detail_url: &str,
) -> Vec<VideoFormat> {
let mut formats = Vec::new();
for playlist in value
.get("playlist")
@@ -994,7 +1033,8 @@ impl Pornhd3xProvider {
.unwrap_or("HLS")
.to_string();
let format_name = if url.contains(".m3u8") { "hls" } else { "mp4" };
let format = VideoFormat::new(url, quality.clone(), format_name.to_string())
let format_url = self.proxied_video(options, detail_url, Some(&quality));
let format = VideoFormat::new(format_url, quality.clone(), format_name.to_string())
.format_id(quality.to_ascii_lowercase())
.format_note(quality);
formats.push(format);
@@ -1035,17 +1075,22 @@ impl Pornhd3xProvider {
}
};
let mut formats = self.build_formats(&source_payload);
let direct_url = formats
.first()
.map(|format| format.url.clone())
.or_else(|| {
source_payload
.get("embed_url")
.or_else(|| source_payload.get("embedUrl"))
.and_then(|value| value.as_str())
.map(|value| self.normalize_url(value))
});
let mut formats = self.build_formats(&source_payload, options, &stub.detail_url);
let proxied_url = self.proxied_video(options, &stub.detail_url, None);
let direct_url = if !proxied_url.is_empty() {
Some(proxied_url)
} else {
formats
.first()
.map(|format| format.url.clone())
.or_else(|| {
source_payload
.get("embed_url")
.or_else(|| source_payload.get("embedUrl"))
.and_then(|value| value.as_str())
.map(|value| self.normalize_url(value))
})
};
let Some(url) = direct_url else {
return Ok(None);
@@ -1295,4 +1340,41 @@ mod tests {
.is_some()
);
}
#[test]
fn builds_proxied_video_urls() {
let provider = Pornhd3xProvider::new_for_tests();
let options = ServerOptions {
featured: None,
category: None,
sites: None,
filter: None,
language: None,
public_url_base: Some("https://example.com".to_string()),
requester: None,
network: None,
stars: None,
categories: None,
duration: None,
sort: None,
sexuality: None,
};
assert_eq!(
provider.proxied_video(
&options,
"https://www.pornhd3x.tv/movies/example-video",
None,
),
"https://example.com/proxy/pornhd3x/www.pornhd3x.tv/movies/example-video"
);
assert_eq!(
provider.proxied_video(
&options,
"https://www.pornhd3x.tv/movies/example-video",
Some("720p"),
),
"https://example.com/proxy/pornhd3x/www.pornhd3x.tv/movies/example-video/__quality__/720p"
);
}
}