From d9528228badec722062b5b24b9f28c2f26101933 Mon Sep 17 00:00:00 2001 From: Jean-Marie Mineau Date: Sun, 3 Oct 2021 18:54:22 +0200 Subject: [PATCH] accept and reject invites to rooms --- src/matrix_bot/client.py | 67 ++++++++++++++++++++++++++++++++-------- tests/test.py | 1 - 2 files changed, 54 insertions(+), 14 deletions(-) diff --git a/src/matrix_bot/client.py b/src/matrix_bot/client.py index ae7bc77..0187dad 100644 --- a/src/matrix_bot/client.py +++ b/src/matrix_bot/client.py @@ -23,7 +23,7 @@ class Client(Aobject): 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 + whitelist_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. @@ -35,15 +35,16 @@ class Client(Aobject): __rooms_by_id: dict[RoomId, Room] __sync_token_file: AsyncPath __sync_token:Optional[str] - __sync_token_queue:asyncio.Queue[str] - allowed_rooms: Optional[dict[RoomId, Room]] + __sync_token_queue: asyncio.Queue[str] + __invites_queue: asyncio.Queue[tuple[RoomId, nio.responses.InviteInfo]] + whitelist_rooms: Optional[dict[RoomId, Room]] async def __init__( self, username: str, homeserver: str, password: str, - allowed_rooms_names: Optional[list[Union[RoomAlias, RoomId]]]=None, + whitelist_rooms_names: Optional[list[Union[RoomAlias, RoomId]]]=None, sync_token_file:str="./.sync_token", ): """ @@ -51,7 +52,7 @@ class Client(Aobject): 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 + whitelist_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')) sync_token_file: the file where is stored the last sync token received from @@ -71,16 +72,17 @@ class Client(Aobject): else: self.__sync_token = None self.__sync_token_queue = asyncio.Queue() + self.__invites_queue = asyncio.Queue() resp = await self.__client.login(password) if isinstance(resp, nio.responses.LoginError): raise RuntimeError(f"Fail to connect: {resp.message}") - self.allowed_rooms = None - if allowed_rooms_names: - self.allowed_rooms = {} - rooms = await asyncio.gather(*(self.resolve_room(room_name) for room_name in allowed_rooms_names)) + self.whitelist_rooms = None + if whitelist_rooms_names: + self.whitelist_rooms = {} + rooms = await asyncio.gather(*(self.resolve_room(room_name) for room_name in whitelist_rooms_names)) for room in rooms: - self.allowed_rooms[room.id] = room # room uniqueness is handled by self.resolve_room + self.whitelist_rooms[room.id] = room # room uniqueness is handled by self.resolve_room async def resolve_room( self, @@ -134,6 +136,39 @@ class Client(Aobject): await file.write(token) self.__sync_token_queue.task_done() + async def __process_invites(self)->NoReturn: + """ + Process invites to rooms. + """ + while True: + room_id, invite_info = await self.__invites_queue.get() + accept_invite = False + + if self.whitelist_rooms is not None: + if room_id not in self.whitelist_rooms: + print(f"Received invite for {room_id}, but room_id is not in the white list.") # TODO: better logging + else: + accept_invite = True + print(f"Received invite for {room_id}: invite accepted.") # TODO: better logging + else: + accept_invite = True + print(f"Received invite for {room_id}: invite accepted.") # TODO: better logging + + if accept_invite: + result = await self.__client.join(room_id) + if isinstance(result, nio.JoinError): + print(f"Error while joinning room {room_id}: {result.message}") # TODO: better logging + else: + print(f"{room_id} joined") # TODO: better logging + else: + result = await self.__client.room_leave(room_id) + if isinstance(result, nio.RoomLeaveError): + print(f"Error while leaving room {room_id}: {result.message}") # TODO: better logging + else: + print(f"{room_id} left") # TODO: better logging + + self.__invites_queue.task_done() + async def __sync( self, sync_timeout:int=30 @@ -144,15 +179,20 @@ class Client(Aobject): """ while True: sync_resp = await self.__client.sync( - sync_delta*1000, + sync_timeout*1000, since=self.__sync_token ) if isinstance(sync_resp, nio.responses.SyncError): print(f"Error while syncronizing: {sync_resp.message}") # TODO: use proper logging continue + self.__sync_token = sync_resp.next_batch await self.__sync_token_queue.put(self.__sync_token) + invites = sync_resp.rooms.invite + for room_id in invites: + await self.__invites_queue.put((room_id, invites[room_id])) + async def run( self, sync_timeout:int=30 @@ -162,8 +202,9 @@ class Client(Aobject): sync_timeout: the max time in sec between each sync. """ await asyncio.gather( - self.__sync(sync_delta=sync_delta), - self.__save_sync_tocken() + self.__sync(sync_timeout=sync_timeout), + self.__save_sync_tocken(), + self.__process_invites() ) diff --git a/tests/test.py b/tests/test.py index 765db95..c5ea0c3 100644 --- a/tests/test.py +++ b/tests/test.py @@ -16,7 +16,6 @@ async def main(): os.environ["PASSWD"], os.environ["ROOMS"].split(",") ) - print(client.allowed_rooms) await client.run()