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,420 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
WebSocket client wrapper for UnrealOn SDK v1.0
|
|
3
|
-
|
|
4
|
-
Wraps the auto-generated WebSocket client with SDK-specific functionality:
|
|
5
|
-
- Type-safe event handling
|
|
6
|
-
- Automatic reconnection with exponential backoff
|
|
7
|
-
- Command routing integration
|
|
8
|
-
- Health monitoring
|
|
9
|
-
- Error recovery
|
|
10
|
-
"""
|
|
11
|
-
|
|
12
|
-
import asyncio
|
|
13
|
-
import logging
|
|
14
|
-
from typing import Optional, Callable, Dict, Any, Union, Awaitable
|
|
15
|
-
from datetime import datetime
|
|
16
|
-
|
|
17
|
-
from pydantic import BaseModel, Field, ConfigDict
|
|
18
|
-
|
|
19
|
-
from unrealon_sdk.src.core.config import AdapterConfig
|
|
20
|
-
from unrealon_sdk.src.core.exceptions import WebSocketError, ConnectionError
|
|
21
|
-
from unrealon_sdk.src.clients.python_http.models import ConnectionStats
|
|
22
|
-
from unrealon_sdk.src.clients.python_websocket.client import WebSocketClient, WebSocketConfig
|
|
23
|
-
from unrealon_sdk.src.clients.python_websocket.events import SocketEvent
|
|
24
|
-
from unrealon_sdk.src.clients.python_websocket import WebSocketRoutes
|
|
25
|
-
from unrealon_sdk.src.clients.python_websocket.types import (
|
|
26
|
-
ParserCommandEvent,
|
|
27
|
-
ParserWebSocketRegistrationRequest,
|
|
28
|
-
)
|
|
29
|
-
from unrealon_sdk.src.clients.python_http.models import SuccessResponse, ErrorResponse
|
|
30
|
-
|
|
31
|
-
# Import from centralized logging service
|
|
32
|
-
from unrealon_sdk.src.enterprise.logging.service import LoggingRequest
|
|
33
|
-
|
|
34
|
-
# Use DTO models for type-safe data structures
|
|
35
|
-
from unrealon_sdk.src.dto.websocket import WebSocketConnectionState, WebSocketStateInfo
|
|
36
|
-
from unrealon_sdk.src.utils import generate_correlation_id
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
# WebSocketConnectionState moved to unrealon_sdk.dto.websocket
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class WebSocketClientWrapper:
|
|
43
|
-
"""
|
|
44
|
-
Wrapper for auto-generated WebSocket client.
|
|
45
|
-
|
|
46
|
-
Provides SDK-specific functionality while using the generated client
|
|
47
|
-
for actual WebSocket communication.
|
|
48
|
-
|
|
49
|
-
Features:
|
|
50
|
-
- Automatic reconnection with exponential backoff
|
|
51
|
-
- Type-safe event handling with Pydantic validation
|
|
52
|
-
- Command routing integration
|
|
53
|
-
- Health monitoring and diagnostics
|
|
54
|
-
- Error recovery and circuit breaker pattern
|
|
55
|
-
"""
|
|
56
|
-
|
|
57
|
-
def __init__(self, config: AdapterConfig, parser_id: str, logger: logging.Logger):
|
|
58
|
-
"""
|
|
59
|
-
Initialize WebSocket client wrapper.
|
|
60
|
-
|
|
61
|
-
Args:
|
|
62
|
-
config: Adapter configuration
|
|
63
|
-
parser_id: Unique parser identifier
|
|
64
|
-
logger: Logger instance
|
|
65
|
-
"""
|
|
66
|
-
self.config = config
|
|
67
|
-
self.parser_id = parser_id
|
|
68
|
-
self.logger = logger
|
|
69
|
-
|
|
70
|
-
# Create WebSocket configuration from adapter config
|
|
71
|
-
# Build parser-specific WebSocket URL using generated routes
|
|
72
|
-
parser_ws_url = WebSocketRoutes.get_parser_url(config.server_url, parser_id)
|
|
73
|
-
|
|
74
|
-
ws_config = WebSocketConfig(
|
|
75
|
-
url=parser_ws_url, # Use parser-specific endpoint from generated routes
|
|
76
|
-
auto_connect=False, # We handle connection manually
|
|
77
|
-
reconnection_attempts=5,
|
|
78
|
-
reconnection_delay=1,
|
|
79
|
-
timeout=config.request_timeout_ms / 1000, # Convert to seconds
|
|
80
|
-
auth={"api_key": config.api_key, "parser_id": parser_id},
|
|
81
|
-
headers={"User-Agent": f"UnrealOn-SDK/1.0 Parser/{parser_id}"},
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
# Initialize the generated WebSocket client
|
|
85
|
-
self._client = WebSocketClient(ws_config)
|
|
86
|
-
|
|
87
|
-
# Event handlers (can be sync or async)
|
|
88
|
-
self._command_handler: Optional[
|
|
89
|
-
Callable[[ParserCommandEvent], Union[None, Awaitable[None]]]
|
|
90
|
-
] = None
|
|
91
|
-
self._connection_handler: Optional[Callable[[str, Any], Union[None, Awaitable[None]]]] = (
|
|
92
|
-
None
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
# State tracking
|
|
96
|
-
self._reconnect_count = 0
|
|
97
|
-
self._last_ping: Optional[datetime] = None
|
|
98
|
-
self._connection_established = False
|
|
99
|
-
|
|
100
|
-
# Setup internal event handlers
|
|
101
|
-
self._setup_event_handlers()
|
|
102
|
-
|
|
103
|
-
self.logger.debug(f"WebSocketClientWrapper initialized for parser {parser_id}")
|
|
104
|
-
|
|
105
|
-
async def _call_handler(self, handler: Optional[Callable[..., Any]], *args: Any) -> None:
|
|
106
|
-
"""
|
|
107
|
-
Safely call handler, supporting both sync and async handlers.
|
|
108
|
-
|
|
109
|
-
Args:
|
|
110
|
-
handler: Handler function (sync or async)
|
|
111
|
-
*args: Arguments to pass to handler
|
|
112
|
-
"""
|
|
113
|
-
if handler is None:
|
|
114
|
-
return
|
|
115
|
-
|
|
116
|
-
try:
|
|
117
|
-
result = handler(*args)
|
|
118
|
-
if asyncio.iscoroutine(result):
|
|
119
|
-
await result
|
|
120
|
-
except Exception as e:
|
|
121
|
-
self.logger.error(f"Error in handler: {e}")
|
|
122
|
-
|
|
123
|
-
def _setup_event_handlers(self) -> None:
|
|
124
|
-
"""Setup event handlers for the generated WebSocket client."""
|
|
125
|
-
|
|
126
|
-
@self._client.on(SocketEvent.CONNECT) # type: ignore[misc]
|
|
127
|
-
async def on_connect(data: Any) -> None:
|
|
128
|
-
"""Handle WebSocket connection established."""
|
|
129
|
-
self._connection_established = True
|
|
130
|
-
self._reconnect_count = 0
|
|
131
|
-
self._last_ping = datetime.utcnow()
|
|
132
|
-
|
|
133
|
-
self.logger.info("WebSocket connection established")
|
|
134
|
-
|
|
135
|
-
# Small delay to ensure Socket.IO client is fully ready to emit
|
|
136
|
-
await asyncio.sleep(0.1)
|
|
137
|
-
|
|
138
|
-
# Send parser registration to server using auto-generated Pydantic v2 model
|
|
139
|
-
try:
|
|
140
|
-
developer_id = "dev_integration_test" # Extract from API key if needed
|
|
141
|
-
|
|
142
|
-
registration_request = ParserWebSocketRegistrationRequest(
|
|
143
|
-
parser_id=self.parser_id, developer_id=developer_id
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
# Use the underlying Socket.IO client directly for proper event emission
|
|
147
|
-
self.logger.debug(f"🔍 Emitting parser_register: event={SocketEvent.PARSER_REGISTER.value}, data={registration_request.model_dump()}")
|
|
148
|
-
await self._client.sio.emit(
|
|
149
|
-
SocketEvent.PARSER_REGISTER.value,
|
|
150
|
-
registration_request.model_dump(),
|
|
151
|
-
namespace='/'
|
|
152
|
-
)
|
|
153
|
-
self.logger.debug(f"🔍 Emit completed successfully")
|
|
154
|
-
self.logger.info(f"🚀 Sent parser registration: {self.parser_id}")
|
|
155
|
-
except Exception as e:
|
|
156
|
-
self.logger.error(f"Failed to send parser registration: {e}")
|
|
157
|
-
|
|
158
|
-
await self._call_handler(
|
|
159
|
-
self._connection_handler, "connected", {"timestamp": datetime.utcnow().isoformat()}
|
|
160
|
-
)
|
|
161
|
-
|
|
162
|
-
@self._client.on(SocketEvent.DISCONNECT) # type: ignore[misc]
|
|
163
|
-
async def on_disconnect(data: Any) -> None:
|
|
164
|
-
"""Handle WebSocket disconnection."""
|
|
165
|
-
self._connection_established = False
|
|
166
|
-
|
|
167
|
-
self.logger.warning("WebSocket connection lost")
|
|
168
|
-
|
|
169
|
-
await self._call_handler(
|
|
170
|
-
self._connection_handler, "disconnected", {"reason": data or "unknown"}
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
@self._client.on(SocketEvent.PARSER_COMMAND) # type: ignore[misc]
|
|
174
|
-
async def on_parser_command(data: Any) -> None:
|
|
175
|
-
"""Handle incoming parser command."""
|
|
176
|
-
try:
|
|
177
|
-
# Validate and parse command using Pydantic
|
|
178
|
-
command_event = ParserCommandEvent.model_validate(data)
|
|
179
|
-
|
|
180
|
-
self.logger.debug(f"Received command: {command_event.command_id}")
|
|
181
|
-
|
|
182
|
-
await self._call_handler(self._command_handler, command_event)
|
|
183
|
-
|
|
184
|
-
if self._command_handler is None:
|
|
185
|
-
self.logger.warning(
|
|
186
|
-
f"No command handler registered for command {command_event.command_id}"
|
|
187
|
-
)
|
|
188
|
-
|
|
189
|
-
except Exception as e:
|
|
190
|
-
self.logger.error(f"Error processing command: {e}")
|
|
191
|
-
await self._call_handler(
|
|
192
|
-
self._connection_handler,
|
|
193
|
-
"error",
|
|
194
|
-
{"error": str(e), "context": "command_processing"},
|
|
195
|
-
)
|
|
196
|
-
|
|
197
|
-
@self._client.on(SocketEvent.PING) # type: ignore[misc]
|
|
198
|
-
async def on_ping(data: Any) -> None:
|
|
199
|
-
"""Handle ping from server."""
|
|
200
|
-
self._last_ping = datetime.utcnow()
|
|
201
|
-
|
|
202
|
-
# Respond with pong
|
|
203
|
-
await self._client.emit(
|
|
204
|
-
SocketEvent.PONG,
|
|
205
|
-
{"timestamp": self._last_ping.isoformat(), "parser_id": self.parser_id},
|
|
206
|
-
)
|
|
207
|
-
|
|
208
|
-
@self._client.on(SocketEvent.ERROR) # type: ignore[misc]
|
|
209
|
-
async def on_error(data: Any) -> None:
|
|
210
|
-
"""Handle WebSocket errors."""
|
|
211
|
-
error_msg = (
|
|
212
|
-
data.get("message", "Unknown WebSocket error")
|
|
213
|
-
if isinstance(data, dict)
|
|
214
|
-
else str(data)
|
|
215
|
-
)
|
|
216
|
-
|
|
217
|
-
self.logger.error(f"WebSocket error: {error_msg}")
|
|
218
|
-
|
|
219
|
-
await self._call_handler(
|
|
220
|
-
self._connection_handler, "error", {"error": error_msg, "context": "websocket"}
|
|
221
|
-
)
|
|
222
|
-
|
|
223
|
-
async def connect(self) -> None:
|
|
224
|
-
"""
|
|
225
|
-
Connect to WebSocket server.
|
|
226
|
-
|
|
227
|
-
Raises:
|
|
228
|
-
WebSocketError: If connection fails
|
|
229
|
-
"""
|
|
230
|
-
try:
|
|
231
|
-
self.logger.info(f"Connecting to WebSocket server: {self.config.server_url}")
|
|
232
|
-
|
|
233
|
-
success = await self._client.connect()
|
|
234
|
-
if not success:
|
|
235
|
-
raise WebSocketError("Failed to establish WebSocket connection")
|
|
236
|
-
|
|
237
|
-
# Wait for connection to be fully established
|
|
238
|
-
timeout = self.config.request_timeout_ms / 1000
|
|
239
|
-
start_time = datetime.utcnow()
|
|
240
|
-
|
|
241
|
-
while not self._connection_established:
|
|
242
|
-
if (datetime.utcnow() - start_time).total_seconds() > timeout:
|
|
243
|
-
raise WebSocketError("Connection timeout")
|
|
244
|
-
await asyncio.sleep(0.1)
|
|
245
|
-
|
|
246
|
-
self.logger.info("WebSocket connection established successfully")
|
|
247
|
-
|
|
248
|
-
except Exception as e:
|
|
249
|
-
self.logger.error(f"WebSocket connection failed: {e}")
|
|
250
|
-
raise WebSocketError(f"Connection failed: {e}")
|
|
251
|
-
|
|
252
|
-
async def disconnect(self) -> None:
|
|
253
|
-
"""Disconnect from WebSocket server."""
|
|
254
|
-
try:
|
|
255
|
-
self.logger.info("Disconnecting from WebSocket server")
|
|
256
|
-
|
|
257
|
-
await self._client.disconnect()
|
|
258
|
-
self._connection_established = False
|
|
259
|
-
|
|
260
|
-
self.logger.info("WebSocket disconnected successfully")
|
|
261
|
-
|
|
262
|
-
except Exception as e:
|
|
263
|
-
self.logger.error(f"Error during WebSocket disconnect: {e}")
|
|
264
|
-
raise WebSocketError(f"Disconnect failed: {e}")
|
|
265
|
-
|
|
266
|
-
async def reconnect(self) -> None:
|
|
267
|
-
"""
|
|
268
|
-
Reconnect to WebSocket server with exponential backoff.
|
|
269
|
-
|
|
270
|
-
Raises:
|
|
271
|
-
WebSocketError: If reconnection fails
|
|
272
|
-
"""
|
|
273
|
-
self._reconnect_count += 1
|
|
274
|
-
|
|
275
|
-
# Calculate backoff delay (exponential with jitter)
|
|
276
|
-
base_delay = min(2**self._reconnect_count, 60) # Max 60 seconds
|
|
277
|
-
jitter = base_delay * 0.1 # 10% jitter
|
|
278
|
-
delay = base_delay + (jitter * (0.5 - asyncio.get_event_loop().time() % 1))
|
|
279
|
-
|
|
280
|
-
self.logger.info(
|
|
281
|
-
f"Attempting WebSocket reconnection #{self._reconnect_count} in {delay:.2f}s"
|
|
282
|
-
)
|
|
283
|
-
|
|
284
|
-
await asyncio.sleep(delay)
|
|
285
|
-
|
|
286
|
-
try:
|
|
287
|
-
# Disconnect first if needed
|
|
288
|
-
if self._connection_established:
|
|
289
|
-
await self.disconnect()
|
|
290
|
-
|
|
291
|
-
# Attempt new connection
|
|
292
|
-
await self.connect()
|
|
293
|
-
|
|
294
|
-
self.logger.info(f"WebSocket reconnection #{self._reconnect_count} successful")
|
|
295
|
-
|
|
296
|
-
except Exception as e:
|
|
297
|
-
self.logger.error(f"WebSocket reconnection #{self._reconnect_count} failed: {e}")
|
|
298
|
-
raise WebSocketError(f"Reconnection failed: {e}")
|
|
299
|
-
|
|
300
|
-
async def send_response(self, response: Union[SuccessResponse, ErrorResponse]) -> None:
|
|
301
|
-
"""
|
|
302
|
-
Send command response back to server.
|
|
303
|
-
|
|
304
|
-
Args:
|
|
305
|
-
response: Command response to send
|
|
306
|
-
|
|
307
|
-
Raises:
|
|
308
|
-
WebSocketError: If sending fails
|
|
309
|
-
"""
|
|
310
|
-
if not self.is_connected():
|
|
311
|
-
raise WebSocketError("Not connected to WebSocket server")
|
|
312
|
-
|
|
313
|
-
try:
|
|
314
|
-
# Convert response to dict for transmission
|
|
315
|
-
response_data = response.model_dump()
|
|
316
|
-
|
|
317
|
-
await self._client.emit(SocketEvent.COMMAND_RESPONSE, response_data)
|
|
318
|
-
|
|
319
|
-
self.logger.debug(f"Sent response: {response.success}")
|
|
320
|
-
|
|
321
|
-
except Exception as e:
|
|
322
|
-
self.logger.error(f"Failed to send response: {e}")
|
|
323
|
-
raise WebSocketError(f"Failed to send response: {e}")
|
|
324
|
-
|
|
325
|
-
async def send_log(self, log_request: LoggingRequest) -> None:
|
|
326
|
-
"""
|
|
327
|
-
Send log entry to server.
|
|
328
|
-
|
|
329
|
-
Args:
|
|
330
|
-
log_request: Log entry to send
|
|
331
|
-
|
|
332
|
-
Raises:
|
|
333
|
-
WebSocketError: If sending fails
|
|
334
|
-
"""
|
|
335
|
-
if not self.is_connected():
|
|
336
|
-
# Don't raise error for logging - just skip
|
|
337
|
-
self.logger.debug("Skipping log transmission - not connected")
|
|
338
|
-
return
|
|
339
|
-
|
|
340
|
-
try:
|
|
341
|
-
# Convert log request to dict for transmission
|
|
342
|
-
log_data = log_request.model_dump()
|
|
343
|
-
|
|
344
|
-
await self._client.emit(SocketEvent.LOG_ENTRY, log_data)
|
|
345
|
-
|
|
346
|
-
self.logger.debug(f"Sent log entry: {log_request.level}")
|
|
347
|
-
|
|
348
|
-
except Exception as e:
|
|
349
|
-
self.logger.error(f"Failed to send log entry: {e}")
|
|
350
|
-
# Don't raise error for logging failures
|
|
351
|
-
|
|
352
|
-
def set_command_handler(
|
|
353
|
-
self, handler: Callable[[ParserCommandEvent], Union[None, Awaitable[None]]]
|
|
354
|
-
) -> None:
|
|
355
|
-
"""
|
|
356
|
-
Set command handler function.
|
|
357
|
-
|
|
358
|
-
Args:
|
|
359
|
-
handler: Function to handle incoming commands
|
|
360
|
-
"""
|
|
361
|
-
self._command_handler = handler
|
|
362
|
-
self.logger.debug("Command handler registered")
|
|
363
|
-
|
|
364
|
-
def set_connection_handler(
|
|
365
|
-
self, handler: Callable[[str, Any], Union[None, Awaitable[None]]]
|
|
366
|
-
) -> None:
|
|
367
|
-
"""
|
|
368
|
-
Set connection event handler function.
|
|
369
|
-
|
|
370
|
-
Args:
|
|
371
|
-
handler: Function to handle connection events
|
|
372
|
-
"""
|
|
373
|
-
self._connection_handler = handler
|
|
374
|
-
self.logger.debug("Connection handler registered")
|
|
375
|
-
|
|
376
|
-
def is_connected(self) -> bool:
|
|
377
|
-
"""Check if WebSocket is connected."""
|
|
378
|
-
# TEMPORARY FIX: Only check our internal flag, not auto-generated client flag
|
|
379
|
-
# The auto-generated client's .connected flag becomes False incorrectly
|
|
380
|
-
return self._connection_established
|
|
381
|
-
|
|
382
|
-
def get_connection_state(self) -> WebSocketStateInfo:
|
|
383
|
-
"""Get current connection state as type-safe Pydantic model."""
|
|
384
|
-
# Build state from our internal tracking (no raw dict usage)
|
|
385
|
-
return WebSocketStateInfo(
|
|
386
|
-
status=WebSocketConnectionState.CONNECTED if self.is_connected() else WebSocketConnectionState.DISCONNECTED,
|
|
387
|
-
session_id=self.parser_id,
|
|
388
|
-
last_ping=self._last_ping.isoformat() if self._last_ping else None,
|
|
389
|
-
connection_time=getattr(self, "_connection_time", None),
|
|
390
|
-
connected=self.is_connected(),
|
|
391
|
-
connecting=getattr(self, "_connecting", False),
|
|
392
|
-
error=None, # Could be extended to track last error
|
|
393
|
-
last_connected=self._last_ping.isoformat() if self._last_ping else None,
|
|
394
|
-
reconnect_count=self._reconnect_count,
|
|
395
|
-
)
|
|
396
|
-
|
|
397
|
-
async def health_check(self) -> WebSocketStateInfo:
|
|
398
|
-
"""
|
|
399
|
-
Perform health check of WebSocket connection.
|
|
400
|
-
|
|
401
|
-
Returns:
|
|
402
|
-
Type-safe WebSocketStateInfo model (NO raw Dict usage!)
|
|
403
|
-
"""
|
|
404
|
-
return self.get_connection_state()
|
|
405
|
-
|
|
406
|
-
def get_statistics(self) -> ConnectionStats:
|
|
407
|
-
"""
|
|
408
|
-
Get WebSocket connection statistics.
|
|
409
|
-
|
|
410
|
-
Returns:
|
|
411
|
-
ConnectionStats with typed connection statistics
|
|
412
|
-
"""
|
|
413
|
-
return ConnectionStats(
|
|
414
|
-
total_connections=1 if self.is_connected() else 0,
|
|
415
|
-
parser_connections=1 if self.is_connected() else 0,
|
|
416
|
-
client_connections=1 if self.is_connected() else 0,
|
|
417
|
-
active_rooms=0, # Client doesn't track rooms
|
|
418
|
-
max_connections=1, # Single client connection
|
|
419
|
-
metrics=None, # Can be extended later
|
|
420
|
-
)
|