Skip to main content

rustenium_identity/
identity.rs

1use serde::{Deserialize, Serialize};
2
3/// Top-level identity record. Serialises to/from the MongoDB document
4/// schema produced by persona_generator.py.
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub enum IdentityCountryGeo {
7    US,
8    UK,
9    JP,
10    DE,
11    FR,
12    CA,
13    AU,
14    IN,
15    BR,
16    KR,
17    IT,
18    ES,
19    NL,
20    PL,
21    SE,
22    MX,
23    SG,
24    ZA,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct Identity {
29    pub id: Option<u64>,
30
31    /// None device_model implies desktop/laptop
32    pub device_model: Option<String>,
33    pub has_battery: bool,
34    pub has_mouse: bool,
35    pub has_touch: bool,
36
37    pub os: Os,
38    pub os_version: String,
39    pub platform: PlatformInfo,
40
41    pub browser: Browser,
42    /// e.g. [124, 0, 6367, 78]
43    pub browser_version: Vec<u16>,
44
45    pub screen: ScreenResolution,
46    pub hardware_concurrency: u8,
47    /// deviceMemory in GiB
48    pub memory: u8,
49    pub gpu: Gpu,
50
51    pub geo: IdentityCountryGeo,
52
53    /// e.g. ["en-US", "en"]
54    pub language: Vec<String>,
55    pub history_count: Option<u16>,
56    /// Full URL with credentials
57    pub proxy: Option<String>,
58    /// IANA timezone string. If None, fetched from ip-api.com via proxy.
59    pub timezone: Option<String>,
60}
61
62impl Identity {
63    /// Deserialize from a raw JSON string (MongoDB extended JSON).
64    pub fn from_json(s: &str) -> Result<Self, serde_json::Error> {
65        serde_json::from_str(s)
66    }
67
68    /// Deserialize from a BSON Document.
69    #[cfg(feature = "bson")]
70    pub fn from_bson(doc: bson::Document) -> Result<Self, bson::de::Error> {
71        bson::from_document(doc)
72    }
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct PlatformInfo {
77    pub bitness: Option<String>,
78    pub architecture: Option<String>,
79    pub navigator_platform: NavigatorPlatform,
80    pub version: String,
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
84pub enum NavigatorPlatform {
85    #[serde(rename = "Win32")]
86    Win32,
87    #[serde(rename = "MacIntel")]
88    MacIntel,
89    #[serde(rename = "Linux x86_64")]
90    LinuxX86_64,
91    #[serde(rename = "Linux armv81")]
92    LinuxArmV81,
93    #[serde(rename = "iPhone")]
94    IPhone,
95    Other(String),
96}
97
98impl NavigatorPlatform {
99    pub fn as_str(&self) -> &str {
100        match self {
101            Self::Win32 => "Win32",
102            Self::MacIntel => "MacIntel",
103            Self::LinuxX86_64 => "Linux x86_64",
104            Self::LinuxArmV81 => "Linux armv81",
105            Self::IPhone => "iPhone",
106            Self::Other(s) => s.as_str(),
107        }
108    }
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
112pub struct ScreenResolution {
113    pub logical_width: u16,
114    pub logical_height: u16,
115    pub original_width: u16,
116    pub original_height: u16,
117    pub density_pixel_ratio: f32,
118}
119
120/// GPU identity — drives WebGL parameter spoofing.
121#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct Gpu {
123    pub vendor: String,
124    /// e.g. "ANGLE (NVIDIA GeForce RTX 3080...)"
125    pub webgl_renderer: String,
126    /// Exact UNMASKED_VENDOR_WEBGL string, e.g. "Google Inc. (NVIDIA)"
127    pub webgl_vendor: String,
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize)]
131pub enum Os {
132    Windows,
133    Macintosh,
134    Linux,
135    Android,
136    Ios,
137}
138
139#[derive(Debug, Clone, Serialize, Deserialize)]
140#[serde(rename_all = "lowercase")]
141pub enum Browser {
142    Chrome,
143    Safari,
144    Edge,
145}