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