feat: Унифицирован формат сообщений

This commit is contained in:
AURUMVORXX
2025-11-06 00:59:58 +05:00
parent 13d4a69ad2
commit 1f821b4478
3 changed files with 74 additions and 45 deletions

View File

@@ -45,9 +45,7 @@ class PyG2O
function _send(data, uuid = "none")
{
if (uuid != "none")
data["uuid"] <- uuid;
_connection.send(JSON.dump_ansi(data, 2));
}
@@ -56,7 +54,7 @@ class PyG2O
if (!_silent)
print("[PyG2O] Successfully connected to " + url);
_send({"init_temp_tokens": _clientTokens});
_send({"event": "init_temp_tokens", "token": _clientTokens});
}
function _onClose(url, message)
@@ -98,7 +96,7 @@ class PyG2O
addEventHandler("onPlayerJoin", function(playerid){
local new_token = _globalInstance.generateClientPassword();
_globalInstance._send({"create_temp_token": new_token})
_globalInstance._send({"event": "create_temp_token", "token": new_token})
_clientTokens[playerid] <- new_token;
local packet = Packet();
@@ -108,6 +106,6 @@ addEventHandler("onPlayerJoin", function(playerid){
});
addEventHandler("onPlayerDisconnect", function(playerid, reason){
_globalInstance._send({"remove_temp_token": _clientTokens[playerid]});
_globalInstance._send({"event": "remove_temp_token", "token": _clientTokens[playerid]});
delete _clientTokens[playerid];
});

View File

@@ -1,5 +1,4 @@
import inspect
from fastapi import WebSocket
_EVENTS = {}
@@ -16,14 +15,31 @@ def event(event_name: str, priority: int = 9999):
return func
return inlineEvent
async def call_event(event_name: str, connection: WebSocket, uuid: str | None, *args, **kwargs):
async def call_event(event_name: str, **kwargs):
from .server import Server
if event_name not in _EVENTS:
return
for item in _EVENTS[event_name]:
result = await item['function'](*args, **kwargs)
if uuid is None or result is None:
sig = inspect.signature(item['function'])
params = list(sig.parameters.keys())
args = {}
for param in params:
args[param] = kwargs.get(param)
if any(p.kind == p.VAR_KEYWORD for p in sig.parameters.values()):
result = await item['function'](**kwargs)
else:
result = await item['function'](**args)
if result is None:
return
await Server.send(connection = connection, uuid = uuid, message = result)
await Server.send(
connection = kwargs['connection'],
uuid = kwargs['uuid'],
event = 'backend_response',
message = result,
)

View File

@@ -1,5 +1,6 @@
from __future__ import annotations
import json
from types import SimpleNamespace
import loguru
import asyncio
from weakref import WeakValueDictionary, WeakSet, finalize
@@ -33,18 +34,24 @@ class Server:
cls._register_routes(app)
@classmethod
def publish(cls, topic: str, message) -> asyncio.Future:
def publish(cls, topic: str, event: str, message: dict) -> asyncio.Future | None:
try:
if topic not in cls._topics:
raise KeyError('Клиентов прослушивающих этот топик не существует')
# Формируем сообщение
request, data = cls._make_request()
data['data'] = message
data['event'] = event
data.update(message)
data = json.dumps(data)
# Меняем синтаксис под Squirrel
data = data.replace("'", '\\"').replace('True', 'true').replace('False', 'false')
asyncio.create_task(cls._send_to_topic(topic, data))
return request
except ValueError:
cls._logger.exception('message должен быть типа dict')
@classmethod
async def _send_to_topic(cls, topic, data):
@@ -52,15 +59,19 @@ class Server:
await connection.send_text(data)
@classmethod
async def send(cls, connection: WebSocket, message, uuid: str):
async def send(cls, connection: WebSocket, event: str, message: dict, uuid: str | None = None):
try:
data = {
'event': event,
'uuid': uuid,
'data': message,
}
data.update(message)
data = json.dumps(data)
# Меняем синтаксис под Squirrel
data = data.replace("'", '\\"').replace('True', 'true').replace('False', 'false')
await connection.send_text(data)
except ValueError:
cls._logger.exception('message должен быть типа dict')
@classmethod
def _make_request(cls):
@@ -70,7 +81,6 @@ class Server:
data = {
'uuid': request_id,
'data': None,
}
return request, data
@@ -136,29 +146,34 @@ class Server:
async def _process_message(cls, connection: WebSocket, message: dict):
match message:
case {'event': event, **kwargs}:
try:
cls._requests[kwargs['uuid']].set_result(kwargs.get('data'))
except KeyError:
uuid = kwargs.get('uuid')
if uuid is not None:
del kwargs['uuid']
asyncio.create_task(call_event(event, connection, uuid, **kwargs))
case {'subscribe': topics}:
case {'event': 'subscribe', 'topics': topics}:
await cls._subscribe(topics, connection)
case {'unsubscribe': topics}:
case {'event': 'unsubscribe', 'topics': topics}:
await cls._unsubscribe(topics, connection)
case {'create_temp_token': token}:
case {'event': 'create_temp_token', 'token': token}:
cls._temp_tokens.append(token)
case {'remove_temp_token': token}:
case {'event': 'remove_temp_token', 'token': token}:
cls._temp_tokens.remove(token)
case {'init_temp_tokens': tokens}:
case {'event': 'init_temp_tokens', 'tokens': tokens}:
cls._temp_tokens = cls._temp_tokens + list(tokens.items())
case {'event': 'sq_response', 'uuid': uuid, 'data': data}:
try:
cls._requests[uuid].set_result(data)
except KeyError:
...
case {'event': event, 'uuid': uuid, **kwargs}:
try:
cls._requests[uuid].set_result(SimpleNamespace(**kwargs))
except KeyError:
kwargs['uuid'] = uuid
kwargs['connection'] = connection
asyncio.create_task(call_event(event, **kwargs))
case _:
raise ValueError(f'Неподдерживаемый тип PyG2O сообщения: {message}')