From 1f821b44783e09c6b28a5e4d66dbecf6ab57e92d Mon Sep 17 00:00:00 2001 From: AURUMVORXX Date: Thu, 6 Nov 2025 00:59:58 +0500 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=A3=D0=BD=D0=B8=D1=84=D0=B8=D1=86?= =?UTF-8?q?=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=20=D1=84=D0=BE=D1=80=D0=BC?= =?UTF-8?q?=D0=B0=D1=82=20=D1=81=D0=BE=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/server/main.nut | 10 ++--- src/pyg2o/event.py | 26 ++++++++++--- src/pyg2o/server.py | 83 ++++++++++++++++++++++++----------------- 3 files changed, 74 insertions(+), 45 deletions(-) diff --git a/include/server/main.nut b/include/server/main.nut index 32e7b93..6495e80 100644 --- a/include/server/main.nut +++ b/include/server/main.nut @@ -45,9 +45,7 @@ class PyG2O function _send(data, uuid = "none") { - if (uuid != "none") - data["uuid"] <- uuid; - + 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]; }); diff --git a/src/pyg2o/event.py b/src/pyg2o/event.py index b008cf7..0721c23 100644 --- a/src/pyg2o/event.py +++ b/src/pyg2o/event.py @@ -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, + ) diff --git a/src/pyg2o/server.py b/src/pyg2o/server.py index 6822ef9..ad4d4c8 100644 --- a/src/pyg2o/server.py +++ b/src/pyg2o/server.py @@ -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: - if topic not in cls._topics: - raise KeyError('Клиентов прослушивающих этот топик не существует') + 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 = json.dumps(data) - # Меняем синтаксис под Squirrel - data = data.replace("'", '\\"').replace('True', 'true').replace('False', 'false') + # Формируем сообщение + request, data = cls._make_request() + data['event'] = event + data.update(message) + data = json.dumps(data) - asyncio.create_task(cls._send_to_topic(topic, data)) - return request + # Меняем синтаксис под 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): - data = { - 'uuid': uuid, - 'data': message, - } - data = json.dumps(data) - # Меняем синтаксис под Squirrel - data = data.replace("'", '\\"').replace('True', 'true').replace('False', 'false') - await connection.send_text(data) + async def send(cls, connection: WebSocket, event: str, message: dict, uuid: str | None = None): + try: + data = { + 'event': event, + 'uuid': uuid, + } + 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}')