use crate::identity::{Browser, Identity, Os};
use crate::error::IdentityError;
fn full_version(parts: &[u16]) -> String {
parts.iter().map(|v| v.to_string()).collect::<Vec<_>>().join(".")
}
pub fn build_user_agent(identity: &Identity) -> Result<String, IdentityError> {
let chrome_full = full_version(&identity.browser_version);
match (&identity.os, &identity.browser) {
(Os::Windows, Browser::Chrome) => {
let nt_version = windows_nt_version(&identity.os_version);
Ok(format!(
"Mozilla/5.0 (Windows NT {}; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{} Safari/537.36",
nt_version, chrome_full
))
}
(Os::Macintosh, Browser::Chrome) => {
let osx_underscored = identity.os_version.replace('.', "_");
Ok(format!(
"Mozilla/5.0 (Macintosh; Intel Mac OS X {}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{} Safari/537.36",
osx_underscored, chrome_full
))
}
(Os::Android, Browser::Chrome) => {
let device = identity.device_model.as_deref().unwrap_or("Pixel 7");
Ok(format!(
"Mozilla/5.0 (Linux; Android {}; {}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{} Mobile Safari/537.36",
identity.os_version, device, chrome_full
))
}
(Os::Android, Browser::Edge) => {
let device = identity.device_model.as_deref().unwrap_or("Pixel 7");
Ok(format!(
"Mozilla/5.0 (Linux; Android {}; {}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{} Mobile EdgA/{} Safari/537.36",
identity.os_version, device, chrome_full, chrome_full
))
}
(Os::Ios, Browser::Safari) => {
let os_underscored = identity.os_version.replace('.', "_");
let nav_platform = identity.platform.navigator_platform.as_str();
Ok(format!(
"Mozilla/5.0 ({}; CPU iPhone OS {} like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/{} Mobile/15E148 Safari/604.1",
nav_platform, os_underscored, full_version(&identity.browser_version)
))
}
(Os::Ios, Browser::Chrome) => {
let os_underscored = identity.os_version.replace('.', "_");
let nav_platform = identity.platform.navigator_platform.as_str();
Ok(format!(
"Mozilla/5.0 ({}; CPU iPhone OS {} like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/{} Mobile/15E148 Safari/604.1",
nav_platform, os_underscored, chrome_full
))
}
(Os::Ios, Browser::Edge) => {
let os_underscored = identity.os_version.replace('.', "_");
let nav_platform = identity.platform.navigator_platform.as_str();
Ok(format!(
"Mozilla/5.0 ({}; CPU iPhone OS {} like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/{} EdgiOS/{} Mobile/15E148 Safari/604.1",
nav_platform, os_underscored, full_version(&identity.browser_version), chrome_full
))
}
(Os::Macintosh, Browser::Safari) => {
let osx_underscored = identity.os_version.replace('.', "_");
Ok(format!(
"Mozilla/5.0 (Macintosh; Intel Mac OS X {}) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/{} Safari/605.1.15",
osx_underscored, full_version(&identity.browser_version)
))
}
(Os::Linux, Browser::Chrome) => {
Ok(format!(
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{} Safari/537.36",
chrome_full
))
}
(Os::Windows, Browser::Edge) => {
let nt_version = windows_nt_version(&identity.os_version);
Ok(format!(
"Mozilla/5.0 (Windows NT {}; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{} Safari/537.36 Edg/{}",
nt_version, chrome_full, chrome_full
))
}
(Os::Macintosh, Browser::Edge) => {
let osx_underscored = identity.os_version.replace('.', "_");
Ok(format!(
"Mozilla/5.0 (Macintosh; Intel Mac OS X {}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{} Safari/537.36 Edg/{}",
osx_underscored, chrome_full, chrome_full
))
}
(os, browser) => Err(IdentityError::UaError(format!(
"unsupported OS/browser combination: {:?}/{:?}",
os, browser
))),
}
}
fn windows_nt_version(os_version: &str) -> &str {
match os_version {
"11" => "10.0",
"10" => "10.0",
"8.1" => "6.3",
"8" => "6.2",
"7" => "6.1",
_ => "10.0",
}
}