unrealon 2.0.9__py3-none-any.whl → 2.0.11__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,432 @@
1
+ """
2
+ NoDriverStealth - Integration with NoDriver
3
+
4
+ Provides integration with NoDriver for next-generation bot detection bypass:
5
+ - Async-first architecture
6
+ - No external ChromeDriver dependency
7
+ - Built-in stealth capabilities
8
+ - Advanced BotD bypass
9
+ """
10
+
11
+ import logging
12
+ import asyncio
13
+ from typing import Dict, Any, Optional, List
14
+
15
+ logger = logging.getLogger(__name__)
16
+ logger.setLevel(logging.DEBUG)
17
+
18
+ class NoDriverStealth:
19
+ """
20
+ Integration with NoDriver
21
+
22
+ NoDriver is the next-generation successor to undetected-chromedriver
23
+ with async-first architecture and built-in stealth capabilities
24
+ """
25
+
26
+ def __init__(self, logger_bridge=None):
27
+ """Initialize NoDriverStealth"""
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_nodriver_config(self) -> Dict[str, Any]:
52
+ """
53
+ Get optimized configuration for NoDriver
54
+
55
+ Returns:
56
+ Dict with NoDriver configuration
57
+ """
58
+ return {
59
+ "headless": False, # Recommend headed for best stealth
60
+ "browser_args": self.get_nodriver_arguments(),
61
+ "user_data_dir": None, # Use temporary profile
62
+ "lang": "en-US",
63
+ "sandbox": False,
64
+ "incognito": False, # Regular mode for better stealth
65
+ "host": "localhost",
66
+ "port": 0, # Auto-assign port
67
+ }
68
+
69
+ def get_nodriver_arguments(self) -> List[str]:
70
+ """
71
+ Get optimized browser arguments for NoDriver
72
+
73
+ Returns:
74
+ List of browser arguments for maximum stealth
75
+ """
76
+ return [
77
+ # Core stealth arguments
78
+ "--no-first-run",
79
+ "--no-default-browser-check",
80
+ "--disable-blink-features=AutomationControlled",
81
+ "--disable-features=VizDisplayCompositor",
82
+
83
+ # Enhanced stealth for NoDriver
84
+ "--disable-web-security",
85
+ "--disable-client-side-phishing-detection",
86
+ "--disable-component-extensions-with-background-pages",
87
+ "--disable-default-apps",
88
+ "--disable-domain-reliability",
89
+ "--disable-background-networking",
90
+ "--disable-translate",
91
+ "--disable-ipc-flooding-protection",
92
+
93
+ # Performance optimization
94
+ "--no-sandbox",
95
+ "--disable-dev-shm-usage",
96
+ "--disable-background-timer-throttling",
97
+ "--disable-backgrounding-occluded-windows",
98
+ "--disable-renderer-backgrounding",
99
+ "--disable-field-trial-config",
100
+ "--disable-back-forward-cache",
101
+
102
+ # System integration
103
+ "--disable-hang-monitor",
104
+ "--disable-prompt-on-repost",
105
+ "--disable-sync",
106
+ "--metrics-recording-only",
107
+ "--no-report-upload",
108
+
109
+ # Window and display
110
+ "--window-size=1366,768",
111
+ "--start-maximized",
112
+
113
+ # Media settings
114
+ "--mute-audio",
115
+ "--disable-audio-output",
116
+
117
+ # Extensions (minimal for realism)
118
+ "--disable-extensions-except=",
119
+
120
+ # Memory optimization
121
+ "--max_old_space_size=4096",
122
+ "--memory-pressure-off",
123
+
124
+ # Additional NoDriver optimizations
125
+ "--disable-logging",
126
+ "--disable-gpu-logging",
127
+ "--silent",
128
+ ]
129
+
130
+ async def create_nodriver_browser(self, **kwargs) -> Optional[Any]:
131
+ """
132
+ Create NoDriver browser instance
133
+
134
+ Args:
135
+ **kwargs: Additional configuration options
136
+
137
+ Returns:
138
+ NoDriver browser instance or None if failed
139
+ """
140
+ try:
141
+ import nodriver as uc
142
+
143
+ self._logger("🚀 Creating NoDriver browser...", "info")
144
+
145
+ # Get base configuration
146
+ config = self.get_nodriver_config()
147
+ config.update(kwargs)
148
+
149
+ # Create browser
150
+ browser = await uc.start(**config)
151
+
152
+ # Apply additional stealth measures
153
+ await self.apply_nodriver_stealth(browser)
154
+
155
+ self._logger("✅ NoDriver browser created successfully", "info")
156
+ return browser
157
+
158
+ except ImportError as e:
159
+ self._logger(f"❌ NoDriver not available: {e}", "error")
160
+ return None
161
+ except Exception as e:
162
+ self._logger(f"❌ Failed to create NoDriver browser: {e}", "error")
163
+ return None
164
+
165
+ async def apply_nodriver_stealth(self, browser) -> bool:
166
+ """
167
+ Apply additional stealth measures to NoDriver browser
168
+
169
+ Args:
170
+ browser: NoDriver browser instance
171
+
172
+ Returns:
173
+ True if successful
174
+ """
175
+ try:
176
+ self._logger("🛡️ Applying NoDriver stealth measures...", "info")
177
+
178
+ # Get the main tab/page
179
+ page = await browser.get("about:blank")
180
+
181
+ # Apply comprehensive stealth scripts
182
+ await self.apply_stealth_scripts(page)
183
+
184
+ self._logger("✅ NoDriver stealth measures applied", "info")
185
+ return True
186
+
187
+ except Exception as e:
188
+ self._logger(f"❌ Failed to apply NoDriver stealth: {e}", "error")
189
+ return False
190
+
191
+ async def apply_stealth_scripts(self, page) -> None:
192
+ """
193
+ Apply comprehensive stealth scripts to NoDriver page
194
+
195
+ Args:
196
+ page: NoDriver page instance
197
+ """
198
+ # Enhanced webdriver removal
199
+ webdriver_script = """
200
+ // Comprehensive webdriver removal for NoDriver
201
+ Object.defineProperty(navigator, 'webdriver', {
202
+ get: () => undefined,
203
+ configurable: true
204
+ });
205
+
206
+ // Remove from prototype
207
+ if (navigator.webdriver !== undefined) {
208
+ delete Object.getPrototypeOf(navigator).webdriver;
209
+ }
210
+
211
+ // Remove automation indicators
212
+ ['__webdriver_evaluate', '__selenium_evaluate', '__webdriver_script_function',
213
+ '__fxdriver_evaluate', '__driver_unwrapped', '__webdriver_unwrapped',
214
+ '_Selenium_IDE_Recorder', '_selenium', 'calledSelenium',
215
+ '_WEBDRIVER_ELEM_CACHE', 'ChromeDriverw', '$cdc_asdjflasutopfhvcZLmcfl_'].forEach(prop => {
216
+ delete window[prop];
217
+ delete document[prop];
218
+ });
219
+ """
220
+
221
+ # Chrome object creation
222
+ chrome_script = """
223
+ // Create realistic Chrome object for NoDriver
224
+ if (!window.chrome) {
225
+ window.chrome = {
226
+ runtime: {
227
+ onConnect: null,
228
+ onMessage: null,
229
+ sendMessage: () => {},
230
+ connect: () => ({
231
+ onMessage: { addListener: () => {}, removeListener: () => {} },
232
+ onDisconnect: { addListener: () => {}, removeListener: () => {} },
233
+ postMessage: () => {}
234
+ }),
235
+ id: undefined
236
+ },
237
+ app: {
238
+ isInstalled: false
239
+ },
240
+ csi: () => {},
241
+ loadTimes: () => ({
242
+ requestTime: Date.now() / 1000,
243
+ startLoadTime: Date.now() / 1000,
244
+ commitLoadTime: Date.now() / 1000,
245
+ finishDocumentLoadTime: Date.now() / 1000,
246
+ finishLoadTime: Date.now() / 1000,
247
+ firstPaintTime: Date.now() / 1000,
248
+ firstPaintAfterLoadTime: 0,
249
+ navigationType: 'Other'
250
+ })
251
+ };
252
+ }
253
+ """
254
+
255
+ # Plugin spoofing
256
+ plugin_script = """
257
+ // Plugin spoofing for NoDriver
258
+ const plugins = [
259
+ {
260
+ name: 'Chrome PDF Plugin',
261
+ filename: 'internal-pdf-viewer',
262
+ description: 'Portable Document Format',
263
+ length: 1
264
+ },
265
+ {
266
+ name: 'Chrome PDF Viewer',
267
+ filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai',
268
+ description: 'Portable Document Format',
269
+ length: 1
270
+ }
271
+ ];
272
+
273
+ Object.defineProperty(navigator, 'plugins', {
274
+ get: () => plugins,
275
+ configurable: true
276
+ });
277
+ """
278
+
279
+ # WebGL spoofing
280
+ webgl_script = """
281
+ // WebGL spoofing for NoDriver
282
+ const originalGetParameter = WebGLRenderingContext.prototype.getParameter;
283
+ WebGLRenderingContext.prototype.getParameter = function(parameter) {
284
+ if (parameter === 37445) return 'Intel Inc.';
285
+ if (parameter === 37446) return 'Intel Iris OpenGL Engine';
286
+ return originalGetParameter.call(this, parameter);
287
+ };
288
+ """
289
+
290
+ # Apply all scripts
291
+ scripts = [webdriver_script, chrome_script, plugin_script, webgl_script]
292
+
293
+ for script in scripts:
294
+ try:
295
+ await page.evaluate(script)
296
+ except Exception as e:
297
+ self._logger(f"⚠️ Script application warning: {e}", "warning")
298
+
299
+ async def test_nodriver_stealth(self, test_url: str) -> Dict[str, Any]:
300
+ """
301
+ Test NoDriver stealth effectiveness
302
+
303
+ Args:
304
+ test_url: URL to test stealth effectiveness
305
+
306
+ Returns:
307
+ Dict with test results
308
+ """
309
+ browser = None
310
+ try:
311
+ self._logger(f"🧪 Testing NoDriver stealth on {test_url}...", "info")
312
+
313
+ # Create browser
314
+ browser = await self.create_nodriver_browser(headless=True)
315
+ if not browser:
316
+ return {
317
+ "success": False,
318
+ "error": "Failed to create NoDriver browser"
319
+ }
320
+
321
+ # Navigate to test page
322
+ page = await browser.get(test_url)
323
+
324
+ # Wait for page to load
325
+ await asyncio.sleep(5)
326
+
327
+ # Extract detection results
328
+ try:
329
+ results = await page.evaluate("""
330
+ () => {
331
+ return {
332
+ userAgent: navigator.userAgent,
333
+ webdriver: navigator.webdriver !== undefined,
334
+ chrome: !!window.chrome,
335
+ plugins: navigator.plugins.length,
336
+ languages: navigator.languages ? navigator.languages.length : 0,
337
+ botDetectionResults: window.botDetectionResults || null
338
+ };
339
+ }
340
+ """)
341
+
342
+ return {
343
+ "success": True,
344
+ "results": results,
345
+ "is_bot": results.get("webdriver", False),
346
+ "user_agent": results.get("userAgent", ""),
347
+ "chrome_object": results.get("chrome", False),
348
+ "plugins_count": results.get("plugins", 0),
349
+ "bot_detection": results.get("botDetectionResults")
350
+ }
351
+
352
+ except Exception as e:
353
+ return {
354
+ "success": False,
355
+ "error": f"Failed to extract results: {e}"
356
+ }
357
+
358
+ except Exception as e:
359
+ self._logger(f"❌ NoDriver test failed: {e}", "error")
360
+ return {
361
+ "success": False,
362
+ "error": str(e)
363
+ }
364
+ finally:
365
+ if browser:
366
+ try:
367
+ browser.stop()
368
+ except:
369
+ pass
370
+
371
+ async def create_stealth_page(self, browser, url: str):
372
+ """
373
+ Create a new page with full stealth applied
374
+
375
+ Args:
376
+ browser: NoDriver browser instance
377
+ url: URL to navigate to
378
+
379
+ Returns:
380
+ NoDriver page with stealth applied
381
+ """
382
+ try:
383
+ # Create new page
384
+ page = await browser.get(url)
385
+
386
+ # Apply stealth scripts
387
+ await self.apply_stealth_scripts(page)
388
+
389
+ return page
390
+
391
+ except Exception as e:
392
+ self._logger(f"❌ Failed to create stealth page: {e}", "error")
393
+ return None
394
+
395
+ def get_stealth_info(self) -> Dict[str, Any]:
396
+ """
397
+ Get information about NoDriver capabilities
398
+
399
+ Returns:
400
+ Dict with capability information
401
+ """
402
+ return {
403
+ "library": "nodriver",
404
+ "architecture": "async-first",
405
+ "features": {
406
+ "no_external_chromedriver": True,
407
+ "built_in_stealth": True,
408
+ "async_operations": True,
409
+ "devtools_protocol": True,
410
+ "automatic_updates": True,
411
+ "headless_support": True,
412
+ "headed_mode_recommended": True,
413
+ "memory_efficient": True
414
+ },
415
+ "bypass_capabilities": {
416
+ "cloudflare": True,
417
+ "datadome": True,
418
+ "imperva": True,
419
+ "botd": "advanced",
420
+ "recaptcha": True,
421
+ "advanced_fingerprinting": True,
422
+ "waf_bypass": True
423
+ },
424
+ "advantages": [
425
+ "No ChromeDriver dependency",
426
+ "Better performance with async operations",
427
+ "Built-in stealth capabilities",
428
+ "Regular updates and maintenance",
429
+ "Advanced DevTools Protocol usage"
430
+ ],
431
+ "description": "Next-generation bot detection bypass with async architecture"
432
+ }
@@ -0,0 +1,179 @@
1
+ """
2
+ PlaywrightStealth - Integration with playwright-stealth 2.0.0
3
+
4
+ Provides integration with playwright-stealth library for detection bypass:
5
+ - Configuration of all available stealth options
6
+ - Application to pages and contexts
7
+ - Error handling and fallback
8
+ """
9
+
10
+ import logging
11
+ from playwright.async_api import Page, BrowserContext
12
+
13
+ # CRITICAL REQUIREMENTS COMPLIANCE - NO INLINE IMPORTS!
14
+ from playwright_stealth import Stealth
15
+
16
+ logger = logging.getLogger(__name__)
17
+ logger.setLevel(logging.DEBUG)
18
+
19
+ class PlaywrightStealth:
20
+ """
21
+ Integration with playwright-stealth 2.0.0
22
+
23
+ Provides application of all available stealth techniques
24
+ from playwright-stealth library for maximum detection bypass
25
+ """
26
+
27
+ def __init__(self, logger_bridge=None):
28
+ """Initialize PlaywrightStealth"""
29
+ self.logger_bridge = logger_bridge
30
+ self.stealth_config = self._create_stealth_config()
31
+
32
+ def _logger(self, message: str, level: str = "info") -> None:
33
+ """Private wrapper for logger with bridge support"""
34
+ if self.logger_bridge:
35
+ if level == "info":
36
+ self.logger_bridge.log_info(message)
37
+ elif level == "error":
38
+ self.logger_bridge.log_error(message)
39
+ elif level == "warning":
40
+ self.logger_bridge.log_warning(message)
41
+ else:
42
+ self.logger_bridge.log_info(message)
43
+ else:
44
+ if level == "info":
45
+ logger.info(message)
46
+ elif level == "error":
47
+ logger.error(message)
48
+ elif level == "warning":
49
+ logger.warning(message)
50
+ else:
51
+ logger.info(message)
52
+
53
+ def _create_stealth_config(self) -> Stealth:
54
+ """
55
+ Create comprehensive stealth configuration
56
+ Enables ALL available stealth features for maximum protection
57
+ """
58
+ return Stealth(
59
+ # 🔥 CRITICAL: Core webdriver removal
60
+ navigator_webdriver=True, # Remove navigator.webdriver property
61
+
62
+ # 🎭 Chrome object spoofing
63
+ chrome_runtime=True, # Enable chrome runtime spoofing
64
+ chrome_app=True, # Enable chrome app spoofing
65
+ chrome_csi=True, # Enable chrome CSI spoofing
66
+ chrome_load_times=True, # Enable load times spoofing
67
+
68
+ # 🌐 Navigator spoofing
69
+ navigator_languages=True, # Spoof languages
70
+ navigator_permissions=True, # Spoof permissions
71
+ navigator_plugins=True, # Spoof plugins
72
+ navigator_user_agent=True, # Spoof user agent - CRITICAL for headless
73
+ navigator_vendor=True, # Spoof navigator vendor
74
+ navigator_platform=True, # Spoof platform
75
+ navigator_hardware_concurrency=True, # Spoof hardware concurrency
76
+
77
+ # 🎨 WebGL and Canvas spoofing
78
+ webgl_vendor=True, # Spoof WebGL vendor - CRITICAL for BotD
79
+ hairline=True, # Enable hairline spoofing - helps with canvas fingerprinting
80
+
81
+ # 🔧 Modern browser features
82
+ sec_ch_ua=True, # Enable sec-ch-ua spoofing - modern Chrome headers
83
+ iframe_content_window=True, # Enable iframe spoofing
84
+ media_codecs=True, # Enable media codecs spoofing
85
+ )
86
+
87
+ async def apply_stealth(self, page: Page) -> bool:
88
+ """
89
+ Apply playwright-stealth to page
90
+
91
+ Args:
92
+ page: Playwright page instance
93
+
94
+ Returns:
95
+ True if successful, False otherwise
96
+ """
97
+ try:
98
+ self._logger("🎭 Applying playwright-stealth 2.0.0...", "info")
99
+
100
+ # Apply stealth using new 2.0.0 API
101
+ await self.stealth_config.apply_stealth_async(page)
102
+
103
+ self._logger("✅ Playwright-stealth 2.0.0 applied successfully", "info")
104
+ return True
105
+
106
+ except Exception as e:
107
+ self._logger(f"❌ Playwright-stealth failed: {e}", "error")
108
+ return False
109
+
110
+ async def apply_stealth_to_context(self, context: BrowserContext) -> bool:
111
+ """
112
+ Apply stealth to browser context
113
+
114
+ Args:
115
+ context: Playwright browser context
116
+
117
+ Returns:
118
+ True if successful, False otherwise
119
+ """
120
+ try:
121
+ self._logger("🎭 Applying playwright-stealth to context...", "info")
122
+
123
+ # For context, we need to apply stealth to each new page
124
+ # This is handled by the context's page creation events
125
+
126
+ # Add init script for basic webdriver removal at context level
127
+ webdriver_removal_script = """
128
+ // Basic webdriver removal at context level
129
+ Object.defineProperty(navigator, 'webdriver', {
130
+ get: () => undefined,
131
+ configurable: true
132
+ });
133
+
134
+ // Remove from prototype
135
+ if (navigator.webdriver !== undefined) {
136
+ delete Object.getPrototypeOf(navigator).webdriver;
137
+ }
138
+ """
139
+
140
+ await context.add_init_script(webdriver_removal_script)
141
+
142
+ self._logger("✅ Playwright-stealth context setup completed", "info")
143
+ return True
144
+
145
+ except Exception as e:
146
+ self._logger(f"❌ Playwright-stealth context setup failed: {e}", "error")
147
+ return False
148
+
149
+ def get_stealth_info(self) -> dict:
150
+ """
151
+ Get information about current stealth configuration
152
+
153
+ Returns:
154
+ Dict with stealth configuration details
155
+ """
156
+ return {
157
+ "library": "playwright-stealth",
158
+ "version": "2.0.0",
159
+ "features_enabled": {
160
+ "navigator_webdriver": True,
161
+ "chrome_runtime": True,
162
+ "chrome_app": True,
163
+ "chrome_csi": True,
164
+ "chrome_load_times": True,
165
+ "navigator_languages": True,
166
+ "navigator_permissions": True,
167
+ "navigator_plugins": True,
168
+ "navigator_user_agent": True,
169
+ "navigator_vendor": True,
170
+ "navigator_platform": True,
171
+ "navigator_hardware_concurrency": True,
172
+ "webgl_vendor": True,
173
+ "hairline": True,
174
+ "sec_ch_ua": True,
175
+ "iframe_content_window": True,
176
+ "media_codecs": True,
177
+ },
178
+ "description": "Comprehensive stealth configuration with all features enabled"
179
+ }