Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.1.1 #4

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 68 additions & 23 deletions DMBotNetwork/side/side_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ class Client:
_ear_task: Optional[asyncio.Task] = None # lol

_viva_alp: bool = True
_login: str = None
_password: str = None
_login: Optional[str] = None
_password: Optional[str] = None
_content_path: Optional[Path] = None
_temp_fold: Optional[Path] = None
_server_name: Optional[str] = None

_is_connected: bool = False
Expand Down Expand Up @@ -71,11 +72,15 @@ async def _call_method(
logger.error(f"Error calling method '{method_name}' in {cls.__name__}: {e}")

@classmethod
async def connect(cls, host, port) -> None:
async def connect(cls, host: str, port: int) -> None:
if not all((cls._login, cls._password, cls._content_path)):
logger.warning("Login, password or content_path not set, abort connect")
return

cls._reader, cls._writer = await asyncio.open_connection(host, port)
cls._is_connected = True

cls._ear_task = asyncio.create_task(cls._ear)
cls._ear_task = asyncio.create_task(cls._ear())

@classmethod
def is_connected(cls) -> bool:
Expand All @@ -89,6 +94,24 @@ def get_auth_lp(cls) -> bool:
def set_auth_lp(cls, value: bool) -> None:
cls._viva_alp = value

@classmethod
def get_login(cls) -> Optional[str]:
return cls._login

@classmethod
def set_login(cls, value: str) -> None:
cls._login = value

@classmethod
def set_password(cls, value: str) -> None:
cls._password = value

@classmethod
def set_up_content_path(cls, value: Path | str) -> None:
cls._content_path = Path(value)
cls._temp_fold = cls._content_path / "temp"
cls._temp_fold.mkdir(exist_ok=True)

@classmethod
async def disconnect(cls) -> None:
cls._is_connected = False
Expand Down Expand Up @@ -144,33 +167,44 @@ async def _ear(cls) -> None:
cls._server_name = receive_packet.get(
"server_name", "Not_Set_Server_Name"
)
Path(cls._content_path / cls._server_name).mkdir(exist_ok=True) # type: ignore
await cls._auth()

elif code == NetCode.REQ_FILE_DOWNLOAD:
await cls._download_file(receive_packet)
cls._download_file(receive_packet)

elif code == NetCode.END_FILE_DOWNLOAD:
cls._move_file(receive_packet)

else:
logger.error("Unknown 'code' type from server")

@classmethod
async def send_packet(self, code: NCAnyType, **kwargs: Any) -> None:
async def req_net(cls, type: str, **kwargs: Any) -> None:
await cls.send_packet(NetCode.REQ_NET.value, type=type, **kwargs)

@classmethod
async def send_packet(cls, code: NCAnyType, **kwargs: Any) -> None:
payload = {"code": code, **kwargs}

await self.send_raw(msgpack.packb(payload))
await cls._send_raw(msgpack.packb(payload)) # type: ignore

@classmethod
async def send_raw(self, data: bytes) -> None:
if self._writer is None:
async def _send_raw(cls, data: bytes) -> None:
if cls._writer is None:
raise ValueError("StreamWriter is not set")

self._writer.write(len(data).to_bytes(4, byteorder="big"))
await self._writer.drain()
cls._writer.write(len(data).to_bytes(4, byteorder="big"))
await cls._writer.drain()

self._writer.write(data)
await self._writer.drain()
cls._writer.write(data)
await cls._writer.drain()

@classmethod
async def _receive_packet(cls) -> Any:
if not cls._reader:
return

data_size_bytes = await cls._reader.readexactly(4)
data_size = int.from_bytes(data_size_bytes, "big")

Expand All @@ -181,16 +215,16 @@ async def _receive_packet(cls) -> Any:
def _log(cls, code: NCLogType, receive_packet: dict) -> None:
msg = receive_packet.get("message", "Not set")

if code == NetCode.REQ_LOG_DEBUG:
if code == NetCode.REQ_LOG_DEBUG.value:
logger.debug(msg)

elif code == NetCode.REQ_LOG_INFO:
elif code == NetCode.REQ_LOG_INFO.value:
logger.info(msg)

elif code == NetCode.REQ_LOG_WARNING:
elif code == NetCode.REQ_LOG_WARNING.value:
logger.warning(msg)

elif code == NetCode.REQ_LOG_ERROR:
elif code == NetCode.REQ_LOG_ERROR.value:
logger.error(msg)

else:
Expand All @@ -200,27 +234,38 @@ def _log(cls, code: NCLogType, receive_packet: dict) -> None:
async def _auth(cls) -> None:
if cls._viva_alp:
await cls.send_packet(
NetCode.ANSWER_AUTH_ALP, login=cls._login, password=cls._password
NetCode.ANSWER_AUTH_ALP.value, login=cls._login, password=cls._password
)

else:
await cls.send_packet(
NetCode.ANSWER_AUTH_REG, login=cls._login, password=cls._password
NetCode.ANSWER_AUTH_REG.value, login=cls._login, password=cls._password
)

@classmethod
async def _download_file(cls, receive_packet: dict) -> None:
def _download_file(cls, receive_packet: dict) -> None:
try:
file_name = receive_packet.get("file_name", None)
chunk = receive_packet.get("chunk", None)

if not chunk or file_name:
return

file_path: Path = cls._content_path / cls._server_name / file_name
file_path: Path = cls._content_path / cls._temp_fold / file_name # type: ignore

with file_path.open("wb") as file:
with file_path.open("wb+") as file:
file.write(chunk)

except Exception as e:
await logger.error(f"Error receiving file: {e}")
logger.error(f"Error receiving file: {e}")

@classmethod
def _move_file(cls, receive_packet: dict) -> None:
file_name = receive_packet.get("file_name")
if not file_name:
return

file_path: Path = cls._content_path / cls._temp_fold / file_name # type: ignore
if file_path.exists():
path_serve = cls._content_path / cls._server_name / file_name # type: ignore
file_path.rename(path_serve)
10 changes: 5 additions & 5 deletions DMBotNetwork/side/side_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import logging
from asyncio import StreamReader, StreamWriter
from pathlib import Path
from typing import Any, Dict, Optional, Set, get_type_hints
from typing import Any, Dict, Optional, get_type_hints

from ..units import ClientUnit
from ..utils import NetCode, ServerDB
Expand All @@ -15,11 +15,10 @@ class Server:
_network_methods: Dict[str, Any] = {}

_connections: Dict[str, ClientUnit] = {}
_one_time_token: Set[str] = {}

_allow_registration: bool = True
_timeout: float = 30.0
_server_name: str = None
_server_name: Optional[str] = None

_is_online: bool = False
_main_server: Optional[asyncio.AbstractServer] = None
Expand Down Expand Up @@ -75,7 +74,7 @@ async def start(
cls,
host: str = "localhost",
main_port: int = 5000,
db_file_path: Path | str = None,
db_file_path: Path | str = "",
base_owner_password: str = "owner_password",
timeout: float = 30.0,
allow_registration: bool = True,
Expand All @@ -94,6 +93,7 @@ async def start(

cls._allow_registration = allow_registration
cls._timeout = timeout
cls._server_name = server_name

cls._main_server = await asyncio.start_server(
cls._main_client_handler, host, main_port
Expand Down Expand Up @@ -209,7 +209,7 @@ async def _main_client_handler(
# Auth
@classmethod
async def _auth(cls, cl_unit: ClientUnit) -> None:
await cl_unit.send_packet(NetCode.REQ_AUTH, server_name=cls._server_name)
await cl_unit.send_packet(NetCode.REQ_AUTH.value, server_name=cls._server_name)
receive_packet = await asyncio.wait_for(cl_unit._receive_packet(), cls._timeout)

if not isinstance(receive_packet, dict):
Expand Down
19 changes: 11 additions & 8 deletions DMBotNetwork/units/client_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,31 +40,31 @@ def writer(self) -> StreamWriter:
return self._writer

@property
def reader(self) -> StreamWriter:
def reader(self) -> StreamReader:
return self._reader

# Net
async def req_net(self, type: str, **kwargs: Any) -> None:
await self.send_packet(NetCode.REQ_NET, type=type, **kwargs)
await self.send_packet(NetCode.REQ_NET.value, type=type, **kwargs)

# Logs
async def log_debug(self, message: str) -> None:
await self.send_packet(NetCode.REQ_LOG_DEBUG, message=message)
await self.send_packet(NetCode.REQ_LOG_DEBUG.value, message=message)

async def log_info(self, message: str) -> None:
await self.send_packet(NetCode.REQ_LOG_INFO, message=message)
await self.send_packet(NetCode.REQ_LOG_INFO.value, message=message)

async def log_warning(self, message: str) -> None:
await self.send_packet(NetCode.REQ_LOG_WARNING, message=message)
await self.send_packet(NetCode.REQ_LOG_WARNING.value, message=message)

async def log_error(self, message: str) -> None:
await self.send_packet(NetCode.REQ_LOG_ERROR, message=message)
await self.send_packet(NetCode.REQ_LOG_ERROR.value, message=message)

# Send
async def send_packet(self, code: NCAnyType, **kwargs: Any) -> None:
payload = {"code": code, **kwargs}

await self.send_raw(msgpack.packb(payload))
await self.send_raw(msgpack.packb(payload)) # type: ignore

async def send_raw(self, data: bytes) -> None:
if self._writer is None:
Expand All @@ -88,10 +88,13 @@ async def send_file(
while True:
chunk = file.read(chunk_size)
if not chunk:
await self.send_packet(
NetCode.END_FILE_DOWNLOAD.value, file_name=file_name
)
break

await self.send_packet(
NetCode.REQ_FILE_DOWNLOAD, file_name=file_name, chunk=chunk
NetCode.REQ_FILE_DOWNLOAD.value, file_name=file_name, chunk=chunk
)

except Exception as e:
Expand Down
20 changes: 10 additions & 10 deletions DMBotNetwork/utils/net_code_encode.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@


class NetCode(Enum):
REQ_AUTH: int = 10 # Запрос аунтификации
ANSWER_AUTH_ALP: int = 11 # Ответ запроса аунтификации через логин пароль
ANSWER_AUTH_REG: int = 12 # Ответ запроса регестрации
REQ_AUTH = 10 # Запрос аунтификации
ANSWER_AUTH_ALP = 11 # Ответ запроса аунтификации через логин пароль
ANSWER_AUTH_REG = 12 # Ответ запроса регестрации

REQ_NET: int = 20 # Запрос net метода клиента
REQ_FILE_DOWNLOAD: int = 21
END_FILE_DOWNLOAD: int = 22
REQ_NET = 20 # Запрос net метода клиента
REQ_FILE_DOWNLOAD = 21
END_FILE_DOWNLOAD = 22

# Лог ивенты
REQ_LOG_DEBUG: int = 30
REQ_LOG_INFO: int = 31
REQ_LOG_WARNING: int = 32
REQ_LOG_ERROR: int = 33
REQ_LOG_DEBUG = 30
REQ_LOG_INFO = 31
REQ_LOG_WARNING = 32
REQ_LOG_ERROR = 33


NCReqType = Literal[10]
Expand Down
Loading
Loading