Autoformat

This commit is contained in:
hhh
2024-05-27 17:12:21 +03:00
parent 0afca0dd67
commit 918d5af851
25 changed files with 358 additions and 378 deletions

View File

@@ -1,9 +1,4 @@
from .server import run, run_without_onion
from .integration import integrate_onion
from .server import run, run_without_onion
__all__ = [
'run',
'run_without_onion',
'integrate_onion'
]
__all__ = ["run", "run_without_onion", "integrate_onion"]

View File

@@ -1,11 +1,11 @@
from attrs import define
from fastapi import WebSocket
from dragonion_core.proto.web.webmessage import (
WebErrorMessage,
set_time,
webmessages_union,
webmessage_error_message_literal,
WebErrorMessage
webmessages_union,
)
from fastapi import WebSocket
@define
@@ -19,21 +19,14 @@ class Connection(object):
"""
Sends WebMessage object to this connection
:param obj: Should be some type of WebMessage
:return:
:return:
"""
await self.ws.send_text(set_time(obj).to_json())
async def send_error(
self,
error_message: webmessage_error_message_literal
):
async def send_error(self, error_message: webmessage_error_message_literal):
"""
Sends error with specified messages
:param error_message: See webmessage_error_message_literal for available
:return:
:return:
"""
await self.send_webmessage(
WebErrorMessage(
error_message=error_message
)
)
await self.send_webmessage(WebErrorMessage(error_message=error_message))

View File

