unrealon 1.0.9__py3-none-any.whl → 1.1.0__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.
Files changed (302) hide show
  1. unrealon/__init__.py +23 -21
  2. unrealon-1.1.0.dist-info/METADATA +164 -0
  3. unrealon-1.1.0.dist-info/RECORD +82 -0
  4. {unrealon-1.0.9.dist-info → unrealon-1.1.0.dist-info}/WHEEL +1 -1
  5. unrealon-1.1.0.dist-info/entry_points.txt +9 -0
  6. {unrealon-1.0.9.dist-info → unrealon-1.1.0.dist-info/licenses}/LICENSE +1 -1
  7. unrealon_bridge/__init__.py +114 -0
  8. unrealon_bridge/cli.py +316 -0
  9. unrealon_bridge/client/__init__.py +93 -0
  10. unrealon_bridge/client/base.py +78 -0
  11. unrealon_bridge/client/commands.py +89 -0
  12. unrealon_bridge/client/connection.py +90 -0
  13. unrealon_bridge/client/events.py +65 -0
  14. unrealon_bridge/client/health.py +38 -0
  15. unrealon_bridge/client/html_parser.py +146 -0
  16. unrealon_bridge/client/logging.py +139 -0
  17. unrealon_bridge/client/proxy.py +70 -0
  18. unrealon_bridge/client/scheduler.py +450 -0
  19. unrealon_bridge/client/session.py +70 -0
  20. unrealon_bridge/configs/__init__.py +14 -0
  21. unrealon_bridge/configs/bridge_config.py +212 -0
  22. unrealon_bridge/configs/bridge_config.yaml +39 -0
  23. unrealon_bridge/models/__init__.py +138 -0
  24. unrealon_bridge/models/base.py +28 -0
  25. unrealon_bridge/models/command.py +41 -0
  26. unrealon_bridge/models/events.py +40 -0
  27. unrealon_bridge/models/html_parser.py +79 -0
  28. unrealon_bridge/models/logging.py +55 -0
  29. unrealon_bridge/models/parser.py +63 -0
  30. unrealon_bridge/models/proxy.py +41 -0
  31. unrealon_bridge/models/requests.py +95 -0
  32. unrealon_bridge/models/responses.py +88 -0
  33. unrealon_bridge/models/scheduler.py +592 -0
  34. unrealon_bridge/models/session.py +28 -0
  35. unrealon_bridge/server/__init__.py +91 -0
  36. unrealon_bridge/server/base.py +171 -0
  37. unrealon_bridge/server/handlers/__init__.py +23 -0
  38. unrealon_bridge/server/handlers/command.py +110 -0
  39. unrealon_bridge/server/handlers/html_parser.py +139 -0
  40. unrealon_bridge/server/handlers/logging.py +95 -0
  41. unrealon_bridge/server/handlers/parser.py +95 -0
  42. unrealon_bridge/server/handlers/proxy.py +75 -0
  43. unrealon_bridge/server/handlers/scheduler.py +545 -0
  44. unrealon_bridge/server/handlers/session.py +66 -0
  45. unrealon_browser/__init__.py +61 -18
  46. unrealon_browser/{src/cli → cli}/browser_cli.py +6 -13
  47. unrealon_browser/{src/cli → cli}/cookies_cli.py +5 -1
  48. unrealon_browser/{src/core → core}/browser_manager.py +2 -2
  49. unrealon_browser/{src/managers → managers}/captcha.py +1 -1
  50. unrealon_browser/{src/managers → managers}/cookies.py +1 -1
  51. unrealon_browser/managers/logger_bridge.py +231 -0
  52. unrealon_browser/{src/managers → managers}/profile.py +1 -1
  53. unrealon_driver/__init__.py +73 -19
  54. unrealon_driver/browser/__init__.py +8 -0
  55. unrealon_driver/browser/config.py +74 -0
  56. unrealon_driver/browser/manager.py +416 -0
  57. unrealon_driver/exceptions.py +28 -0
  58. unrealon_driver/parser/__init__.py +55 -0
  59. unrealon_driver/parser/cli_manager.py +141 -0
  60. unrealon_driver/parser/daemon_manager.py +227 -0
  61. unrealon_driver/parser/managers/__init__.py +46 -0
  62. unrealon_driver/parser/managers/browser.py +51 -0
  63. unrealon_driver/parser/managers/config.py +281 -0
  64. unrealon_driver/parser/managers/error.py +412 -0
  65. unrealon_driver/parser/managers/html.py +732 -0
  66. unrealon_driver/parser/managers/logging.py +609 -0
  67. unrealon_driver/parser/managers/result.py +321 -0
  68. unrealon_driver/parser/parser_manager.py +628 -0
  69. unrealon/sdk_config.py +0 -88
  70. unrealon-1.0.9.dist-info/METADATA +0 -810
  71. unrealon-1.0.9.dist-info/RECORD +0 -246
  72. unrealon_browser/pyproject.toml +0 -182
  73. unrealon_browser/src/__init__.py +0 -62
  74. unrealon_browser/src/managers/logger_bridge.py +0 -395
  75. unrealon_driver/README.md +0 -204
  76. unrealon_driver/pyproject.toml +0 -187
  77. unrealon_driver/src/__init__.py +0 -90
  78. unrealon_driver/src/cli/__init__.py +0 -10
  79. unrealon_driver/src/cli/main.py +0 -66
  80. unrealon_driver/src/cli/simple.py +0 -510
  81. unrealon_driver/src/config/__init__.py +0 -11
  82. unrealon_driver/src/config/auto_config.py +0 -478
  83. unrealon_driver/src/core/__init__.py +0 -18
  84. unrealon_driver/src/core/exceptions.py +0 -289
  85. unrealon_driver/src/core/parser.py +0 -638
  86. unrealon_driver/src/dto/__init__.py +0 -66
  87. unrealon_driver/src/dto/cli.py +0 -119
  88. unrealon_driver/src/dto/config.py +0 -18
  89. unrealon_driver/src/dto/events.py +0 -237
  90. unrealon_driver/src/dto/execution.py +0 -313
  91. unrealon_driver/src/dto/services.py +0 -311
  92. unrealon_driver/src/execution/__init__.py +0 -23
  93. unrealon_driver/src/execution/daemon_mode.py +0 -317
  94. unrealon_driver/src/execution/interactive_mode.py +0 -88
  95. unrealon_driver/src/execution/modes.py +0 -45
  96. unrealon_driver/src/execution/scheduled_mode.py +0 -209
  97. unrealon_driver/src/execution/test_mode.py +0 -250
  98. unrealon_driver/src/logging/__init__.py +0 -24
  99. unrealon_driver/src/logging/driver_logger.py +0 -512
  100. unrealon_driver/src/services/__init__.py +0 -24
  101. unrealon_driver/src/services/browser_service.py +0 -726
  102. unrealon_driver/src/services/llm/__init__.py +0 -15
  103. unrealon_driver/src/services/llm/browser_llm_service.py +0 -363
  104. unrealon_driver/src/services/llm/llm.py +0 -195
  105. unrealon_driver/src/services/logger_service.py +0 -232
  106. unrealon_driver/src/services/metrics_service.py +0 -185
  107. unrealon_driver/src/services/scheduler_service.py +0 -489
  108. unrealon_driver/src/services/websocket_service.py +0 -362
  109. unrealon_driver/src/utils/__init__.py +0 -16
  110. unrealon_driver/src/utils/service_factory.py +0 -317
  111. unrealon_driver/src/utils/time_formatter.py +0 -338
  112. unrealon_llm/README.md +0 -44
  113. unrealon_llm/__init__.py +0 -26
  114. unrealon_llm/pyproject.toml +0 -154
  115. unrealon_llm/src/__init__.py +0 -228
  116. unrealon_llm/src/cli/__init__.py +0 -0
  117. unrealon_llm/src/core/__init__.py +0 -11
  118. unrealon_llm/src/core/smart_client.py +0 -438
  119. unrealon_llm/src/dto/__init__.py +0 -155
  120. unrealon_llm/src/dto/models/__init__.py +0 -0
  121. unrealon_llm/src/dto/models/config.py +0 -343
  122. unrealon_llm/src/dto/models/core.py +0 -328
  123. unrealon_llm/src/dto/models/enums.py +0 -123
  124. unrealon_llm/src/dto/models/html_analysis.py +0 -345
  125. unrealon_llm/src/dto/models/statistics.py +0 -473
  126. unrealon_llm/src/dto/models/translation.py +0 -383
  127. unrealon_llm/src/dto/models/type_conversion.py +0 -462
  128. unrealon_llm/src/dto/schemas/__init__.py +0 -0
  129. unrealon_llm/src/exceptions.py +0 -392
  130. unrealon_llm/src/llm_config/__init__.py +0 -20
  131. unrealon_llm/src/llm_config/logging_config.py +0 -178
  132. unrealon_llm/src/llm_logging/__init__.py +0 -42
  133. unrealon_llm/src/llm_logging/llm_events.py +0 -107
  134. unrealon_llm/src/llm_logging/llm_logger.py +0 -466
  135. unrealon_llm/src/managers/__init__.py +0 -15
  136. unrealon_llm/src/managers/cache_manager.py +0 -67
  137. unrealon_llm/src/managers/cost_manager.py +0 -107
  138. unrealon_llm/src/managers/request_manager.py +0 -298
  139. unrealon_llm/src/modules/__init__.py +0 -0
  140. unrealon_llm/src/modules/html_processor/__init__.py +0 -25
  141. unrealon_llm/src/modules/html_processor/base_processor.py +0 -415
  142. unrealon_llm/src/modules/html_processor/details_processor.py +0 -85
  143. unrealon_llm/src/modules/html_processor/listing_processor.py +0 -91
  144. unrealon_llm/src/modules/html_processor/models/__init__.py +0 -20
  145. unrealon_llm/src/modules/html_processor/models/processing_models.py +0 -40
  146. unrealon_llm/src/modules/html_processor/models/universal_model.py +0 -56
  147. unrealon_llm/src/modules/html_processor/processor.py +0 -102
  148. unrealon_llm/src/modules/llm/__init__.py +0 -0
  149. unrealon_llm/src/modules/translator/__init__.py +0 -0
  150. unrealon_llm/src/provider.py +0 -116
  151. unrealon_llm/src/utils/__init__.py +0 -95
  152. unrealon_llm/src/utils/common.py +0 -64
  153. unrealon_llm/src/utils/data_extractor.py +0 -188
  154. unrealon_llm/src/utils/html_cleaner.py +0 -767
  155. unrealon_llm/src/utils/language_detector.py +0 -308
  156. unrealon_llm/src/utils/models_cache.py +0 -592
  157. unrealon_llm/src/utils/smart_counter.py +0 -229
  158. unrealon_llm/src/utils/token_counter.py +0 -189
  159. unrealon_sdk/README.md +0 -25
  160. unrealon_sdk/__init__.py +0 -30
  161. unrealon_sdk/pyproject.toml +0 -231
  162. unrealon_sdk/src/__init__.py +0 -150
  163. unrealon_sdk/src/cli/__init__.py +0 -12
  164. unrealon_sdk/src/cli/commands/__init__.py +0 -22
  165. unrealon_sdk/src/cli/commands/benchmark.py +0 -42
  166. unrealon_sdk/src/cli/commands/diagnostics.py +0 -573
  167. unrealon_sdk/src/cli/commands/health.py +0 -46
  168. unrealon_sdk/src/cli/commands/integration.py +0 -498
  169. unrealon_sdk/src/cli/commands/reports.py +0 -43
  170. unrealon_sdk/src/cli/commands/security.py +0 -36
  171. unrealon_sdk/src/cli/commands/server.py +0 -483
  172. unrealon_sdk/src/cli/commands/servers.py +0 -56
  173. unrealon_sdk/src/cli/commands/tests.py +0 -55
  174. unrealon_sdk/src/cli/main.py +0 -126
  175. unrealon_sdk/src/cli/utils/reporter.py +0 -519
  176. unrealon_sdk/src/clients/openapi.yaml +0 -3347
  177. unrealon_sdk/src/clients/python_http/__init__.py +0 -3
  178. unrealon_sdk/src/clients/python_http/api_config.py +0 -228
  179. unrealon_sdk/src/clients/python_http/models/BaseModel.py +0 -12
  180. unrealon_sdk/src/clients/python_http/models/BroadcastDeliveryStats.py +0 -33
  181. unrealon_sdk/src/clients/python_http/models/BroadcastMessage.py +0 -17
  182. unrealon_sdk/src/clients/python_http/models/BroadcastMessageRequest.py +0 -35
  183. unrealon_sdk/src/clients/python_http/models/BroadcastPriority.py +0 -10
  184. unrealon_sdk/src/clients/python_http/models/BroadcastResponse.py +0 -21
  185. unrealon_sdk/src/clients/python_http/models/BroadcastResultResponse.py +0 -33
  186. unrealon_sdk/src/clients/python_http/models/BroadcastTarget.py +0 -11
  187. unrealon_sdk/src/clients/python_http/models/ConnectionStats.py +0 -27
  188. unrealon_sdk/src/clients/python_http/models/ConnectionsResponse.py +0 -21
  189. unrealon_sdk/src/clients/python_http/models/DeveloperMessageResponse.py +0 -23
  190. unrealon_sdk/src/clients/python_http/models/ErrorResponse.py +0 -25
  191. unrealon_sdk/src/clients/python_http/models/HTTPValidationError.py +0 -16
  192. unrealon_sdk/src/clients/python_http/models/HealthResponse.py +0 -23
  193. unrealon_sdk/src/clients/python_http/models/HealthStatus.py +0 -33
  194. unrealon_sdk/src/clients/python_http/models/LogLevel.py +0 -10
  195. unrealon_sdk/src/clients/python_http/models/LoggingRequest.py +0 -27
  196. unrealon_sdk/src/clients/python_http/models/LoggingResponse.py +0 -23
  197. unrealon_sdk/src/clients/python_http/models/MaintenanceMode.py +0 -9
  198. unrealon_sdk/src/clients/python_http/models/MaintenanceModeRequest.py +0 -33
  199. unrealon_sdk/src/clients/python_http/models/MaintenanceStatusResponse.py +0 -39
  200. unrealon_sdk/src/clients/python_http/models/ParserCommandRequest.py +0 -25
  201. unrealon_sdk/src/clients/python_http/models/ParserMessageResponse.py +0 -21
  202. unrealon_sdk/src/clients/python_http/models/ParserRegistrationRequest.py +0 -28
  203. unrealon_sdk/src/clients/python_http/models/ParserRegistrationResponse.py +0 -25
  204. unrealon_sdk/src/clients/python_http/models/ParserType.py +0 -10
  205. unrealon_sdk/src/clients/python_http/models/ProxyBlockRequest.py +0 -19
  206. unrealon_sdk/src/clients/python_http/models/ProxyEndpointResponse.py +0 -20
  207. unrealon_sdk/src/clients/python_http/models/ProxyListResponse.py +0 -19
  208. unrealon_sdk/src/clients/python_http/models/ProxyProvider.py +0 -10
  209. unrealon_sdk/src/clients/python_http/models/ProxyPurchaseRequest.py +0 -25
  210. unrealon_sdk/src/clients/python_http/models/ProxyResponse.py +0 -47
  211. unrealon_sdk/src/clients/python_http/models/ProxyRotationRequest.py +0 -23
  212. unrealon_sdk/src/clients/python_http/models/ProxyStatus.py +0 -10
  213. unrealon_sdk/src/clients/python_http/models/ProxyUsageRequest.py +0 -19
  214. unrealon_sdk/src/clients/python_http/models/ProxyUsageStatsResponse.py +0 -26
  215. unrealon_sdk/src/clients/python_http/models/ServiceRegistrationDto.py +0 -23
  216. unrealon_sdk/src/clients/python_http/models/ServiceStatsResponse.py +0 -31
  217. unrealon_sdk/src/clients/python_http/models/SessionStartRequest.py +0 -23
  218. unrealon_sdk/src/clients/python_http/models/SuccessResponse.py +0 -25
  219. unrealon_sdk/src/clients/python_http/models/SystemNotificationResponse.py +0 -23
  220. unrealon_sdk/src/clients/python_http/models/ValidationError.py +0 -18
  221. unrealon_sdk/src/clients/python_http/models/ValidationErrorResponse.py +0 -21
  222. unrealon_sdk/src/clients/python_http/models/WebSocketMetrics.py +0 -21
  223. unrealon_sdk/src/clients/python_http/models/__init__.py +0 -44
  224. unrealon_sdk/src/clients/python_http/services/None_service.py +0 -35
  225. unrealon_sdk/src/clients/python_http/services/ParserManagement_service.py +0 -190
  226. unrealon_sdk/src/clients/python_http/services/ProxyManagement_service.py +0 -289
  227. unrealon_sdk/src/clients/python_http/services/SocketLogging_service.py +0 -187
  228. unrealon_sdk/src/clients/python_http/services/SystemHealth_service.py +0 -119
  229. unrealon_sdk/src/clients/python_http/services/WebSocketAPI_service.py +0 -198
  230. unrealon_sdk/src/clients/python_http/services/__init__.py +0 -0
  231. unrealon_sdk/src/clients/python_http/services/admin_service.py +0 -125
  232. unrealon_sdk/src/clients/python_http/services/async_None_service.py +0 -35
  233. unrealon_sdk/src/clients/python_http/services/async_ParserManagement_service.py +0 -190
  234. unrealon_sdk/src/clients/python_http/services/async_ProxyManagement_service.py +0 -289
  235. unrealon_sdk/src/clients/python_http/services/async_SocketLogging_service.py +0 -189
  236. unrealon_sdk/src/clients/python_http/services/async_SystemHealth_service.py +0 -123
  237. unrealon_sdk/src/clients/python_http/services/async_WebSocketAPI_service.py +0 -200
  238. unrealon_sdk/src/clients/python_http/services/async_admin_service.py +0 -125
  239. unrealon_sdk/src/clients/python_websocket/__init__.py +0 -28
  240. unrealon_sdk/src/clients/python_websocket/client.py +0 -490
  241. unrealon_sdk/src/clients/python_websocket/events.py +0 -732
  242. unrealon_sdk/src/clients/python_websocket/example.py +0 -136
  243. unrealon_sdk/src/clients/python_websocket/types.py +0 -871
  244. unrealon_sdk/src/core/__init__.py +0 -64
  245. unrealon_sdk/src/core/client.py +0 -556
  246. unrealon_sdk/src/core/config.py +0 -465
  247. unrealon_sdk/src/core/exceptions.py +0 -239
  248. unrealon_sdk/src/core/metadata.py +0 -191
  249. unrealon_sdk/src/core/models.py +0 -142
  250. unrealon_sdk/src/core/types.py +0 -68
  251. unrealon_sdk/src/dto/__init__.py +0 -268
  252. unrealon_sdk/src/dto/authentication.py +0 -108
  253. unrealon_sdk/src/dto/cache.py +0 -208
  254. unrealon_sdk/src/dto/common.py +0 -19
  255. unrealon_sdk/src/dto/concurrency.py +0 -393
  256. unrealon_sdk/src/dto/events.py +0 -108
  257. unrealon_sdk/src/dto/health.py +0 -339
  258. unrealon_sdk/src/dto/load_balancing.py +0 -336
  259. unrealon_sdk/src/dto/logging.py +0 -230
  260. unrealon_sdk/src/dto/performance.py +0 -165
  261. unrealon_sdk/src/dto/rate_limiting.py +0 -295
  262. unrealon_sdk/src/dto/resource_pooling.py +0 -128
  263. unrealon_sdk/src/dto/structured_logging.py +0 -112
  264. unrealon_sdk/src/dto/task_scheduling.py +0 -121
  265. unrealon_sdk/src/dto/websocket.py +0 -55
  266. unrealon_sdk/src/enterprise/__init__.py +0 -59
  267. unrealon_sdk/src/enterprise/authentication.py +0 -401
  268. unrealon_sdk/src/enterprise/cache_manager.py +0 -578
  269. unrealon_sdk/src/enterprise/error_recovery.py +0 -494
  270. unrealon_sdk/src/enterprise/event_system.py +0 -549
  271. unrealon_sdk/src/enterprise/health_monitor.py +0 -747
  272. unrealon_sdk/src/enterprise/load_balancer.py +0 -964
  273. unrealon_sdk/src/enterprise/logging/__init__.py +0 -68
  274. unrealon_sdk/src/enterprise/logging/cleanup.py +0 -156
  275. unrealon_sdk/src/enterprise/logging/development.py +0 -744
  276. unrealon_sdk/src/enterprise/logging/service.py +0 -410
  277. unrealon_sdk/src/enterprise/multithreading_manager.py +0 -853
  278. unrealon_sdk/src/enterprise/performance_monitor.py +0 -539
  279. unrealon_sdk/src/enterprise/proxy_manager.py +0 -696
  280. unrealon_sdk/src/enterprise/rate_limiter.py +0 -652
  281. unrealon_sdk/src/enterprise/resource_pool.py +0 -763
  282. unrealon_sdk/src/enterprise/task_scheduler.py +0 -709
  283. unrealon_sdk/src/internal/__init__.py +0 -10
  284. unrealon_sdk/src/internal/command_router.py +0 -497
  285. unrealon_sdk/src/internal/connection_manager.py +0 -397
  286. unrealon_sdk/src/internal/http_client.py +0 -446
  287. unrealon_sdk/src/internal/websocket_client.py +0 -420
  288. unrealon_sdk/src/provider.py +0 -471
  289. unrealon_sdk/src/utils.py +0 -234
  290. /unrealon_browser/{src/cli → cli}/__init__.py +0 -0
  291. /unrealon_browser/{src/cli → cli}/interactive_mode.py +0 -0
  292. /unrealon_browser/{src/cli → cli}/main.py +0 -0
  293. /unrealon_browser/{src/core → core}/__init__.py +0 -0
  294. /unrealon_browser/{src/dto → dto}/__init__.py +0 -0
  295. /unrealon_browser/{src/dto → dto}/models/config.py +0 -0
  296. /unrealon_browser/{src/dto → dto}/models/core.py +0 -0
  297. /unrealon_browser/{src/dto → dto}/models/dataclasses.py +0 -0
  298. /unrealon_browser/{src/dto → dto}/models/detection.py +0 -0
  299. /unrealon_browser/{src/dto → dto}/models/enums.py +0 -0
  300. /unrealon_browser/{src/dto → dto}/models/statistics.py +0 -0
  301. /unrealon_browser/{src/managers → managers}/__init__.py +0 -0
  302. /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)