-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserverlet.py
More file actions
108 lines (94 loc) · 3.33 KB
/
Copy pathserverlet.py
File metadata and controls
108 lines (94 loc) · 3.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import threading
import asyncio
import socket
import sys
import os
from concurrent.futures import ThreadPoolExecutor
from dotenv import load_dotenv
from colorama import init, Fore, Style
from utils.database import Database
from utils.objects.cafe import Cafe
from utils.system.handle_client import handle_client
from utils.api import APIServer
from utils.filter import ProfanityModel
init(autoreset=True)
load_dotenv()
class CafeServer:
def __init__(self) -> None:
self.host = os.getenv("SERVER_HOST")
self.port = int(os.getenv("SERVER_PORT"))
self.max_conn = int(os.getenv("MAX_CONN"))
self.running = False
self.clients = {}
self.players = []
self.db = Database()
self.marketplace = Cafe.get_marketplace()
self.executor = ThreadPoolExecutor(max_workers=3)
self.profanity_model = ProfanityModel()
self.socket = None
@staticmethod
async def send_response(writer, response):
try:
writer.write(response.raw_response.encode())
await writer.drain()
except ConnectionResetError:
print(
f"{Fore.YELLOW}\n[INFO] Connection reset by client: {writer.get_extra_info('peername')}"
)
except Exception as e:
print(f"{Fore.RED}[ERROR] Unexpected error while sending response: {e}")
def bind_socket(self) -> None:
try:
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind((self.host, self.port))
print(
f"{Fore.GREEN}[INFO] Bound to {self.host}:{self.port}{Style.RESET_ALL}"
)
except (PermissionError, OSError) as e:
sys.stderr.write(f"{Fore.RED}[ERROR] {e}{Style.RESET_ALL}")
sys.exit(1)
def start(self) -> None:
try:
asyncio.run(self.run_server())
except KeyboardInterrupt:
self.stop()
async def run_server(self) -> None:
server = await asyncio.start_server(
lambda reader, writer: handle_client(self, reader, writer),
self.host,
self.port,
reuse_address=True,
)
self.running = True
print(
f"{Fore.GREEN}[INFO] Server listening on {self.host}:{self.port}...{Style.RESET_ALL}"
)
api_server = APIServer(self)
api_thread = threading.Thread(target=api_server.start, daemon=True)
api_thread.start()
async with server:
try:
await server.serve_forever()
except asyncio.CancelledError:
pass
finally:
api_thread.join()
def stop(self) -> None:
self.running = False
if self.socket:
self.socket.close()
print(f"{Fore.RED}[INFO] Server stopped.{Style.RESET_ALL}")
def start_server():
server = CafeServer()
print(f"{Fore.GREEN}[INFO] Starting the server...{Style.RESET_ALL}")
server.start()
if __name__ == "__main__":
try:
start_server()
except KeyboardInterrupt:
print(f"{Fore.YELLOW}\n[INFO] Shutting down server...{Style.RESET_ALL}")
sys.exit(0)
except Exception as e:
print(f"{Fore.RED}[ERROR] Error: {e}{Style.RESET_ALL}")
sys.exit(1)