feat(downloader): route terabox via local Playwright resolver
Deploy Scraper / build-and-deploy (push) Canceled after 0s
Deploy Scraper / build-and-deploy (push) Canceled after 0s
Replace dead tera2.sylyt93.workers.dev (NXDOMAIN) with a local terabox-resolver service (systemd, :4092) that uses Playwright + residential proxy + user cookies to resolve TeraBox share links end-to-end to real signed dlink. Proven path: navigate terabox.app directly, duplicate cookies across .terabox.app domains, call /share/list from browser context. Supports directories (child files).
This commit is contained in:
@@ -2804,55 +2804,94 @@ pub async fn fetch_terabox(url: &str) -> Result<DownloadResult, ScrapingError> {
|
||||
|
||||
let surl = surl.ok_or_else(|| ScrapingError::Http("SURL not found.".to_string()))?;
|
||||
|
||||
// Call local TeraBox resolver (Playwright + residential proxy + cookies)
|
||||
let resolver_url = std::env::var("TERABOX_RESOLVER_URL")
|
||||
.unwrap_or_else(|_| "http://127.0.0.1:4092".to_string());
|
||||
let resolve_url = format!("{}/resolve?surl={}", resolver_url, surl);
|
||||
|
||||
let client = http_client();
|
||||
let resp = client
|
||||
.client()
|
||||
.get("https://tera2.sylyt93.workers.dev/info")
|
||||
.query(&[("s", &surl)])
|
||||
.header("origin", "https://www.kauruka.com")
|
||||
.header("referer", "https://www.kauruka.com/")
|
||||
.get(&resolve_url)
|
||||
.header(USER_AGENT, "Mozilla/5.0")
|
||||
.timeout(Duration::from_secs(15))
|
||||
.timeout(Duration::from_secs(60))
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| ScrapingError::Http(format!("TeraBox info fetch failed: {}", e)))?
|
||||
.json::<serde_json::Value>()
|
||||
.await
|
||||
.map_err(|e| ScrapingError::Http(format!("TeraBox JSON parse failed: {}", e)))?;
|
||||
.map_err(|e| ScrapingError::Http(format!("TeraBox resolver fetch failed: {}", e)))?;
|
||||
|
||||
if let Some(download_url) = resp.get("url").and_then(|v| v.as_str()) {
|
||||
let mut result = DownloadResult::success(
|
||||
resp.get("name")
|
||||
.and_then(|v| v.as_str())
|
||||
.map(|s| s.to_string()),
|
||||
);
|
||||
result.provider = Some("terabox".to_string());
|
||||
result.thumbnail = resp
|
||||
.get("img")
|
||||
if !resp.status().is_success() {
|
||||
let status = resp.status();
|
||||
let body = resp.text().await.unwrap_or_default();
|
||||
return Ok(DownloadResult::error(format!(
|
||||
"TeraBox resolver returned HTTP {}: {}",
|
||||
status, body
|
||||
)));
|
||||
}
|
||||
|
||||
let data: serde_json::Value = resp
|
||||
.json()
|
||||
.await
|
||||
.map_err(|e| ScrapingError::Http(format!("TeraBox resolver JSON parse failed: {}", e)))?;
|
||||
|
||||
if let Some(error) = data.get("error").and_then(|v| v.as_str()) {
|
||||
return Ok(DownloadResult::error(error));
|
||||
}
|
||||
|
||||
let file_name = data
|
||||
.get("file_name")
|
||||
.and_then(|v| v.as_str())
|
||||
.map(|s| s.to_string());
|
||||
|
||||
let mut result = DownloadResult::success(file_name.clone());
|
||||
result.provider = Some("terabox".to_string());
|
||||
result.thumbnail = data
|
||||
.get("thumbnail")
|
||||
.and_then(|v| v.as_str())
|
||||
.map(|s| s.to_string());
|
||||
|
||||
// Primary download link
|
||||
if let Some(download_url) = data.get("download_link").and_then(|v| v.as_str()) {
|
||||
let size_bytes = data.get("file_size").and_then(|v| v.as_u64()).unwrap_or(0);
|
||||
|
||||
result.media.push(MediaItem {
|
||||
url: download_url.to_string(),
|
||||
quality: None,
|
||||
file_type: Some(MediaType::File),
|
||||
extension: None,
|
||||
thumbnail: None,
|
||||
file_size: None,
|
||||
size_bytes: None,
|
||||
file_size: Some(format_filesize(size_bytes)),
|
||||
size_bytes: Some(size_bytes),
|
||||
frame_width: None,
|
||||
frame_height: None,
|
||||
note: None,
|
||||
});
|
||||
|
||||
Ok(result)
|
||||
} else {
|
||||
Ok(DownloadResult::error(
|
||||
resp.get("error")
|
||||
// Directory: add child file links
|
||||
if let Some(files) = data.get("files").and_then(|v| v.as_array()) {
|
||||
for f in files {
|
||||
if let Some(furl) = f.get("download_link").and_then(|v| v.as_str()) {
|
||||
let fsize = f.get("file_size").and_then(|v| v.as_u64()).unwrap_or(0);
|
||||
result.media.push(MediaItem {
|
||||
url: furl.to_string(),
|
||||
quality: None,
|
||||
file_type: Some(MediaType::File),
|
||||
extension: None,
|
||||
thumbnail: None,
|
||||
file_size: Some(format_filesize(fsize)),
|
||||
size_bytes: Some(fsize),
|
||||
frame_width: None,
|
||||
frame_height: None,
|
||||
note: f
|
||||
.get("file_name")
|
||||
.and_then(|v| v.as_str())
|
||||
.unwrap_or("Failed to fetch TeraBox info"),
|
||||
))
|
||||
.map(|s| s.to_string()),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub async fn fetch_videy(url: &str) -> Result<DownloadResult, ScrapingError> {
|
||||
|
||||
Reference in New Issue
Block a user