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

88 lines
2.8 KiB
Python

"""
The Client class.
Connect to the matrix server and handle interactions with the server.
"""
import asyncio
import nio
from typing import (
Optional,
NoReturn,
Union
)
from .utils import (
Room,
RoomAlias,
RoomId
)
class Client:
"""
Connect to the matrix server and handle interactions with the
server.
allowed_rooms: dict of the rooms where the bot is allowed to connect, indexed
by id (the name starting with '!'). If set to None, the bot connect to
all room where it is invited.
"""
__client: nio.AsyncClient
allowed_rooms: Optional[dict[RoomId, Room]]
def __init__(
self,
username: str,
homeserver: str,
password: str,
allowed_rooms_names: Optional[list[Union[RoomAlias, RoomId]]]=None
):
"""
Initialize the Client.
username: the username used by the bot
homeserver: the matrix home server of the bot (expl: "https://matrix.org")
password: the password of the user
allowed_rooms: the list of the rooms where the bot is allowed to connect
(given by room id (expl: '!xxx:matrix.org') of room alias (expl:
'#xxx:matrix.org'))
"""
loop = asyncio.get_event_loop()
self.__client = nio.AsyncClient(
homeserver,
username
)
resp = loop.run_until_complete(self.__client.login(password))
if isinstance(resp, nio.responses.LoginError):
raise RuntimeError(f"Fail to connect: {resp.message}")
# Where is the async map when you need it?
self.allowed_rooms = None
if allowed_rooms_names:
self.allowed_rooms = {}
for room_name in allowed_rooms_names:
room = loop.run_until_complete(self.resolve_room(room_name))
if room.id in self.allowed_rooms:
self.allowed_rooms[room.id].aliases.update(room.aliases)
else:
self.allowed_rooms[room.id] = room
async def resolve_room(
self,
room_name: Union[RoomAlias, RoomId]
)->Room:
"""
Lookup a room from its id or alias.
"""
if len(room_name) == 0:
raise ValueError(f"Invalid room_name: {room_name}")
if room_name[0] == '!':
return Room(id=room_name)
elif room_name[0] != '#':
raise ValueError(f"Invalid room_name: {room_name}")
else:
resp = await self.__client.room_resolve_alias(room_name)
if isinstance(resp, nio.responses.RoomResolveAliasError):
raise RuntimeError(f"Error while resolving alias: {resp.message}")
return Room(id=resp.room_id,aliases={room_name})