diff --git a/squinnondation/hazel.py b/squinnondation/hazel.py index 27dea5f..a8c07f4 100644 --- a/squinnondation/hazel.py +++ b/squinnondation/hazel.py @@ -15,7 +15,7 @@ class Hazelnut: """ A hazelnut is a connected client, with its socket. """ - def __init__(self, nickname: str = "anonymous", address: str = "localhost", port: int = 2500): + def __init__(self, nickname: str = None, address: str = "localhost", port: int = 2500): self.nickname = nickname try: @@ -174,7 +174,7 @@ class Squirrel(Hazelnut): elif key != "\n": # Insert the pressed key in the current message new_buffer = self.input_buffer[:self.input_index] + key + self.input_buffer[self.input_index:] - if len(DataTLV.construct(f"<{self.nickname}> {new_buffer}")) > 255 - 8 - 4: + if len(DataTLV.construct(f"{self.nickname}: {new_buffer}")) > 255 - 8 - 4: # The message is too long to be sent once. We don't allow the user to type any other character. curses.beep() return @@ -190,7 +190,7 @@ class Squirrel(Hazelnut): if not msg: return - msg = f"<{self.nickname}> {msg}" + msg = f"{self.nickname}: {msg}" self.add_message(msg) pkt = Packet.construct(DataTLV.construct(msg)) @@ -257,7 +257,7 @@ class Squirrel(Hazelnut): Add a new system log message. TODO: Configure logging levels to ignore some messages. """ - return self.add_message(f" *{msg}*") + return self.add_message(f"system: *{msg}*") def print_markdown(self, pad: Any, y: int, x: int, msg: str, bold: bool = False, italic: bool = False, underline: bool = False, strike: bool = False) -> int: @@ -363,6 +363,8 @@ class Squirrel(Hazelnut): if i + y_offset > curses.LINES - 3: break + msg = re.sub("([^:]*): (.*)", "<\\1> \\2", msg, 1) + if not re.match("<.*> .*", msg): msg = " " + msg match = re.match("<(.*)> (.*)", msg) diff --git a/squinnondation/messages.py b/squinnondation/messages.py index 869ae87..fd9d672 100644 --- a/squinnondation/messages.py +++ b/squinnondation/messages.py @@ -1,6 +1,6 @@ # Copyright (C) 2020 by eichhornchen, ÿnérant # SPDX-License-Identifier: GPL-3.0-or-later - +import re from typing import Any, List, Optional from ipaddress import IPv6Address from enum import Enum @@ -207,7 +207,21 @@ class DataTLV(TLV): A message has been sent. We log it. TODO: Check that the tuple (sender_id, nonce) is unique to avoid duplicates. """ - squirrel.add_message(self.data.decode('UTF-8')) + msg = self.data.decode('UTF-8') + squirrel.add_message(msg) + nickname_match = re.match("(.*): (.*)", msg) + if nickname_match is None: + squirrel.send_packet(sender, Packet.construct(WarningTLV.construct( + "Unable to retrieve your username. Please use the syntax 'nickname: message'"))) + else: + nickname = nickname_match.group(1) + if sender.nickname is None: + sender.nickname = nickname + elif sender.nickname != nickname: + squirrel.send_packet(sender, Packet.construct(WarningTLV.construct( + "It seems that you used two different nicknames. " + f"Known nickname: {sender.nickname}, found: {nickname}"))) + sender.nickname = nickname @staticmethod def construct(message: str) -> "DataTLV": @@ -281,7 +295,7 @@ class WarningTLV(TLV): def unmarshal(self, raw_data: bytes) -> None: self.type = raw_data[0] self.length = raw_data[1] - self.message = raw_data[2:self.length].decode("UTF-8") + self.message = raw_data[2:self.length + 2].decode("UTF-8") def marshal(self) -> bytes: return self.type.to_bytes(1, sys.byteorder) + \ @@ -289,7 +303,15 @@ class WarningTLV(TLV): self.message.encode("UTF-8")[:self.length] def handle(self, squirrel: Any, sender: Any) -> None: - squirrel.add_message(f" *A client warned you: {self.message}*") + squirrel.add_message(f"warning: *A client warned you: {self.message}*") + + @staticmethod + def construct(message: str) -> "WarningTLV": + tlv = WarningTLV() + tlv.type = 7 + tlv.message = message + tlv.length = len(tlv.message.encode("UTF-8")) + return tlv class Packet: