168 lines
4.7 KiB
Python
168 lines
4.7 KiB
Python
import socket
|
|
import threading
|
|
import json
|
|
import logging
|
|
from pathlib import Path
|
|
|
|
logging.basicConfig(
|
|
filename="server.log",
|
|
level=logging.INFO,
|
|
format="%(asctime)s [%(levelname)s] %(message)s",
|
|
)
|
|
|
|
def log(msg):
|
|
print(msg)
|
|
logging.info(msg)
|
|
|
|
def get_local_ip():
|
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
try:
|
|
s.connect(("8.8.8.8", 80))
|
|
return s.getsockname()[0]
|
|
except:
|
|
return "127.0.0.1"
|
|
finally:
|
|
s.close()
|
|
|
|
local_ip = get_local_ip()
|
|
|
|
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
|
|
host = "0.0.0.0"
|
|
port = 44703
|
|
|
|
server.bind((host, port))
|
|
server.listen()
|
|
|
|
actual_port = server.getsockname()[1]
|
|
|
|
log(f"[SERVER] LAN IP: {local_ip}")
|
|
log(f"[SERVER] Server live at {local_ip}:{actual_port}")
|
|
|
|
chats_file = Path("chats2.json")
|
|
|
|
if not chats_file.exists():
|
|
with open(chats_file, "w") as f:
|
|
json.dump({"general": {"users": [], "messages": []}}, f, indent=4)
|
|
|
|
lock = threading.Lock()
|
|
clients_lock = threading.Lock()
|
|
|
|
def load_chats():
|
|
with lock:
|
|
try:
|
|
with chats_file.open("r", encoding="utf-8") as f:
|
|
return json.load(f)
|
|
except:
|
|
return {"general": {"users": [], "messages": []}}
|
|
|
|
def save_chats(data):
|
|
with lock:
|
|
with chats_file.open("w", encoding="utf-8") as f:
|
|
json.dump(data, f, indent=4)
|
|
|
|
clients = []
|
|
chat_clients = {}
|
|
|
|
def handle_client(client_socket, addr):
|
|
with clients_lock:
|
|
clients.append(client_socket)
|
|
|
|
log(f"[SERVER] Client connected: {addr}")
|
|
|
|
username = None
|
|
|
|
try:
|
|
username = client_socket.recv(1024).decode("utf-8").strip()
|
|
log(f"[SERVER] User connected: {username}")
|
|
|
|
chats = load_chats()
|
|
client_socket.sendall(json.dumps(chats).encode("utf-8"))
|
|
|
|
while True:
|
|
data = client_socket.recv(4096)
|
|
if not data:
|
|
break
|
|
|
|
try:
|
|
request = json.loads(data.decode("utf-8"))
|
|
except json.JSONDecodeError:
|
|
continue
|
|
|
|
action = request.get("action")
|
|
chats = load_chats()
|
|
|
|
if action == "new_chat":
|
|
chat_name = request["chat_name"]
|
|
users = request.get("users", [username])
|
|
|
|
if chat_name not in chats:
|
|
chats[chat_name] = {"users": users, "messages": []}
|
|
save_chats(chats)
|
|
log(f"[SERVER] New chat created: {chat_name}")
|
|
|
|
client_socket.sendall(json.dumps(chats).encode("utf-8"))
|
|
|
|
elif action == "message":
|
|
chat_name = request["chat_name"]
|
|
message = request["message"]
|
|
|
|
if chat_name in chats:
|
|
chats[chat_name]["messages"].append({
|
|
"user": username,
|
|
"message": message
|
|
})
|
|
|
|
save_chats(chats)
|
|
log(f"[SERVER] {username} in {chat_name}: {message}")
|
|
|
|
with clients_lock:
|
|
for client in clients[:]:
|
|
try:
|
|
client.sendall(json.dumps(chats).encode("utf-8"))
|
|
except:
|
|
try:
|
|
client.close()
|
|
except:
|
|
pass
|
|
clients.remove(client)
|
|
|
|
elif action == "add_user":
|
|
chat_name = request["chat"]
|
|
new_user = request["user"]
|
|
|
|
if chat_name in chats:
|
|
if new_user not in chats[chat_name]["users"]:
|
|
chats[chat_name]["users"].append(new_user)
|
|
save_chats(chats)
|
|
log(f"[SERVER] Added {new_user} to {chat_name}")
|
|
|
|
client_socket.sendall(json.dumps(chats).encode("utf-8"))
|
|
|
|
elif action == "openchat":
|
|
chat_name = request["chat_name"]
|
|
if chat_name in chats:
|
|
client_socket.sendall(json.dumps(chats).encode("utf-8"))
|
|
else:
|
|
client_socket.sendall(json.dumps(chats).encode("utf-8"))
|
|
|
|
except Exception as e:
|
|
log(f"[ERROR] {e}")
|
|
|
|
finally:
|
|
with clients_lock:
|
|
if client_socket in clients:
|
|
clients.remove(client_socket)
|
|
|
|
client_socket.close()
|
|
log(f"[SERVER] Client disconnected: {addr}")
|
|
|
|
while True:
|
|
client_sock, address = server.accept()
|
|
threading.Thread(
|
|
target=handle_client,
|
|
args=(client_sock, address),
|
|
daemon=True
|
|
).start()
|