import socket import threading import json import sqlite3 from datetime import datetime class ChatServer: def __init__(self, host='0.0.0.0', port=5555): self.host = host self.port = port self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server.bind((host, port)) self.server.listen() self.clients = {} self.groups = {'General': set()} self.setup_database() def setup_database(self): self.db = sqlite3.connect('chat_server.db', check_same_thread=False) cursor = self.db.cursor() cursor.execute(''' CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE, password TEXT ) ''') cursor.execute(''' CREATE TABLE IF NOT EXISTS messages ( id INTEGER PRIMARY KEY AUTOINCREMENT, sender TEXT, receiver TEXT, message TEXT, timestamp DATETIME, is_group INTEGER ) ''') self.db.commit() def handle_client(self, client, address): username = None try: while True: message = client.recv(1024).decode('utf-8') if not message: break data = json.loads(message) if data['type'] == 'login': username = data['username'] password = data['password'] if self.authenticate_user(username, password): self.clients[username] = client self.groups['General'].add(username) client.send(json.dumps({'type': 'login_success'}).encode('utf-8')) self.send_user_list() self.send_group_list(username) self.send_initial_messages(username) else: client.send(json.dumps({'type': 'login_fail'}).encode('utf-8')) elif data['type'] == 'register': username = data['username'] password = data['password'] if self.register_user(username, password): client.send(json.dumps({'type': 'register_success'}).encode('utf-8')) else: client.send(json.dumps({'type': 'register_fail'}).encode('utf-8')) elif data['type'] == 'message': sender = data['sender'] receiver = data['receiver'] msg = data['message'] is_group = data['is_group'] self.save_message(sender, receiver, msg, is_group) if is_group: for member in self.groups.get(receiver, set()): if member in self.clients and member != sender: self.clients[member].send(json.dumps({ 'type': 'message', 'sender': sender, 'receiver': receiver, 'message': msg, 'is_group': True }).encode('utf-8')) else: if receiver in self.clients: self.clients[receiver].send(json.dumps({ 'type': 'message', 'sender': sender, 'receiver': receiver, 'message': msg, 'is_group': False }).encode('utf-8')) elif data['type'] == 'create_group': group_name = data['group_name'] if group_name not in self.groups: self.groups[group_name] = set() for user in data['members']: if user in self.clients: self.groups[group_name].add(user) self.send_group_list_to_all() except Exception as e: print(f"Error handling client: {e}") finally: if username and username in self.clients: del self.clients[username] for group in self.groups.values(): if username in group: group.remove(username) self.send_user_list() client.close() def authenticate_user(self, username, password): cursor = self.db.cursor() cursor.execute('SELECT * FROM users WHERE username=? AND password=?', (username, password)) return cursor.fetchone() is not None def register_user(self, username, password): try: cursor = self.db.cursor() cursor.execute('INSERT INTO users (username, password) VALUES (?, ?)', (username, password)) self.db.commit() return True except sqlite3.IntegrityError: return False def save_message(self, sender, receiver, message, is_group): cursor = self.db.cursor() cursor.execute(''' INSERT INTO messages (sender, receiver, message, timestamp, is_group) VALUES (?, ?, ?, ?, ?) ''', (sender, receiver, message, datetime.now(), 1 if is_group else 0)) self.db.commit() def send_user_list(self): user_list = list(self.clients.keys()) for client in self.clients.values(): client.send(json.dumps({ 'type': 'user_list', 'users': user_list }).encode('utf-8')) def send_group_list(self, username): group_list = [group for group, members in self.groups.items() if username in members] if username in self.clients: self.clients[username].send(json.dumps({ 'type': 'group_list', 'groups': group_list }).encode('utf-8')) def send_group_list_to_all(self): for username in self.clients: self.send_group_list(username) def send_initial_messages(self, username): cursor = self.db.cursor() cursor.execute(''' SELECT sender, receiver, message, timestamp, is_group FROM messages WHERE receiver=? OR (is_group=1 AND receiver IN ( SELECT group_name FROM groups WHERE member=? )) OR sender=? ORDER BY timestamp ''', (username, username, username)) messages = [] for sender, receiver, message, timestamp, is_group in cursor.fetchall(): messages.append({ 'sender': sender, 'receiver': receiver, 'message': message, 'timestamp': timestamp, 'is_group': is_group }) if username in self.clients: self.clients[username].send(json.dumps({ 'type': 'initial_messages', 'messages': messages }).encode('utf-8')) def start(self): print(f"Server started on {self.host}:{self.port}") while True: client, address = self.server.accept() thread = threading.Thread(target=self.handle_client, args=(client, address)) thread.start() if __name__ == "__main__": server = ChatServer() server.start()