95 lines
3.0 KiB
Python
95 lines
3.0 KiB
Python
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()
|
|
|