1use crate::error::IdentityError;
16use crate::identity::{
17 Browser, Gpu, Identity, IdentityCountryGeo, NavigatorPlatform, Os, PlatformInfo,
18 ScreenResolution,
19};
20
21fn win_platform(ver: &str) -> PlatformInfo {
26 PlatformInfo {
27 bitness: Some("64".into()),
28 architecture: Some("x86".into()),
29 navigator_platform: NavigatorPlatform::Win32,
30 version: ver.into(),
31 }
32}
33
34fn mac_platform(ver: &str) -> PlatformInfo {
35 PlatformInfo {
36 bitness: Some("64".into()),
37 architecture: Some("arm".into()),
38 navigator_platform: NavigatorPlatform::MacIntel,
39 version: ver.into(),
40 }
41}
42
43fn lin_platform(ver: &str) -> PlatformInfo {
44 PlatformInfo {
45 bitness: Some("64".into()),
46 architecture: Some("x86".into()),
47 navigator_platform: NavigatorPlatform::LinuxX86_64,
48 version: ver.into(),
49 }
50}
51
52fn screen(lw: u16, lh: u16, ow: u16, oh: u16, dpr: f32) -> ScreenResolution {
53 ScreenResolution {
54 logical_width: lw,
55 logical_height: lh,
56 original_width: ow,
57 original_height: oh,
58 density_pixel_ratio: dpr,
59 }
60}
61
62fn nvidia_gpu(model: &str) -> Gpu {
63 Gpu {
64 vendor: "NVIDIA Corporation".into(),
65 webgl_renderer: format!("ANGLE (NVIDIA {} Direct3D11 vs_5_0 ps_5_0)", model),
66 webgl_vendor: "Google Inc. (NVIDIA)".into(),
67 }
68}
69
70fn intel_gpu(model: &str) -> Gpu {
71 Gpu {
72 vendor: "Intel Inc.".into(),
73 webgl_renderer: format!("ANGLE (Intel, {} Direct3D11 vs_5_0 ps_5_0)", model),
74 webgl_vendor: "Google Inc. (Intel)".into(),
75 }
76}
77
78fn apple_gpu(model: &str) -> Gpu {
79 Gpu {
80 vendor: "Apple".into(),
81 webgl_renderer: model.into(),
82 webgl_vendor: "Apple".into(),
83 }
84}
85
86fn amd_gpu(model: &str) -> Gpu {
87 Gpu {
88 vendor: "Advanced Micro Devices, Inc.".into(),
89 webgl_renderer: format!("ANGLE (AMD, {} Direct3D11 vs_5_0 ps_5_0)", model),
90 webgl_vendor: "Google Inc. (AMD)".into(),
91 }
92}
93
94fn all() -> [Identity; 10] {
99 [
100 Identity {
102 id: Some(1),
103 device_model: None,
104 has_battery: false,
105 has_mouse: true,
106 has_touch: false,
107 os: Os::Windows,
108 os_version: "15.0.0".into(),
109 platform: win_platform("15.0.0"),
110 browser: Browser::Chrome,
111 browser_version: vec![124, 0, 6367, 78],
112 screen: screen(1280, 720, 1920, 1080, 1.0),
113 hardware_concurrency: 16,
114 memory: 16,
115 gpu: nvidia_gpu("GeForce RTX 3080"),
116 geo: IdentityCountryGeo::US,
117 language: vec!["en-US".into(), "en".into()],
118 history_count: Some(12),
119 proxy: None,
120 timezone: None,
121 },
122 Identity {
124 id: Some(2),
125 device_model: None,
126 has_battery: false,
127 has_mouse: true,
128 has_touch: false,
129 os: Os::Windows,
130 os_version: "10.0.0".into(),
131 platform: win_platform("10.0.0"),
132 browser: Browser::Edge,
133 browser_version: vec![123, 0, 2420, 65],
134 screen: screen(1366, 768, 1366, 768, 1.0),
135 hardware_concurrency: 8,
136 memory: 8,
137 gpu: intel_gpu("Intel(R) UHD Graphics 630"),
138 geo: IdentityCountryGeo::US,
139 language: vec!["en-US".into(), "en".into()],
140 history_count: Some(5),
141 proxy: None,
142 timezone: None,
143 },
144 Identity {
146 id: Some(3),
147 device_model: None,
148 has_battery: true,
149 has_mouse: true,
150 has_touch: false,
151 os: Os::Macintosh,
152 os_version: "13.4.1".into(),
153 platform: mac_platform("13.4.1"),
154 browser: Browser::Safari,
155 browser_version: vec![17, 0, 0, 0],
156 screen: screen(2560, 1600, 2560, 1600, 2.0),
157 hardware_concurrency: 10,
158 memory: 16,
159 gpu: apple_gpu("Apple M2"),
160 geo: IdentityCountryGeo::UK,
161 language: vec!["en-GB".into(), "en".into()],
162 history_count: Some(20),
163 proxy: None,
164 timezone: None,
165 },
166 Identity {
168 id: Some(4),
169 device_model: None,
170 has_battery: true,
171 has_mouse: true,
172 has_touch: false,
173 os: Os::Macintosh,
174 os_version: "12.6.0".into(),
175 platform: mac_platform("12.6.0"),
176 browser: Browser::Chrome,
177 browser_version: vec![124, 0, 6367, 82],
178 screen: screen(1440, 900, 2880, 1800, 2.0),
179 hardware_concurrency: 8,
180 memory: 8,
181 gpu: apple_gpu("Apple M1"),
182 geo: IdentityCountryGeo::US,
183 language: vec!["en-US".into(), "en".into()],
184 history_count: Some(7),
185 proxy: None,
186 timezone: None,
187 },
188 Identity {
190 id: Some(5),
191 device_model: None,
192 has_battery: false,
193 has_mouse: true,
194 has_touch: false,
195 os: Os::Linux,
196 os_version: "22.04".into(),
197 platform: lin_platform("22.04"),
198 browser: Browser::Chrome,
199 browser_version: vec![124, 0, 6367, 79],
200 screen: screen(1920, 1080, 1920, 1080, 1.0),
201 hardware_concurrency: 12,
202 memory: 16,
203 gpu: nvidia_gpu("GeForce GTX 1650"),
204 geo: IdentityCountryGeo::US,
205 language: vec!["en-US".into(), "en".into()],
206 history_count: Some(3),
207 proxy: None,
208 timezone: None,
209 },
210 Identity {
212 id: Some(6),
213 device_model: Some("Pixel 7".into()),
214 has_battery: true,
215 has_mouse: false,
216 has_touch: true,
217 os: Os::Android,
218 os_version: "13".into(),
219 platform: PlatformInfo {
220 bitness: None,
221 architecture: None,
222 navigator_platform: NavigatorPlatform::LinuxArmV81,
223 version: "13".into(),
224 },
225 browser: Browser::Chrome,
226 browser_version: vec![124, 0, 6367, 82],
227 screen: screen(412, 915, 1080, 2400, 2.625),
228 hardware_concurrency: 8,
229 memory: 8,
230 gpu: Gpu {
231 vendor: "Qualcomm".into(),
232 webgl_renderer: "Adreno (TM) 730".into(),
233 webgl_vendor: "Qualcomm".into(),
234 },
235 geo: IdentityCountryGeo::US,
236 language: vec!["en-US".into(), "en".into()],
237 history_count: Some(2),
238 proxy: None,
239 timezone: None,
240 },
241 Identity {
243 id: Some(7),
244 device_model: Some("iPhone 15".into()),
245 has_battery: true,
246 has_mouse: false,
247 has_touch: true,
248 os: Os::Ios,
249 os_version: "17.0".into(),
250 platform: PlatformInfo {
251 bitness: None,
252 architecture: None,
253 navigator_platform: NavigatorPlatform::IPhone,
254 version: "17.0".into(),
255 },
256 browser: Browser::Safari,
257 browser_version: vec![17, 0, 0, 0],
258 screen: screen(393, 852, 1179, 2556, 3.0),
259 hardware_concurrency: 6,
260 memory: 6,
261 gpu: apple_gpu("Apple A16 GPU"),
262 geo: IdentityCountryGeo::US,
263 language: vec!["en-US".into(), "en".into()],
264 history_count: Some(4),
265 proxy: None,
266 timezone: None,
267 },
268 Identity {
270 id: Some(8),
271 device_model: None,
272 has_battery: true,
273 has_mouse: true,
274 has_touch: true,
275 os: Os::Windows,
276 os_version: "11.0.0".into(),
277 platform: win_platform("11.0.0"),
278 browser: Browser::Chrome,
279 browser_version: vec![123, 0, 6312, 122],
280 screen: screen(1920, 1200, 1920, 1200, 1.0),
281 hardware_concurrency: 8,
282 memory: 16,
283 gpu: amd_gpu("AMD Radeon RX 6600"),
284 geo: IdentityCountryGeo::FR,
285 language: vec!["fr-FR".into(), "fr".into(), "en".into()],
286 history_count: Some(9),
287 proxy: None,
288 timezone: None,
289 },
290 Identity {
292 id: Some(9),
293 device_model: None,
294 has_battery: true,
295 has_mouse: true,
296 has_touch: false,
297 os: Os::Macintosh,
298 os_version: "14.2.1".into(),
299 platform: mac_platform("14.2.1"),
300 browser: Browser::Chrome,
301 browser_version: vec![124, 0, 6367, 91],
302 screen: screen(1512, 982, 3024, 1964, 2.0),
303 hardware_concurrency: 12,
304 memory: 36,
305 gpu: apple_gpu("Apple M3 Pro"),
306 geo: IdentityCountryGeo::DE,
307 language: vec!["de-DE".into(), "de".into(), "en".into()],
308 history_count: Some(15),
309 proxy: None,
310 timezone: None,
311 },
312 Identity {
314 id: Some(10),
315 device_model: Some("SM-S911B".into()),
316 has_battery: true,
317 has_mouse: false,
318 has_touch: true,
319 os: Os::Android,
320 os_version: "14".into(),
321 platform: PlatformInfo {
322 bitness: None,
323 architecture: None,
324 navigator_platform: NavigatorPlatform::LinuxArmV81,
325 version: "14".into(),
326 },
327 browser: Browser::Chrome,
328 browser_version: vec![124, 0, 6367, 82],
329 screen: screen(360, 780, 1080, 2340, 3.0),
330 hardware_concurrency: 8,
331 memory: 8,
332 gpu: Gpu {
333 vendor: "Qualcomm".into(),
334 webgl_renderer: "ANGLE (Qualcomm, Adreno (TM) 750, OpenGL ES 3.2)".into(),
335 webgl_vendor: "Google Inc. (Qualcomm)".into(),
336 },
337 geo: IdentityCountryGeo::US,
338 language: vec!["en-US".into(), "en".into()],
339 history_count: Some(6),
340 proxy: None,
341 timezone: None,
342 },
343 ]
344}
345
346pub fn presets() -> Vec<Identity> {
352 all().to_vec()
353}
354
355pub fn get_by_id(id: u64) -> Result<Identity, IdentityError> {
360 all()
361 .into_iter()
362 .find(|p| p.id == Some(id))
363 .ok_or(IdentityError::NotFound(id))
364}
365
366pub fn random() -> Identity {
371 let idx = entropy_index(all().len());
372 all().into_iter().nth(idx).expect("preset index in bounds")
373}
374
375fn entropy_index(len: usize) -> usize {
380 use std::time::{SystemTime, UNIX_EPOCH};
381 let nanos = SystemTime::now()
382 .duration_since(UNIX_EPOCH)
383 .map(|d| d.subsec_nanos())
384 .unwrap_or(42);
385 (nanos as usize) % len
386}