Skip to main content

rustenium_identity/
lib.rs

1pub mod identity;
2pub mod ua;
3pub mod tz;
4pub mod error;
5pub mod cdp;
6pub mod script;
7pub mod preset;
8pub mod local_proxy_server;
9
10use error::IdentityError;
11use local_proxy_server::start_overlay;
12use rustenium::browsers::chrome::browser::{ChromeBrowser, ChromeConfig};
13
14pub use identity::*;
15pub use error::IdentityError as Error;
16
17/// Configuration for launching an identity-spoofed browser session.
18pub struct IdentityConfig {
19    pub identity: Identity,
20    pub chrome: ChromeConfig,
21}
22
23impl From<Identity> for IdentityConfig {
24    fn from(identity: Identity) -> Self {
25        Self {
26            identity,
27            chrome: ChromeConfig {
28                enable_bidi: false,
29                enable_cdp: true,
30                ..Default::default()
31            },
32        }
33    }
34}
35
36impl IdentityConfig {
37    pub fn new(identity: Identity, chrome: ChromeConfig) -> Self {
38        Self { identity, chrome }
39    }
40}
41
42/// A rustenium browser session with an identity applied.
43pub struct IdentitySession {
44    identity: Identity,
45    browser: ChromeBrowser,
46}
47
48impl IdentitySession {
49    /// Launch a new Chromium instance from the given config.
50    /// Applies all CDP emulation overrides and registers the stealth
51    /// bootstrap script before returning.
52    pub async fn launch(config: impl Into<IdentityConfig>) -> Result<Self, IdentityError> {
53        let config = config.into();
54        let timezone = tz::resolve_timezone(
55            config.identity.timezone.as_deref(),
56            config.identity.proxy.as_deref(),
57        )
58        .await?;
59
60        let mut chrome_config = config.chrome;
61        chrome_config.enable_bidi = false;
62        chrome_config.enable_cdp = true;
63
64        if let Some(ref proxy_url) = config.identity.proxy {
65            if !proxy_url.is_empty() {
66                let local_addr = start_overlay(proxy_url)
67                    .await
68                    .map_err(|e| IdentityError::ProxyError(e.to_string()))?;
69                let mut flags = chrome_config.browser_flags.unwrap_or_default();
70                flags.push(format!("--proxy-server=http://127.0.0.1:{}", local_addr.port()));
71                chrome_config.browser_flags = Some(flags);
72            }
73        }
74
75        let mut browser = ChromeBrowser::new(chrome_config).await;
76
77        cdp::apply_identity(&mut browser, &config.identity, &timezone).await?;
78
79        Ok(Self {
80            identity: config.identity,
81            browser,
82        })
83    }
84
85    /// Access the underlying rustenium ChromeBrowser.
86    pub fn browser(&self) -> &ChromeBrowser {
87        &self.browser
88    }
89
90    /// Mutable access to the underlying rustenium ChromeBrowser.
91    pub fn browser_mut(&mut self) -> &mut ChromeBrowser {
92        &mut self.browser
93    }
94
95    /// Get the identity.
96    pub fn identity(&self) -> &Identity {
97        &self.identity
98    }
99}