mirror of
https://github.com/Xevion/tcp-chat.git
synced 2025-12-08 10:08:45 -06:00
Improved formatting of users with colors, distinguishing of server messages, more message info
This commit is contained in:
@@ -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'<<span style="color: {color}">{nickname}</span>> {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])
|
||||
|
||||
58
constants.py
58
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, ]
|
||||
|
||||
75
oserver.py
75
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!'
|
||||
}
|
||||
))
|
||||
|
||||
Reference in New Issue
Block a user