from asyncio import create_task, run, start_server, IncompleteReadError
|
|
from asyncio.streams import StreamReader, StreamWriter
|
|
from logging import basicConfig, info, INFO
|
|
import logging
|
|
from os import getenv
|
|
from sys import exc_info
|
|
|
|
from dotenv import load_dotenv
|
|
|
|
load_dotenv("../.env")
|
|
|
|
from paircd.client import Client # noqa: E402
|
|
from paircd.handlers import handle_cmd, register_cmd_handlers # noqa: E402
|
|
from paircd.message import parse_message # noqa: E402
|
|
from paircd.server import Server # noqa: E402
|
|
|
|
basicConfig(format="%(asctime)s [%(levelname)s] - %(message)s", level=INFO)
|
|
|
|
|
|
async def read_forever(server: Server, client: Client) -> None:
|
|
while not client.closed:
|
|
try:
|
|
raw_msg = await client.reader.readuntil(b"\r\n")
|
|
except IncompleteReadError:
|
|
logging.warning("client connection closed", exc_info=exc_info())
|
|
await server.disconnect_client(client.nickname, "Connection reset by peer")
|
|
break
|
|
|
|
msg = parse_message(raw_msg)
|
|
await handle_cmd(server, client, msg)
|
|
|
|
|
|
async def serve() -> None:
|
|
bind_addr = getenv("BIND_ADDR") or "0.0.0.0"
|
|
port = getenv("PORT") or 6667
|
|
|
|
irc_server = Server()
|
|
register_cmd_handlers()
|
|
|
|
async def register_client(reader: StreamReader, writer: StreamWriter) -> None:
|
|
client = Client(
|
|
hostname=writer.get_extra_info("peername")[0],
|
|
reader=reader,
|
|
writer=writer,
|
|
)
|
|
create_task(read_forever(irc_server, client))
|
|
create_task(client.write_until_closed(irc_server))
|
|
|
|
server = await start_server(
|
|
register_client,
|
|
bind_addr,
|
|
port,
|
|
reuse_port=True,
|
|
)
|
|
|
|
info(f"Listening on {bind_addr}:{port}")
|
|
async with server:
|
|
await server.serve_forever()
|
|
|
|
|
|
def main() -> None:
|
|
run(serve())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|