unrealon 2.0.10__py3-none-any.whl → 2.0.12__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,361 @@
1
+ """
2
+ UndetectedChrome - Integration with undetected-chromedriver
3
+
4
+ Provides integration with undetected-chromedriver for advanced bot detection bypass:
5
+ - Automatic ChromeDriver patching
6
+ - Selenium stealth integration
7
+ - Advanced Chrome arguments
8
+ - BotD bypass optimization
9
+ """
10
+
11
+ import logging
12
+ from typing import Dict, Any, Optional, List
13
+ import random
14
+
15
+ logger = logging.getLogger(__name__)
16
+ logger.setLevel(logging.DEBUG)
17
+
18
+ class UndetectedChrome:
19
+ """
20
+ Integration with undetected-chromedriver
21
+
22
+ Provides seamless integration with undetected-chromedriver
23
+ for maximum bot detection bypass effectiveness
24
+ """
25
+
26
+ def __init__(self, logger_bridge=None):
27
+ """Initialize UndetectedChrome"""
28
+ self.logger_bridge = logger_bridge
29
+
30
+ def _logger(self, message: str, level: str = "info") -> None:
31
+ """Private wrapper for logger with bridge support"""
32
+ if self.logger_bridge:
33
+ if level == "info":
34
+ self.logger_bridge.log_info(message)
35
+ elif level == "error":
36
+ self.logger_bridge.log_error(message)
37
+ elif level == "warning":
38
+ self.logger_bridge.log_warning(message)
39
+ else:
40
+ self.logger_bridge.log_info(message)
41
+ else:
42
+ if level == "info":
43
+ logger.info(message)
44
+ elif level == "error":
45
+ logger.error(message)
46
+ elif level == "warning":
47
+ logger.warning(message)
48
+ else:
49
+ logger.info(message)
50
+
51
+ def get_undetected_chrome_options(self) -> Dict[str, Any]:
52
+ """
53
+ Get optimized options for undetected-chromedriver
54
+
55
+ Returns:
56
+ Dict with Chrome options optimized for stealth
57
+ """
58
+ return {
59
+ "headless": False, # Recommend headed mode for best results
60
+ "use_subprocess": False,
61
+ "version_main": None, # Auto-detect Chrome version
62
+ "driver_executable_path": None, # Auto-download
63
+ "browser_executable_path": None, # Use system Chrome
64
+ "user_data_dir": None, # Use temporary profile
65
+ "suppress_welcome": True,
66
+ "no_sandbox": True,
67
+ "disable_gpu": False, # Keep GPU for WebGL consistency
68
+ "log_level": 3, # Suppress logs
69
+ }
70
+
71
+ def get_enhanced_chrome_arguments(self) -> List[str]:
72
+ """
73
+ Get enhanced Chrome arguments for undetected-chromedriver
74
+
75
+ Returns:
76
+ List of Chrome arguments optimized for stealth
77
+ """
78
+ return [
79
+ # Core stealth arguments
80
+ "--no-first-run",
81
+ "--no-default-browser-check",
82
+ "--disable-blink-features=AutomationControlled",
83
+ "--disable-features=VizDisplayCompositor",
84
+
85
+ # Enhanced stealth for BotD bypass
86
+ "--disable-web-security",
87
+ "--disable-client-side-phishing-detection",
88
+ "--disable-component-extensions-with-background-pages",
89
+ "--disable-default-apps",
90
+ "--disable-domain-reliability",
91
+ "--disable-background-networking",
92
+ "--disable-translate",
93
+ "--disable-ipc-flooding-protection",
94
+
95
+ # Performance and stability
96
+ "--no-sandbox",
97
+ "--disable-dev-shm-usage",
98
+ "--disable-background-timer-throttling",
99
+ "--disable-backgrounding-occluded-windows",
100
+ "--disable-renderer-backgrounding",
101
+ "--disable-field-trial-config",
102
+ "--disable-back-forward-cache",
103
+
104
+ # System integration
105
+ "--disable-hang-monitor",
106
+ "--disable-prompt-on-repost",
107
+ "--disable-sync",
108
+ "--metrics-recording-only",
109
+ "--no-report-upload",
110
+
111
+ # Realistic window settings
112
+ "--window-size=1366,768",
113
+ "--start-maximized",
114
+
115
+ # Audio and media
116
+ "--mute-audio",
117
+ "--disable-audio-output",
118
+
119
+ # Extensions (keep minimal for realism)
120
+ "--disable-extensions-except=",
121
+
122
+ # Memory and performance
123
+ "--max_old_space_size=4096",
124
+ "--memory-pressure-off",
125
+ ]
126
+
127
+ def get_random_user_agent(self) -> str:
128
+ """
129
+ Get random realistic user agent
130
+
131
+ Returns:
132
+ Random user agent string
133
+ """
134
+ user_agents = [
135
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
136
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
137
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
138
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
139
+ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
140
+ ]
141
+ return random.choice(user_agents)
142
+
143
+ def create_undetected_driver(self, headless: bool = False, **kwargs) -> Any:
144
+ """
145
+ Create undetected ChromeDriver instance
146
+
147
+ Args:
148
+ headless: Whether to run in headless mode
149
+ **kwargs: Additional options for undetected_chromedriver
150
+
151
+ Returns:
152
+ Configured undetected ChromeDriver instance
153
+ """
154
+ try:
155
+ import undetected_chromedriver as uc
156
+ from selenium_stealth import stealth
157
+
158
+ self._logger("🚗 Creating undetected ChromeDriver...", "info")
159
+
160
+ # Get base options
161
+ options = self.get_undetected_chrome_options()
162
+ options.update(kwargs)
163
+ options["headless"] = headless
164
+
165
+ # Create Chrome options
166
+ chrome_options = uc.ChromeOptions()
167
+
168
+ # Add enhanced arguments
169
+ for arg in self.get_enhanced_chrome_arguments():
170
+ chrome_options.add_argument(arg)
171
+
172
+ # Add random user agent
173
+ user_agent = self.get_random_user_agent()
174
+ chrome_options.add_argument(f'--user-agent={user_agent}')
175
+
176
+ # Disable automation indicators
177
+ chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
178
+ chrome_options.add_experimental_option('useAutomationExtension', False)
179
+
180
+ # Create driver
181
+ driver = uc.Chrome(options=chrome_options, **options)
182
+
183
+ # Apply selenium-stealth
184
+ stealth(
185
+ driver,
186
+ languages=["en-US", "en"],
187
+ vendor="Google Inc.",
188
+ platform="Win32",
189
+ webgl_vendor="Intel Inc.",
190
+ renderer="Intel Iris OpenGL Engine",
191
+ fix_hairline=True,
192
+ )
193
+
194
+ # Remove webdriver property
195
+ driver.execute_script("""
196
+ Object.defineProperty(navigator, 'webdriver', {
197
+ get: () => undefined
198
+ });
199
+ """)
200
+
201
+ self._logger("✅ Undetected ChromeDriver created successfully", "info")
202
+ return driver
203
+
204
+ except ImportError as e:
205
+ self._logger(f"❌ undetected-chromedriver not available: {e}", "error")
206
+ return None
207
+ except Exception as e:
208
+ self._logger(f"❌ Failed to create undetected ChromeDriver: {e}", "error")
209
+ return None
210
+
211
+ def apply_selenium_stealth(self, driver) -> bool:
212
+ """
213
+ Apply selenium-stealth to existing driver
214
+
215
+ Args:
216
+ driver: Selenium WebDriver instance
217
+
218
+ Returns:
219
+ True if successful
220
+ """
221
+ try:
222
+ from selenium_stealth import stealth
223
+
224
+ self._logger("🛡️ Applying selenium-stealth...", "info")
225
+
226
+ stealth(
227
+ driver,
228
+ languages=["en-US", "en"],
229
+ vendor="Google Inc.",
230
+ platform="Win32",
231
+ webgl_vendor="Intel Inc.",
232
+ renderer="Intel Iris OpenGL Engine",
233
+ fix_hairline=True,
234
+ )
235
+
236
+ # Additional webdriver removal
237
+ driver.execute_script("""
238
+ // Enhanced webdriver removal
239
+ Object.defineProperty(navigator, 'webdriver', {
240
+ get: () => undefined
241
+ });
242
+
243
+ // Remove automation indicators
244
+ ['__webdriver_evaluate', '__selenium_evaluate', '__webdriver_script_function',
245
+ '__fxdriver_evaluate', '__driver_unwrapped', '__webdriver_unwrapped',
246
+ '_Selenium_IDE_Recorder', '_selenium', 'calledSelenium'].forEach(prop => {
247
+ delete window[prop];
248
+ });
249
+ """)
250
+
251
+ self._logger("✅ Selenium-stealth applied successfully", "info")
252
+ return True
253
+
254
+ except ImportError as e:
255
+ self._logger(f"❌ selenium-stealth not available: {e}", "error")
256
+ return False
257
+ except Exception as e:
258
+ self._logger(f"❌ Failed to apply selenium-stealth: {e}", "error")
259
+ return False
260
+
261
+ def test_undetected_chrome(self, test_url: str) -> Dict[str, Any]:
262
+ """
263
+ Test undetected ChromeDriver effectiveness
264
+
265
+ Args:
266
+ test_url: URL to test stealth effectiveness
267
+
268
+ Returns:
269
+ Dict with test results
270
+ """
271
+ driver = None
272
+ try:
273
+ self._logger(f"🧪 Testing undetected ChromeDriver on {test_url}...", "info")
274
+
275
+ # Create driver
276
+ driver = self.create_undetected_driver(headless=True)
277
+ if not driver:
278
+ return {
279
+ "success": False,
280
+ "error": "Failed to create undetected ChromeDriver"
281
+ }
282
+
283
+ # Navigate to test page
284
+ driver.get(test_url)
285
+
286
+ # Wait for page to load
287
+ import time
288
+ time.sleep(5)
289
+
290
+ # Extract basic detection info
291
+ try:
292
+ results = driver.execute_script("""
293
+ return {
294
+ userAgent: navigator.userAgent,
295
+ webdriver: navigator.webdriver !== undefined,
296
+ chrome: !!window.chrome,
297
+ plugins: navigator.plugins.length,
298
+ languages: navigator.languages ? navigator.languages.length : 0,
299
+ botDetectionResults: window.botDetectionResults || null
300
+ };
301
+ """)
302
+
303
+ return {
304
+ "success": True,
305
+ "results": results,
306
+ "is_bot": results.get("webdriver", False),
307
+ "user_agent": results.get("userAgent", ""),
308
+ "chrome_object": results.get("chrome", False),
309
+ "plugins_count": results.get("plugins", 0),
310
+ "bot_detection": results.get("botDetectionResults")
311
+ }
312
+
313
+ except Exception as e:
314
+ return {
315
+ "success": False,
316
+ "error": f"Failed to extract results: {e}"
317
+ }
318
+
319
+ except Exception as e:
320
+ self._logger(f"❌ Undetected Chrome test failed: {e}", "error")
321
+ return {
322
+ "success": False,
323
+ "error": str(e)
324
+ }
325
+ finally:
326
+ if driver:
327
+ try:
328
+ driver.quit()
329
+ except:
330
+ pass
331
+
332
+ def get_stealth_info(self) -> Dict[str, Any]:
333
+ """
334
+ Get information about undetected-chromedriver capabilities
335
+
336
+ Returns:
337
+ Dict with capability information
338
+ """
339
+ return {
340
+ "library": "undetected-chromedriver",
341
+ "selenium_stealth": "selenium-stealth",
342
+ "features": {
343
+ "automatic_chromedriver_patching": True,
344
+ "webdriver_property_removal": True,
345
+ "user_agent_spoofing": True,
346
+ "chrome_arguments_optimization": True,
347
+ "selenium_stealth_integration": True,
348
+ "random_user_agents": True,
349
+ "headless_support": True,
350
+ "headed_mode_recommended": True
351
+ },
352
+ "bypass_capabilities": {
353
+ "cloudflare": True,
354
+ "datadome": True,
355
+ "imperva": True,
356
+ "botd": "partial",
357
+ "recaptcha": True,
358
+ "basic_detection": True
359
+ },
360
+ "description": "Most effective solution for Selenium-based bot detection bypass"
361
+ }
@@ -60,15 +60,20 @@ from .decorators import (
60
60
  timing
61
61
  )
