feat: Унифицирован формат сообщений
This commit is contained in:
@@ -45,9 +45,7 @@ class PyG2O
|
|||||||
|
|
||||||
function _send(data, uuid = "none")
|
function _send(data, uuid = "none")
|
||||||
{
|
{
|
||||||
if (uuid != "none")
|
data["uuid"] <- uuid;
|
||||||
data["uuid"] <- uuid;
|
|
||||||
|
|
||||||
_connection.send(JSON.dump_ansi(data, 2));
|
_connection.send(JSON.dump_ansi(data, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +54,7 @@ class PyG2O
|
|||||||
if (!_silent)
|
if (!_silent)
|
||||||
print("[PyG2O] Successfully connected to " + url);
|
print("[PyG2O] Successfully connected to " + url);
|
||||||
|
|
||||||
_send({"init_temp_tokens": _clientTokens});
|
_send({"event": "init_temp_tokens", "token": _clientTokens});
|
||||||
}
|
}
|
||||||
|
|
||||||
function _onClose(url, message)
|
function _onClose(url, message)
|
||||||
@@ -98,7 +96,7 @@ class PyG2O
|
|||||||
|
|
||||||
addEventHandler("onPlayerJoin", function(playerid){
|
addEventHandler("onPlayerJoin", function(playerid){
|
||||||
local new_token = _globalInstance.generateClientPassword();
|
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;
|
_clientTokens[playerid] <- new_token;
|
||||||
|
|
||||||
local packet = Packet();
|
local packet = Packet();
|
||||||
@@ -108,6 +106,6 @@ addEventHandler("onPlayerJoin", function(playerid){
|
|||||||
});
|
});
|
||||||
|
|
||||||
addEventHandler("onPlayerDisconnect", function(playerid, reason){
|
addEventHandler("onPlayerDisconnect", function(playerid, reason){
|
||||||
_globalInstance._send({"remove_temp_token": _clientTokens[playerid]});
|
_globalInstance._send({"event": "remove_temp_token", "token": _clientTokens[playerid]});
|
||||||
delete _clientTokens[playerid];
|
delete _clientTokens[playerid];
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import inspect
|
import inspect
|
||||||
from fastapi import WebSocket
|
|
||||||
|
|
||||||
_EVENTS = {}
|
_EVENTS = {}
|
||||||
|
|
||||||
@@ -16,14 +15,31 @@ def event(event_name: str, priority: int = 9999):
|
|||||||
return func
|
return func
|
||||||
return inlineEvent
|
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
|
from .server import Server
|
||||||
|
|
||||||
if event_name not in _EVENTS:
|
if event_name not in _EVENTS:
|
||||||
return
|
return
|
||||||
|
|
||||||
for item in _EVENTS[event_name]:
|
for item in _EVENTS[event_name]:
|
||||||
result = await item['function'](*args, **kwargs)
|
sig = inspect.signature(item['function'])
|
||||||
if uuid is None or result is None:
|
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
|
return
|
||||||
await Server.send(connection = connection, uuid = uuid, message = result)
|
|
||||||
|
await Server.send(
|
||||||
|
connection = kwargs['connection'],
|
||||||
|
uuid = kwargs['uuid'],
|
||||||
|
event = 'backend_response',
|
||||||
|
message = result,
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import json
|
import json
|
||||||
|
from types import SimpleNamespace
|
||||||
import loguru
|
import loguru
|
||||||
import asyncio
|
import asyncio
|
||||||
from weakref import WeakValueDictionary, WeakSet, finalize
|
from weakref import WeakValueDictionary, WeakSet, finalize
|
||||||
@@ -33,18 +34,24 @@ class Server:
|
|||||||
cls._register_routes(app)
|
cls._register_routes(app)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def publish(cls, topic: str, message) -> asyncio.Future:
|
def publish(cls, topic: str, event: str, message: dict) -> asyncio.Future | None:
|
||||||
if topic not in cls._topics:
|
try:
|
||||||
raise KeyError('Клиентов прослушивающих этот топик не существует')
|
if topic not in cls._topics:
|
||||||
|
raise KeyError('Клиентов прослушивающих этот топик не существует')
|
||||||
|
|
||||||
request, data = cls._make_request()
|
# Формируем сообщение
|
||||||
data['data'] = message
|
request, data = cls._make_request()
|
||||||
data = json.dumps(data)
|
data['event'] = event
|
||||||
# Меняем синтаксис под Squirrel
|
data.update(message)
|
||||||
data = data.replace("'", '\\"').replace('True', 'true').replace('False', 'false')
|
data = json.dumps(data)
|
||||||
|
|
||||||
asyncio.create_task(cls._send_to_topic(topic, data))
|
# Меняем синтаксис под Squirrel
|
||||||
return request
|
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
|
@classmethod
|
||||||
async def _send_to_topic(cls, topic, data):
|
async def _send_to_topic(cls, topic, data):
|
||||||
@@ -52,15 +59,19 @@ class Server:
|
|||||||
await connection.send_text(data)
|
await connection.send_text(data)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def send(cls, connection: WebSocket, message, uuid: str):
|
async def send(cls, connection: WebSocket, event: str, message: dict, uuid: str | None = None):
|
||||||
data = {
|
try:
|
||||||
'uuid': uuid,
|
data = {
|
||||||
'data': message,
|
'event': event,
|
||||||
}
|
'uuid': uuid,
|
||||||
data = json.dumps(data)
|
}
|
||||||
# Меняем синтаксис под Squirrel
|
data.update(message)
|
||||||
data = data.replace("'", '\\"').replace('True', 'true').replace('False', 'false')
|
data = json.dumps(data)
|
||||||
await connection.send_text(data)
|
# Меняем синтаксис под Squirrel
|
||||||
|
data = data.replace("'", '\\"').replace('True', 'true').replace('False', 'false')
|
||||||
|
await connection.send_text(data)
|
||||||
|
except ValueError:
|
||||||
|
cls._logger.exception('message должен быть типа dict')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _make_request(cls):
|
def _make_request(cls):
|
||||||
@@ -70,7 +81,6 @@ class Server:
|
|||||||
|
|
||||||
data = {
|
data = {
|
||||||
'uuid': request_id,
|
'uuid': request_id,
|
||||||
'data': None,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return request, data
|
return request, data
|
||||||
@@ -136,29 +146,34 @@ class Server:
|
|||||||
async def _process_message(cls, connection: WebSocket, message: dict):
|
async def _process_message(cls, connection: WebSocket, message: dict):
|
||||||
match message:
|
match message:
|
||||||
|
|
||||||
case {'event': event, **kwargs}:
|
case {'event': 'subscribe', 'topics': topics}:
|
||||||
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}:
|
|
||||||
await cls._subscribe(topics, connection)
|
await cls._subscribe(topics, connection)
|
||||||
|
|
||||||
case {'unsubscribe': topics}:
|
case {'event': 'unsubscribe', 'topics': topics}:
|
||||||
await cls._unsubscribe(topics, connection)
|
await cls._unsubscribe(topics, connection)
|
||||||
|
|
||||||
case {'create_temp_token': token}:
|
case {'event': 'create_temp_token', 'token': token}:
|
||||||
cls._temp_tokens.append(token)
|
cls._temp_tokens.append(token)
|
||||||
|
|
||||||
case {'remove_temp_token': token}:
|
case {'event': 'remove_temp_token', 'token': token}:
|
||||||
cls._temp_tokens.remove(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())
|
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 _:
|
case _:
|
||||||
raise ValueError(f'Неподдерживаемый тип PyG2O сообщения: {message}')
|
raise ValueError(f'Неподдерживаемый тип PyG2O сообщения: {message}')
|
||||||
|
|||||||
Reference in New Issue
Block a user