shooshtime fix

This commit is contained in:
Simon
2026-03-23 13:46:55 +00:00
parent 90ce9c684b
commit 99fe4c947c
5 changed files with 417 additions and 11 deletions

View File

@@ -1,6 +1,9 @@
use crate::DbPool;
use crate::api::ClientVersion;
use crate::providers::{Provider, report_provider_error, report_provider_error_background};
use crate::providers::{
Provider, build_proxy_url, report_provider_error, report_provider_error_background,
strip_url_scheme,
};
use crate::status::*;
use crate::util::cache::VideoCache;
use crate::util::parse_abbreviated_number;
@@ -16,6 +19,7 @@ use regex::Regex;
use scraper::{ElementRef, Html, Selector};
use std::sync::{Arc, RwLock};
use std::{thread, vec};
use url::Url;
pub const CHANNEL_METADATA: crate::providers::ProviderChannelMetadata =
crate::providers::ProviderChannelMetadata {
@@ -608,6 +612,41 @@ impl ShooshtimeProvider {
}
}
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 == "shooshtime.com" || host == "www.shooshtime.com")
&& url.path().starts_with("/videos/")
}
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 = target.trim_end_matches('/').to_string();
target.push_str("/__quality__/");
target.push_str(&quality.replace(' ', "%20"));
}
build_proxy_url(options, "shooshtime", &target)
}
fn search_sort_param(sort: &str) -> Option<&'static str> {
match Self::normalize_sort(sort) {
"viewed" => Some("video_viewed"),
@@ -906,6 +945,7 @@ impl ShooshtimeProvider {
mut item: VideoItem,
html: &str,
page_url: &str,
options: &ServerOptions,
) -> Result<VideoItem> {
let flashvars_regex = Self::regex(r#"(?s)var\s+flashvars\s*=\s*\{(.*?)\};"#)?;
let value_regex = |key: &str| Self::regex(&format!(r#"{key}:\s*'([^']*)'"#));
@@ -935,17 +975,17 @@ impl ShooshtimeProvider {
let mut formats = Vec::new();
if let Some(url) = &primary_url {
let format_url = self.proxied_video(options, page_url, Some(&primary_quality));
formats.push(
VideoFormat::new(url.clone(), primary_quality.clone(), "mp4".to_string())
.format_id(primary_quality.clone())
.http_header("Referer".to_string(), page_url.to_string()),
VideoFormat::new(format_url, primary_quality.clone(), "mp4".to_string())
.format_id(primary_quality.clone()),
);
}
if let Some(url) = &alt_url {
let format_url = self.proxied_video(options, page_url, Some(&alt_quality));
formats.push(
VideoFormat::new(url.clone(), alt_quality.clone(), "mp4".to_string())
.format_id(alt_quality.clone())
.http_header("Referer".to_string(), page_url.to_string()),
VideoFormat::new(format_url, alt_quality.clone(), "mp4".to_string())
.format_id(alt_quality.clone()),
);
}
@@ -1115,6 +1155,10 @@ impl ShooshtimeProvider {
if let Some(title) = title {
item.title = title;
}
let proxied_url = self.proxied_video(options, page_url, None);
if !proxied_url.is_empty() {
item.url = proxied_url;
}
if !formats.is_empty() {
item = item.formats(formats);
}
@@ -1134,7 +1178,7 @@ impl ShooshtimeProvider {
item = item.uploader_url(uploader_url);
}
if !tags.is_empty() {
item = item.tags(tags);
item.tags = Some(tags);
}
if item.preview.is_none() {
if let Some(preview) = preview_url.as_ref() {
@@ -1171,7 +1215,7 @@ impl ShooshtimeProvider {
}
};
match self.apply_detail_video(item, &html, &page_url) {
match self.apply_detail_video(item, &html, &page_url, options) {
Ok(item) => item,
Err(error) => {
report_provider_error_background(
@@ -1328,7 +1372,26 @@ mod tests {
"#;
let enriched = provider
.apply_detail_video(item, html, "https://shooshtime.com/videos/example/123/")
.apply_detail_video(
item,
html,
"https://shooshtime.com/videos/example/123/",
&crate::videos::ServerOptions {
featured: None,
category: None,
sites: None,
filter: None,
language: None,
public_url_base: None,
requester: None,
network: None,
stars: None,
categories: None,
duration: None,
sort: None,
sexuality: None,
},
)
.unwrap();
assert_eq!(enriched.thumb, "https://shooshtime.com/list-thumb.jpg");
@@ -1337,4 +1400,37 @@ mod tests {
Some("https://shooshtime.com/detail-thumb.jpg")
);
}
#[test]
fn builds_proxied_video_urls() {
let provider = ShooshtimeProvider::new();
let options = crate::videos::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://shooshtime.com/videos/example/123/", None,),
"https://example.com/proxy/shooshtime/shooshtime.com/videos/example/123/"
);
assert_eq!(
provider.proxied_video(
&options,
"https://shooshtime.com/videos/example/123/",
Some("720p"),
),
"https://example.com/proxy/shooshtime/shooshtime.com/videos/example/123/__quality__/720p"
);
}
}