diff --git a/htdocs/openwebrx.js b/htdocs/openwebrx.js index cbfd7c5f..1725d6fa 100644 --- a/htdocs/openwebrx.js +++ b/htdocs/openwebrx.js @@ -120,8 +120,8 @@ function jumpBySteps(steps) { } } -function recvChatMessage(sender, text) { - divlog('' + sender + ': ' +function recvChatMessage(sender, text, color = "white") { + divlog('' + sender + ': ' + text + '', false); } @@ -1178,7 +1178,7 @@ function on_ws_recv(evt) { divlog(json['value'], true); break; case 'chat_message': - recvChatMessage(json['sender'], json['text']); + recvChatMessage(json['sender'], json['text'], json['color']); break; case 'backoff': divlog("Server is currently busy: " + json['reason'], true); diff --git a/owrx/client.py b/owrx/client.py index 2c38b39a..42d53cfc 100644 --- a/owrx/client.py +++ b/owrx/client.py @@ -1,4 +1,5 @@ from owrx.config import Config +from owrx.color import ColorCache from datetime import datetime, timedelta import threading @@ -29,6 +30,9 @@ class ClientRegistry(object): def __init__(self): self.clients = [] self.bans = {} + self.chat = {} + self.chatCount = 0 + self.chatColors = ColorCache() Config.get().wireProperty("max_clients", self._checkClientCount) super().__init__() @@ -51,6 +55,8 @@ class ClientRegistry(object): def removeClient(self, client): try: + if client in self.chat: + del self.chat[client] self.clients.remove(client) except ValueError: pass @@ -62,9 +68,18 @@ class ClientRegistry(object): client.close() # Broadcast chat message to all connected clients. - def broadcastChatMessage(self, sender: str, text: str): + def broadcastChatMessage(self, client, text: str): + if client in self.chat: + name = self.chat[client]["name"] + color = self.chat[client]["color"] + else: + name = "User%04d" % (self.chatCount + 1) + color = self.chatColors.getColor(name) + self.chat[client] = { "name": name, "color": color } + self.chatCount = (self.chatCount + 1) % 9999 + for c in self.clients: - c.write_chat_message(sender, text) + c.write_chat_message(name, text, color) # List all active and banned clients. def listAll(self): diff --git a/owrx/color.py b/owrx/color.py new file mode 100644 index 00000000..6897209b --- /dev/null +++ b/owrx/color.py @@ -0,0 +1,30 @@ +class ColorCache: + def __init__(self): + # Use these colors for labels + self.colors = [ + "#FFFFFF", "#999999", "#FF9999", "#FFCC99", "#FFFF99", "#CCFF99", + "#99FF99", "#99FFCC", "#99FFFF", "#99CCFF", "#9999FF", "#CC99FF", + "#FF99FF", "#FF99CC", + ] + # Labels are cached here + self.colorBuf = {} + + # Get a unique color for a given ID, reusing colors as we go + def getColor(self, id: str) -> str: + if id in self.colorBuf: + # Sort entries in order of freshness + color = self.colorBuf.pop(id) + elif len(self.colorBuf) < len(self.colors): + # Assign each initial entry color based on its order + color = self.colors[len(self.colorBuf)] + else: + # If we run out of colors, reuse the oldest entry + color = self.colorBuf.pop(next(iter(self.colorBuf))) + # Done + self.colorBuf[id] = color + return color + + def rename(self, old_id: str, new_id: str): + if old_id in self.colorBuf and new_id != old_id: + self.colorBuf[new_id] = self.colorBuf[old_id] + del self.colorBuf[old_id] diff --git a/owrx/connection.py b/owrx/connection.py index 67a6cc0f..a0ac39f9 100644 --- a/owrx/connection.py +++ b/owrx/connection.py @@ -21,7 +21,6 @@ from abc import ABCMeta, abstractmethod import json import threading import struct -import re import logging @@ -346,8 +345,7 @@ class OpenWebRxReceiverClient(OpenWebRxClient, SdrSourceEventClient): elif message["type"] == "sendmessage": if "text" in message: ClientRegistry.getSharedInstance().broadcastChatMessage( - re.sub("^::ffff:", "", self.conn.getIp()), - message["text"] + self, message["text"] ) else: @@ -491,9 +489,14 @@ class OpenWebRxReceiverClient(OpenWebRxClient, SdrSourceEventClient): def write_backoff_message(self, reason): self.send({"type": "backoff", "reason": reason}) - def write_chat_message(self, sender, text): + def write_chat_message(self, sender, text, color = "white"): logger.debug("Sending {0}".format({"type": "chat_message", "sender": sender, "text": text})) - self.send({"type": "chat_message", "sender": sender, "text": text}) + self.send({ + "type": "chat_message", + "sender": sender, + "text": text, + "color": color + }) def write_modes(self, modes): def to_json(m): diff --git a/owrx/toolbox.py b/owrx/toolbox.py index ba359702..c1ece78f 100644 --- a/owrx/toolbox.py +++ b/owrx/toolbox.py @@ -1,5 +1,6 @@ from owrx.storage import Storage from owrx.config import Config +from owrx.color import ColorCache from csdr.module import LineBasedModule from pycsdr.types import Format from datetime import datetime @@ -13,38 +14,6 @@ import logging logger = logging.getLogger(__name__) -class ColorCache: - def __init__(self): - # Use these colors for labels - self.colors = [ - "#FFFFFF", "#999999", "#FF9999", "#FFCC99", "#FFFF99", "#CCFF99", - "#99FF99", "#99FFCC", "#99FFFF", "#99CCFF", "#9999FF", "#CC99FF", - "#FF99FF", "#FF99CC", - ] - # Labels are cached here - self.colorBuf = {} - - # Get a unique color for a given ID, reusing colors as we go - def getColor(self, id: str) -> str: - if id in self.colorBuf: - # Sort entries in order of freshness - color = self.colorBuf.pop(id) - elif len(self.colorBuf) < len(self.colors): - # Assign each initial entry color based on its order - color = self.colors[len(self.colorBuf)] - else: - # If we run out of colors, reuse the oldest entry - color = self.colorBuf.pop(next(iter(self.colorBuf))) - # Done - self.colorBuf[id] = color - return color - - def rename(self, old_id: str, new_id: str): - if old_id in self.colorBuf and new_id != old_id: - self.colorBuf[new_id] = self.colorBuf[old_id] - del self.colorBuf[old_id] - - class TextParser(LineBasedModule): def __init__(self, filePrefix: str = None, service: bool = False): self.service = service