|
|
- 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 "<unknown>"
- username = self.username or "<unknown>"
- 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", "", "")
- )
|