add a wrapper for message callbacks

This commit is contained in:
histausse 2021-10-05 19:05:21 +02:00
parent 66cbd31f82
commit 139b9e138b
Signed by: histausse
GPG key ID: 67486F107F62E9E9
4 changed files with 52 additions and 10 deletions

View file

@ -3,3 +3,9 @@
A package implementing a reusable class to make matrix bots
This is inventing the wheel once again, but who care? It's fun :)
## TODO:
- Use more of nio features and less custom hacks (like, use callback for the
invite policy stuff, and nio.Room is way better than my custom type)

View file

@ -1,3 +1,4 @@
from __future__ import annotations
"""
The Client class.
Connect to the matrix server and handle interactions with the server.
@ -9,6 +10,8 @@ import nio
from aiopath import AsyncPath
from typing import (
Any,
Awaitable,
Callable,
Optional,
NoReturn,
Union
@ -32,6 +35,8 @@ class Client(Aobject):
Connect to the matrix server and handle interactions with the
server.
user: the user id of the client (exp: @bot:matrix.org)
/!\ The client is initialized asyncronously: `client = await Client(...)`
"""
@ -43,6 +48,7 @@ class Client(Aobject):
__sync_token_queue: asyncio.Queue[str]
__invite_queue: asyncio.Queue[tuple[RoomId, nio.responses.InviteInfo]]
__invite_policy: InvitePolicy
user: str
async def __init__(
self,
@ -81,6 +87,7 @@ class Client(Aobject):
if isinstance(resp, nio.responses.LoginError):
raise RuntimeError(f"Fail to connect: {resp.message}")
log.info("logged in")
self.user_id = self.__client.user_id
async def resolve_room(
self,
@ -283,6 +290,18 @@ class Client(Aobject):
for room_id in invites:
await self.__invite_queue.put((room_id, invites[room_id]))
def add_message_callback(
self,
callback: Callable[[Client, nio.rooms.Room, nio.events.room_events.RoomMessageText], Awaitable[None]]
):
"""
Add a callback called when a message is received.
The callback is an async function that take the client, the room and the event message in arg.
"""
async def new_callback(room: nio.rooms.Room, msg: nio.events.room_events.RoomMessageText):
await callback(self, room, msg)
self.__client.add_event_callback(new_callback, nio.RoomMessageText)
async def run(
self,
sync_timeout:int=30

View file

@ -1,11 +1,15 @@
from __future__ import annotations
"""
Utilities for the bot.
"""
from typing import TYPE_CHECKING
from dataclasses import (
dataclass,
field
)
if TYPE_CHECKING:
from .client import Client
RoomAlias = str
RoomId = str
@ -17,3 +21,18 @@ class Room:
id: RoomId
aliases: set[RoomAlias] = field(default_factory=set)
def ignore_client_message(
callback: Callable[[Client, nio.rooms.Room, nio.events.room_events.RoomMessageText], Awaitable[None]]
)->Callable[[Client, nio.rooms.Room, nio.events.room_events.RoomMessageText], Awaitable[None]]:
"""
Decorator for message callback.
The decorated callback will ignore message sent by the client.
"""
async def new_callback(
client: Client,
room: nio.rooms.Room,
message: nio.events.room_events.RoomMessageText
):
if client.user_id != message.sender:
await callback(client, room, message)
return new_callback

View file

@ -1,5 +1,5 @@
"""
Not really tests, because I don't know how to testt without a whole matrix server.
Not really tests, because I don't know how to test without a whole matrix server.
"""
import asyncio
@ -12,10 +12,15 @@ from matrix_bot.invite_policy import (
DeclineAll,
WhiteList
)
from matrix_bot.utils import ignore_client_message
from getpass import getpass
logging.basicConfig(format="%(levelname)s: %(message)s", level=logging.DEBUG)
@ignore_client_message
async def callback(client, room, event):
await client.send_message(room.room_id, "Hello!")
async def main():
load_dotenv()
client = await Client(
@ -23,25 +28,18 @@ async def main():
os.environ["HOMESERVER"],
os.environ["PASSWD"],
)
client.add_message_callback(callback)
withelisted_room_names = os.environ["ROOMS"].split(",")
whitelist_policy = await WhiteList(client, withelisted_room_names)
room_name = withelisted_room_names[0]
client.set_invite_policy(whitelist_policy)
await client.send_message(room_name, "Beware of Greeks bearing gifts")
await asyncio.sleep(5)
await asyncio.sleep(1)
await client.send_formated_message(
room_name,
"<b><font color='red'>Beware of Greeks bearing gifts</font></b>",
"Beware of Greeks bearing gifts"
)
await asyncio.sleep(5)
await client.send_firework_message(room_name, "fire")
await asyncio.sleep(5)
await client.send_confetti_message(room_name, "confetti")
await asyncio.sleep(5)
await client.send_snow_message(room_name, "snow")
await asyncio.sleep(5)
await client.send_space_invader_message(room_name, "space")
await client.run()