porndish fix

This commit is contained in:
Simon
2026-03-17 00:57:50 +00:00
parent 0d20fc7a7e
commit a977381b3b
4 changed files with 500 additions and 9 deletions

View File

@@ -231,6 +231,10 @@ impl PorndishProvider {
matches!(host, "myvidplay.com" | "www.myvidplay.com")
}
fn is_vidara_host(host: &str) -> bool {
matches!(host, "vidara.so" | "www.vidara.so")
}
fn is_allowed_list_url(url: &str) -> bool {
let Some(url) = Self::parse_url(url) else {
return false;
@@ -294,6 +298,35 @@ impl PorndishProvider {
Self::is_myvidplay_host(host) && url.path().starts_with("/pass_md5/")
}
fn is_allowed_vidara_iframe_url(url: &str) -> bool {
let Some(url) = Self::parse_url(url) else {
return false;
};
if url.scheme() != "https" {
return false;
}
let Some(host) = url.host_str() else {
return false;
};
Self::is_vidara_host(host) && url.path().starts_with("/e/")
}
fn vidara_api_url(iframe_url: &str) -> Option<String> {
let url = Self::parse_url(iframe_url)?;
if !Self::is_allowed_vidara_iframe_url(iframe_url) {
return None;
}
let filecode = url
.path_segments()?
.filter(|segment| !segment.is_empty())
.next_back()?
.to_string();
if filecode.is_empty() {
return None;
}
Some(format!("https://vidara.so/api/stream?filecode={filecode}"))
}
fn proxied_thumb(&self, options: &ServerOptions, thumb: &str) -> String {
if thumb.is_empty() {
return String::new();
@@ -304,6 +337,13 @@ impl PorndishProvider {
build_proxy_url(options, "porndish-thumb", &strip_url_scheme(thumb))
}
fn proxied_video(&self, options: &ServerOptions, page_url: &str) -> String {
if page_url.is_empty() || !Self::is_allowed_detail_url(page_url) {
return String::new();
}
build_proxy_url(options, "porndish", &strip_url_scheme(page_url))
}
fn push_unique(target: &Arc<RwLock<Vec<FilterOption>>>, item: FilterOption) {
if let Ok(mut values) = target.write() {
if !values.iter().any(|value| value.id == item.id) {
@@ -805,6 +845,27 @@ sys.stdout.buffer.write(response.content)
Ok(format!("{base}{suffix}?token={token}&expiry={now}"))
}
async fn resolve_vidara_stream(&self, iframe_url: &str) -> Result<String> {
let api_url = Self::vidara_api_url(iframe_url)
.ok_or_else(|| Error::from(format!("blocked vidara iframe url: {iframe_url}")))?;
let response = Self::fetch_html(&api_url, Some(iframe_url)).await?;
let json: serde_json::Value = serde_json::from_str(&response)
.map_err(|error| Error::from(format!("vidara json parse failed: {error}")))?;
let stream_url = json
.get("streaming_url")
.and_then(|value| value.as_str())
.unwrap_or("")
.trim()
.to_string();
if stream_url.is_empty() || !(stream_url.starts_with("https://") || stream_url.starts_with("http://")) {
return Err(Error::from("vidara stream missing streaming_url".to_string()));
}
Ok(stream_url)
}
fn parse_embed_source(fragment: &str) -> Result<Option<(String, String)>> {
let iframe_regex = Self::regex(r#"(?is)<iframe[^>]+src="([^"]+)"[^>]*>"#)?;
Ok(iframe_regex.captures(fragment).and_then(|captures| {
@@ -947,25 +1008,71 @@ sys.stdout.buffer.write(response.content)
item.tags = Some(tags);
}
let mut fallback_embed: Option<(String, String)> = None;
let mut selected_embed: Option<(String, String)> = None;
for fragment in self.extract_iframe_fragments(html)? {
let Some((embed_html, iframe_url)) = Self::parse_embed_source(&fragment)? else {
continue;
};
let iframe_url = self.normalize_url(&iframe_url);
if Self::is_allowed_vidara_iframe_url(&iframe_url) {
selected_embed = Some((embed_html, iframe_url));
break;
}
if fallback_embed.is_none()
&& (Self::is_allowed_myvidplay_iframe_url(&iframe_url)
|| iframe_url.starts_with("https://"))
{
fallback_embed = Some((embed_html, iframe_url));
}
}
if let Some((embed_html, iframe_url)) = selected_embed.or(fallback_embed) {
item.embed = Some(VideoEmbed {
html: embed_html,
source: iframe_url.clone(),
});
if iframe_url.contains("myvidplay.com") {
let proxy_url = self.proxied_video(options, page_url);
if Self::is_allowed_vidara_iframe_url(&iframe_url) {
match self.resolve_vidara_stream(&iframe_url).await {
Ok(_stream_url) => {
if !proxy_url.is_empty() {
item.url = proxy_url.clone();
item.formats = Some(vec![VideoFormat::new(
proxy_url,
"sd".to_string(),
"m3u8".to_string(),
)]);
} else {
item.url = page_url.to_string();
}
}
Err(error) => {
report_provider_error_background(
"porndish",
"resolve_vidara_stream",
&format!("iframe_url={iframe_url}; error={error}"),
);
item.url = page_url.to_string();
}
}
} else if Self::is_allowed_myvidplay_iframe_url(&iframe_url) {
match self.resolve_myvidplay_stream(&iframe_url).await {
Ok(stream_url) => {
item.url = stream_url.clone();
let mut format =
VideoFormat::new(stream_url.clone(), "sd".to_string(), "mp4".to_string());
format.add_http_header("Referer".to_string(), iframe_url.clone());
item.formats = Some(vec![format]);
Ok(_stream_url) => {
if !proxy_url.is_empty() {
item.url = proxy_url.clone();
item.formats = Some(vec![VideoFormat::new(
proxy_url,
"sd".to_string(),
"mp4".to_string(),
)]);
} else {
item.url = page_url.to_string();
}
}
Err(error) => {
report_provider_error_background(
@@ -979,8 +1086,6 @@ sys.stdout.buffer.write(response.content)
} else {
item.url = iframe_url;
}
break;
}
if item.formats.is_none() && item.url != page_url {
@@ -1286,6 +1391,9 @@ mod tests {
assert!(PorndishProvider::is_allowed_myvidplay_pass_url(
"https://myvidplay.com/pass_md5/abc/def"
));
assert!(PorndishProvider::is_allowed_vidara_iframe_url(
"https://vidara.so/e/abc123"
));
assert!(!PorndishProvider::is_allowed_list_url(
"https://169.254.169.254/latest/meta-data/"
@@ -1299,5 +1407,8 @@ mod tests {
assert!(!PorndishProvider::is_allowed_myvidplay_pass_url(
"https://example.com/pass_md5/abc/def"
));
assert!(!PorndishProvider::is_allowed_vidara_iframe_url(
"https://example.com/e/abc123"
));
}
}