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 == "remove_message": chat_name = request["chat_name"] index = request.get("index") if chat_name in chats: if 0 <= index < len(chats[chat_name]["messages"]): # optioneel: check of de gebruiker eigenaar is van het bericht msg_user = chats[chat_name]["messages"][index]["user"] if msg_user == request["by"]: # alleen eigen berichten verwijderen chats[chat_name]["messages"].pop(index) save_chats(chats) 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 == "get_users": chat_name = request["chat"] if chat_name in chats: users = chats[chat_name]["users"] client_socket.sendall(json.dumps({ "type": "users_list", "users": users }).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()