unrealon 1.1.5__py3-none-any.whl → 2.0.4__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.
- {unrealon-1.1.5.dist-info/licenses → unrealon-2.0.4.dist-info}/LICENSE +1 -1
- unrealon-2.0.4.dist-info/METADATA +491 -0
- unrealon-2.0.4.dist-info/RECORD +129 -0
- {unrealon-1.1.5.dist-info → unrealon-2.0.4.dist-info}/WHEEL +2 -1
- unrealon-2.0.4.dist-info/entry_points.txt +3 -0
- unrealon-2.0.4.dist-info/top_level.txt +3 -0
- unrealon_browser/__init__.py +5 -2
- unrealon_browser/cli/browser_cli.py +18 -9
- unrealon_browser/cli/interactive_mode.py +18 -7
- unrealon_browser/core/browser_manager.py +76 -13
- unrealon_browser/dto/__init__.py +21 -0
- unrealon_browser/dto/bot_detection.py +175 -0
- unrealon_browser/dto/models/config.py +14 -1
- unrealon_browser/managers/__init__.py +4 -1
- unrealon_browser/managers/logger_bridge.py +3 -6
- unrealon_browser/managers/page_wait_manager.py +198 -0
- unrealon_browser/stealth/__init__.py +27 -0
- unrealon_browser/stealth/bypass_techniques.pyc +0 -0
- unrealon_browser/stealth/manager.pyc +0 -0
- unrealon_browser/stealth/nodriver_stealth.pyc +0 -0
- unrealon_browser/stealth/playwright_stealth.pyc +0 -0
- unrealon_browser/stealth/scanner_tester.pyc +0 -0
- unrealon_browser/stealth/undetected_chrome.pyc +0 -0
- unrealon_core/__init__.py +160 -0
- unrealon_core/config/__init__.py +16 -0
- unrealon_core/config/environment.py +98 -0
- unrealon_core/config/urls.py +93 -0
- unrealon_core/enums/__init__.py +24 -0
- unrealon_core/enums/status.py +216 -0
- unrealon_core/enums/types.py +240 -0
- unrealon_core/error_handling/__init__.py +45 -0
- unrealon_core/error_handling/circuit_breaker.py +292 -0
- unrealon_core/error_handling/error_context.py +324 -0
- unrealon_core/error_handling/recovery.py +371 -0
- unrealon_core/error_handling/retry.py +268 -0
- unrealon_core/exceptions/__init__.py +46 -0
- unrealon_core/exceptions/base.py +292 -0
- unrealon_core/exceptions/communication.py +22 -0
- unrealon_core/exceptions/driver.py +11 -0
- unrealon_core/exceptions/proxy.py +11 -0
- unrealon_core/exceptions/task.py +12 -0
- unrealon_core/exceptions/validation.py +17 -0
- unrealon_core/models/__init__.py +98 -0
- unrealon_core/models/arq_context.py +252 -0
- unrealon_core/models/arq_responses.py +125 -0
- unrealon_core/models/base.py +291 -0
- unrealon_core/models/bridge_stats.py +58 -0
- unrealon_core/models/communication.py +39 -0
- unrealon_core/models/config.py +47 -0
- unrealon_core/models/connection_stats.py +47 -0
- unrealon_core/models/driver.py +30 -0
- unrealon_core/models/driver_details.py +98 -0
- unrealon_core/models/logging.py +28 -0
- unrealon_core/models/task.py +21 -0
- unrealon_core/models/typed_responses.py +210 -0
- unrealon_core/models/websocket/__init__.py +91 -0
- unrealon_core/models/websocket/base.py +49 -0
- unrealon_core/models/websocket/config.py +200 -0
- unrealon_core/models/websocket/driver.py +215 -0
- unrealon_core/models/websocket/errors.py +138 -0
- unrealon_core/models/websocket/heartbeat.py +100 -0
- unrealon_core/models/websocket/logging.py +261 -0
- unrealon_core/models/websocket/proxy.py +496 -0
- unrealon_core/models/websocket/tasks.py +275 -0
- unrealon_core/models/websocket/utils.py +153 -0
- unrealon_core/models/websocket_session.py +144 -0
- unrealon_core/monitoring/__init__.py +43 -0
- unrealon_core/monitoring/alerts.py +398 -0
- unrealon_core/monitoring/dashboard.py +307 -0
- unrealon_core/monitoring/health_check.py +354 -0
- unrealon_core/monitoring/metrics.py +352 -0
- unrealon_core/utils/__init__.py +11 -0
- unrealon_core/utils/time.py +61 -0
- unrealon_core/version.py +219 -0
- unrealon_driver/__init__.py +88 -50
- unrealon_driver/core_module/__init__.py +34 -0
- unrealon_driver/core_module/base.py +184 -0
- unrealon_driver/core_module/config.py +30 -0
- unrealon_driver/core_module/event_manager.py +127 -0
- unrealon_driver/core_module/protocols.py +98 -0
- unrealon_driver/core_module/registry.py +146 -0
- unrealon_driver/decorators/__init__.py +15 -0
- unrealon_driver/decorators/retry.py +117 -0
- unrealon_driver/decorators/schedule.py +137 -0
- unrealon_driver/decorators/task.py +61 -0
- unrealon_driver/decorators/timing.py +132 -0
- unrealon_driver/driver/__init__.py +20 -0
- unrealon_driver/driver/communication/__init__.py +10 -0
- unrealon_driver/driver/communication/session.py +203 -0
- unrealon_driver/driver/communication/websocket_client.py +197 -0
- unrealon_driver/driver/core/__init__.py +10 -0
- unrealon_driver/driver/core/config.py +85 -0
- unrealon_driver/driver/core/driver.py +221 -0
- unrealon_driver/driver/factory/__init__.py +9 -0
- unrealon_driver/driver/factory/manager_factory.py +130 -0
- unrealon_driver/driver/lifecycle/__init__.py +11 -0
- unrealon_driver/driver/lifecycle/daemon.py +76 -0
- unrealon_driver/driver/lifecycle/initialization.py +97 -0
- unrealon_driver/driver/lifecycle/shutdown.py +48 -0
- unrealon_driver/driver/monitoring/__init__.py +9 -0
- unrealon_driver/driver/monitoring/health.py +63 -0
- unrealon_driver/driver/utilities/__init__.py +10 -0
- unrealon_driver/driver/utilities/logging.py +51 -0
- unrealon_driver/driver/utilities/serialization.py +61 -0
- unrealon_driver/managers/__init__.py +32 -0
- unrealon_driver/managers/base.py +174 -0
- unrealon_driver/managers/browser.py +98 -0
- unrealon_driver/managers/cache.py +116 -0
- unrealon_driver/managers/http.py +107 -0
- unrealon_driver/managers/logger.py +286 -0
- unrealon_driver/managers/proxy.py +99 -0
- unrealon_driver/managers/registry.py +87 -0
- unrealon_driver/managers/threading.py +54 -0
- unrealon_driver/managers/update.py +107 -0
- unrealon_driver/utils/__init__.py +9 -0
- unrealon_driver/utils/time.py +10 -0
- unrealon/__init__.py +0 -40
- unrealon-1.1.5.dist-info/METADATA +0 -621
- unrealon-1.1.5.dist-info/RECORD +0 -54
- unrealon-1.1.5.dist-info/entry_points.txt +0 -9
- unrealon_browser/managers/stealth.py +0 -388
- unrealon_driver/exceptions.py +0 -33
- unrealon_driver/html_analyzer/__init__.py +0 -32
- unrealon_driver/html_analyzer/cleaner.py +0 -657
- unrealon_driver/html_analyzer/config.py +0 -64
- unrealon_driver/html_analyzer/manager.py +0 -247
- unrealon_driver/html_analyzer/models.py +0 -115
- unrealon_driver/html_analyzer/websocket_analyzer.py +0 -157
- unrealon_driver/models/__init__.py +0 -31
- unrealon_driver/models/websocket.py +0 -98
- unrealon_driver/parser/__init__.py +0 -36
- unrealon_driver/parser/cli_manager.py +0 -142
- unrealon_driver/parser/daemon_manager.py +0 -403
- unrealon_driver/parser/managers/__init__.py +0 -25
- unrealon_driver/parser/managers/config.py +0 -293
- unrealon_driver/parser/managers/error.py +0 -412
- unrealon_driver/parser/managers/result.py +0 -321
- unrealon_driver/parser/parser_manager.py +0 -458
- unrealon_driver/smart_logging/__init__.py +0 -24
- unrealon_driver/smart_logging/models.py +0 -44
- unrealon_driver/smart_logging/smart_logger.py +0 -406
- unrealon_driver/smart_logging/unified_logger.py +0 -525
- unrealon_driver/websocket/__init__.py +0 -31
- unrealon_driver/websocket/client.py +0 -249
- unrealon_driver/websocket/config.py +0 -188
- unrealon_driver/websocket/manager.py +0 -90
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Page Wait Manager - Convenient methods for different page loading scenarios
|
|
3
|
+
"""
|
|
4
|
+
import asyncio
|
|
5
|
+
from typing import Optional
|
|
6
|
+
from playwright.async_api import Page
|
|
7
|
+
|
|
8
|
+
from .logger_bridge import BrowserLoggerBridge as LoggingBridge
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class PageWaitManager:
|
|
12
|
+
"""Manager for different page waiting strategies"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, page: Optional[Page], logger_bridge: LoggingBridge):
|
|
15
|
+
self._page = page
|
|
16
|
+
self.logger_bridge = logger_bridge
|
|
17
|
+
|
|
18
|
+
def update_page(self, page: Optional[Page]):
|
|
19
|
+
"""Update the page reference"""
|
|
20
|
+
self._page = page
|
|
21
|
+
|
|
22
|
+
# Quick wait methods with fallback
|
|
23
|
+
async def wait_fast_with_fallback(self) -> bool:
|
|
24
|
+
"""Fast wait - networkidle 5s, fallback to domcontentloaded 3s"""
|
|
25
|
+
if not self._page:
|
|
26
|
+
return False
|
|
27
|
+
|
|
28
|
+
self.logger_bridge.log_info("🚀 Fast wait with fallback (networkidle 5s → domcontentloaded 3s)")
|
|
29
|
+
|
|
30
|
+
# Try networkidle first
|
|
31
|
+
if await self._wait_for_state("networkidle", 5000):
|
|
32
|
+
return True
|
|
33
|
+
|
|
34
|
+
# Fallback to domcontentloaded
|
|
35
|
+
self.logger_bridge.log_info("⏳ Networkidle timeout, trying domcontentloaded...")
|
|
36
|
+
return await self._wait_for_state("domcontentloaded", 3000)
|
|
37
|
+
|
|
38
|
+
async def wait_safe_with_fallback(self) -> bool:
|
|
39
|
+
"""Safe wait - networkidle 10s, fallback to domcontentloaded 5s"""
|
|
40
|
+
if not self._page:
|
|
41
|
+
return False
|
|
42
|
+
|
|
43
|
+
self.logger_bridge.log_info("🛡️ Safe wait with fallback (networkidle 10s → domcontentloaded 5s)")
|
|
44
|
+
|
|
45
|
+
# Try networkidle first
|
|
46
|
+
if await self._wait_for_state("networkidle", 10000):
|
|
47
|
+
return True
|
|
48
|
+
|
|
49
|
+
# Fallback to domcontentloaded
|
|
50
|
+
self.logger_bridge.log_info("⏳ Networkidle timeout, trying domcontentloaded...")
|
|
51
|
+
return await self._wait_for_state("domcontentloaded", 5000)
|
|
52
|
+
|
|
53
|
+
# Generic methods
|
|
54
|
+
async def wait_fast(self) -> bool:
|
|
55
|
+
"""Fast wait - domcontentloaded 3s"""
|
|
56
|
+
if not self._page:
|
|
57
|
+
return False
|
|
58
|
+
|
|
59
|
+
self.logger_bridge.log_info("⚡ Fast wait (domcontentloaded 3s)")
|
|
60
|
+
return await self._wait_for_state("domcontentloaded", 3000)
|
|
61
|
+
|
|
62
|
+
async def wait_standard(self) -> bool:
|
|
63
|
+
"""Standard wait - networkidle 10s"""
|
|
64
|
+
if not self._page:
|
|
65
|
+
return False
|
|
66
|
+
|
|
67
|
+
self.logger_bridge.log_info("⏳ Standard wait (networkidle 10s)")
|
|
68
|
+
return await self._wait_for_state("networkidle", 10000)
|
|
69
|
+
|
|
70
|
+
async def wait_full_load(self) -> bool:
|
|
71
|
+
"""Full page load including images - load 30s"""
|
|
72
|
+
if not self._page:
|
|
73
|
+
return False
|
|
74
|
+
|
|
75
|
+
self.logger_bridge.log_info("🖼️ Full load wait (load 30s)")
|
|
76
|
+
return await self._wait_for_state("load", 30000)
|
|
77
|
+
|
|
78
|
+
async def wait_minimal(self) -> bool:
|
|
79
|
+
"""Minimal wait - domcontentloaded 1s"""
|
|
80
|
+
if not self._page:
|
|
81
|
+
return False
|
|
82
|
+
|
|
83
|
+
self.logger_bridge.log_info("⚡ Minimal wait (domcontentloaded 1s)")
|
|
84
|
+
return await self._wait_for_state("domcontentloaded", 1000)
|
|
85
|
+
|
|
86
|
+
# Specialized methods
|
|
87
|
+
async def wait_spa(self) -> bool:
|
|
88
|
+
"""Single Page Application wait - networkidle 15s"""
|
|
89
|
+
if not self._page:
|
|
90
|
+
return False
|
|
91
|
+
|
|
92
|
+
self.logger_bridge.log_info("⚛️ SPA wait (networkidle 15s)")
|
|
93
|
+
return await self._wait_for_state("networkidle", 15000)
|
|
94
|
+
|
|
95
|
+
# Custom methods
|
|
96
|
+
async def wait_custom(self, wait_type: str = "networkidle", timeout: int = 10000) -> bool:
|
|
97
|
+
"""Custom wait with specified parameters"""
|
|
98
|
+
if not self._page:
|
|
99
|
+
return False
|
|
100
|
+
|
|
101
|
+
self.logger_bridge.log_info(f"🔧 Custom wait ({wait_type} {timeout}ms)")
|
|
102
|
+
return await self._wait_for_state(wait_type, timeout)
|
|
103
|
+
|
|
104
|
+
async def wait_with_fallback(self,
|
|
105
|
+
primary_type: str = "networkidle",
|
|
106
|
+
primary_timeout: int = 10000,
|
|
107
|
+
fallback_type: str = "domcontentloaded",
|
|
108
|
+
fallback_timeout: int = 5000) -> bool:
|
|
109
|
+
"""Wait with custom fallback strategy"""
|
|
110
|
+
if not self._page:
|
|
111
|
+
return False
|
|
112
|
+
|
|
113
|
+
self.logger_bridge.log_info(f"🔄 Fallback wait ({primary_type} {primary_timeout}ms → {fallback_type} {fallback_timeout}ms)")
|
|
114
|
+
|
|
115
|
+
# Try primary first
|
|
116
|
+
if await self._wait_for_state(primary_type, primary_timeout):
|
|
117
|
+
return True
|
|
118
|
+
|
|
119
|
+
# Fallback
|
|
120
|
+
self.logger_bridge.log_info(f"⏳ {primary_type} timeout, trying {fallback_type}...")
|
|
121
|
+
return await self._wait_for_state(fallback_type, fallback_timeout)
|
|
122
|
+
|
|
123
|
+
# Helper methods
|
|
124
|
+
async def _wait_for_state(self, wait_type: str, timeout: int) -> bool:
|
|
125
|
+
"""Internal method to wait for specific state"""
|
|
126
|
+
if not self._page:
|
|
127
|
+
return False
|
|
128
|
+
|
|
129
|
+
try:
|
|
130
|
+
if wait_type == "networkidle":
|
|
131
|
+
await self._page.wait_for_load_state("networkidle", timeout=timeout)
|
|
132
|
+
elif wait_type == "domcontentloaded":
|
|
133
|
+
await self._page.wait_for_load_state("domcontentloaded", timeout=timeout)
|
|
134
|
+
elif wait_type == "load":
|
|
135
|
+
await self._page.wait_for_load_state("load", timeout=timeout)
|
|
136
|
+
else:
|
|
137
|
+
# Default to networkidle
|
|
138
|
+
await self._page.wait_for_load_state("networkidle", timeout=timeout)
|
|
139
|
+
|
|
140
|
+
self.logger_bridge.log_info(f"✅ Page ready ({wait_type})")
|
|
141
|
+
return True
|
|
142
|
+
|
|
143
|
+
except Exception as e:
|
|
144
|
+
self.logger_bridge.log_warning(f"⚠️ Page ready timeout ({wait_type}): {e}")
|
|
145
|
+
return False
|
|
146
|
+
|
|
147
|
+
# Utility methods
|
|
148
|
+
async def wait_for_selector(self, selector: str, timeout: int = 10000) -> bool:
|
|
149
|
+
"""Wait for specific selector to appear"""
|
|
150
|
+
if not self._page:
|
|
151
|
+
return False
|
|
152
|
+
|
|
153
|
+
try:
|
|
154
|
+
self.logger_bridge.log_info(f"🎯 Waiting for selector: {selector}")
|
|
155
|
+
await self._page.wait_for_selector(selector, timeout=timeout)
|
|
156
|
+
self.logger_bridge.log_info(f"✅ Selector found: {selector}")
|
|
157
|
+
return True
|
|
158
|
+
except Exception as e:
|
|
159
|
+
self.logger_bridge.log_warning(f"⚠️ Selector timeout: {selector} - {e}")
|
|
160
|
+
return False
|
|
161
|
+
|
|
162
|
+
async def wait_for_text(self, text: str, timeout: int = 10000) -> bool:
|
|
163
|
+
"""Wait for specific text to appear on page"""
|
|
164
|
+
if not self._page:
|
|
165
|
+
return False
|
|
166
|
+
|
|
167
|
+
try:
|
|
168
|
+
self.logger_bridge.log_info(f"📝 Waiting for text: {text}")
|
|
169
|
+
await self._page.wait_for_function(
|
|
170
|
+
f"document.body.innerText.includes('{text}')",
|
|
171
|
+
timeout=timeout
|
|
172
|
+
)
|
|
173
|
+
self.logger_bridge.log_info(f"✅ Text found: {text}")
|
|
174
|
+
return True
|
|
175
|
+
except Exception as e:
|
|
176
|
+
self.logger_bridge.log_warning(f"⚠️ Text timeout: {text} - {e}")
|
|
177
|
+
return False
|
|
178
|
+
|
|
179
|
+
async def wait_for_url_change(self, timeout: int = 10000) -> bool:
|
|
180
|
+
"""Wait for URL to change"""
|
|
181
|
+
if not self._page:
|
|
182
|
+
return False
|
|
183
|
+
|
|
184
|
+
try:
|
|
185
|
+
current_url = self._page.url
|
|
186
|
+
self.logger_bridge.log_info(f"🔗 Waiting for URL change from: {current_url}")
|
|
187
|
+
|
|
188
|
+
await self._page.wait_for_function(
|
|
189
|
+
f"window.location.href !== '{current_url}'",
|
|
190
|
+
timeout=timeout
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
new_url = self._page.url
|
|
194
|
+
self.logger_bridge.log_info(f"✅ URL changed to: {new_url}")
|
|
195
|
+
return True
|
|
196
|
+
except Exception as e:
|
|
197
|
+
self.logger_bridge.log_warning(f"⚠️ URL change timeout: {e}")
|
|
198
|
+
return False
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""
|
|
2
|
+
UnrealOn Stealth Package - Advanced anti-detection system
|
|
3
|
+
|
|
4
|
+
Modular bot detection bypass system:
|
|
5
|
+
- PlaywrightStealth: playwright-stealth integration
|
|
6
|
+
- UndetectedChrome: undetected-chromedriver support
|
|
7
|
+
- NoDriverStealth: NoDriver integration
|
|
8
|
+
- BypassTechniques: advanced BotD bypass techniques
|
|
9
|
+
- StealthManager: main coordinator for all techniques
|
|
10
|
+
- ScannerTester: real-world testing through UnrealOn scanner
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from .manager import StealthManager
|
|
14
|
+
from .playwright_stealth import PlaywrightStealth
|
|
15
|
+
from .undetected_chrome import UndetectedChrome
|
|
16
|
+
from .nodriver_stealth import NoDriverStealth
|
|
17
|
+
from .bypass_techniques import BypassTechniques
|
|
18
|
+
from .scanner_tester import ScannerTester
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"StealthManager",
|
|
22
|
+
"PlaywrightStealth",
|
|
23
|
+
"UndetectedChrome",
|
|
24
|
+
"NoDriverStealth",
|
|
25
|
+
"BypassTechniques",
|
|
26
|
+
"ScannerTester"
|
|
27
|
+
]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""
|
|
2
|
+
UnrealOn Core Package
|
|
3
|
+
|
|
4
|
+
Core models, enums, and exceptions for the UnrealOn RPC system.
|
|
5
|
+
This package provides the foundational data structures and utilities
|
|
6
|
+
used across all UnrealOn components.
|
|
7
|
+
|
|
8
|
+
Phase 1: Bedrock Foundation
|
|
9
|
+
- Base Pydantic models with strict validation
|
|
10
|
+
- Core enums and constants
|
|
11
|
+
- Custom exceptions hierarchy
|
|
12
|
+
- 100% test coverage required
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
# Import unified version system
|
|
16
|
+
from unrealon_core.version import get_rpc_version, get_version_info
|
|
17
|
+
|
|
18
|
+
__version__ = get_rpc_version()
|
|
19
|
+
__author__ = "UnrealOn Team"
|
|
20
|
+
|
|
21
|
+
# Import main components for easy access
|
|
22
|
+
from .models.base import UnrealOnBaseModel, TimestampedModel, IdentifiedModel, StatusModel
|
|
23
|
+
from .models.arq_context import (
|
|
24
|
+
ARQWorkerContext, ARQWorkerStats, TaskAssignmentParams, TaskResultParams,
|
|
25
|
+
LogEntryParams, DriverRegistrationParams, HeartbeatParams
|
|
26
|
+
)
|
|
27
|
+
from .models.arq_responses import (
|
|
28
|
+
TaskAssignmentResponse, TaskResultResponse, LogEntryResponse,
|
|
29
|
+
DriverRegistrationResponse, HeartbeatResponse, PingResponse
|
|
30
|
+
)
|
|
31
|
+
from .models.typed_responses import (
|
|
32
|
+
HealthCheckResult, StatusInfo, SessionInfo, ProxyStats,
|
|
33
|
+
ThreadStats, CacheStats, BatchStats
|
|
34
|
+
)
|
|
35
|
+
from .models.communication import (
|
|
36
|
+
MessageType as WebSocketMessageType, WebSocketMessage,
|
|
37
|
+
DriverRegistrationMessage, RegistrationResponseMessage,
|
|
38
|
+
TaskAssignmentMessage, TaskResultMessage,
|
|
39
|
+
LogEntryMessage, LogBatchMessage,
|
|
40
|
+
HeartbeatMessage, ConfigurationUpdateMessage,
|
|
41
|
+
ErrorMessage, AckMessage,
|
|
42
|
+
create_error_message, create_ack_message,
|
|
43
|
+
# Data models for strict typing
|
|
44
|
+
TaskAssignmentData, TaskResultData,
|
|
45
|
+
DriverRegistrationData, HeartbeatData, LogEntryData, LogContext
|
|
46
|
+
)
|
|
47
|
+
from .enums.status import DriverStatus, TaskStatus, ProxyStatus, LogLevel
|
|
48
|
+
from .enums.types import MessageType, ProxyType, TaskPriority
|
|
49
|
+
from .exceptions.base import UnrealOnError
|
|
50
|
+
from .exceptions.validation import ValidationError as UnrealOnValidationError
|
|
51
|
+
from .exceptions.communication import CommunicationError
|
|
52
|
+
|
|
53
|
+
# Error handling system
|
|
54
|
+
from .error_handling import (
|
|
55
|
+
RetryConfig, RetryStrategy, RetryResult,
|
|
56
|
+
ExponentialBackoff, LinearBackoff, FixedBackoff,
|
|
57
|
+
retry_async, retry_sync,
|
|
58
|
+
CircuitBreakerConfig, CircuitBreakerState,
|
|
59
|
+
CircuitBreaker, circuit_breaker,
|
|
60
|
+
ErrorContext, ErrorSeverity,
|
|
61
|
+
create_error_context, format_error_context,
|
|
62
|
+
RecoveryStrategy, RecoveryAction,
|
|
63
|
+
AutoRecovery, recovery_handler
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# Monitoring system
|
|
67
|
+
from .monitoring import (
|
|
68
|
+
HealthStatus, HealthCheckResult, ComponentHealth,
|
|
69
|
+
HealthChecker, health_check_decorator,
|
|
70
|
+
MetricType, MetricValue, Metric,
|
|
71
|
+
MetricsCollector, counter, gauge, histogram, timer,
|
|
72
|
+
AlertSeverity, AlertRule, Alert,
|
|
73
|
+
AlertManager, alert_on_condition,
|
|
74
|
+
DashboardData, SystemStatus,
|
|
75
|
+
MonitoringDashboard, get_system_overview
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# Configuration system
|
|
79
|
+
from .config import (
|
|
80
|
+
EnvironmentConfig, URLConfig,
|
|
81
|
+
get_environment_config, get_url_config
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
__all__ = [
|
|
85
|
+
# Version info
|
|
86
|
+
"__version__",
|
|
87
|
+
"__author__",
|
|
88
|
+
"__phase__",
|
|
89
|
+
|
|
90
|
+
# Base models
|
|
91
|
+
"UnrealOnBaseModel",
|
|
92
|
+
"TimestampedModel",
|
|
93
|
+
"IdentifiedModel",
|
|
94
|
+
"StatusModel",
|
|
95
|
+
|
|
96
|
+
# WebSocket Communication models
|
|
97
|
+
"WebSocketMessageType",
|
|
98
|
+
"WebSocketMessage",
|
|
99
|
+
"DriverRegistrationMessage",
|
|
100
|
+
"RegistrationResponseMessage",
|
|
101
|
+
"TaskAssignmentMessage",
|
|
102
|
+
"TaskResultMessage",
|
|
103
|
+
"LogEntryMessage",
|
|
104
|
+
"LogBatchMessage",
|
|
105
|
+
"HeartbeatMessage",
|
|
106
|
+
"ConfigurationUpdateMessage",
|
|
107
|
+
"ErrorMessage",
|
|
108
|
+
"AckMessage",
|
|
109
|
+
"create_error_message",
|
|
110
|
+
"create_ack_message",
|
|
111
|
+
|
|
112
|
+
# Data models for strict typing
|
|
113
|
+
"TaskAssignmentData",
|
|
114
|
+
"TaskResultData",
|
|
115
|
+
"DriverRegistrationData",
|
|
116
|
+
"HeartbeatData",
|
|
117
|
+
"LogEntryData",
|
|
118
|
+
"LogContext",
|
|
119
|
+
|
|
120
|
+
# Status enums
|
|
121
|
+
"DriverStatus",
|
|
122
|
+
"TaskStatus",
|
|
123
|
+
"ProxyStatus",
|
|
124
|
+
"LogLevel",
|
|
125
|
+
|
|
126
|
+
# Type enums
|
|
127
|
+
"MessageType",
|
|
128
|
+
"ProxyType",
|
|
129
|
+
"TaskPriority",
|
|
130
|
+
|
|
131
|
+
# Exceptions
|
|
132
|
+
"UnrealOnError",
|
|
133
|
+
"UnrealOnValidationError",
|
|
134
|
+
"CommunicationError",
|
|
135
|
+
|
|
136
|
+
# Error handling system
|
|
137
|
+
"RetryConfig", "RetryStrategy", "RetryResult",
|
|
138
|
+
"ExponentialBackoff", "LinearBackoff", "FixedBackoff",
|
|
139
|
+
"retry_async", "retry_sync",
|
|
140
|
+
"CircuitBreakerConfig", "CircuitBreakerState",
|
|
141
|
+
"CircuitBreaker", "circuit_breaker",
|
|
142
|
+
"ErrorContext", "ErrorSeverity",
|
|
143
|
+
"create_error_context", "format_error_context",
|
|
144
|
+
"RecoveryStrategy", "RecoveryAction",
|
|
145
|
+
"AutoRecovery", "recovery_handler",
|
|
146
|
+
|
|
147
|
+
# Monitoring system
|
|
148
|
+
"HealthStatus", "HealthCheckResult", "ComponentHealth",
|
|
149
|
+
"HealthChecker", "health_check_decorator",
|
|
150
|
+
"MetricType", "MetricValue", "Metric",
|
|
151
|
+
"MetricsCollector", "counter", "gauge", "histogram", "timer",
|
|
152
|
+
"AlertSeverity", "AlertRule", "Alert",
|
|
153
|
+
"AlertManager", "alert_on_condition",
|
|
154
|
+
"DashboardData", "SystemStatus",
|
|
155
|
+
"MonitoringDashboard", "get_system_overview",
|
|
156
|
+
|
|
157
|
+
# Configuration system
|
|
158
|
+
"EnvironmentConfig", "URLConfig",
|
|
159
|
+
"get_environment_config", "get_url_config",
|
|
160
|
+
]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Configuration management for UnrealOn platform.
|
|
3
|
+
|
|
4
|
+
This module provides centralized configuration management with support for
|
|
5
|
+
development and production environments.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .environment import EnvironmentConfig, get_environment_config
|
|
9
|
+
from .urls import URLConfig, get_url_config
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"EnvironmentConfig",
|
|
13
|
+
"URLConfig",
|
|
14
|
+
"get_environment_config",
|
|
15
|
+
"get_url_config",
|
|
16
|
+
]
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Environment configuration management.
|
|
3
|
+
|
|
4
|
+
Handles switching between development and production environments.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
from enum import Enum
|
|
9
|
+
from typing import Optional
|
|
10
|
+
from pydantic import BaseModel, Field, ConfigDict
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Environment(str, Enum):
|
|
14
|
+
"""Environment types."""
|
|
15
|
+
DEVELOPMENT = "development"
|
|
16
|
+
PRODUCTION = "production"
|
|
17
|
+
TESTING = "testing"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class EnvironmentConfig(BaseModel):
|
|
21
|
+
"""Environment configuration settings."""
|
|
22
|
+
|
|
23
|
+
model_config = ConfigDict(
|
|
24
|
+
# Add any specific config here if needed
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
environment: Environment = Field(
|
|
28
|
+
default=Environment.DEVELOPMENT,
|
|
29
|
+
description="Current environment"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
debug: bool = Field(
|
|
33
|
+
default=True,
|
|
34
|
+
description="Enable debug mode"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
log_level: str = Field(
|
|
38
|
+
default="INFO",
|
|
39
|
+
description="Logging level"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
@classmethod
|
|
43
|
+
def from_env(cls) -> "EnvironmentConfig":
|
|
44
|
+
"""Create config from environment variables."""
|
|
45
|
+
env_name = os.getenv("UNREALON_ENV", "development").lower()
|
|
46
|
+
|
|
47
|
+
# Map environment names
|
|
48
|
+
env_mapping = {
|
|
49
|
+
"dev": Environment.DEVELOPMENT,
|
|
50
|
+
"development": Environment.DEVELOPMENT,
|
|
51
|
+
"prod": Environment.PRODUCTION,
|
|
52
|
+
"production": Environment.PRODUCTION,
|
|
53
|
+
"test": Environment.TESTING,
|
|
54
|
+
"testing": Environment.TESTING,
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
environment = env_mapping.get(env_name, Environment.DEVELOPMENT)
|
|
58
|
+
|
|
59
|
+
return cls(
|
|
60
|
+
environment=environment,
|
|
61
|
+
debug=environment != Environment.PRODUCTION,
|
|
62
|
+
log_level=os.getenv("UNREALON_LOG_LEVEL", "DEBUG" if environment != Environment.PRODUCTION else "INFO")
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def is_development(self) -> bool:
|
|
67
|
+
"""Check if running in development mode."""
|
|
68
|
+
return self.environment == Environment.DEVELOPMENT
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def is_production(self) -> bool:
|
|
72
|
+
"""Check if running in production mode."""
|
|
73
|
+
return self.environment == Environment.PRODUCTION
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def is_testing(self) -> bool:
|
|
77
|
+
"""Check if running in testing mode."""
|
|
78
|
+
return self.environment == Environment.TESTING
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
# Global config instance
|
|
82
|
+
_environment_config: Optional[EnvironmentConfig] = None
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def get_environment_config() -> EnvironmentConfig:
|
|
86
|
+
"""Get the global environment configuration."""
|
|
87
|
+
global _environment_config
|
|
88
|
+
|
|
89
|
+
if _environment_config is None:
|
|
90
|
+
_environment_config = EnvironmentConfig.from_env()
|
|
91
|
+
|
|
92
|
+
return _environment_config
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def set_environment_config(config: EnvironmentConfig) -> None:
|
|
96
|
+
"""Set the global environment configuration."""
|
|
97
|
+
global _environment_config
|
|
98
|
+
_environment_config = config
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""
|
|
2
|
+
URL configuration management.
|
|
3
|
+
|
|
4
|
+
Provides centralized URL management with environment-specific endpoints.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Optional
|
|
8
|
+
from pydantic import BaseModel, Field, HttpUrl, ConfigDict
|
|
9
|
+
from .environment import get_environment_config, Environment
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class URLConfig(BaseModel):
|
|
13
|
+
"""URL configuration for different services."""
|
|
14
|
+
|
|
15
|
+
model_config = ConfigDict(
|
|
16
|
+
# Add any specific config here if needed
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
# Scanner/Detection URLs
|
|
20
|
+
scanner_url: str = Field(
|
|
21
|
+
description="URL for browser detection and stealth testing"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# Cloud platform URLs
|
|
25
|
+
cloud_base_url: str = Field(
|
|
26
|
+
description="Base URL for UnrealOn Cloud platform"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
# API endpoints
|
|
30
|
+
api_base_url: str = Field(
|
|
31
|
+
description="Base URL for API endpoints"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
@classmethod
|
|
35
|
+
def for_environment(cls, environment: Optional[Environment] = None) -> "URLConfig":
|
|
36
|
+
"""Create URL config for specific environment."""
|
|
37
|
+
if environment is None:
|
|
38
|
+
environment = get_environment_config().environment
|
|
39
|
+
|
|
40
|
+
if environment == Environment.PRODUCTION:
|
|
41
|
+
return cls(
|
|
42
|
+
scanner_url="https://cloud.unrealon.com/scanner",
|
|
43
|
+
cloud_base_url="https://cloud.unrealon.com",
|
|
44
|
+
api_base_url="https://api.unrealon.com"
|
|
45
|
+
)
|
|
46
|
+
elif environment == Environment.TESTING:
|
|
47
|
+
return cls(
|
|
48
|
+
scanner_url="https://staging.unrealon.com/scanner",
|
|
49
|
+
cloud_base_url="https://staging.unrealon.com",
|
|
50
|
+
api_base_url="https://api-staging.unrealon.com"
|
|
51
|
+
)
|
|
52
|
+
else: # Development
|
|
53
|
+
return cls(
|
|
54
|
+
scanner_url="http://localhost:3000/scanner",
|
|
55
|
+
cloud_base_url="http://localhost:3000",
|
|
56
|
+
api_base_url="http://localhost:8000"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def stealth_test_url(self) -> str:
|
|
61
|
+
"""Get the URL for stealth testing (replaces bot.sannysoft.com)."""
|
|
62
|
+
return self.scanner_url
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def detection_test_url(self) -> str:
|
|
66
|
+
"""Get the URL for browser detection testing."""
|
|
67
|
+
return self.scanner_url
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
# Global config instance
|
|
71
|
+
_url_config: Optional[URLConfig] = None
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def get_url_config() -> URLConfig:
|
|
75
|
+
"""Get the global URL configuration."""
|
|
76
|
+
global _url_config
|
|
77
|
+
|
|
78
|
+
if _url_config is None:
|
|
79
|
+
_url_config = URLConfig.for_environment()
|
|
80
|
+
|
|
81
|
+
return _url_config
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def set_url_config(config: URLConfig) -> None:
|
|
85
|
+
"""Set the global URL configuration."""
|
|
86
|
+
global _url_config
|
|
87
|
+
_url_config = config
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def reset_url_config() -> None:
|
|
91
|
+
"""Reset URL config to reload from environment."""
|
|
92
|
+
global _url_config
|
|
93
|
+
_url_config = None
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""
|
|
2
|
+
UnrealOn Core Enums
|
|
3
|
+
|
|
4
|
+
All enums and constants used across the UnrealOn system.
|
|
5
|
+
These provide type safety and consistent values throughout the codebase.
|
|
6
|
+
|
|
7
|
+
Phase 1: Foundation enums with strict validation
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from .status import DriverStatus, TaskStatus, ProxyStatus, LogLevel
|
|
11
|
+
from .types import MessageType, ProxyType, TaskPriority
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
# Status enums
|
|
15
|
+
"DriverStatus",
|
|
16
|
+
"TaskStatus",
|
|
17
|
+
"ProxyStatus",
|
|
18
|
+
"LogLevel",
|
|
19
|
+
|
|
20
|
+
# Type enums
|
|
21
|
+
"MessageType",
|
|
22
|
+
"ProxyType",
|
|
23
|
+
"TaskPriority",
|
|
24
|
+
]
|