Skip to content

Commit

Permalink
Удаление методов загрузки данных
Browse files Browse the repository at this point in the history
  • Loading branch information
themanyfaceddemon committed Aug 26, 2024
1 parent bf69db9 commit 5a12b67
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 113 deletions.
114 changes: 40 additions & 74 deletions DMBotNetwork/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
"""Вызывает зарегистрированный метод по его имени.
Expand Down Expand Up @@ -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:
"""Управляет процессом подключения и прослушивания сообщений в фоне."""
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -183,45 +208,14 @@ async def _authenticate(cls) -> None:
"""Аутентифицирует клиента на сервере.
"""
try:
await cls.send_data({
await cls._send_data({
"login": cls._login,
"password": cls._password
})

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:
"""Слушает входящие сообщения от сервера и обрабатывает их."""
Expand All @@ -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}")
Expand All @@ -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 = {
Expand Down
40 changes: 1 addition & 39 deletions DMBotNetwork/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -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] = {}
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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}")
Expand Down Expand Up @@ -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:
"""Отправляет данные клиенту.
Expand Down

0 comments on commit 5a12b67

Please sign in to comment.