python ircd using asyncio
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

59 lines
1.8 KiB

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", "", "")
)