diff --git a/chatserver/server.py b/chatserver/server.py index 37b20a3..94d79ad 100644 --- a/chatserver/server.py +++ b/chatserver/server.py @@ -84,6 +84,89 @@ def handle_message(username, chat_room, message): if client_sock != server_socket and chat_rooms.get(client_sock) == chat_room: client_sock.send(send_message) +def handle_command(username, chat_room, command, sock=None): + """Process commands sent by clients.""" + if command.strip() == "%?": + help_message = ( + "Help: (%?)\n" + "Send messages like normal. Use enter to send a message.\n" + "Available Commands:\n" + "\t%? : Show this help prompt.\n" + "\t%! : Exit from the Chat Server.\n" + "\t%* : Switch to another chatroom.\n" + "\t%$ : Change Username.\n" + "\t%@ : Send a direct message to a user.\n" + ) + if sock: + sock.send(help_message.encode('utf-8')) + else: + socketio.emit('message', {'username': 'Server', 'message': help_message}, room=chat_room) + return + + if command.strip() == "%*": + if sock: + sock.send(b"\nEnter chatroom name: \n") + client_states[sock] = "WAITING_FOR_NEW_CHATROOM" + else: + socketio.emit('message', {'username': 'Server', 'message': "Enter chatroom name:"}, room=chat_room) + return + + if command.strip() == "%$": + if sock: + sock.send(b"\nEnter new username: \n") + client_states[sock] = "WAITING_FOR_NEW_USERNAME" + else: + socketio.emit('message', {'username': 'Server', 'message': "Enter new username:"}, room=chat_room) + return + + if command.strip().startswith("%@ "): + parts = command.strip().split(' ', 2) + if len(parts) < 3: + error_message = "Invalid direct message format. Use: %@ " + if sock: + sock.send(f"\n{error_message}\n".encode('utf-8')) + else: + socketio.emit('message', {'username': 'Server', 'message': error_message}, room=chat_room) + else: + target_username = parts[1] + dm_message = parts[2] + target_sock = None + for s, info in client_info.items(): + if info.get("username") == target_username: + target_sock = s + break + if target_sock: + sender_username = username + target_sock.send(f"DM from {sender_username}: {dm_message}\n".encode('utf-8')) + if sock: + sock.send(b"\nDirect message sent.\n") + else: + socketio.emit('message', {'username': 'Server', 'message': "Direct message sent."}, room=chat_room) + else: + error_message = "User not found." + if sock: + sock.send(f"\n{error_message}\n".encode('utf-8')) + else: + socketio.emit('message', {'username': 'Server', 'message': error_message}, room=chat_room) + return + + if command.strip() == "%stop": + if client_info.get(sock, {}).get("is_admin"): + print("\nAdmin has stopped the server.") + global quitFlag + quitFlag = False + if sock: + sock.send(b"\nServer is stopping...\n") + else: + socketio.emit('message', {'username': 'Server', 'message': "Server is stopping..."}, room=chat_room) + else: + error_message = "You do not have permission to stop the server." + if sock: + sock.send(f"\n{error_message}\n".encode('utf-8')) + else: + socketio.emit('message', {'username': 'Server', 'message': error_message}, room=chat_room) + return + # REST API Endpoints @app.route('/send_message', methods=['POST']) def send_message(): @@ -96,10 +179,12 @@ def send_message(): if not username or not message: return jsonify({"error": "Username and message are required"}), 400 - # Use the centralized message handling function - handle_message(username, chat_room, message) + if message.strip().startswith("%"): + handle_command(username, chat_room, message) + else: + handle_message(username, chat_room, message) - return jsonify({"status": "Message sent and saved in history"}), 200 + return jsonify({"status": "Message sent and processed"}), 200 @app.route('/create_chatroom', methods=['POST']) def create_chatroom(): @@ -168,8 +253,10 @@ def handle_send_message(data): emit('error', {'message': 'Username and message are required'}) return - # Use the centralized message handling function - handle_message(username, chat_room, message) + if message.strip().startswith("%"): + handle_command(username, chat_room, message) + else: + handle_message(username, chat_room, message) # Chat server logic def chat_server(): @@ -248,51 +335,13 @@ def chat_server(): del chat_rooms[sock] del client_states[sock] print("\nClient has closed connection.") - elif message.strip() == "%?": - print("\nClient requested help.") - sock.send(b"Help: (%?)\n") - sock.send(b"Send messages like normal. Use enter to send a message.\n") - sock.send(b"Available Commands:\n") - sock.send(b"\t%? : Show this help prompt.\n") - sock.send(b"\t%! : Exit from the Chat Server.\n") - sock.send(b"\t%* : Switch to another chatroom.\n") - sock.send(b"\t%$ : Change Username.\n") - sock.send(b"\t%@ : Send a direct message to a user.\n") - if client_info[sock].get("is_admin"): - sock.send(b"\t%stop : Stop the server.\n") - elif message.strip() == "%*": - sock.send(b"\nEnter chatroom name: \n") - client_states[sock] = "WAITING_FOR_NEW_CHATROOM" - elif message.strip() == "%$": - sock.send(b"\nEnter new username: \n") - client_states[sock] = "WAITING_FOR_NEW_USERNAME" - elif message.strip().startswith("%@ "): - parts = message.strip().split(' ', 2) - if len(parts) < 3: - sock.send(b"\nInvalid direct message format. Use: %@ \n") - else: - target_username = parts[1] - dm_message = parts[2] - target_sock = None - for s, info in client_info.items(): - if info.get("username") == target_username: - target_sock = s - break - if target_sock: - sender_username = client_info[sock]["username"] - target_sock.send(f"DM from {sender_username}: {dm_message}\n".encode('utf-8')) - sock.send(b"\nDirect message sent.\n") - else: - sock.send(b"\nUser not found.\n") - elif message.strip() == "%stop" and client_info[sock].get("is_admin"): - print("\nAdmin has stopped the server.") - quitFlag = False else: - username = client_info[sock]["username"] - chat_room = chat_rooms[sock] - - # Use the centralized message handling function - handle_message(username, chat_room, message) + if message.strip().startswith("%"): + handle_command(client_info[sock]["username"], chat_rooms[sock], message, sock) + else: + username = client_info[sock]["username"] + chat_room = chat_rooms[sock] + handle_message(username, chat_room, message) else: sock.close() socket_list.remove(sock)