feat: add anti-detect functionality

This commit is contained in:
zhom
2025-07-07 06:19:43 +04:00
parent 198046fca9
commit 703ca2c50b
30 changed files with 5844 additions and 759 deletions
+194
View File
@@ -259,6 +259,14 @@ pub fn is_browser_version_nightly(
// Chromium builds are generally stable snapshots
false
}
"camoufox" => {
// For Camoufox, all releases are generally stable unless marked as prerelease
if let Some(name) = release_name {
name.to_lowercase().contains("alpha")
} else {
false
}
}
_ => {
// Default fallback
is_nightly_version(version)
@@ -856,6 +864,31 @@ impl ApiClient {
}
/// Check if a Brave release has compatible assets for the given platform and architecture
fn has_compatible_camoufox_asset(
&self,
assets: &[crate::browser::GithubAsset],
os: &str,
arch: &str,
) -> bool {
let (os_name, arch_name) = match (os, arch) {
("windows", "x64") => ("win", "x86_64"),
("windows", "arm64") => ("win", "arm64"),
("linux", "x64") => ("lin", "x86_64"),
("linux", "arm64") => ("lin", "arm64"),
("macos", "x64") => ("mac", "x86_64"),
("macos", "arm64") => ("mac", "arm64"),
_ => return false,
};
// Look for assets matching the pattern: camoufox-{version}-{release}-{os}.{arch}.zip
assets.iter().any(|asset| {
let name = asset.name.to_lowercase();
name.starts_with("camoufox-")
&& name.contains(&format!("-{os_name}.{arch_name}.zip"))
&& name.ends_with(".zip")
})
}
fn has_compatible_brave_asset(
assets: &[crate::browser::GithubAsset],
os: &str,
@@ -996,6 +1029,128 @@ impl ApiClient {
)
}
pub async fn fetch_camoufox_releases_with_caching(
&self,
no_caching: bool,
) -> Result<Vec<GithubRelease>, Box<dyn std::error::Error + Send + Sync>> {
// Check cache first (unless bypassing)
if !no_caching {
if let Some(cached_releases) = self.load_cached_github_releases("camoufox") {
println!(
"Using cached Camoufox releases, count: {}",
cached_releases.len()
);
return Ok(cached_releases);
}
}
println!("Fetching Camoufox releases from GitHub API...");
let url = format!(
"{}/repos/daijro/camoufox/releases?per_page=100",
self.github_api_base
);
let response = self
.client
.get(url)
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36")
.send()
.await?;
if !response.status().is_success() {
return Err(format!("GitHub API returned status: {}", response.status()).into());
}
// Get the response text first for better error reporting
let response_text = response.text().await?;
// Try to parse the JSON with better error handling
let releases: Vec<GithubRelease> = match serde_json::from_str(&response_text) {
Ok(releases) => releases,
Err(e) => {
eprintln!("Failed to parse GitHub API response for Camoufox releases:");
eprintln!("Error: {e}");
eprintln!(
"Response text (first 500 chars): {}",
if response_text.len() > 500 {
&response_text[..500]
} else {
&response_text
}
);
return Err(format!("Failed to parse GitHub API response: {e}").into());
}
};
println!(
"Fetched {} total Camoufox releases from GitHub",
releases.len()
);
// Get platform info to filter appropriate releases
let (os, arch) = Self::get_platform_info();
println!("Filtering for platform: {os}/{arch}");
// Filter releases that have assets compatible with the current platform
let mut compatible_releases: Vec<GithubRelease> = releases
.into_iter()
.enumerate()
.filter_map(|(i, release)| {
let has_compatible = self.has_compatible_camoufox_asset(&release.assets, &os, &arch);
if !has_compatible {
println!(
"Release {} ({}) has no compatible assets for {}/{}",
i, release.tag_name, os, arch
);
println!(
" Available assets: {:?}",
release.assets.iter().map(|a| &a.name).collect::<Vec<_>>()
);
}
if has_compatible {
Some(release)
} else {
None
}
})
.collect();
println!(
"After platform filtering: {} compatible releases",
compatible_releases.len()
);
// Sort by version (latest first) with debugging
println!(
"Before sorting: {:?}",
compatible_releases
.iter()
.map(|r| &r.tag_name)
.take(10)
.collect::<Vec<_>>()
);
sort_github_releases(&mut compatible_releases);
println!(
"After sorting: {:?}",
compatible_releases
.iter()
.map(|r| &r.tag_name)
.take(10)
.collect::<Vec<_>>()
);
// Cache the results (unless bypassing cache)
if !no_caching {
if let Err(e) = self.save_cached_github_releases("camoufox", &compatible_releases) {
eprintln!("Failed to cache Camoufox releases: {e}");
} else {
println!("Cached {} Camoufox releases", compatible_releases.len());
}
}
Ok(compatible_releases)
}
pub async fn fetch_tor_releases_with_caching(
&self,
no_caching: bool,
@@ -1798,4 +1953,43 @@ mod tests {
let result = client.fetch_zen_releases_with_caching(true).await;
assert!(result.is_err());
}
#[test]
fn test_camoufox_beta_version_parsing() {
// Test specific Camoufox beta versions that are causing issues
let v22 = VersionComponent::parse("135.0.5beta22");
let v24 = VersionComponent::parse("135.0.5beta24");
println!("v22: {v22:?}");
println!("v24: {v24:?}");
// v24 should be greater than v22
assert!(
v24 > v22,
"135.0.5beta24 should be greater than 135.0.5beta22"
);
// Test other beta version combinations
let v1 = VersionComponent::parse("135.0.5beta1");
let v2 = VersionComponent::parse("135.0.5beta2");
assert!(v2 > v1, "135.0.5beta2 should be greater than 135.0.5beta1");
// Test sorting of multiple versions
let mut versions = vec![
"135.0.5beta22".to_string(),
"135.0.5beta24".to_string(),
"135.0.5beta23".to_string(),
"135.0.5beta21".to_string(),
];
sort_versions(&mut versions);
println!("Sorted versions: {versions:?}");
// Should be sorted from newest to oldest
assert_eq!(versions[0], "135.0.5beta24");
assert_eq!(versions[1], "135.0.5beta23");
assert_eq!(versions[2], "135.0.5beta22");
assert_eq!(versions[3], "135.0.5beta21");
}
}