from asyncio import StreamReader, StreamWriter, Queue from dataclasses import dataclass, field from datetime import datetime from logging import log, INFO from paircd.reply import RPL_CREATED, RPL_MYINFO, RPL_WELCOME, RPL_YOURHOST from paircd.message import Message from typing import Set @dataclass class Client: hostname: str reader: StreamReader writer: StreamWriter msg_queue: Queue = field(default_factory=Queue) nickname: str = "" username: str = "" realname: str = "" registered: bool = False away: str = "" channels: Set[str] = field(default_factory=set) def id(self) -> str: 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}") async def write_forever(self) -> None: while True: msg = await self.msg_queue.get() self.writer.write(msg) await self.writer.drain() def write_message(self, message: Message) -> None: self.msg_queue.put_nowait(message.encode()) def register(self) -> None: if self.registered: return if not (self.nickname and self.username and self.realname): return self.registered = True self.log("registered") self.write_message(RPL_WELCOME(self.nickname, self.id())) self.write_message(RPL_YOURHOST(self.nickname, "localhost", "paircd-0.0.1")) # TODO: Pull timestamp from server instance self.write_message(RPL_CREATED(self.nickname, datetime.utcnow())) # TODO: Display list of supported user & channel modes self.write_message( RPL_MYINFO(self.nickname, "localhost", "paircd-0.0.1", "", "") )