unrealon 1.0.9__py3-none-any.whl → 1.1.1__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/__init__.py +23 -21
- unrealon-1.1.1.dist-info/METADATA +722 -0
- unrealon-1.1.1.dist-info/RECORD +82 -0
- {unrealon-1.0.9.dist-info → unrealon-1.1.1.dist-info}/WHEEL +1 -1
- unrealon-1.1.1.dist-info/entry_points.txt +9 -0
- {unrealon-1.0.9.dist-info → unrealon-1.1.1.dist-info/licenses}/LICENSE +1 -1
- unrealon_bridge/__init__.py +114 -0
- unrealon_bridge/cli.py +316 -0
- unrealon_bridge/client/__init__.py +93 -0
- unrealon_bridge/client/base.py +78 -0
- unrealon_bridge/client/commands.py +89 -0
- unrealon_bridge/client/connection.py +90 -0
- unrealon_bridge/client/events.py +65 -0
- unrealon_bridge/client/health.py +38 -0
- unrealon_bridge/client/html_parser.py +146 -0
- unrealon_bridge/client/logging.py +139 -0
- unrealon_bridge/client/proxy.py +70 -0
- unrealon_bridge/client/scheduler.py +450 -0
- unrealon_bridge/client/session.py +70 -0
- unrealon_bridge/configs/__init__.py +14 -0
- unrealon_bridge/configs/bridge_config.py +212 -0
- unrealon_bridge/configs/bridge_config.yaml +39 -0
- unrealon_bridge/models/__init__.py +138 -0
- unrealon_bridge/models/base.py +28 -0
- unrealon_bridge/models/command.py +41 -0
- unrealon_bridge/models/events.py +40 -0
- unrealon_bridge/models/html_parser.py +79 -0
- unrealon_bridge/models/logging.py +55 -0
- unrealon_bridge/models/parser.py +63 -0
- unrealon_bridge/models/proxy.py +41 -0
- unrealon_bridge/models/requests.py +95 -0
- unrealon_bridge/models/responses.py +88 -0
- unrealon_bridge/models/scheduler.py +592 -0
- unrealon_bridge/models/session.py +28 -0
- unrealon_bridge/server/__init__.py +91 -0
- unrealon_bridge/server/base.py +171 -0
- unrealon_bridge/server/handlers/__init__.py +23 -0
- unrealon_bridge/server/handlers/command.py +110 -0
- unrealon_bridge/server/handlers/html_parser.py +139 -0
- unrealon_bridge/server/handlers/logging.py +95 -0
- unrealon_bridge/server/handlers/parser.py +95 -0
- unrealon_bridge/server/handlers/proxy.py +75 -0
- unrealon_bridge/server/handlers/scheduler.py +545 -0
- unrealon_bridge/server/handlers/session.py +66 -0
- unrealon_browser/__init__.py +61 -18
- unrealon_browser/{src/cli → cli}/browser_cli.py +6 -13
- unrealon_browser/{src/cli → cli}/cookies_cli.py +5 -1
- unrealon_browser/{src/core → core}/browser_manager.py +2 -2
- unrealon_browser/{src/managers → managers}/captcha.py +1 -1
- unrealon_browser/{src/managers → managers}/cookies.py +1 -1
- unrealon_browser/managers/logger_bridge.py +231 -0
- unrealon_browser/{src/managers → managers}/profile.py +1 -1
- unrealon_driver/__init__.py +73 -19
- unrealon_driver/browser/__init__.py +8 -0
- unrealon_driver/browser/config.py +74 -0
- unrealon_driver/browser/manager.py +416 -0
- unrealon_driver/exceptions.py +28 -0
- unrealon_driver/parser/__init__.py +55 -0
- unrealon_driver/parser/cli_manager.py +141 -0
- unrealon_driver/parser/daemon_manager.py +227 -0
- unrealon_driver/parser/managers/__init__.py +46 -0
- unrealon_driver/parser/managers/browser.py +51 -0
- unrealon_driver/parser/managers/config.py +281 -0
- unrealon_driver/parser/managers/error.py +412 -0
- unrealon_driver/parser/managers/html.py +732 -0
- unrealon_driver/parser/managers/logging.py +609 -0
- unrealon_driver/parser/managers/result.py +321 -0
- unrealon_driver/parser/parser_manager.py +628 -0
- unrealon/sdk_config.py +0 -88
- unrealon-1.0.9.dist-info/METADATA +0 -810
- unrealon-1.0.9.dist-info/RECORD +0 -246
- unrealon_browser/pyproject.toml +0 -182
- unrealon_browser/src/__init__.py +0 -62
- unrealon_browser/src/managers/logger_bridge.py +0 -395
- unrealon_driver/README.md +0 -204
- unrealon_driver/pyproject.toml +0 -187
- unrealon_driver/src/__init__.py +0 -90
- unrealon_driver/src/cli/__init__.py +0 -10
- unrealon_driver/src/cli/main.py +0 -66
- unrealon_driver/src/cli/simple.py +0 -510
- unrealon_driver/src/config/__init__.py +0 -11
- unrealon_driver/src/config/auto_config.py +0 -478
- unrealon_driver/src/core/__init__.py +0 -18
- unrealon_driver/src/core/exceptions.py +0 -289
- unrealon_driver/src/core/parser.py +0 -638
- unrealon_driver/src/dto/__init__.py +0 -66
- unrealon_driver/src/dto/cli.py +0 -119
- unrealon_driver/src/dto/config.py +0 -18
- unrealon_driver/src/dto/events.py +0 -237
- unrealon_driver/src/dto/execution.py +0 -313
- unrealon_driver/src/dto/services.py +0 -311
- unrealon_driver/src/execution/__init__.py +0 -23
- unrealon_driver/src/execution/daemon_mode.py +0 -317
- unrealon_driver/src/execution/interactive_mode.py +0 -88
- unrealon_driver/src/execution/modes.py +0 -45
- unrealon_driver/src/execution/scheduled_mode.py +0 -209
- unrealon_driver/src/execution/test_mode.py +0 -250
- unrealon_driver/src/logging/__init__.py +0 -24
- unrealon_driver/src/logging/driver_logger.py +0 -512
- unrealon_driver/src/services/__init__.py +0 -24
- unrealon_driver/src/services/browser_service.py +0 -726
- unrealon_driver/src/services/llm/__init__.py +0 -15
- unrealon_driver/src/services/llm/browser_llm_service.py +0 -363
- unrealon_driver/src/services/llm/llm.py +0 -195
- unrealon_driver/src/services/logger_service.py +0 -232
- unrealon_driver/src/services/metrics_service.py +0 -185
- unrealon_driver/src/services/scheduler_service.py +0 -489
- unrealon_driver/src/services/websocket_service.py +0 -362
- unrealon_driver/src/utils/__init__.py +0 -16
- unrealon_driver/src/utils/service_factory.py +0 -317
- unrealon_driver/src/utils/time_formatter.py +0 -338
- unrealon_llm/README.md +0 -44
- unrealon_llm/__init__.py +0 -26
- unrealon_llm/pyproject.toml +0 -154
- unrealon_llm/src/__init__.py +0 -228
- unrealon_llm/src/cli/__init__.py +0 -0
- unrealon_llm/src/core/__init__.py +0 -11
- unrealon_llm/src/core/smart_client.py +0 -438
- unrealon_llm/src/dto/__init__.py +0 -155
- unrealon_llm/src/dto/models/__init__.py +0 -0
- unrealon_llm/src/dto/models/config.py +0 -343
- unrealon_llm/src/dto/models/core.py +0 -328
- unrealon_llm/src/dto/models/enums.py +0 -123
- unrealon_llm/src/dto/models/html_analysis.py +0 -345
- unrealon_llm/src/dto/models/statistics.py +0 -473
- unrealon_llm/src/dto/models/translation.py +0 -383
- unrealon_llm/src/dto/models/type_conversion.py +0 -462
- unrealon_llm/src/dto/schemas/__init__.py +0 -0
- unrealon_llm/src/exceptions.py +0 -392
- unrealon_llm/src/llm_config/__init__.py +0 -20
- unrealon_llm/src/llm_config/logging_config.py +0 -178
- unrealon_llm/src/llm_logging/__init__.py +0 -42
- unrealon_llm/src/llm_logging/llm_events.py +0 -107
- unrealon_llm/src/llm_logging/llm_logger.py +0 -466
- unrealon_llm/src/managers/__init__.py +0 -15
- unrealon_llm/src/managers/cache_manager.py +0 -67
- unrealon_llm/src/managers/cost_manager.py +0 -107
- unrealon_llm/src/managers/request_manager.py +0 -298
- unrealon_llm/src/modules/__init__.py +0 -0
- unrealon_llm/src/modules/html_processor/__init__.py +0 -25
- unrealon_llm/src/modules/html_processor/base_processor.py +0 -415
- unrealon_llm/src/modules/html_processor/details_processor.py +0 -85
- unrealon_llm/src/modules/html_processor/listing_processor.py +0 -91
- unrealon_llm/src/modules/html_processor/models/__init__.py +0 -20
- unrealon_llm/src/modules/html_processor/models/processing_models.py +0 -40
- unrealon_llm/src/modules/html_processor/models/universal_model.py +0 -56
- unrealon_llm/src/modules/html_processor/processor.py +0 -102
- unrealon_llm/src/modules/llm/__init__.py +0 -0
- unrealon_llm/src/modules/translator/__init__.py +0 -0
- unrealon_llm/src/provider.py +0 -116
- unrealon_llm/src/utils/__init__.py +0 -95
- unrealon_llm/src/utils/common.py +0 -64
- unrealon_llm/src/utils/data_extractor.py +0 -188
- unrealon_llm/src/utils/html_cleaner.py +0 -767
- unrealon_llm/src/utils/language_detector.py +0 -308
- unrealon_llm/src/utils/models_cache.py +0 -592
- unrealon_llm/src/utils/smart_counter.py +0 -229
- unrealon_llm/src/utils/token_counter.py +0 -189
- unrealon_sdk/README.md +0 -25
- unrealon_sdk/__init__.py +0 -30
- unrealon_sdk/pyproject.toml +0 -231
- unrealon_sdk/src/__init__.py +0 -150
- unrealon_sdk/src/cli/__init__.py +0 -12
- unrealon_sdk/src/cli/commands/__init__.py +0 -22
- unrealon_sdk/src/cli/commands/benchmark.py +0 -42
- unrealon_sdk/src/cli/commands/diagnostics.py +0 -573
- unrealon_sdk/src/cli/commands/health.py +0 -46
- unrealon_sdk/src/cli/commands/integration.py +0 -498
- unrealon_sdk/src/cli/commands/reports.py +0 -43
- unrealon_sdk/src/cli/commands/security.py +0 -36
- unrealon_sdk/src/cli/commands/server.py +0 -483
- unrealon_sdk/src/cli/commands/servers.py +0 -56
- unrealon_sdk/src/cli/commands/tests.py +0 -55
- unrealon_sdk/src/cli/main.py +0 -126
- unrealon_sdk/src/cli/utils/reporter.py +0 -519
- unrealon_sdk/src/clients/openapi.yaml +0 -3347
- unrealon_sdk/src/clients/python_http/__init__.py +0 -3
- unrealon_sdk/src/clients/python_http/api_config.py +0 -228
- unrealon_sdk/src/clients/python_http/models/BaseModel.py +0 -12
- unrealon_sdk/src/clients/python_http/models/BroadcastDeliveryStats.py +0 -33
- unrealon_sdk/src/clients/python_http/models/BroadcastMessage.py +0 -17
- unrealon_sdk/src/clients/python_http/models/BroadcastMessageRequest.py +0 -35
- unrealon_sdk/src/clients/python_http/models/BroadcastPriority.py +0 -10
- unrealon_sdk/src/clients/python_http/models/BroadcastResponse.py +0 -21
- unrealon_sdk/src/clients/python_http/models/BroadcastResultResponse.py +0 -33
- unrealon_sdk/src/clients/python_http/models/BroadcastTarget.py +0 -11
- unrealon_sdk/src/clients/python_http/models/ConnectionStats.py +0 -27
- unrealon_sdk/src/clients/python_http/models/ConnectionsResponse.py +0 -21
- unrealon_sdk/src/clients/python_http/models/DeveloperMessageResponse.py +0 -23
- unrealon_sdk/src/clients/python_http/models/ErrorResponse.py +0 -25
- unrealon_sdk/src/clients/python_http/models/HTTPValidationError.py +0 -16
- unrealon_sdk/src/clients/python_http/models/HealthResponse.py +0 -23
- unrealon_sdk/src/clients/python_http/models/HealthStatus.py +0 -33
- unrealon_sdk/src/clients/python_http/models/LogLevel.py +0 -10
- unrealon_sdk/src/clients/python_http/models/LoggingRequest.py +0 -27
- unrealon_sdk/src/clients/python_http/models/LoggingResponse.py +0 -23
- unrealon_sdk/src/clients/python_http/models/MaintenanceMode.py +0 -9
- unrealon_sdk/src/clients/python_http/models/MaintenanceModeRequest.py +0 -33
- unrealon_sdk/src/clients/python_http/models/MaintenanceStatusResponse.py +0 -39
- unrealon_sdk/src/clients/python_http/models/ParserCommandRequest.py +0 -25
- unrealon_sdk/src/clients/python_http/models/ParserMessageResponse.py +0 -21
- unrealon_sdk/src/clients/python_http/models/ParserRegistrationRequest.py +0 -28
- unrealon_sdk/src/clients/python_http/models/ParserRegistrationResponse.py +0 -25
- unrealon_sdk/src/clients/python_http/models/ParserType.py +0 -10
- unrealon_sdk/src/clients/python_http/models/ProxyBlockRequest.py +0 -19
- unrealon_sdk/src/clients/python_http/models/ProxyEndpointResponse.py +0 -20
- unrealon_sdk/src/clients/python_http/models/ProxyListResponse.py +0 -19
- unrealon_sdk/src/clients/python_http/models/ProxyProvider.py +0 -10
- unrealon_sdk/src/clients/python_http/models/ProxyPurchaseRequest.py +0 -25
- unrealon_sdk/src/clients/python_http/models/ProxyResponse.py +0 -47
- unrealon_sdk/src/clients/python_http/models/ProxyRotationRequest.py +0 -23
- unrealon_sdk/src/clients/python_http/models/ProxyStatus.py +0 -10
- unrealon_sdk/src/clients/python_http/models/ProxyUsageRequest.py +0 -19
- unrealon_sdk/src/clients/python_http/models/ProxyUsageStatsResponse.py +0 -26
- unrealon_sdk/src/clients/python_http/models/ServiceRegistrationDto.py +0 -23
- unrealon_sdk/src/clients/python_http/models/ServiceStatsResponse.py +0 -31
- unrealon_sdk/src/clients/python_http/models/SessionStartRequest.py +0 -23
- unrealon_sdk/src/clients/python_http/models/SuccessResponse.py +0 -25
- unrealon_sdk/src/clients/python_http/models/SystemNotificationResponse.py +0 -23
- unrealon_sdk/src/clients/python_http/models/ValidationError.py +0 -18
- unrealon_sdk/src/clients/python_http/models/ValidationErrorResponse.py +0 -21
- unrealon_sdk/src/clients/python_http/models/WebSocketMetrics.py +0 -21
- unrealon_sdk/src/clients/python_http/models/__init__.py +0 -44
- unrealon_sdk/src/clients/python_http/services/None_service.py +0 -35
- unrealon_sdk/src/clients/python_http/services/ParserManagement_service.py +0 -190
- unrealon_sdk/src/clients/python_http/services/ProxyManagement_service.py +0 -289
- unrealon_sdk/src/clients/python_http/services/SocketLogging_service.py +0 -187
- unrealon_sdk/src/clients/python_http/services/SystemHealth_service.py +0 -119
- unrealon_sdk/src/clients/python_http/services/WebSocketAPI_service.py +0 -198
- unrealon_sdk/src/clients/python_http/services/__init__.py +0 -0
- unrealon_sdk/src/clients/python_http/services/admin_service.py +0 -125
- unrealon_sdk/src/clients/python_http/services/async_None_service.py +0 -35
- unrealon_sdk/src/clients/python_http/services/async_ParserManagement_service.py +0 -190
- unrealon_sdk/src/clients/python_http/services/async_ProxyManagement_service.py +0 -289
- unrealon_sdk/src/clients/python_http/services/async_SocketLogging_service.py +0 -189
- unrealon_sdk/src/clients/python_http/services/async_SystemHealth_service.py +0 -123
- unrealon_sdk/src/clients/python_http/services/async_WebSocketAPI_service.py +0 -200
- unrealon_sdk/src/clients/python_http/services/async_admin_service.py +0 -125
- unrealon_sdk/src/clients/python_websocket/__init__.py +0 -28
- unrealon_sdk/src/clients/python_websocket/client.py +0 -490
- unrealon_sdk/src/clients/python_websocket/events.py +0 -732
- unrealon_sdk/src/clients/python_websocket/example.py +0 -136
- unrealon_sdk/src/clients/python_websocket/types.py +0 -871
- unrealon_sdk/src/core/__init__.py +0 -64
- unrealon_sdk/src/core/client.py +0 -556
- unrealon_sdk/src/core/config.py +0 -465
- unrealon_sdk/src/core/exceptions.py +0 -239
- unrealon_sdk/src/core/metadata.py +0 -191
- unrealon_sdk/src/core/models.py +0 -142
- unrealon_sdk/src/core/types.py +0 -68
- unrealon_sdk/src/dto/__init__.py +0 -268
- unrealon_sdk/src/dto/authentication.py +0 -108
- unrealon_sdk/src/dto/cache.py +0 -208
- unrealon_sdk/src/dto/common.py +0 -19
- unrealon_sdk/src/dto/concurrency.py +0 -393
- unrealon_sdk/src/dto/events.py +0 -108
- unrealon_sdk/src/dto/health.py +0 -339
- unrealon_sdk/src/dto/load_balancing.py +0 -336
- unrealon_sdk/src/dto/logging.py +0 -230
- unrealon_sdk/src/dto/performance.py +0 -165
- unrealon_sdk/src/dto/rate_limiting.py +0 -295
- unrealon_sdk/src/dto/resource_pooling.py +0 -128
- unrealon_sdk/src/dto/structured_logging.py +0 -112
- unrealon_sdk/src/dto/task_scheduling.py +0 -121
- unrealon_sdk/src/dto/websocket.py +0 -55
- unrealon_sdk/src/enterprise/__init__.py +0 -59
- unrealon_sdk/src/enterprise/authentication.py +0 -401
- unrealon_sdk/src/enterprise/cache_manager.py +0 -578
- unrealon_sdk/src/enterprise/error_recovery.py +0 -494
- unrealon_sdk/src/enterprise/event_system.py +0 -549
- unrealon_sdk/src/enterprise/health_monitor.py +0 -747
- unrealon_sdk/src/enterprise/load_balancer.py +0 -964
- unrealon_sdk/src/enterprise/logging/__init__.py +0 -68
- unrealon_sdk/src/enterprise/logging/cleanup.py +0 -156
- unrealon_sdk/src/enterprise/logging/development.py +0 -744
- unrealon_sdk/src/enterprise/logging/service.py +0 -410
- unrealon_sdk/src/enterprise/multithreading_manager.py +0 -853
- unrealon_sdk/src/enterprise/performance_monitor.py +0 -539
- unrealon_sdk/src/enterprise/proxy_manager.py +0 -696
- unrealon_sdk/src/enterprise/rate_limiter.py +0 -652
- unrealon_sdk/src/enterprise/resource_pool.py +0 -763
- unrealon_sdk/src/enterprise/task_scheduler.py +0 -709
- unrealon_sdk/src/internal/__init__.py +0 -10
- unrealon_sdk/src/internal/command_router.py +0 -497
- unrealon_sdk/src/internal/connection_manager.py +0 -397
- unrealon_sdk/src/internal/http_client.py +0 -446
- unrealon_sdk/src/internal/websocket_client.py +0 -420
- unrealon_sdk/src/provider.py +0 -471
- unrealon_sdk/src/utils.py +0 -234
- /unrealon_browser/{src/cli → cli}/__init__.py +0 -0
- /unrealon_browser/{src/cli → cli}/interactive_mode.py +0 -0
- /unrealon_browser/{src/cli → cli}/main.py +0 -0
- /unrealon_browser/{src/core → core}/__init__.py +0 -0
- /unrealon_browser/{src/dto → dto}/__init__.py +0 -0
- /unrealon_browser/{src/dto → dto}/models/config.py +0 -0
- /unrealon_browser/{src/dto → dto}/models/core.py +0 -0
- /unrealon_browser/{src/dto → dto}/models/dataclasses.py +0 -0
- /unrealon_browser/{src/dto → dto}/models/detection.py +0 -0
- /unrealon_browser/{src/dto → dto}/models/enums.py +0 -0
- /unrealon_browser/{src/dto → dto}/models/statistics.py +0 -0
- /unrealon_browser/{src/managers → managers}/__init__.py +0 -0
- /unrealon_browser/{src/managers → managers}/stealth.py +0 -0
|
@@ -1,490 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
UnrealServer Python WebSocket Client
|
|
3
|
-
|
|
4
|
-
Asyncio-based WebSocket client with automatic reconnection,
|
|
5
|
-
event routing, and full type safety.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
import asyncio
|
|
9
|
-
import json
|
|
10
|
-
import logging
|
|
11
|
-
from datetime import datetime
|
|
12
|
-
from typing import Any, Callable, Dict, List, Optional, Union
|
|
13
|
-
from dataclasses import dataclass, field
|
|
14
|
-
|
|
15
|
-
import socketio
|
|
16
|
-
from pydantic import BaseModel, Field
|
|
17
|
-
|
|
18
|
-
from .events import SocketEvent, EventType
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
logger = logging.getLogger(__name__)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
@dataclass
|
|
25
|
-
class WebSocketConfig:
|
|
26
|
-
"""Configuration for WebSocket client."""
|
|
27
|
-
|
|
28
|
-
url: str
|
|
29
|
-
auto_connect: bool = True
|
|
30
|
-
reconnection_attempts: int = 5
|
|
31
|
-
reconnection_delay: float = 1
|
|
32
|
-
timeout: float = 10
|
|
33
|
-
namespace: str = "/"
|
|
34
|
-
auth: Optional[Dict[str, Any]] = None
|
|
35
|
-
headers: Dict[str, str] = field(default_factory=dict)
|
|
36
|
-
|
|
37
|
-
def __post_init__(self):
|
|
38
|
-
"""Post-initialization processing."""
|
|
39
|
-
# Socket.IO client expects HTTP URLs, not WebSocket URLs
|
|
40
|
-
# Keep HTTP/HTTPS format for proper Socket.IO connection
|
|
41
|
-
|
|
42
|
-
# Add default headers
|
|
43
|
-
if "User-Agent" not in self.headers:
|
|
44
|
-
self.headers["User-Agent"] = "UnrealServer-Python-WebSocket-Client/1.0"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
@dataclass
|
|
48
|
-
class ConnectionState:
|
|
49
|
-
"""Current state of WebSocket connection."""
|
|
50
|
-
|
|
51
|
-
connected: bool = False
|
|
52
|
-
connecting: bool = False
|
|
53
|
-
error: Optional[str] = None
|
|
54
|
-
last_connected: Optional[datetime] = None
|
|
55
|
-
reconnect_count: int = 0
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
class WebSocketClient:
|
|
59
|
-
"""
|
|
60
|
-
UnrealServer WebSocket Client with automatic reconnection.
|
|
61
|
-
|
|
62
|
-
Features:
|
|
63
|
-
- Automatic reconnection with exponential backoff
|
|
64
|
-
- Event-based message handling
|
|
65
|
-
- Type-safe event emission
|
|
66
|
-
- Connection state management
|
|
67
|
-
- Async/await support
|
|
68
|
-
|
|
69
|
-
Usage:
|
|
70
|
-
client = WebSocketClient("ws://localhost:8080")
|
|
71
|
-
await client.connect()
|
|
72
|
-
|
|
73
|
-
@client.on(SocketEvent.MESSAGE_RECEIVED)
|
|
74
|
-
async def handle_message(data):
|
|
75
|
-
print(f"Received: {data}")
|
|
76
|
-
|
|
77
|
-
await client.emit(SocketEvent.PING, {"timestamp": "now"})
|
|
78
|
-
"""
|
|
79
|
-
|
|
80
|
-
def __init__(self, config: Union[str, WebSocketConfig]):
|
|
81
|
-
if isinstance(config, str):
|
|
82
|
-
config = WebSocketConfig(url=config)
|
|
83
|
-
|
|
84
|
-
self.config = config
|
|
85
|
-
self.state = ConnectionState()
|
|
86
|
-
self.logger = logging.getLogger(f"{self.__class__.__name__}")
|
|
87
|
-
|
|
88
|
-
# Initialize Socket.IO client
|
|
89
|
-
# Note: Heartbeat/ping settings are managed by the server, client just responds
|
|
90
|
-
# FIXED: Enable auto-reconnection (default Socket.IO behavior)
|
|
91
|
-
self.sio = socketio.AsyncClient(
|
|
92
|
-
reconnection=True,
|
|
93
|
-
reconnection_attempts=self.config.reconnection_attempts,
|
|
94
|
-
reconnection_delay=self.config.reconnection_delay,
|
|
95
|
-
logger=self.logger.getChild("socketio"),
|
|
96
|
-
engineio_logger=self.logger.getChild("engineio")
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
# Event handlers
|
|
100
|
-
self._event_handlers: Dict[str, List[Callable]] = {}
|
|
101
|
-
|
|
102
|
-
# Setup internal event handlers
|
|
103
|
-
self._setup_internal_handlers()
|
|
104
|
-
|
|
105
|
-
async def connect(self) -> bool:
|
|
106
|
-
"""
|
|
107
|
-
Connect to WebSocket server.
|
|
108
|
-
|
|
109
|
-
Returns:
|
|
110
|
-
bool: True if connection successful, False otherwise
|
|
111
|
-
"""
|
|
112
|
-
if self.state.connected or self.state.connecting:
|
|
113
|
-
self.logger.debug("Already connected or connecting")
|
|
114
|
-
return self.state.connected
|
|
115
|
-
|
|
116
|
-
try:
|
|
117
|
-
self.state.connecting = True
|
|
118
|
-
self.state.error = None
|
|
119
|
-
|
|
120
|
-
self.logger.info(f"Connecting to {self.config.url}")
|
|
121
|
-
|
|
122
|
-
await self.sio.connect(
|
|
123
|
-
url=self.config.url,
|
|
124
|
-
headers=self.config.headers,
|
|
125
|
-
auth=self.config.auth,
|
|
126
|
-
namespaces=[self.config.namespace],
|
|
127
|
-
wait_timeout=self.config.timeout
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
return True
|
|
131
|
-
|
|
132
|
-
except Exception as e:
|
|
133
|
-
self.logger.error(f"Connection failed: {e}")
|
|
134
|
-
self.state.error = str(e)
|
|
135
|
-
return False
|
|
136
|
-
finally:
|
|
137
|
-
self.state.connecting = False
|
|
138
|
-
|
|
139
|
-
async def disconnect(self) -> None:
|
|
140
|
-
"""Disconnect from WebSocket server."""
|
|
141
|
-
try:
|
|
142
|
-
if self.sio.connected:
|
|
143
|
-
await self.sio.disconnect()
|
|
144
|
-
|
|
145
|
-
self.state.connected = False
|
|
146
|
-
self.state.connecting = False
|
|
147
|
-
self.logger.info("Disconnected from WebSocket server")
|
|
148
|
-
|
|
149
|
-
except Exception as e:
|
|
150
|
-
self.logger.error(f"Error during disconnect: {e}")
|
|
151
|
-
|
|
152
|
-
async def emit(self, event: SocketEvent, data: Any = None) -> bool:
|
|
153
|
-
"""
|
|
154
|
-
Emit event to server.
|
|
155
|
-
|
|
156
|
-
Args:
|
|
157
|
-
event: SocketEvent to emit
|
|
158
|
-
data: Data to send with the event
|
|
159
|
-
|
|
160
|
-
Returns:
|
|
161
|
-
bool: True if emission successful, False otherwise
|
|
162
|
-
"""
|
|
163
|
-
if not self.state.connected:
|
|
164
|
-
self.logger.warning(f"Cannot emit {event.value}: not connected")
|
|
165
|
-
return False
|
|
166
|
-
|
|
167
|
-
try:
|
|
168
|
-
# Serialize data if it's a Pydantic model
|
|
169
|
-
if isinstance(data, BaseModel):
|
|
170
|
-
data = data.model_dump()
|
|
171
|
-
|
|
172
|
-
await self.sio.emit(event.value, data, namespace=self.config.namespace)
|
|
173
|
-
self.logger.debug(f"Emitted event: {event.value}")
|
|
174
|
-
return True
|
|
175
|
-
|
|
176
|
-
except Exception as e:
|
|
177
|
-
self.logger.error(f"Failed to emit {event.value}: {e}")
|
|
178
|
-
return False
|
|
179
|
-
|
|
180
|
-
def on(self, event: SocketEvent):
|
|
181
|
-
"""
|
|
182
|
-
Decorator for event handlers.
|
|
183
|
-
|
|
184
|
-
Usage:
|
|
185
|
-
@client.on(SocketEvent.MESSAGE_RECEIVED)
|
|
186
|
-
async def handle_message(data):
|
|
187
|
-
print(data)
|
|
188
|
-
"""
|
|
189
|
-
def decorator(func: Callable):
|
|
190
|
-
self.add_event_handler(event, func)
|
|
191
|
-
return func
|
|
192
|
-
return decorator
|
|
193
|
-
|
|
194
|
-
def add_event_handler(self, event: SocketEvent, handler: Callable) -> None:
|
|
195
|
-
"""
|
|
196
|
-
Add event handler for specific event.
|
|
197
|
-
|
|
198
|
-
Args:
|
|
199
|
-
event: SocketEvent to handle
|
|
200
|
-
handler: Async function to call when event occurs
|
|
201
|
-
"""
|
|
202
|
-
event_name = event.value
|
|
203
|
-
|
|
204
|
-
if event_name not in self._event_handlers:
|
|
205
|
-
self._event_handlers[event_name] = []
|
|
206
|
-
|
|
207
|
-
self._event_handlers[event_name].append(handler)
|
|
208
|
-
|
|
209
|
-
# Register with Socket.IO client
|
|
210
|
-
@self.sio.on(event_name, namespace=self.config.namespace)
|
|
211
|
-
async def wrapper(data=None):
|
|
212
|
-
await self._handle_event(event_name, data)
|
|
213
|
-
|
|
214
|
-
self.logger.debug(f"Added handler for {event_name}")
|
|
215
|
-
|
|
216
|
-
def remove_event_handler(self, event: SocketEvent, handler: Callable) -> None:
|
|
217
|
-
"""
|
|
218
|
-
Remove specific event handler.
|
|
219
|
-
|
|
220
|
-
Args:
|
|
221
|
-
event: SocketEvent to remove handler from
|
|
222
|
-
handler: Handler function to remove
|
|
223
|
-
"""
|
|
224
|
-
event_name = event.value
|
|
225
|
-
|
|
226
|
-
if event_name in self._event_handlers:
|
|
227
|
-
try:
|
|
228
|
-
self._event_handlers[event_name].remove(handler)
|
|
229
|
-
self.logger.debug(f"Removed handler for {event_name}")
|
|
230
|
-
except ValueError:
|
|
231
|
-
self.logger.warning(f"Handler not found for {event_name}")
|
|
232
|
-
|
|
233
|
-
async def wait_for_event(self, event: SocketEvent, timeout: Optional[float] = None) -> Any:
|
|
234
|
-
"""
|
|
235
|
-
Wait for a specific event to occur.
|
|
236
|
-
|
|
237
|
-
Args:
|
|
238
|
-
event: SocketEvent to wait for
|
|
239
|
-
timeout: Maximum time to wait (seconds)
|
|
240
|
-
|
|
241
|
-
Returns:
|
|
242
|
-
Event data when received
|
|
243
|
-
|
|
244
|
-
Raises:
|
|
245
|
-
asyncio.TimeoutError: If timeout is reached
|
|
246
|
-
"""
|
|
247
|
-
return await self.sio.wait(event.value, namespace=self.config.namespace, timeout=timeout)
|
|
248
|
-
|
|
249
|
-
async def _handle_event(self, event_name: str, data: Any) -> None:
|
|
250
|
-
"""
|
|
251
|
-
Handle incoming event by calling registered handlers.
|
|
252
|
-
|
|
253
|
-
Args:
|
|
254
|
-
event_name: Name of the event
|
|
255
|
-
data: Event data
|
|
256
|
-
"""
|
|
257
|
-
try:
|
|
258
|
-
handlers = self._event_handlers.get(event_name, [])
|
|
259
|
-
|
|
260
|
-
for handler in handlers:
|
|
261
|
-
try:
|
|
262
|
-
if asyncio.iscoroutinefunction(handler):
|
|
263
|
-
await handler(data)
|
|
264
|
-
else:
|
|
265
|
-
handler(data)
|
|
266
|
-
except Exception as e:
|
|
267
|
-
self.logger.error(f"Error in handler for {event_name}: {e}")
|
|
268
|
-
|
|
269
|
-
except Exception as e:
|
|
270
|
-
self.logger.error(f"Error handling event {event_name}: {e}")
|
|
271
|
-
|
|
272
|
-
def _setup_internal_handlers(self) -> None:
|
|
273
|
-
"""Setup internal Socket.IO event handlers."""
|
|
274
|
-
|
|
275
|
-
@self.sio.on('connect', namespace=self.config.namespace)
|
|
276
|
-
async def on_connect():
|
|
277
|
-
self.state.connected = True
|
|
278
|
-
self.state.connecting = False
|
|
279
|
-
self.state.last_connected = datetime.utcnow()
|
|
280
|
-
self.state.reconnect_count = 0
|
|
281
|
-
self.state.error = None
|
|
282
|
-
self.logger.info("✅ Connected to WebSocket server")
|
|
283
|
-
|
|
284
|
-
@self.sio.on('disconnect', namespace=self.config.namespace)
|
|
285
|
-
async def on_disconnect():
|
|
286
|
-
self.state.connected = False
|
|
287
|
-
self.state.connecting = False
|
|
288
|
-
self.logger.info("❌ Disconnected from WebSocket server")
|
|
289
|
-
|
|
290
|
-
@self.sio.on('connect_error', namespace=self.config.namespace)
|
|
291
|
-
async def on_connect_error(data):
|
|
292
|
-
self.state.connecting = False
|
|
293
|
-
self.state.error = str(data) if data else "Connection error"
|
|
294
|
-
self.state.reconnect_count += 1
|
|
295
|
-
self.logger.error(f"💥 Connection error: {data}")
|
|
296
|
-
|
|
297
|
-
# Setup handlers for all known socket events
|
|
298
|
-
@self.sio.on('connect', namespace=self.config.namespace)
|
|
299
|
-
async def on_connect_handler(data=None):
|
|
300
|
-
await self._handle_event('connect', data)
|
|
301
|
-
@self.sio.on('disconnect', namespace=self.config.namespace)
|
|
302
|
-
async def on_disconnect_handler(data=None):
|
|
303
|
-
await self._handle_event('disconnect', data)
|
|
304
|
-
@self.sio.on('ping', namespace=self.config.namespace)
|
|
305
|
-
async def on_ping_handler(data=None):
|
|
306
|
-
await self._handle_event('ping', data)
|
|
307
|
-
@self.sio.on('pong', namespace=self.config.namespace)
|
|
308
|
-
async def on_pong_handler(data=None):
|
|
309
|
-
await self._handle_event('pong', data)
|
|
310
|
-
@self.sio.on('parser_register', namespace=self.config.namespace)
|
|
311
|
-
async def on_parser_register_handler(data=None):
|
|
312
|
-
await self._handle_event('parser_register', data)
|
|
313
|
-
@self.sio.on('parser_command', namespace=self.config.namespace)
|
|
314
|
-
async def on_parser_command_handler(data=None):
|
|
315
|
-
await self._handle_event('parser_command', data)
|
|
316
|
-
@self.sio.on('parser_status', namespace=self.config.namespace)
|
|
317
|
-
async def on_parser_status_handler(data=None):
|
|
318
|
-
await self._handle_event('parser_status', data)
|
|
319
|
-
@self.sio.on('parser_registered', namespace=self.config.namespace)
|
|
320
|
-
async def on_parser_registered_handler(data=None):
|
|
321
|
-
await self._handle_event('parser_registered', data)
|
|
322
|
-
@self.sio.on('parser_disconnected', namespace=self.config.namespace)
|
|
323
|
-
async def on_parser_disconnected_handler(data=None):
|
|
324
|
-
await self._handle_event('parser_disconnected', data)
|
|
325
|
-
@self.sio.on('command_request', namespace=self.config.namespace)
|
|
326
|
-
async def on_command_request_handler(data=None):
|
|
327
|
-
await self._handle_event('command_request', data)
|
|
328
|
-
@self.sio.on('command_response', namespace=self.config.namespace)
|
|
329
|
-
async def on_command_response_handler(data=None):
|
|
330
|
-
await self._handle_event('command_response', data)
|
|
331
|
-
@self.sio.on('command_status', namespace=self.config.namespace)
|
|
332
|
-
async def on_command_status_handler(data=None):
|
|
333
|
-
await self._handle_event('command_status', data)
|
|
334
|
-
@self.sio.on('health_status', namespace=self.config.namespace)
|
|
335
|
-
async def on_health_status_handler(data=None):
|
|
336
|
-
await self._handle_event('health_status', data)
|
|
337
|
-
@self.sio.on('health_check', namespace=self.config.namespace)
|
|
338
|
-
async def on_health_check_handler(data=None):
|
|
339
|
-
await self._handle_event('health_check', data)
|
|
340
|
-
@self.sio.on('admin_subscribe', namespace=self.config.namespace)
|
|
341
|
-
async def on_admin_subscribe_handler(data=None):
|
|
342
|
-
await self._handle_event('admin_subscribe', data)
|
|
343
|
-
@self.sio.on('admin_unsubscribe', namespace=self.config.namespace)
|
|
344
|
-
async def on_admin_unsubscribe_handler(data=None):
|
|
345
|
-
await self._handle_event('admin_unsubscribe', data)
|
|
346
|
-
@self.sio.on('admin_broadcast', namespace=self.config.namespace)
|
|
347
|
-
async def on_admin_broadcast_handler(data=None):
|
|
348
|
-
await self._handle_event('admin_broadcast', data)
|
|
349
|
-
@self.sio.on('admin_notification', namespace=self.config.namespace)
|
|
350
|
-
async def on_admin_notification_handler(data=None):
|
|
351
|
-
await self._handle_event('admin_notification', data)
|
|
352
|
-
@self.sio.on('system_notification', namespace=self.config.namespace)
|
|
353
|
-
async def on_system_notification_handler(data=None):
|
|
354
|
-
await self._handle_event('system_notification', data)
|
|
355
|
-
@self.sio.on('system_event', namespace=self.config.namespace)
|
|
356
|
-
async def on_system_event_handler(data=None):
|
|
357
|
-
await self._handle_event('system_event', data)
|
|
358
|
-
@self.sio.on('maintenance_notification', namespace=self.config.namespace)
|
|
359
|
-
async def on_maintenance_notification_handler(data=None):
|
|
360
|
-
await self._handle_event('maintenance_notification', data)
|
|
361
|
-
@self.sio.on('developer_message', namespace=self.config.namespace)
|
|
362
|
-
async def on_developer_message_handler(data=None):
|
|
363
|
-
await self._handle_event('developer_message', data)
|
|
364
|
-
@self.sio.on('log_entry', namespace=self.config.namespace)
|
|
365
|
-
async def on_log_entry_handler(data=None):
|
|
366
|
-
await self._handle_event('log_entry', data)
|
|
367
|
-
@self.sio.on('error', namespace=self.config.namespace)
|
|
368
|
-
async def on_error_handler(data=None):
|
|
369
|
-
await self._handle_event('error', data)
|
|
370
|
-
|
|
371
|
-
@property
|
|
372
|
-
def connected(self) -> bool:
|
|
373
|
-
"""Check if client is connected."""
|
|
374
|
-
return self.state.connected
|
|
375
|
-
|
|
376
|
-
@property
|
|
377
|
-
def connecting(self) -> bool:
|
|
378
|
-
"""Check if client is connecting."""
|
|
379
|
-
return self.state.connecting
|
|
380
|
-
|
|
381
|
-
def get_state(self) -> ConnectionState:
|
|
382
|
-
"""Get current connection state."""
|
|
383
|
-
return self.state
|
|
384
|
-
|
|
385
|
-
async def __aenter__(self):
|
|
386
|
-
"""Async context manager entry."""
|
|
387
|
-
await self.connect()
|
|
388
|
-
return self
|
|
389
|
-
|
|
390
|
-
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
391
|
-
"""Async context manager exit."""
|
|
392
|
-
await self.disconnect()
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
# WebSocket event constants for easy access
|
|
396
|
-
class WS_EVENTS:
|
|
397
|
-
"""WebSocket event names for type safety and easy access."""
|
|
398
|
-
|
|
399
|
-
# Socket.IO built-in events
|
|
400
|
-
CONNECT = 'connect'
|
|
401
|
-
DISCONNECT = 'disconnect'
|
|
402
|
-
CONNECTING = 'connecting'
|
|
403
|
-
CONNECTED = 'connected'
|
|
404
|
-
DISCONNECTED = 'disconnected'
|
|
405
|
-
|
|
406
|
-
# Custom events
|
|
407
|
-
PING = 'ping'
|
|
408
|
-
PONG = 'pong'
|
|
409
|
-
PARSER_REGISTER = 'parser_register'
|
|
410
|
-
PARSER_COMMAND = 'parser_command'
|
|
411
|
-
PARSER_STATUS = 'parser_status'
|
|
412
|
-
PARSER_REGISTERED = 'parser_registered'
|
|
413
|
-
PARSER_DISCONNECTED = 'parser_disconnected'
|
|
414
|
-
COMMAND_REQUEST = 'command_request'
|
|
415
|
-
COMMAND_RESPONSE = 'command_response'
|
|
416
|
-
COMMAND_STATUS = 'command_status'
|
|
417
|
-
HEALTH_STATUS = 'health_status'
|
|
418
|
-
HEALTH_CHECK = 'health_check'
|
|
419
|
-
ADMIN_SUBSCRIBE = 'admin_subscribe'
|
|
420
|
-
ADMIN_UNSUBSCRIBE = 'admin_unsubscribe'
|
|
421
|
-
ADMIN_BROADCAST = 'admin_broadcast'
|
|
422
|
-
ADMIN_NOTIFICATION = 'admin_notification'
|
|
423
|
-
SYSTEM_NOTIFICATION = 'system_notification'
|
|
424
|
-
SYSTEM_EVENT = 'system_event'
|
|
425
|
-
MAINTENANCE_NOTIFICATION = 'maintenance_notification'
|
|
426
|
-
DEVELOPER_MESSAGE = 'developer_message'
|
|
427
|
-
LOG_ENTRY = 'log_entry'
|
|
428
|
-
ERROR = 'error'
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
# WebSocket route constants for server communication
|
|
432
|
-
class WebSocketRoutes:
|
|
433
|
-
"""WebSocket endpoint routes for UnrealServer communication."""
|
|
434
|
-
|
|
435
|
-
# Socket.IO endpoint for parser connections
|
|
436
|
-
PARSER_CONNECTION_ENDPOINT = "/socket.io"
|
|
437
|
-
# Socket.IO endpoint for developer dashboard connections
|
|
438
|
-
CLIENT_CONNECTION_ENDPOINT = "/socket.io"
|
|
439
|
-
|
|
440
|
-
@classmethod
|
|
441
|
-
def get_parser_url(cls, base_url: str, parser_id: str) -> str:
|
|
442
|
-
"""
|
|
443
|
-
Build parser WebSocket URL for server connection.
|
|
444
|
-
|
|
445
|
-
Args:
|
|
446
|
-
base_url: Server base URL (e.g., 'wss://api.unrealon.com')
|
|
447
|
-
parser_id: Parser identifier
|
|
448
|
-
|
|
449
|
-
Returns:
|
|
450
|
-
Complete WebSocket URL for parser connection
|
|
451
|
-
|
|
452
|
-
Example:
|
|
453
|
-
>>> WebSocketRoutes.get_parser_url('wss://api.unrealon.com', 'amazon-parser')
|
|
454
|
-
'wss://api.unrealon.com/socket.io'
|
|
455
|
-
"""
|
|
456
|
-
base = base_url.rstrip('/')
|
|
457
|
-
# For Socket.IO, parser_id is passed via auth, not URL path
|
|
458
|
-
return f"{base}{cls.PARSER_CONNECTION_ENDPOINT}"
|
|
459
|
-
|
|
460
|
-
@classmethod
|
|
461
|
-
def get_client_url(cls, base_url: str, developer_id: str) -> str:
|
|
462
|
-
"""
|
|
463
|
-
Build client/developer WebSocket URL for dashboard connection.
|
|
464
|
-
|
|
465
|
-
Args:
|
|
466
|
-
base_url: Server base URL
|
|
467
|
-
developer_id: Developer identifier
|
|
468
|
-
|
|
469
|
-
Returns:
|
|
470
|
-
Complete WebSocket URL for client connection
|
|
471
|
-
"""
|
|
472
|
-
base = base_url.rstrip('/')
|
|
473
|
-
# For Socket.IO, developer_id is passed via auth, not URL path
|
|
474
|
-
return f"{base}{cls.CLIENT_CONNECTION_ENDPOINT}"
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
# Convenience function for creating clients
|
|
478
|
-
def create_client(url: str, **kwargs) -> WebSocketClient:
|
|
479
|
-
"""
|
|
480
|
-
Create a WebSocket client with the given URL.
|
|
481
|
-
|
|
482
|
-
Args:
|
|
483
|
-
url: WebSocket server URL
|
|
484
|
-
**kwargs: Additional configuration options
|
|
485
|
-
|
|
486
|
-
Returns:
|
|
487
|
-
WebSocketClient: Configured client instance
|
|
488
|
-
"""
|
|
489
|
-
config = WebSocketConfig(url=url, **kwargs)
|
|
490
|
-
return WebSocketClient(config)
|