62
62
 
63
+ # Utilities - Cross-platform compatibility
64
+ from .utils import (
65
+ PlatformCompatibility,
66
+ ensure_platform_compatibility,
67
+ get_platform_info
68
+ )
69
+
63
70
  __version__ = get_driver_version()
64
71
  __author__ = "UnrealOn Team"
65
- __phase__ = "Phase 3.8: Clean Refactor"
66
72
 
67
73
  __all__ = [
68
74
  # Version
69
75
  "__version__",
70
76
  "__author__",
71
- "__phase__",
72
77
 
73
78
  # Core API
74
79
  "UniversalDriver",
@@ -102,4 +107,9 @@ __all__ = [
102
107
  "retry",
103
108
  "schedule",
104
109
  "timing",
110
+
111
+ # Utilities
112
+ "PlatformCompatibility",
113
+ "ensure_platform_compatibility",
114
+ "get_platform_info",
105
115
  ]
@@ -81,11 +81,18 @@ class ManagerFactory:
81
81
  @staticmethod
82
82
  def _setup_browser_manager(driver: 'UniversalDriver', registry: ManagerRegistry):
83
83
  """Setup browser manager."""
84
+ # Get proxy URL from proxy manager if enabled
85
+ proxy_url = None
86
+ if driver.config.proxy_enabled and hasattr(driver, 'proxy') and driver.proxy:
87
+ proxy_url = driver.proxy.get_proxy()
88
+
84
89
  browser_config = BrowserManagerConfig(
85
90
  enabled=True,
86
91
  headless=driver.config.browser_headless,
87
92
  timeout=driver.config.browser_timeout,
88
- parser_name=driver.driver_id
93
+ parser_name=driver.driver_id,
94
+ proxy_enabled=driver.config.proxy_enabled,
95
+ proxy_url=proxy_url
89
96
  )
90
97
  driver.browser = BrowserManager(browser_config)
91
98
  registry.register(driver.browser)
@@ -17,6 +17,11 @@ class BrowserManagerConfig(ManagerConfig):
17
17
  headless: bool = Field(default=True, description="Run headless")
18
18
  parser_name: str = Field(..., description="Parser name for browser")
19
19
  stealth_warmup_enabled: bool = Field(default=False, description="Enable stealth warmup")
20
+
21
+ # Proxy settings
22
+ proxy_enabled: bool = Field(default=False, description="Enable proxy usage")
23
+ proxy_url: Optional[str] = Field(default=None, description="Proxy URL (http://user:pass@host:port)")
24
+ proxy_timeout: int = Field(default=30, description="Proxy timeout in seconds")
20
25
 
21
26
 
22
27
  class BrowserManager(BaseManager):
@@ -53,6 +58,12 @@ class BrowserManager(BaseManager):
53
58
  try:
54
59
  self.logger.info("🚀 Starting browser (lazy initialization)...")
55
60
 
61
+ # Log proxy status
62
+ if self.config.proxy_enabled and self.config.proxy_url:
63
+ self.logger.info(f"🔒 Proxy enabled: {self.config.proxy_url}")
64
+ else:
65
+ self.logger.info("🌐 No proxy configured")
66
+
56
67
  # Create browser config with proper headless mode
57
68
  browser_mode = BrowserMode.HEADLESS if self.config.headless else BrowserMode.HEADED
58
69
 
@@ -62,8 +73,12 @@ class BrowserManager(BaseManager):
62
73
  stealth_warmup_enabled=self.config.stealth_warmup_enabled
63
74
  )
