surrender to the async devil and use blackmagic to initialize asyncronously an object
This commit is contained in:
parent
ee81cf93af
commit
e368d661ac
3 changed files with 62 additions and 9 deletions
17
src/matrix_bot/async_utils.py
Normal file
17
src/matrix_bot/async_utils.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
"""
|
||||
Some utilities to help with async stuff.
|
||||
"""
|
||||
|
||||
class Aobject(object):
|
||||
"""
|
||||
Inheriting this class allows you to define an async __init__.
|
||||
So you can create objects by doing something like `await MyClass(params)`
|
||||
Copied from https://newbedev.com/how-to-set-class-attribute-with-await-in-init
|
||||
"""
|
||||
async def __new__(cls, *a, **kw):
|
||||
instance = super().__new__(cls)
|
||||
await instance.__init__(*a, **kw)
|
||||
return instance
|
||||
|
||||
async def __init__(self):
|
||||
pass
|
|
@ -10,13 +10,14 @@ from typing import (
|
|||
NoReturn,
|
||||
Union
|
||||
)
|
||||
from .async_utils import Aobject
|
||||
from .utils import (
|
||||
Room,
|
||||
RoomAlias,
|
||||
RoomId
|
||||
)
|
||||
|
||||
class Client:
|
||||
class Client(Aobject):
|
||||
"""
|
||||
Connect to the matrix server and handle interactions with the
|
||||
server.
|
||||
|
@ -24,6 +25,8 @@ class Client:
|
|||
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.
|
||||
|
||||
/!\ The client is initialized asyncronously: `client = await Client(...)`
|
||||
"""
|
||||
|
||||
__client: nio.AsyncClient
|
||||
|
@ -31,7 +34,7 @@ class Client:
|
|||
__rooms_by_id: dict[RoomId, Room]
|
||||
allowed_rooms: Optional[dict[RoomId, Room]]
|
||||
|
||||
def __init__(
|
||||
async def __init__(
|
||||
self,
|
||||
username: str,
|
||||
homeserver: str,
|
||||
|
@ -47,23 +50,22 @@ class Client:
|
|||
(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
|
||||
)
|
||||
self.__rooms_by_aliases = {}
|
||||
self.__rooms_by_id = {}
|
||||
resp = loop.run_until_complete(self.__client.login(password))
|
||||
resp = await 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?
|
||||
# TODO: 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))
|
||||
room = await self.resolve_room(room_name)
|
||||
self.allowed_rooms[room.id] = room # room uniqueness is handled by self.resolve_room
|
||||
|
||||
|
||||
|
@ -107,3 +109,30 @@ class Client:
|
|||
self.__rooms_by_aliases[room_name] = room
|
||||
return room
|
||||
|
||||
async def sync(
|
||||
self,
|
||||
sync_delta:int=30
|
||||
)->NoReturn:
|
||||
"""
|
||||
Sync with the server every sync_delta seconds.
|
||||
sync_delta: the time in sec between each sync.
|
||||
"""
|
||||
while True:
|
||||
sync_resp = await self.__client.sync(sync_delta*1000)
|
||||
if isinstance(sync_resp, nio.responses.SyncError):
|
||||
print(f"Error while syncronizing: {sync_resp.message}") # TODO: use proper logging
|
||||
continue
|
||||
print(sync_resp)
|
||||
|
||||
async def run(
|
||||
self,
|
||||
sync_delta:int=30
|
||||
)->NoReturn:
|
||||
"""
|
||||
Run the bot: sync with the server and execute callbacks.
|
||||
"""
|
||||
await asyncio.gather(
|
||||
self.sync(sync_delta=sync_delta)
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -2,18 +2,25 @@
|
|||
Not really tests, because I don't know how to testt without a whole matrix server.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
from matrix_bot.client import Client
|
||||
from getpass import getpass
|
||||
|
||||
if __name__ == "__main__":
|
||||
async def main():
|
||||
load_dotenv()
|
||||
client = Client(
|
||||
client = await Client(
|
||||
os.environ["MUSER"],
|
||||
os.environ["HOMESERVER"],
|
||||
os.environ["PASSWD"],
|
||||
os.environ["ROOMS"].split(",")
|
||||
)
|
||||
print(client.allowed_rooms)
|
||||
# print(client.allowed_rooms)
|
||||
await client.run()
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
||||
|
|
Loading…
Reference in a new issue