import asyncio import json from typing import Optional, Awaitable, Callable import websockets from loguru import logger class GsCoreClient: def __init__(self): self._ws = None self._url: str = "" self._recv_task: Optional[asyncio.Task] = None self._message_handler: Optional[Callable[[dict], Awaitable[None]]] = None def configure(self, url: str, handler: Callable[[dict], Awaitable[None]]): self._url = url self._message_handler = handler async def connect(self): if not self._url: logger.warning("[GsCoreClient] gscore_url 未配置,跳过连接") return False if self._ws is not None: return True try: logger.info(f"[GsCoreClient] 连接早柚核心: {self._url}") self._ws = await websockets.connect(self._url, max_size=10**7) loop = asyncio.get_running_loop() self._recv_task = loop.create_task(self._recv_loop()) return True except Exception as e: logger.error(f"[GsCoreClient] 连接早柚核心失败: {e}") self._ws = None return False async def _recv_loop(self): if not self._ws: return while True: try: msg = await self._ws.recv() if isinstance(msg, bytes): msg_str = msg.decode("utf-8") else: msg_str = msg try: payload = json.loads(msg_str) except Exception as e: logger.exception(f"[GsCoreClient] 解析核心返回失败: {e}") continue if self._message_handler: try: await self._message_handler(payload) except Exception as e: logger.exception(f"[GsCoreClient] 处理核心返回失败: {e}") except websockets.exceptions.ConnectionClosed as e: logger.warning(f"[GsCoreClient] WebSocket连接关闭: {e}") break except Exception as e: logger.exception(f"[GsCoreClient] 接收消息异常: {e}") break await asyncio.sleep(0) async def send(self, message: str) -> bool: if not self._ws: ok = await self.connect() if not ok: return False try: await self._ws.send(message.encode("utf-8")) return True except Exception as e: logger.error(f"[GsCoreClient] 发送消息失败: {e}") return False async def reconnect(self): await self.close() await self.connect() async def close(self): if self._recv_task: self._recv_task.cancel() self._recv_task = None if self._ws: try: await self._ws.close() except Exception: pass self._ws = None gs_core_client = GsCoreClient()