@@ -1,25 +1,24 @@
from attrs import define
from .connection import Connection
from .exceptions import GotInvalidWebmessage
from datetime import datetime
from json.decoder import JSONDecodeError
from typing import Dict
from attrs import define
from dragonion_core.proto.web.webmessage import (
WebBroadcastableMessage,
WebConnectionMessage,
WebConnectionResultMessage,
WebDisconnectMessage,
WebErrorMessage,
WebMessageMessage,
WebNotificationMessage,
set_time,
webmessage_error_message_literal,
webmessages_union,
)
from fastapi import WebSocket
from json.decoder import JSONDecodeError
from dragonion_core.proto.web.webmessage import (
webmessages_union,
set_time,
WebMessageMessage,
WebBroadcastableMessage,
WebNotificationMessage,
webmessage_error_message_literal,
WebErrorMessage,
WebConnectionMessage,
WebDisconnectMessage,
WebConnectionResultMessage
)
from datetime import datetime
from .connection import Connection
from .exceptions import GotInvalidWebmessage
@define
@@ -28,62 +27,65 @@ class Room(object):
async def accept_connection(self, ws: WebSocket) -> Connection | None:
"""
Accepts connection, checks username availability and adds it to dict of
connections
:param ws: Websocket of connection
:return:
Accepts connection, checks username availability and adds it to dict of
connections
:param ws: Websocket of connection
:return:
"""
print('Incoming connection')
print("Incoming connection")
await ws.accept()
try:
connection_message = WebConnectionMessage.from_json(
await ws.receive_text()
)
connection_message = WebConnectionMessage.from_json(await ws.receive_text())
except JSONDecodeError:
await ws.send_text(set_time(WebErrorMessage(
'invalid_webmessage'
)).to_json())
await ws.close(reason='invalid_webmessage')
return
await ws.send_text(
set_time(WebErrorMessage("invalid_webmessage")).to_json()
)
await ws.close(reason="invalid_webmessage")
return
connection = Connection(
username=connection_message.username,
ws=ws,
public_key=connection_message.public_key,
password=connection_message.password
password=connection_message.password,
)
if connection_message.username in self.connections.keys():
await connection.send_error(
'username_exists'
)
await ws.close(reason='username_exists')
return
await connection.send_error("username_exists")
await ws.close(reason="username_exists")
return
self.connections[connection_message.username] = connection
await connection.send_webmessage(WebConnectionResultMessage(
connected_users=dict(
map(
lambda i, j: (i, j),
[_username for _username in list(self.connections.keys())
if self.connections[_username].password ==
connection_message.password],
[_connection.public_key for _connection
in self.connections.values() if _connection.password ==
connection_message.password]
await connection.send_webmessage(
WebConnectionResultMessage(
connected_users=dict(
map(
lambda i, j: (i, j),
[
_username
for _username in list(self.connections.keys())
if self.connections[_username].password
== connection_message.password
],
[
_connection.public_key
for _connection in self.connections.values()
if _connection.password == connection_message.password
],
)
)
)
))
)
await self.broadcast_webmessage(connection_message)
print(f'[{datetime.now().time()}] Accepted {connection_message.username}')
print(f"[{datetime.now().time()}] Accepted {connection_message.username}")
return connection
async def broadcast_webmessage(self, obj: webmessages_union):
"""
Broadcasts WebMessages to all connections in room
:param obj:
:return:
:param obj:
:return:
"""
for connection in self.connections.values():
await connection.send_webmessage(obj)
@@ -91,11 +93,11 @@ class Room(object):
async def broadcast_message(self, broadcastable: WebBroadcastableMessage):
"""
Broadcasts message to every user in room
:param broadcastable: String object with json representation of
:param broadcastable: String object with json representation of
WebBroadcastableMessage
:return:
:return:
"""
try:
try:
for to_username in broadcastable.messages.keys():
try:
await self.connections[to_username].send_webmessage(
@@ -110,28 +112,17 @@ class Room(object):
"""
Broadcasts notification from server
:param message: Content
:return:
:return:
"""
await self.broadcast_webmessage(
WebNotificationMessage(
message=message
)
)
await self.broadcast_webmessage(WebNotificationMessage(message=message))
async def broadcast_error(
self,
error_message: webmessage_error_message_literal
):
async def broadcast_error(self, error_message: webmessage_error_message_literal):
"""
Broadcasts server error
:param error_message: See webmessage_error_message_literal
:return:
:return:
"""
await self.broadcast_webmessage(
WebErrorMessage(
error_message=error_message
)
)
await self.broadcast_webmessage(WebErrorMessage(error_message=error_message))
async def broadcast_user_disconnected(self, username: str):
"""
@@ -139,18 +130,14 @@ class Room(object):
:param username: Username of user that disconnected
:return:
"""
await self.broadcast_webmessage(
WebDisconnectMessage(
username=username
)
)
await self.broadcast_webmessage(WebDisconnectMessage(username=username))
async def get_connection_by(self, attribute: str, value: str) -> Connection | None:
"""
Search for connection by attribute and value in it
:param attribute:
:param value:
:return:
:param attribute:
:param value:
:return:
"""
for connection in self.connections.values():
if getattr(connection, attribute) == value:
@@ -158,11 +145,11 @@ class Room(object):
async def disconnect(self, connection: Connection, close_reason: str | None = None):
"""
Disconnects by connection object.
:param connection: Object of connection.
Disconnects by connection object.
:param connection: Object of connection.
It can be obtained using get_connection_by
:param close_reason: Reason if exists
:return:
:return:
"""
if connection not in self.connections.values():
return
@@ -170,9 +157,7 @@ class Room(object):
del self.connections[connection.username]
try:
await connection.ws.close(
reason=close_reason
)
await connection.ws.close(reason=close_reason)
except Exception as e:
assert e

View File

@@ -1,10 +1,9 @@
from .connection import Connection
from .room import Room
from typing import Dict
from dragonion_core.proto.web.webmessage import (
webmessage_error_message_literal
)
from dragonion_core.proto.web.webmessage import webmessage_error_message_literal
from .connection import Connection
from .room import Room
class Service(object):
@@ -21,10 +20,7 @@ class Service(object):
for room in self.rooms.values():
await room.broadcast_notification(message)
async def broadcast_error(
self,
error_message: webmessage_error_message_literal
):
async def broadcast_error(self, error_message: webmessage_error_message_literal):
for room in self.rooms.values():
await room.broadcast_error(error_message)
@@ -32,31 +28,31 @@ class Service(object):
"""
Searches for room by valid connection object in it
:param connection: Connection in unknown room to search
:return:
:return:
"""
for room in self.rooms.values():
if connection in room.connections.values():
return room
async def get_connection_by_attribute(
self, attribute: str, value: str
self, attribute: str, value: str
) -> Connection:
"""
Gets connection in some room by attribute and value in it
:param attribute:
:param value:
:return:
:param attribute:
:param value:
:return:
"""
for room in self.rooms.values():
if connection := await room.get_connection_by(attribute, value):
return connection
async def close_room(self, room_name: str, reason: str = 'Unknown reason'):
async def close_room(self, room_name: str, reason: str = "Unknown reason"):
"""
Closes all connections in room
:param room_name: Close name
:param reason: Reason to close room, default is Unknown reason
:return:
:return:
"""
room = self.rooms.get(room_name)
if room is None:
@@ -64,6 +60,5 @@ class Service(object):
for connection in room.connections.values():
await room.disconnect(
connection=connection,
close_reason=f'Room is closed: {reason}'
connection=connection, close_reason=f"Room is closed: {reason}"
)

View File

@@ -1,13 +1,11 @@
from fastapi import WebSocket, WebSocketDisconnect
from .managers.service import Service
from dragonion_core.proto.web.webmessage import (
webmessages_union,
WebMessage
)
from .managers.exceptions import GotInvalidWebmessage
from datetime import datetime
from dragonion_core.proto.web.webmessage import WebMessage, webmessages_union
from fastapi import WebSocket, WebSocketDisconnect
from .managers.exceptions import GotInvalidWebmessage
from .managers.service import Service
service = Service()

View File

@@ -1,15 +1,15 @@
import sys
from dragonion_server.utils.onion import Onion
from dragonion_core.proto.file import AuthFile
from dragonion_server.utils.config.db import services
from rich import print
from dragonion_server.utils.config.db import services
from dragonion_server.utils.onion import Onion
def integrate_onion(port: int, name: str) -> Onion:
"""
Starts onion service, writes it to config
Starts onion service, writes it to config
:param port: Port, where local service is started
:param name: Name of service to get or write to config
:return: Onion object, that is connected and service is started
@@ -23,16 +23,20 @@ def integrate_onion(port: int, name: str) -> Onion:
if not onion.connected_to_tor:
onion.cleanup()
sys.exit(1)
print(f'[green]Available on[/] '
f'{(onion_host := onion.start_onion_service(name))}.onion')
print(
f"[green]Available on[/] "
f"{(onion_host := onion.start_onion_service(name))}.onion"
)
auth = AuthFile(name)
auth['host'] = f'{onion_host}.onion'
auth['auth'] = onion.auth_string
print(f'To connect to server just share [green]{auth.filename}[/] file')
print(f'Or use [#ff901b]service id[/] and [#564ec3]auth string[/]: \n'
f'[#ff901b]{onion_host}[/] \n'
f'[#564ec3]{services[name].client_auth_priv_key}[/]')
auth["host"] = f"{onion_host}.onion"
auth["auth"] = onion.auth_string
print(f"To connect to server just share [green]{auth.filename}[/] file")
print(
f"Or use [#ff901b]service id[/] and [#564ec3]auth string[/]: \n"
f"[#ff901b]{onion_host}[/] \n"
f"[#564ec3]{services[name].client_auth_priv_key}[/]"
)
return onion

View File

@@ -1,6 +1,6 @@
from fastapi import APIRouter, WebSocket
from .handlers.websocket_server import serve_websocket
from .handlers.websocket_server import serve_websocket
router = APIRouter()

View File

@@ -1,6 +1,8 @@
from fastapi import FastAPI
import uvicorn
from fastapi import FastAPI
from dragonion_server.utils.onion import get_available_port
from .integration import integrate_onion
from .routes import router
@@ -8,15 +10,15 @@ from .routes import router
def get_app(port: int, name: str) -> FastAPI:
"""
Creates FastAPI object and runs integrate_onion
:param port: Must be same with port on which uvicorn is running
:param port: Must be same with port on which uvicorn is running
:param name: Name of service
:return: FastAPI object with onion.cleanup function on shutdown
"""
onion = integrate_onion(port, name)
return FastAPI(
title=f'dragonion-server: {name}',
description=f'Secure dragonion chat endpoint server - service {name}',
on_shutdown=[onion.cleanup]
title=f"dragonion-server: {name}",
description=f"Secure dragonion chat endpoint server - service {name}",
on_shutdown=[onion.cleanup],
)
@@ -25,22 +27,22 @@ def run(name: str, port: int | None = get_available_port()):
Runs service with specified name and starts onion
:param name: Name of service
:param port: Port where to start service, if not specified - gets random available
:return:
:return:
"""
if port is None:
port = get_available_port()
app = get_app(port, name)
app.include_router(router)
uvicorn.run(app, host='0.0.0.0', port=port)
uvicorn.run(app, host="0.0.0.0", port=port)
def run_without_onion(name: str, port: int | None = get_available_port()):
if port is None:
port = get_available_port()
app = FastAPI(
title=f'dragonion-server: {name}',
description=f'Secure dragonion chat endpoint server - service {name}'
title=f"dragonion-server: {name}",
description=f"Secure dragonion chat endpoint server - service {name}",
)
app.include_router(router)
uvicorn.run(app, host='0.0.0.0', port=port)
uvicorn.run(app, host="0.0.0.0", port=port)