rustenium-identity 0.1.10

A versatile stealth overlay for rustenium
Documentation
use serde::{Deserialize, Serialize};

/// Top-level identity record. Serialises to/from the MongoDB document
/// schema produced by persona_generator.py.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum IdentityCountryGeo {
    US,
    UK,
    JP,
    DE,
    FR,
    CA,
    AU,
    IN,
    BR,
    KR,
    IT,
    ES,
    NL,
    PL,
    SE,
    MX,
    SG,
    ZA,
}

impl IdentityCountryGeo {
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::US => "US",
            Self::UK => "UK",
            Self::JP => "JP",
            Self::DE => "DE",
            Self::FR => "FR",
            Self::CA => "CA",
            Self::AU => "AU",
            Self::IN => "IN",
            Self::BR => "BR",
            Self::KR => "KR",
            Self::IT => "IT",
            Self::ES => "ES",
            Self::NL => "NL",
            Self::PL => "PL",
            Self::SE => "SE",
            Self::MX => "MX",
            Self::SG => "SG",
            Self::ZA => "ZA",
        }
    }
}

impl TryFrom<&str> for IdentityCountryGeo {
    type Error = String;

    fn try_from(s: &str) -> Result<Self, Self::Error> {
        match s {
            "US" => Ok(Self::US),
            "UK" => Ok(Self::UK),
            "JP" => Ok(Self::JP),
            "DE" => Ok(Self::DE),
            "FR" => Ok(Self::FR),
            "CA" => Ok(Self::CA),
            "AU" => Ok(Self::AU),
            "IN" => Ok(Self::IN),
            "BR" => Ok(Self::BR),
            "KR" => Ok(Self::KR),
            "IT" => Ok(Self::IT),
            "ES" => Ok(Self::ES),
            "NL" => Ok(Self::NL),
            "PL" => Ok(Self::PL),
            "SE" => Ok(Self::SE),
            "MX" => Ok(Self::MX),
            "SG" => Ok(Self::SG),
            "ZA" => Ok(Self::ZA),
            other => Err(format!("unknown country code: {other}")),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Identity {
    pub id: Option<u64>,

    /// None device_model implies desktop/laptop
    pub device_model: Option<String>,
    pub has_battery: bool,
    pub has_mouse: bool,
    pub has_touch: bool,

    pub os: Os,
    pub os_version: String,
    pub platform: PlatformInfo,

    pub browser: Browser,
    /// e.g. [124, 0, 6367, 78]
    pub browser_version: Vec<u16>,

    pub screen: ScreenResolution,
    pub hardware_concurrency: u8,
    /// deviceMemory in GiB
    pub memory: u8,
    pub gpu: Gpu,

    pub geo: IdentityCountryGeo,

    /// e.g. ["en-US", "en"]
    pub language: Vec<String>,
    pub history_count: Option<u16>,
    /// Full URL with credentials
    pub proxy: Option<String>,
    /// IANA timezone string. If None, fetched from ip-api.com via proxy.
    pub timezone: Option<String>,
}

impl Identity {
    /// Deserialize from a raw JSON string (MongoDB extended JSON).
    pub fn from_json(s: &str) -> Result<Self, serde_json::Error> {
        serde_json::from_str(s)
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlatformInfo {
    pub bitness: Option<String>,
    pub architecture: Option<String>,
    pub navigator_platform: NavigatorPlatform,
    pub version: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum NavigatorPlatform {
    #[serde(rename = "Win32")]
    Win32,
    #[serde(rename = "MacIntel")]
    MacIntel,
    #[serde(rename = "Linux x86_64")]
    LinuxX86_64,
    #[serde(rename = "Linux armv81")]
    LinuxArmV81,
    #[serde(rename = "iPhone")]
    IPhone,
    Other(String),
}

impl NavigatorPlatform {
    pub fn as_str(&self) -> &str {
        match self {
            Self::Win32 => "Win32",
            Self::MacIntel => "MacIntel",
            Self::LinuxX86_64 => "Linux x86_64",
            Self::LinuxArmV81 => "Linux armv81",
            Self::IPhone => "iPhone",
            Self::Other(s) => s.as_str(),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ScreenResolution {
    pub logical_width: u16,
    pub logical_height: u16,
    pub original_width: u16,
    pub original_height: u16,
    pub density_pixel_ratio: f32,
}

/// GPU identity — drives WebGL parameter spoofing.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Gpu {
    pub vendor: String,
    /// e.g. "ANGLE (NVIDIA GeForce RTX 3080...)"
    pub webgl_renderer: String,
    /// Exact UNMASKED_VENDOR_WEBGL string, e.g. "Google Inc. (NVIDIA)"
    pub webgl_vendor: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Os {
    Windows,
    Macintosh,
    Linux,
    Android,
    Ios,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Browser {
    Chrome,
    Safari,
    Edge,
}