From 5a12b6751de63fb62619030ce0921752696ea408 Mon Sep 17 00:00:00 2001 From: themanyfaceddemon Date: Mon, 26 Aug 2024 16:26:40 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=BE=D0=B2=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B8=20=D0=B4=D0=B0=D0=BD?= =?UTF-8?q?=D0=BD=D1=8B=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DMBotNetwork/client.py | 114 +++++++++++++++-------------------------- DMBotNetwork/server.py | 40 +-------------- 2 files changed, 41 insertions(+), 113 deletions(-) diff --git a/DMBotNetwork/client.py b/DMBotNetwork/client.py index df28ca0..caf0262 100644 --- a/DMBotNetwork/client.py +++ b/DMBotNetwork/client.py @@ -33,6 +33,44 @@ def __init_subclass__(cls, **kwargs): if callable(getattr(cls, method)) and method.startswith("net_"): cls._net_methods[method[4:]] = getattr(cls, method) + @classmethod + async def request_method(cls, spec_type: str, **kwargs) -> None: + """Запрашивает выполнение метода на сервере. + + Args: + spec_type (str): Указание метода, который нужно вызвать. + + Raises: + ConnectionError: Если соединение с сервером не установлено. + """ + if not cls._writer: + raise ConnectionError("Not connected to server") + + request_data = { + "action": "net", + "type": spec_type, + **kwargs + } + + try: + await cls._send_data(request_data) + + except Exception as e: + logger.error(f"Error requesting method 'net.{spec_type}'. kwargs: '{kwargs}'. Error: {e}") + + @classmethod + async def connect(cls) -> None: + """Устанавливает соединение с сервером.""" + if not cls._host or not cls._port: + logger.error("Host and port must be set before connecting.") + return + + try: + cls._listen_task = asyncio.create_task(cls._connect_and_listen()) + + except Exception as e: + logger.error(f"Error creating connect task: {e}") + @classmethod async def _call_method(cls, metods_dict: Dict[str, Any], method_name: str, **kwargs) -> Any: """Вызывает зарегистрированный метод по его имени. @@ -62,19 +100,6 @@ async def _call_method(cls, metods_dict: Dict[str, Any], method_name: str, **kwa logger.error(f"Error calling method {method_name}: {e}") return None - @classmethod - async def connect(cls) -> None: - """Устанавливает соединение с сервером.""" - if not cls._host or not cls._port: - logger.error("Host and port must be set before connecting.") - return - - try: - cls._listen_task = asyncio.create_task(cls._connect_and_listen()) - - except Exception as e: - logger.error(f"Error creating connect task: {e}") - @classmethod async def _connect_and_listen(cls) -> None: """Управляет процессом подключения и прослушивания сообщений в фоне.""" @@ -119,7 +144,7 @@ async def _close(cls) -> None: pass @classmethod - async def send_data(cls, data: Any) -> None: + async def _send_data(cls, data: Any) -> None: """Отправляет данные на сервер. Args: @@ -183,7 +208,7 @@ async def _authenticate(cls) -> None: """Аутентифицирует клиента на сервере. """ try: - await cls.send_data({ + await cls._send_data({ "login": cls._login, "password": cls._password }) @@ -191,37 +216,6 @@ async def _authenticate(cls) -> None: except Exception as e: logger.error(f"Error during authentication: {e}") - @classmethod - async def request_method(cls, action: str, spec_type: str, **kwargs) -> Any: - """Запрашивает выполнение метода на сервере. - - Args: - action (str): Тип действия (net, download). - spec_type (str): Указание метода, который нужно вызвать. - - Raises: - ConnectionError: Если соединение с сервером не установлено. - - Returns: - Any: Результат выполнения сетевого метода или None в случае ошибки. - """ - if not cls._writer: - raise ConnectionError("Not connected to server") - - request_data = { - "action": action, - "type": spec_type, - **kwargs - } - - try: - await cls.send_data(request_data) - return await cls._receive_data() - - except Exception as e: - logger.error(f"Error requesting method '{action}.{spec_type}'. kwargs: '{kwargs}'. Error: {e}") - return None - @classmethod async def listen_for_messages(cls) -> None: """Слушает входящие сообщения от сервера и обрабатывает их.""" @@ -248,9 +242,6 @@ async def listen_for_messages(cls) -> None: async def _req_processor(cls, req_type, server_data: dict) -> None: if req_type == "auth": await cls._authenticate() - - elif req_type == "download": - await cls._download_file(server_data) else: logger.warning(f"Unexpected action type from server: {req_type}") @@ -266,31 +257,6 @@ async def _action_processor(cls, action_type, server_data: dict) -> None: else: logger.warning(f"Unexpected action type from server: {action_type}") - @classmethod - async def _download_file(cls, server_data: dict) -> None: - """Обрабатывает загрузку файла, получая его частями и сохраняя на диск.""" - file_size = server_data.get('file_size', None) - if not file_size: - return - - file_name = server_data.get('file_name', None) - if not file_name: - return - - dir_path = cls._server_file_path / cls._cur_server_name - dir_path.mkdir(parents=True, exist_ok=True) - file_path = dir_path / file_name - - - with open(file_path, "wb") as file: - received_size = 0 - - while received_size < file_size: - chunk_data = await cls._receive_data() - - file.write(chunk_data) - received_size += len(chunk_data) - @classmethod def log_processor(cls, server_data: dict) -> None: log_methods = { diff --git a/DMBotNetwork/server.py b/DMBotNetwork/server.py index b8aecb5..0070231 100644 --- a/DMBotNetwork/server.py +++ b/DMBotNetwork/server.py @@ -13,7 +13,6 @@ class Server: _net_methods: Dict[str, Any] = {} - _download_methods: Dict[str, Any] = {} _connects: Dict[str, Tuple[StreamReader, StreamWriter]] = {} _access_cache: Dict[str, Dict[str, bool]] = {} BASE_ACCESS: Dict[str, bool] = {} @@ -108,15 +107,11 @@ async def _hash_password(self, password: str) -> bytes: return await loop.run_in_executor(None, bcrypt.hashpw, password.encode(), bcrypt.gensalt()) def __init_subclass__(cls, **kwargs): - """Инициализация подклассов сервера. Автоматически регистрирует все методы, начинающиеся с 'net_' или с 'download_'.""" + """Инициализация подклассов сервера. Автоматически регистрирует все методы, начинающиеся с 'net_'.""" super().__init_subclass__(**kwargs) for method in dir(cls): if callable(getattr(cls, method)) and method.startswith("net_"): Server._net_methods[method[4:]] = getattr(cls, method) - - for method in dir(cls): - if callable(getattr(cls, method)) and method.startswith("download_"): - Server._download_methods[method[9:]] = getattr(cls, method) @classmethod async def _call_method(cls, metods_dict: Dict[str, Any], method_name: str, **kwargs) -> Any: @@ -358,9 +353,6 @@ async def _client_handle(self, reader: StreamReader, writer: StreamWriter) -> No if action_type == "net": answer = await Server._call_method(self._net_methods, user_data.get('type'), user_login=login, **user_data) await self.send_data(writer, answer) - - if action_type == "download": - await Server._call_method(self._download_methods, user_data.get('type'), user_login=login, **user_data) except Exception as e: logger.error(f"Error in client handling loop: {e}") @@ -413,36 +405,6 @@ async def send_data_login(self, login: str, data: Any) -> None: await self.send_data(self._connects[login], data) - async def send_file_login(self, login: str, path: Path, file_name: str) -> None: - if login not in self._connects: - raise ValueError("Unknown login") - - await self.send_file(self._connects[login], path, file_name) - - async def send_file(self, writer: StreamWriter, path: Path, file_name: str) -> None: - """Отправляет файл пользователю через writer. - - Args: - writer (StreamWriter): Поток, через который отправляются данные. - path (Path): Путь файла, который надо отправить. - file_name (str): Имя файла для передачи. - - Raises: - Exception: В случае ошибки отправки данных. - """ - try: - file_size = path.stat().st_size - - file_info = {'req': 'download', 'file_size': file_size, 'file_name': file_name} - await self.send_data(writer, file_info) - - with open(path, "rb") as file: - while chunk := file.read(1024 * 1024): # Чтение порции в 1 МБ - await self.send_data(writer, chunk) - - except Exception as e: - logger.error(f"Error sending data: {e}") - async def send_data(self, writer: StreamWriter, data: Any) -> None: """Отправляет данные клиенту.