yaboli/yaboli/client.py
2019-04-13 15:32:58 +00:00

165 lines
4.6 KiB
Python

import asyncio
import functools
import logging
from typing import Dict, List, Optional, Union
from .message import LiveMessage
from .room import Room
from .session import LiveSession
logger = logging.getLogger(__name__)
__all__ = ["Client"]
class Client:
def __init__(self,
default_nick: str,
cookie_file: Optional[str] = None,
) -> None:
self._default_nick = default_nick
self._cookie_file = cookie_file
self._rooms: Dict[str, List[Room]] = {}
self._stop = asyncio.Event()
async def run(self) -> None:
await self.started()
await self._stop.wait()
async def stop(self) -> None:
await self.stopping()
tasks = []
for rooms in self._rooms.values():
for room in rooms:
tasks.append(asyncio.create_task(self.part(room)))
for task in tasks:
await task
self._stop.set()
# Managing rooms
def get(self, room_name: str) -> Optional[Room]:
rooms = self._rooms.get(room_name)
if rooms: # None or [] are False-y
return rooms[0]
else:
return None
def get_all(self, room_name: str) -> List[Room]:
return self._rooms.get(room_name, [])
async def join(self,
room_name: str,
password: Optional[str] = None,
nick: Optional[str] = None,
cookie_file: Union[str, bool] = True,
) -> Optional[Room]:
"""
cookie_file is the name of the file to store the cookies in. If it is
True, the client default is used. If it is False, no cookie file name
will be used.
"""
logger.info(f"Joining &{room_name}")
if nick is None:
nick = self._default_nick
this_cookie_file: Optional[str]
if isinstance(cookie_file, str): # This way, mypy doesn't complain
this_cookie_file = cookie_file
elif cookie_file:
this_cookie_file = self._cookie_file
else:
this_cookie_file = None
room = Room(room_name, password=password, target_nick=nick,
cookie_file=this_cookie_file)
room.register_event("connected",
functools.partial(self.on_connected, room))
room.register_event("snapshot",
functools.partial(self.on_snapshot, room))
room.register_event("send",
functools.partial(self.on_send, room))
room.register_event("join",
functools.partial(self.on_join, room))
room.register_event("part",
functools.partial(self.on_part, room))
room.register_event("nick",
functools.partial(self.on_nick, room))
room.register_event("edit",
functools.partial(self.on_edit, room))
room.register_event("pm",
functools.partial(self.on_pm, room))
room.register_event("disconnect",
functools.partial(self.on_disconnect, room))
if await room.connect():
rooms = self._rooms.get(room_name, [])
rooms.append(room)
self._rooms[room_name] = rooms
return room
else:
logger.warn(f"Could not join &{room.name}")
return None
async def part(self, room: Room) -> None:
logger.info(f"Leaving &{room.name}")
rooms = self._rooms.get(room.name, [])
rooms = [r for r in rooms if r is not room]
self._rooms[room.name] = rooms
await room.disconnect()
# Management stuff - overwrite these functions
async def started(self) -> None:
pass
async def stopping(self) -> None:
pass
# Event stuff - overwrite these functions
async def on_connected(self, room: Room) -> None:
pass
async def on_snapshot(self, room: Room, messages: List[LiveMessage]) -> None:
pass
async def on_send(self, room: Room, message: LiveMessage) -> None:
pass
async def on_join(self, room: Room, user: LiveSession) -> None:
pass
async def on_part(self, room: Room, user: LiveSession) -> None:
pass
async def on_nick(self,
room: Room,
user: LiveSession,
from_nick: str,
to_nick: str
) -> None:
pass
async def on_edit(self, room: Room, message: LiveMessage) -> None:
pass
async def on_pm(self,
room: Room,
from_id: str,
from_nick: str,
from_room: str,
pm_id: str
) -> None:
pass
async def on_disconnect(self, room: Room, reason: str) -> None:
pass