1mod device;
2#[cfg(feature = "emulation-rand")]
3mod rand;
4
5use device::{chrome::*, firefox::*, okhttp::*, safari::*};
6use rquest::{EmulationProvider, EmulationProviderFactory};
7use serde::{Deserialize, Serialize};
8#[cfg(feature = "emulation-rand")]
9use strum_macros::VariantArray;
10use typed_builder::TypedBuilder;
11
12macro_rules! define_emulation_enum {
13 ($(#[$meta:meta])* $name:ident, $default_variant:ident, $($variant:ident => $rename:expr),*) => {
14 $(#[$meta])*
15 #[cfg(not(feature = "emulation-rand"))]
16 #[derive(Clone, Copy, Hash, Debug, PartialEq, Eq, Deserialize, Serialize)]
17 pub enum $name {
18 $(
19 #[serde(rename = $rename)]
20 $variant,
21 )*
22 }
23
24 #[cfg(not(feature = "emulation-rand"))]
25 impl Default for $name {
26 fn default() -> Self {
27 $name::$default_variant
28 }
29 }
30
31 $(#[$meta])*
32 #[cfg(feature = "emulation-rand")]
33 #[derive(Clone, Copy, Hash, Debug, PartialEq, Eq, Deserialize, Serialize, VariantArray)]
34 pub enum $name {
35 $(
36 #[serde(rename = $rename)]
37 $variant,
38 )*
39 }
40
41 #[cfg(feature = "emulation-rand")]
42 impl Default for $name {
43 fn default() -> Self {
44 $name::$default_variant
45 }
46 }
47 };
48}
49
50macro_rules! emulation_match {
51 ($ver:expr, $opt:expr, $($variant:pat => $path:expr),+) => {
52 match $ver {
53 $(
54 $variant => $path($opt),
55 )+
56 }
57 }
58}
59
60define_emulation_enum!(
61 Emulation, Chrome133,
89 Chrome100 => "chrome_100",
90 Chrome101 => "chrome_101",
91 Chrome104 => "chrome_104",
92 Chrome105 => "chrome_105",
93 Chrome106 => "chrome_106",
94 Chrome107 => "chrome_107",
95 Chrome108 => "chrome_108",
96 Chrome109 => "chrome_109",
97 Chrome114 => "chrome_114",
98 Chrome116 => "chrome_116",
99 Chrome117 => "chrome_117",
100 Chrome118 => "chrome_118",
101 Chrome119 => "chrome_119",
102 Chrome120 => "chrome_120",
103 Chrome123 => "chrome_123",
104 Chrome124 => "chrome_124",
105 Chrome126 => "chrome_126",
106 Chrome127 => "chrome_127",
107 Chrome128 => "chrome_128",
108 Chrome129 => "chrome_129",
109 Chrome130 => "chrome_130",
110 Chrome131 => "chrome_131",
111 Chrome132 => "chrome_132",
112 Chrome133 => "chrome_133",
113 SafariIos17_2 => "safari_ios_17.2",
114 SafariIos17_4_1 => "safari_ios_17.4.1",
115 SafariIos16_5 => "safari_ios_16.5",
116 Safari15_3 => "safari_15.3",
117 Safari15_5 => "safari_15.5",
118 Safari15_6_1 => "safari_15.6.1",
119 Safari16 => "safari_16",
120 Safari16_5 => "safari_16.5",
121 Safari17_0 => "safari_17.0",
122 Safari17_2_1 => "safari_17.2.1",
123 Safari17_4_1 => "safari_17.4.1",
124 Safari17_5 => "safari_17.5",
125 Safari18 => "safari_18",
126 SafariIPad18 => "safari_ipad_18",
127 Safari18_2 => "safari_18.2",
128 SafariIos18_1_1 => "safari_ios_18.1.1",
129 Safari18_3 => "safari_18.3",
130 OkHttp3_9 => "okhttp_3.9",
131 OkHttp3_11 => "okhttp_3.11",
132 OkHttp3_13 => "okhttp_3.13",
133 OkHttp3_14 => "okhttp_3.14",
134 OkHttp4_9 => "okhttp_4.9",
135 OkHttp4_10 => "okhttp_4.10",
136 OkHttp4_12 => "okhttp_4.12",
137 OkHttp5 => "okhttp_5",
138 Edge101 => "edge_101",
139 Edge122 => "edge_122",
140 Edge127 => "edge_127",
141 Edge131 => "edge_131",
142 Edge134 => "edge_134",
143 Firefox109 => "firefox_109",
144 Firefox117 => "firefox_117",
145 Firefox128 => "firefox_128",
146 Firefox133 => "firefox_133",
147 Firefox135 => "firefox_135",
148 FirefoxPrivate135 => "firefox_private_135",
149 FirefoxAndroid135 => "firefox_android_135",
150 Firefox136 => "firefox_136",
151 FirefoxPrivate136 => "firefox_private_136"
152);
153
154impl EmulationProviderFactory for Emulation {
156 fn emulation(self) -> EmulationProvider {
157 EmulationOption::builder()
158 .emulation(self)
159 .build()
160 .emulation()
161 }
162}
163
164#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
190pub enum EmulationOS {
191 #[serde(rename = "windows")]
192 Windows,
193 #[serde(rename = "macos")]
194 #[default]
195 MacOS,
196 #[serde(rename = "linux")]
197 Linux,
198 #[serde(rename = "android")]
199 Android,
200 #[serde(rename = "ios")]
201 IOS,
202}
203
204impl EmulationOS {
206 #[inline]
207 fn platform(&self) -> &'static str {
208 match self {
209 EmulationOS::MacOS => "\"macOS\"",
210 EmulationOS::Linux => "\"Linux\"",
211 EmulationOS::Windows => "\"Windows\"",
212 EmulationOS::Android => "\"Android\"",
213 EmulationOS::IOS => "\"iOS\"",
214 }
215 }
216
217 #[inline]
218 fn is_mobile(&self) -> bool {
219 matches!(self, EmulationOS::Android | EmulationOS::IOS)
220 }
221}
222
223#[derive(Default, TypedBuilder)]
224pub struct EmulationOption {
225 #[builder(default)]
227 emulation: Emulation,
228
229 #[builder(default)]
231 emulation_os: EmulationOS,
232
233 #[builder(default = false)]
235 skip_http2: bool,
236
237 #[builder(default = false)]
239 skip_headers: bool,
240}
241
242impl EmulationProviderFactory for EmulationOption {
244 fn emulation(self) -> EmulationProvider {
245 emulation_match!(
246 self.emulation,
247 self,
248
249 Emulation::Chrome100 => v100::emulation,
250 Emulation::Chrome101 => v101::emulation,
251 Emulation::Chrome104 => v104::emulation,
252 Emulation::Chrome105 => v105::emulation,
253 Emulation::Chrome106 => v106::emulation,
254 Emulation::Chrome107 => v107::emulation,
255 Emulation::Chrome108 => v108::emulation,
256 Emulation::Chrome109 => v109::emulation,
257 Emulation::Chrome114 => v114::emulation,
258 Emulation::Chrome116 => v116::emulation,
259 Emulation::Chrome117 => v117::emulation,
260 Emulation::Chrome118 => v118::emulation,
261 Emulation::Chrome119 => v119::emulation,
262 Emulation::Chrome120 => v120::emulation,
263 Emulation::Chrome123 => v123::emulation,
264 Emulation::Chrome124 => v124::emulation,
265 Emulation::Chrome126 => v126::emulation,
266 Emulation::Chrome127 => v127::emulation,
267 Emulation::Chrome128 => v128::emulation,
268 Emulation::Chrome129 => v129::emulation,
269 Emulation::Chrome130 => v130::emulation,
270 Emulation::Chrome131 => v131::emulation,
271 Emulation::Chrome132 => v132::emulation,
272 Emulation::Chrome133 => v133::emulation,
273
274 Emulation::SafariIos17_2 => safari_ios_17_2::emulation,
275 Emulation::SafariIos17_4_1 => safari_ios_17_4_1::emulation,
276 Emulation::SafariIos16_5 => safari_ios_16_5::emulation,
277 Emulation::Safari15_3 => safari15_3::emulation,
278 Emulation::Safari15_5 => safari15_5::emulation,
279 Emulation::Safari15_6_1 => safari15_6_1::emulation,
280 Emulation::Safari16 => safari16::emulation,
281 Emulation::Safari16_5 => safari16_5::emulation,
282 Emulation::Safari17_0 => safari17_0::emulation,
283 Emulation::Safari17_2_1 => safari17_2_1::emulation,
284 Emulation::Safari17_4_1 => safari17_4_1::emulation,
285 Emulation::Safari17_5 => safari17_5::emulation,
286 Emulation::Safari18 => safari18::emulation,
287 Emulation::SafariIPad18 => safari_ipad_18::emulation,
288 Emulation::Safari18_2 => safari18_2::emulation,
289 Emulation::SafariIos18_1_1 => safari_ios_18_1_1::emulation,
290 Emulation::Safari18_3 => safari18_3::emulation,
291
292 Emulation::OkHttp3_9 => okhttp3_9::emulation,
293 Emulation::OkHttp3_11 => okhttp3_11::emulation,
294 Emulation::OkHttp3_13 => okhttp3_13::emulation,
295 Emulation::OkHttp3_14 => okhttp3_14::emulation,
296 Emulation::OkHttp4_9 => okhttp4_9::emulation,
297 Emulation::OkHttp4_10 => okhttp4_10::emulation,
298 Emulation::OkHttp4_12 => okhttp4_12::emulation,
299 Emulation::OkHttp5 => okhttp5::emulation,
300
301 Emulation::Edge101 => edge101::emulation,
302 Emulation::Edge122 => edge122::emulation,
303 Emulation::Edge127 => edge127::emulation,
304 Emulation::Edge131 => edge131::emulation,
305 Emulation::Edge134 => edge134::emulation,
306
307 Emulation::Firefox109 => ff109::emulation,
308 Emulation::Firefox117 => ff117::emulation,
309 Emulation::Firefox128 => ff128::emulation,
310 Emulation::Firefox133 => ff133::emulation,
311 Emulation::Firefox135 => ff135::emulation,
312 Emulation::FirefoxPrivate135 => ff_private_135::emulation,
313 Emulation::FirefoxAndroid135 => ff_android_135::emulation,
314 Emulation::Firefox136 => ff136::emulation,
315 Emulation::FirefoxPrivate136 => ff_private_136::emulation
316 )
317 }
318}