From bf10934c57b843fc43a27cc4156774235e7f9d16 Mon Sep 17 00:00:00 2001 From: Forest Belton <65484+forestbelton@users.noreply.github.com> Date: Tue, 22 Jun 2021 02:30:41 -0400 Subject: [PATCH] Command fixes --- paircd/channel.py | 16 ++++++---------- paircd/handler/join.py | 16 +++++++++++++++- paircd/handler/mode.py | 4 ++-- paircd/handler/who.py | 2 +- paircd/handlers.py | 7 ++++--- paircd/message.py | 2 +- paircd/reply.py | 5 ++++- paircd/server.py | 2 -- 8 files changed, 33 insertions(+), 21 deletions(-) diff --git a/paircd/channel.py b/paircd/channel.py index b99da2d..a14f8f9 100644 --- a/paircd/channel.py +++ b/paircd/channel.py @@ -9,6 +9,7 @@ from paircd.message import Message @dataclass class Channel: name: str + topic: str = "" clients_by_nick: Dict[str, Client] = field(default_factory=dict) msg_queue: Queue = field(default_factory=Queue) @@ -18,17 +19,12 @@ class Channel: def remove_client_by_nick(self, nick: str) -> None: del self.clients_by_nick[nick] - async def process(self) -> None: - while True: - msg = await self.msg_queue.get() - for client in self.clients_by_nick.values(): - # Don't broadcast client's messages back to themselves - if msg.cmd == "PRIVMSG" and msg.prefix == client.id(): - continue - client.write_message(msg) - def write_message(self, msg: Message) -> None: - self.msg_queue.put_nowait(msg) + for client in self.clients_by_nick.values(): + # Don't broadcast client's messages back to themselves + if msg.cmd == "PRIVMSG" and msg.prefix == client.id(): + continue + client.write_message(msg) def get_modes(self) -> List[str]: return [] diff --git a/paircd/handler/join.py b/paircd/handler/join.py index 9432a62..ae9174a 100644 --- a/paircd/handler/join.py +++ b/paircd/handler/join.py @@ -1,4 +1,5 @@ import logging +from paircd.reply import RPL_ENDOFNAMES, RPL_NAMREPLY, RPL_TOPIC from paircd.client import Client from paircd.command_handler import CommandHandler @@ -26,6 +27,19 @@ class JoinHandler(CommandHandler): client.channels.add(channel_name) client.log(f"joined {channel_name}") - await channel.msg_queue.put( + channel.write_message( Message(cmd="JOIN", args=[channel_name], prefix=client.id()) ) + + if channel.topic != "": + client.write_message( + RPL_TOPIC(client.nickname, channel_name, channel.topic) + ) + + client.log("TODO: implement user channel modes", level=logging.WARN) + channel_members = list(channel.clients_by_nick.keys()) + client.write_message( + # "=" means public channel (ref: https://modern.ircdocs.horse/#rplnamreply-353) + RPL_NAMREPLY(client.nickname, "=", channel_name, " ".join(channel_members)) + ) + client.write_message(RPL_ENDOFNAMES(client.nickname, channel_name)) diff --git a/paircd/handler/mode.py b/paircd/handler/mode.py index 1274c8e..22d18c0 100644 --- a/paircd/handler/mode.py +++ b/paircd/handler/mode.py @@ -23,5 +23,5 @@ class ModeHandler(CommandHandler): modes = f"+{modes}" client.log("TODO: implement channel modes", level=logging.WARN) - msg = RPL_CHANNELMODEIS(client.nickname, name, modes, "") - client.write_message(msg) + client.write_message(Message("MODE", args=[name, modes])) + client.write_message(RPL_CHANNELMODEIS(client.nickname, name, modes, "")) diff --git a/paircd/handler/who.py b/paircd/handler/who.py index 4974a27..8fd81f7 100644 --- a/paircd/handler/who.py +++ b/paircd/handler/who.py @@ -34,7 +34,7 @@ class WhoHandler(CommandHandler): channel_name, member.username, member.hostname, - "0", # server + "localhost", # server member.nickname, # TODO: Implement "H", # H = here, G = gone diff --git a/paircd/handlers.py b/paircd/handlers.py index cc7dfb3..7df5b27 100644 --- a/paircd/handlers.py +++ b/paircd/handlers.py @@ -32,11 +32,12 @@ def register_cmd_handlers() -> None: async def handle_cmd(server: Server, client: Client, msg: Message) -> None: - if msg.cmd not in CMD_HANDLERS: - client.log(f"used unknown command {msg.cmd}", level=WARN) + cmd = msg.cmd.upper() + if cmd not in CMD_HANDLERS: + client.log(f"used unknown command {cmd}", level=WARN) return - handler = CMD_HANDLERS[msg.cmd] + handler = CMD_HANDLERS[cmd] if handler.argc is not None and handler.argc != len(msg.args): client.log( "got {len(msg.args)} arguments for {msg.cmd}, expected {handler.argc}", diff --git a/paircd/message.py b/paircd/message.py index f2264ed..118bc6c 100644 --- a/paircd/message.py +++ b/paircd/message.py @@ -22,7 +22,7 @@ class ParsingError(Exception): class Message: cmd: str args: List[str] - prefix: str = "" + prefix: str = "localhost" def encode(self) -> bytes: prefix = self.prefix diff --git a/paircd/reply.py b/paircd/reply.py index dfa0be2..b709f50 100644 --- a/paircd/reply.py +++ b/paircd/reply.py @@ -20,4 +20,7 @@ RPL_WHOISUSER = reply_fn(311, "{0} {1} {2} * :{3}") RPL_ENDOFWHO = reply_fn(315, "{0} :End of /WHO list") RPL_ENDOFWHOIS = reply_fn(318, "{0} :End of /WHOIS list") RPL_CHANNELMODEIS = reply_fn(324, "{0} {1}{2}") -RPL_WHOREPLY = reply_fn(352, "{0} {1} {2} {3} {4} {5} :{6} {7}") +RPL_TOPIC = reply_fn(332, "{0} :{1}") +RPL_WHOREPLY = reply_fn(352, "{0} ~{1} {2} {3} {4} {5} :{6} {7}") +RPL_NAMREPLY = reply_fn(353, "{0} {1} :{2}") +RPL_ENDOFNAMES = reply_fn(366, "{0} :End of /NAMES list") diff --git a/paircd/server.py b/paircd/server.py index 9c7679d..22f982e 100644 --- a/paircd/server.py +++ b/paircd/server.py @@ -1,4 +1,3 @@ -from asyncio import create_task from dataclasses import dataclass, field from typing import Dict @@ -17,7 +16,6 @@ class Server: def get_channel_by_name(self, name: str) -> Channel: if name not in self.channels_by_name: self.channels_by_name[name] = Channel(name=name) - create_task(self.channels_by_name[name].process()) return self.channels_by_name[name] def remove_client_by_name(self, name: str) -> None: