Add fullporner provider with xiaoshenke proxy
- Implement fullporner.com provider with search, pagination, categories, pornstars - Add xiaoshenke.net proxy for Cloudflare-protected embed videos - Proxy fetches signed URLs via FlareSolverr and streams video content - Fix quality bitmask mapping (1=360p, 2=480p, 4=720p, 8=1080p) - Support HEAD/GET/Range for video streaming Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -25,14 +25,14 @@ type AnyErr = Box<dyn std::error::Error + Send + Sync + 'static>;
|
||||
#[derive(serde::Serialize, serde::Deserialize, Clone)]
|
||||
pub struct Requester {
|
||||
#[serde(skip)]
|
||||
client: Client,
|
||||
pub(crate) client: Client,
|
||||
#[serde(skip)]
|
||||
cookie_jar: Arc<Jar>,
|
||||
pub(crate) cookie_jar: Arc<Jar>,
|
||||
#[serde(skip)]
|
||||
debug_trace_id: Option<String>,
|
||||
proxy: bool,
|
||||
pub(crate) debug_trace_id: Option<String>,
|
||||
pub(crate) proxy: bool,
|
||||
flaresolverr_session: Option<String>,
|
||||
user_agent: Option<String>,
|
||||
pub(crate) user_agent: Option<String>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Requester {
|
||||
@@ -75,7 +75,7 @@ impl Requester {
|
||||
.map(|host| host.trim_start_matches("www.").to_ascii_lowercase())
|
||||
}
|
||||
|
||||
fn remember_flaresolverr_user_agent(url: &str, user_agent: &str) {
|
||||
pub(crate) fn remember_flaresolverr_user_agent(url: &str, user_agent: &str) {
|
||||
if user_agent.is_empty() {
|
||||
return;
|
||||
}
|
||||
@@ -155,7 +155,7 @@ impl Requester {
|
||||
default.clone()
|
||||
}
|
||||
|
||||
fn store_flaresolverr_cookies(
|
||||
pub(crate) fn store_flaresolverr_cookies(
|
||||
&mut self,
|
||||
request_url: &str,
|
||||
cookies: &[crate::util::flaresolverr::FlaresolverrCookie],
|
||||
@@ -280,7 +280,7 @@ impl Requester {
|
||||
.unwrap_or_else(|| "none".to_string())
|
||||
}
|
||||
|
||||
fn build_client(cookie_jar: Arc<Jar>, user_agent: Option<&str>) -> Client {
|
||||
pub(crate) fn build_client(cookie_jar: Arc<Jar>, user_agent: Option<&str>) -> Client {
|
||||
let mut builder = Client::builder()
|
||||
.tls_cert_verification(false)
|
||||
.emulation(Emulation::Firefox151)
|
||||
@@ -427,12 +427,66 @@ impl Requester {
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
/// Like [`get_raw_with_headers`], but disables redirect-following so a 3xx response's
|
||||
/// `Location` header can be inspected directly.
|
||||
pub async fn get_no_redirect_raw_with_headers(
|
||||
&mut self,
|
||||
url: &str,
|
||||
headers: Vec<(String, String)>,
|
||||
) -> Result<Response, wreq::Error> {
|
||||
self.adopt_remembered_identity(url);
|
||||
let cookie_preview = self
|
||||
.cookie_header_for_url(url)
|
||||
.map(|cookie| crate::util::flow_debug::preview(&cookie, 160))
|
||||
.unwrap_or_else(|| "none".to_string());
|
||||
#[cfg(not(feature = "debug"))]
|
||||
let _ = &cookie_preview;
|
||||
crate::flow_debug!(
|
||||
"trace={} requester get_no_redirect_raw_with_headers url={} headers={} cookies={} proxy={}",
|
||||
self.debug_trace_id().unwrap_or("none"),
|
||||
crate::util::flow_debug::preview(url, 120),
|
||||
headers.len(),
|
||||
cookie_preview,
|
||||
self.proxy
|
||||
);
|
||||
let mut builder = Client::builder()
|
||||
.tls_cert_verification(false)
|
||||
.emulation(Emulation::Firefox151)
|
||||
.cookie_provider(self.cookie_jar.clone())
|
||||
.redirect(Policy::none());
|
||||
if let Some(user_agent) = self.user_agent.as_deref() {
|
||||
let mut hdrs = HeaderMap::new();
|
||||
if let Ok(value) = HeaderValue::from_str(user_agent) {
|
||||
hdrs.insert(USER_AGENT, value);
|
||||
builder = builder.default_headers(hdrs);
|
||||
}
|
||||
}
|
||||
let client = builder.build().expect("Failed to create HTTP client");
|
||||
|
||||
let mut request = client.get(url).version(Version::HTTP_11);
|
||||
|
||||
if self.proxy {
|
||||
if let Ok(proxy_url) = env::var("BURP_URL") {
|
||||
let proxy = Proxy::all(&proxy_url).unwrap();
|
||||
request = request.proxy(proxy);
|
||||
}
|
||||
}
|
||||
// Set custom headers
|
||||
for (key, value) in headers.iter() {
|
||||
request = request.header(key, value);
|
||||
}
|
||||
|
||||
let response = request.send().await?;
|
||||
self.store_response_cookies(url, &response);
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
pub async fn get_raw_with_headers(
|
||||
&mut self,
|
||||
url: &str,
|
||||
headers: Vec<(String, String)>,
|
||||
) -> Result<Response, wreq::Error> {
|
||||
self.get_raw_with_headers_timeout(url, headers, None).await
|
||||
self.get_raw_with_headers_timeout(url, headers, None, None).await
|
||||
}
|
||||
|
||||
pub async fn get_raw_with_headers_timeout(
|
||||
@@ -440,21 +494,28 @@ impl Requester {
|
||||
url: &str,
|
||||
headers: Vec<(String, String)>,
|
||||
timeout: Option<Duration>,
|
||||
http_version: Option<Version>,
|
||||
) -> Result<Response, wreq::Error> {
|
||||
let cookie_preview = self.debug_cookie_preview_from_owned_headers(url, &headers);
|
||||
#[cfg(not(feature = "debug"))]
|
||||
let _ = &cookie_preview;
|
||||
crate::flow_debug!(
|
||||
"trace={} requester get_raw_with_headers url={} headers={} cookies={} proxy={}",
|
||||
"trace={} requester get_raw_with_headers url={} headers={} cookies={} http_version={:?} proxy={}",
|
||||
self.debug_trace_id().unwrap_or("none"),
|
||||
crate::util::flow_debug::preview(url, 120),
|
||||
headers.len(),
|
||||
cookie_preview,
|
||||
http_version,
|
||||
self.proxy
|
||||
);
|
||||
let client = Self::build_client(self.cookie_jar.clone(), self.user_agent.as_deref());
|
||||
|
||||
let mut request = client.get(url).version(Version::HTTP_11);
|
||||
let mut request = client.get(url);
|
||||
if let Some(version) = http_version {
|
||||
request = request.version(version);
|
||||
} else {
|
||||
request = request.version(Version::HTTP_11);
|
||||
}
|
||||
if let Some(timeout) = timeout {
|
||||
request = request.timeout(timeout);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user