From 67236d2aa8f4b23a15dbe3d9334825e9985b1149 Mon Sep 17 00:00:00 2001 From: Xevion Date: Sat, 9 Jan 2021 13:16:32 -0600 Subject: [PATCH] Improved formatting of users with colors, distinguishing of server messages, more message info --- client/gui.py | 50 +++++++++++++++++++++------------- constants.py | 58 +++++++++++++++++++++++++++++++++++++++ oserver.py | 75 ++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 146 insertions(+), 37 deletions(-) diff --git a/client/gui.py b/client/gui.py index f281ead..5ca03f8 100644 --- a/client/gui.py +++ b/client/gui.py @@ -17,9 +17,10 @@ HEADER_LENGTH = 10 class ReceiveWorker(QThread): - messages = pyqtSignal(str) + messages = pyqtSignal(str, str, str, int) client_list = pyqtSignal(list) error = pyqtSignal() + sent_nick = pyqtSignal() def __init__(self, client: socket.socket, nickname: str, parent=None): QThread.__init__(self, parent) @@ -29,9 +30,11 @@ class ReceiveWorker(QThread): def run(self): while True: try: - length = int(self.client.recv(HEADER_LENGTH).decode('utf-8')) - raw = self.client.recv(length).decode('utf-8') - if len(raw) == 0: + raw_length = self.client.recv(HEADER_LENGTH).decode('utf-8') + if not raw_length: + continue + raw = self.client.recv(int(raw_length)).decode('utf-8') + if not raw: continue message = json.loads(raw) @@ -43,8 +46,9 @@ class ReceiveWorker(QThread): 'nickname': self.nickname } )) + self.sent_nick.emit() elif message['type'] == constants.Types.MESSAGE: - self.messages.emit(message['content']) + self.messages.emit(message['nickname'], message['content'], message['color'], message['time']) elif message['type'] == constants.Types.USER_LIST: self.client_list.emit(message['users']) except: @@ -61,9 +65,12 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.show() # Get Nickname - nicknameDialog = NicknameDialog(self) - nicknameDialog.exec_() - self.nickname = nicknameDialog.lineEdit.text() + while True: + nicknameDialog = NicknameDialog(self) + nicknameDialog.exec_() + self.nickname = nicknameDialog.lineEdit.text().strip() + if len(self.nickname) > 3: + break # Connect to server self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -78,10 +85,13 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.connectionsListTimer = QTimer() self.connectionsListTimer.timeout.connect(self.refreshConnectionsList) self.connectionsListTimer.start(1000 * 30) - self.refreshConnectionsList() + self.receiveThread.sent_nick.connect(self.refreshConnectionsList) + self.messageBox.setPlaceholderText('Type your message here...') self.messageBox.installEventFilter(self) + self.messages = [] + def eventFilter(self, obj, event): if event.type() == QEvent.KeyPress and obj is self.messageBox: if event.key() == Qt.Key_Return and self.messageBox.hasFocus(): @@ -93,16 +103,19 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.messageBox.setTextCursor(cursor) return super().eventFilter(obj, event) - def addMessage(self, message: str) -> None: - self.messageHistory.append(message) + def addMessage(self, nickname: str, message: str, color: str, time: int) -> None: + self.messages.append([nickname, message, color, time]) + self.messageHistory.append(f'<{nickname}> {message}') def sendMessage(self, message: str) -> None: - self.client.send(helpers.prepare_json( - { - 'type': constants.Types.MESSAGE, - 'content': message.strip() - } - )) + message = message.strip() + if len(message) > 0: + self.client.send(helpers.prepare_json( + { + 'type': constants.Types.MESSAGE, + 'content': message + } + )) def refreshConnectionsList(self): self.client.send(helpers.prepare_json( @@ -114,4 +127,5 @@ class MainWindow(QMainWindow, Ui_MainWindow): def updateConnectionsList(self, users): self.connectionsList.clear() - self.connectionsList.addItems(users) + + self.connectionsList.addItems([user['nickname'] for user in users]) diff --git a/constants.py b/constants.py index b37bec6..8169064 100644 --- a/constants.py +++ b/constants.py @@ -3,8 +3,66 @@ class Requests: REFRESH_CONNECTIONS_LIST = 'REFRESH_CLIENT_LIST' GET_HISTORY = 'GET_HISTORY' + class Types: + SERVER_MESSAGE = 'SERVER_MESSAGE' REQUEST = 'REQUEST' NICKNAME = 'NICKNAME' USER_LIST = 'USER_LIST' MESSAGE = 'MESSAGE' + + +class Colors: + AQUA = "#00ffff" + AZURE = "#f0ffff" + BEIGE = "#f5f5dc" + BLACK = "#000000" + BLUE = "#0000ff" + BROWN = "#a52a2a" + CYAN = "#00ffff" + DARKBLUE = "#00008b" + DARKCYAN = "#008b8b" + DARKGREY = "#a9a9a9" + DARKGREEN = "#006400" + DARKKHAKI = "#bdb76b" + DARKMAGENTA = "#8b008b" + DARKOLIVEGREEN = "#556b2f" + DARKORANGE = "#ff8c00" + DARKORCHID = "#9932cc" + DARKRED = "#8b0000" + DARKSALMON = "#e9967a" + DARKVIOLET = "#9400d3" + FUCHSIA = "#ff00ff" + GOLD = "#ffd700" + GREEN = "#008000" + INDIGO = "#4b0082" + KHAKI = "#f0e68c" + LIGHTBLUE = "#add8e6" + LIGHTCYAN = "#e0ffff" + LIGHTGREEN = "#90ee90" + LIGHTGREY = "#d3d3d3" + LIGHTPINK = "#ffb6c1" + LIGHTYELLOW = "#ffffe0" + LIME = "#00ff00" + MAGENTA = "#ff00ff" + MAROON = "#800000" + NAVY = "#000080" + OLIVE = "#808000" + ORANGE = "#ffa500" + PINK = "#ffc0cb" + PURPLE = "#800080" + VIOLET = "#800080" + RED = "#ff0000" + SILVER = "#c0c0c0" + WHITE = "#ffffff" + YELLOW = "#ffff00" + + ALL_NAMES = ['Aqua', 'Azure', 'Beige', 'Black', 'Blue', 'Brown', 'Cyan', 'Dark Blue', 'Dark Cyan', 'Dark Grey', + 'Dark Green', 'Dark Khaki', 'Dark Magenta', 'Dark Olive Green', 'Dark Orange', ' Dark Orchid', 'Dark Red', 'Dark Salmon', + 'Dark Violet', 'Fuchsia', 'Gold', 'Green', 'Indigo', 'Khaki', 'Light Blue', 'Light Cyan', + 'Light Green', 'Light Grey', 'Light Pink', 'Light Yellow', 'Lime', 'Magenta', 'Maroon', 'Navy', + 'Olive', 'Orange', 'Pink', 'Purple', 'Violet', 'Red', 'Silver', 'White', 'Yellow'] + ALL = [AQUA, AZURE, BEIGE, BLACK, BLUE, BROWN, CYAN, DARKBLUE, DARKCYAN, DARKGREY, DARKGREEN, DARKKHAKI, + DARKMAGENTA, DARKOLIVEGREEN, DARKORANGE, DARKORCHID, DARKRED, DARKSALMON, DARKVIOLET, FUCHSIA, GOLD, GREEN, + INDIGO, KHAKI, LIGHTBLUE, LIGHTCYAN, LIGHTGREEN, LIGHTGREY, LIGHTPINK, LIGHTYELLOW, LIME, MAGENTA, MAROON, + NAVY, OLIVE, ORANGE, PINK, PURPLE, VIOLET, RED, SILVER, WHITE, YELLOW, ] diff --git a/oserver.py b/oserver.py index 42e19f4..19b7fcf 100644 --- a/oserver.py +++ b/oserver.py @@ -1,18 +1,19 @@ import json +import random import socket import threading import time import traceback import uuid +from pprint import pprint import constants import helpers -from config import config # Connection Data host = '127.0.0.1' port = 55555 -HEADER_LENGTH = int(config['DEFAULT']['HeaderLength']) +HEADER_LENGTH = 10 # Starting Server server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -23,15 +24,9 @@ server.listen() clients = {} -# Sending Messages To All Connected Clients -def broadcast(message): - print(f'"{message}"') - encoded = helpers.prepare_json({ - 'type': constants.Types.MESSAGE, - 'content': message - }) +def broadcast_data(data): for client in clients.values(): - client['client'].send(encoded) + client['client'].send(data) # Handling Messages From Clients @@ -51,29 +46,68 @@ def handle(client_id): { 'type': constants.Types.USER_LIST, 'users': [ - clients[other]['nickname'] for other in clients.keys() if other != client_id + { + 'nickname': other['nickname'], + 'color': other['color'] + } for other in clients.values() ] } )) elif message['type'] == constants.Types.NICKNAME: - nickname = message['nickname'] if not clients[client_id]['has_nickname']: print("Nickname is {}".format(nickname)) - broadcast("{} joined!".format(nickname)) + broadcast_data(helpers.prepare_json( + { + 'type': constants.Types.MESSAGE, + 'nickname': 'Server', + 'content': f'{nickname} joined!', + 'color': constants.Colors.PINK, + 'time': int(time.time()) + } + )) clients[client_id]['has_nickname'] = True else: print(f'{clients[client_id]["nickname"]} changed their name to {nickname}') clients[client_id]['nickname'] = nickname elif message['type'] == constants.Types.MESSAGE: - broadcast(f'<{nickname}>: {message["content"]}') - + if message['content'] == '/reroll': + color = random.choice(constants.Colors.ALL) + colorname = constants.Colors.ALL_NAMES[constants.Colors.ALL.index(color)] + clients[client_id]['color'] = color + broadcast_data(helpers.prepare_json( + { + 'type': constants.Types.MESSAGE, + 'nickname': 'Server', + 'content': f'Changed your color to {colorname} ({color})', + 'color': constants.Colors.PINK, + 'time': int(time.time()) + } + )) + broadcast_data(helpers.prepare_json( + { + 'type': constants.Types.MESSAGE, + 'nickname': nickname, + 'content': message["content"], + 'color': clients[client_id]['color'], + 'time': int(time.time()) + } + )) except: - # Removing And Closing Clients + traceback.print_exc() + print(f'Closing Client {clients[client_id]["nickname"]}') client.close() del clients[client_id] - broadcast('{} left!'.format(nickname)) + broadcast_data(helpers.prepare_json( + { + 'type': constants.Types.MESSAGE, + 'nickname': 'Server', + 'content': f'{nickname} left!', + 'color': constants.Colors.PINK, + 'time': int(time.time()) + } + )) break @@ -95,14 +129,17 @@ def receive(): clients[client_id] = { 'client': client, + 'id': client_id, 'nickname': client_id[:10], 'first_seen': int(time.time()), - 'has_nickname': False + 'has_nickname': False, + 'color': random.choice(constants.Colors.ALL) } + pprint(clients[client_id]) client.send(helpers.prepare_json( { - 'type': constants.Types.MESSAGE, + 'type': constants.Types.SERVER_MESSAGE, 'content': 'Connected to server!' } ))