Centralize the message and command handling, so that any client can use it.

This commit is contained in:
Charles Descamps 2025-03-28 10:08:54 -07:00
parent 093da92186
commit c5eab3f695

View file

@ -84,6 +84,89 @@ def handle_message(username, chat_room, message):
if client_sock != server_socket and chat_rooms.get(client_sock) == chat_room: if client_sock != server_socket and chat_rooms.get(client_sock) == chat_room:
client_sock.send(send_message) 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%@ <username> <message> : 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: %@ <username> <message>"
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 # REST API Endpoints
@app.route('/send_message', methods=['POST']) @app.route('/send_message', methods=['POST'])
def send_message(): def send_message():
@ -96,10 +179,12 @@ def send_message():
if not username or not message: if not username or not message:
return jsonify({"error": "Username and message are required"}), 400 return jsonify({"error": "Username and message are required"}), 400
# Use the centralized message handling function if message.strip().startswith("%"):
handle_command(username, chat_room, message)
else:
handle_message(username, chat_room, message) 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']) @app.route('/create_chatroom', methods=['POST'])
def create_chatroom(): def create_chatroom():
@ -168,7 +253,9 @@ def handle_send_message(data):
emit('error', {'message': 'Username and message are required'}) emit('error', {'message': 'Username and message are required'})
return return
# Use the centralized message handling function if message.strip().startswith("%"):
handle_command(username, chat_room, message)
else:
handle_message(username, chat_room, message) handle_message(username, chat_room, message)
# Chat server logic # Chat server logic
@ -248,50 +335,12 @@ def chat_server():
del chat_rooms[sock] del chat_rooms[sock]
del client_states[sock] del client_states[sock]
print("\nClient has closed connection.") 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%@ <username> <message> : 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: %@ <username> <message>\n")
else: else:
target_username = parts[1] if message.strip().startswith("%"):
dm_message = parts[2] handle_command(client_info[sock]["username"], chat_rooms[sock], message, sock)
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: else:
username = client_info[sock]["username"] username = client_info[sock]["username"]
chat_room = chat_rooms[sock] chat_room = chat_rooms[sock]
# Use the centralized message handling function
handle_message(username, chat_room, message) handle_message(username, chat_room, message)
else: else:
sock.close() sock.close()