Browse Source

Broadcast message when client updates their nickname

master
Forest Belton 2 years ago
parent
commit
360a4d4a96
4 changed files with 37 additions and 10 deletions
  1. +10
    -0
      paircd/channel.py
  2. +17
    -10
      paircd/handler/nick.py
  3. +2
    -0
      paircd/reply.py
  4. +8
    -0
      paircd/server.py

+ 10
- 0
paircd/channel.py View File

@ -34,3 +34,13 @@ class Channel:
def get_user_modes_by_nick(self, nick: str) -> Set[str]:
return self.modes_by_nick[nick]
def rename_client(self, name: str, new_name: str) -> None:
if name not in self.clients_by_nick:
raise KeyError(f"No client on channel with nick {name}")
if new_name in self.clients_by_nick:
raise KeyError(f"Client already exists with nick {new_name}")
self.clients_by_nick[new_name] = self.clients_by_nick[name]
del self.clients_by_nick[name]
self.modes_by_nick[new_name] = self.modes_by_nick[name]
del self.modes_by_nick[name]

+ 17
- 10
paircd/handler/nick.py View File

@ -1,7 +1,7 @@
from paircd.client import Client
from paircd.command_handler import CommandHandler
from paircd.message import Message
from paircd.reply import ERR_NICKNAMEINUSE
from paircd.reply import ERR_NICKNAMEINUSE, ERR_NONICKNAMEGIVEN, NICK
from paircd.server import Server
@ -11,6 +11,10 @@ class NickHandler(CommandHandler):
async def handle(self, server: Server, client: Client, msg: Message) -> None:
nickname = msg.args[0]
if nickname == "":
target = client.nickname if client.nickname else nickname
client.write_message(ERR_NONICKNAMEGIVEN(target))
return
existing_client = server.get_client_by_name(nickname)
if existing_client is not None:
@ -19,19 +23,22 @@ class NickHandler(CommandHandler):
client.write_message(ERR_NICKNAMEINUSE(target, nickname))
return
# Remove stale references if they exist
if client.nickname:
server.remove_client_by_name(client.nickname)
for channel_name in client.channels:
channel = server.get_channel_by_name(channel_name)
channel.remove_client_by_nick(client.nickname)
rename = client.nickname != ""
old_nick = client.nickname
old_id = client.id()
client.nickname = nickname
if rename:
server.rename_client(old_nick, nickname)
else:
server.add_client(client)
# Add references for client
server.add_client(client)
for channel_name in client.channels:
channel = server.get_channel_by_name(channel_name)
channel.remove_client_by_nick(client.nickname)
if rename:
channel.rename_client(old_nick, nickname)
channel.write_message(NICK(nickname, prefix=old_id))
else:
raise RuntimeError("shouldn't be in any channels without a nick")
client.register()

+ 2
- 0
paircd/reply.py View File

@ -26,6 +26,7 @@ def reply_fn(cmd: Union[int, str], tmpl: str) -> Callable:
# Commands
JOIN = cmd_fn("JOIN", "{0}")
MODE = cmd_fn("MODE", "{0} {1}")
NICK = cmd_fn("NICK", "{0}")
PONG = cmd_fn("PONG", ":{0}")
PRIVMSG = cmd_fn("PRIVMSG", "{0} :{1}")
@ -35,6 +36,7 @@ ERR_NOSUCHSERVER = reply_fn(402, "{0} :No such server")
ERR_NOSUCHCHANNEL = reply_fn(403, "{0} :No such channel")
ERR_CANNOTSENDTOCHAN = reply_fn(404, "{0} :Cannot send to channel")
ERR_TOOMANYCHANNELS = reply_fn(405, "{0} :You have joined too many channels")
ERR_NONICKNAMEGIVEN = reply_fn(431, ":No nickname given")
ERR_NICKNAMEINUSE = reply_fn(433, "{0} :Nickname is already in use")
ERR_NOTEXTTOSEND = reply_fn(412, ":No text to send")
ERR_NOTREGISTERED = reply_fn(451, ":You have not registered")

+ 8
- 0
paircd/server.py View File

@ -25,3 +25,11 @@ class Server:
def remove_client_by_name(self, name: str) -> None:
del self.clients_by_nick[name]
def rename_client(self, name: str, new_name: str) -> None:
if name not in self.clients_by_nick:
raise KeyError(f"No client on server with nick {name}")
if new_name in self.clients_by_nick:
raise KeyError(f"Client already exists with nick {new_name}")
self.clients_by_nick[new_name] = self.clients_by_nick[name]
del self.clients_by_nick[name]

Loading…
Cancel
Save