diff --git a/paircd/channel.py b/paircd/channel.py index 5be7818..b99da2d 100644 --- a/paircd/channel.py +++ b/paircd/channel.py @@ -1,6 +1,6 @@ from asyncio import Queue from dataclasses import dataclass, field -from typing import Dict +from typing import Dict, List from paircd.client import Client from paircd.message import Message @@ -29,3 +29,6 @@ class Channel: def write_message(self, msg: Message) -> None: self.msg_queue.put_nowait(msg) + + def get_modes(self) -> List[str]: + return [] diff --git a/paircd/client.py b/paircd/client.py index 4df17d9..b7c9550 100644 --- a/paircd/client.py +++ b/paircd/client.py @@ -20,7 +20,9 @@ class Client: channels: Set[str] = field(default_factory=set) def id(self) -> str: - return f"{self.nickname}!{self.username}@{self.hostname}" + nickname = self.nickname or "" + username = self.username or "" + return f"{nickname}!{username}@{self.hostname}" def log(self, msg: str, level: int = INFO) -> None: log(level, f"{self.hostname} ({self.id()}) {msg}") diff --git a/paircd/command_handler.py b/paircd/command_handler.py index 6fad9f8..7b965be 100644 --- a/paircd/command_handler.py +++ b/paircd/command_handler.py @@ -1,4 +1,5 @@ from abc import abstractmethod, ABC +from typing import Optional from paircd.client import Client from paircd.message import Message @@ -7,9 +8,9 @@ from paircd.server import Server class CommandHandler(ABC): cmd: str - argc: int + argc: Optional[int] - def __init__(self, cmd: str, argc: int) -> None: + def __init__(self, cmd: str, argc: Optional[int] = None) -> None: self.cmd = cmd self.argc = argc diff --git a/paircd/handler/mode.py b/paircd/handler/mode.py new file mode 100644 index 0000000..1274c8e --- /dev/null +++ b/paircd/handler/mode.py @@ -0,0 +1,27 @@ +import logging +from paircd.reply import RPL_CHANNELMODEIS + +from paircd.client import Client +from paircd.command_handler import CommandHandler +from paircd.message import Message +from paircd.server import Server + + +class ModeHandler(CommandHandler): + def __init__(self) -> None: + super().__init__("MODE") + + async def handle(self, server: Server, client: Client, msg: Message) -> None: + name = msg.args[0] + if not name.startswith("#"): + client.log("TODO: implement user mode queries", level=logging.WARN) + return + + channel = server.get_channel_by_name(name) + modes = "".join(channel.get_modes()) + if modes != "": + modes = f"+{modes}" + + client.log("TODO: implement channel modes", level=logging.WARN) + msg = RPL_CHANNELMODEIS(client.nickname, name, modes, "") + client.write_message(msg) diff --git a/paircd/handlers.py b/paircd/handlers.py index 578e0e5..cc7dfb3 100644 --- a/paircd/handlers.py +++ b/paircd/handlers.py @@ -7,6 +7,7 @@ from paircd.message import Message from paircd.server import Server from paircd.handler.join import JoinHandler +from paircd.handler.mode import ModeHandler from paircd.handler.nick import NickHandler from paircd.handler.privmsg import PrivmsgHandler from paircd.handler.user import UserHandler @@ -14,6 +15,7 @@ from paircd.handler.who import WhoHandler HANDLER_CLASSES = [ JoinHandler, + ModeHandler, NickHandler, PrivmsgHandler, UserHandler, @@ -33,4 +35,13 @@ 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) return - await CMD_HANDLERS[msg.cmd].handle(server, client, msg) + + handler = CMD_HANDLERS[msg.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}", + level=WARN, + ) + return + + await handler.handle(server, client, msg)