64
75
 
65
- # Create browser manager
76
+ # Create browser manager with proxy support
66
77
  self.browser = CoreBrowserManager(browser_config)
78
+
79
+ # Set proxy if enabled (we'll need to modify CoreBrowserManager to support this)
80
+ if self.config.proxy_enabled and self.config.proxy_url:
81
+ self.browser._proxy_url = self.config.proxy_url
67
82
 
68
83
  # Initialize browser
69
84
  await self.browser.initialize_async()
@@ -13,6 +13,7 @@ from .base import BaseManager, ManagerConfig
13
13
  class ProxyManagerConfig(ManagerConfig):
14
14
  """Proxy manager configuration."""
15
15
  proxies: List[str] = Field(default_factory=list, description="List of proxy URLs")
16
+ single_proxy: Optional[str] = Field(default=None, description="Single proxy URL to use")
16
17
  rotation_interval: int = Field(default=300, description="Rotation interval seconds")
17
18
  health_check_interval: int = Field(default=60, description="Health check interval")
18
19
 
@@ -29,11 +30,17 @@ class ProxyManager(BaseManager):
29
30
 
30
31
  async def _initialize(self) -> bool:
31
32
  """Initialize proxy manager."""
32
- self.active_proxies = self.config.proxies.copy()
33
+ # Use single proxy if specified, otherwise use proxy list
34
+ if self.config.single_proxy:
35
+ self.active_proxies = [self.config.single_proxy]
36
+ self.current_proxy = self.config.single_proxy
37
+ else:
38
+ self.active_proxies = self.config.proxies.copy()
39
+ if self.active_proxies:
40
+ self.current_proxy = random.choice(self.active_proxies)
33
41
 
34
- if self.active_proxies:
35
- self.current_proxy = random.choice(self.active_proxies)
36
- # Start rotation task
42
+ # Only start rotation if we have multiple proxies
43
+ if len(self.active_proxies) > 1:
37
44
  self._rotation_task = asyncio.create_task(self._rotation_loop())
38
45
 
39
46
  return True
@@ -1,9 +1,18 @@
1
1
  """
2
- Utility functions for UnrealOn Driver.
3
- """
2
+ Utility modules for UnrealOn Driver.
4
3
 
4
+ Contains cross-platform compatibility and other utility functions.
5
+ """
5
6
  from .time import utc_now
7
+ from .platform_compatibility import (
8
+ PlatformCompatibility,
9
+ ensure_platform_compatibility,
10
+ get_platform_info
11
+ )
6
12
 
7
13
  __all__ = [
8
- "utc_now",
9
- ]
14
+ 'utc_now',
15
+ 'PlatformCompatibility',
16
+ 'ensure_platform_compatibility',
17
+ 'get_platform_info'
18
+ ]