add a wrapper for message callbacks
This commit is contained in:
parent
66cbd31f82
commit
139b9e138b
4 changed files with 52 additions and 10 deletions
|
@ -3,3 +3,9 @@
|
||||||
A package implementing a reusable class to make matrix bots
|
A package implementing a reusable class to make matrix bots
|
||||||
|
|
||||||
This is inventing the wheel once again, but who care? It's fun :)
|
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)
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from __future__ import annotations
|
||||||
"""
|
"""
|
||||||
The Client class.
|
The Client class.
|
||||||
Connect to the matrix server and handle interactions with the server.
|
Connect to the matrix server and handle interactions with the server.
|
||||||
|
@ -9,6 +10,8 @@ import nio
|
||||||
from aiopath import AsyncPath
|
from aiopath import AsyncPath
|
||||||
from typing import (
|
from typing import (
|
||||||
Any,
|
Any,
|
||||||
|
Awaitable,
|
||||||
|
Callable,
|
||||||
Optional,
|
Optional,
|
||||||
NoReturn,
|
NoReturn,
|
||||||
Union
|
Union
|
||||||
|
@ -32,6 +35,8 @@ class Client(Aobject):
|
||||||
Connect to the matrix server and handle interactions with the
|
Connect to the matrix server and handle interactions with the
|
||||||
server.
|
server.
|
||||||
|
|
||||||
|
user: the user id of the client (exp: @bot:matrix.org)
|
||||||
|
|
||||||
/!\ The client is initialized asyncronously: `client = await Client(...)`
|
/!\ The client is initialized asyncronously: `client = await Client(...)`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -43,6 +48,7 @@ class Client(Aobject):
|
||||||
__sync_token_queue: asyncio.Queue[str]
|
__sync_token_queue: asyncio.Queue[str]
|
||||||
__invite_queue: asyncio.Queue[tuple[RoomId, nio.responses.InviteInfo]]
|
__invite_queue: asyncio.Queue[tuple[RoomId, nio.responses.InviteInfo]]
|
||||||
__invite_policy: InvitePolicy
|
__invite_policy: InvitePolicy
|
||||||
|
user: str
|
||||||
|
|
||||||
async def __init__(
|
async def __init__(
|
||||||
self,
|
self,
|
||||||
|
@ -81,6 +87,7 @@ class Client(Aobject):
|
||||||
if isinstance(resp, nio.responses.LoginError):
|
if isinstance(resp, nio.responses.LoginError):
|
||||||
raise RuntimeError(f"Fail to connect: {resp.message}")
|
raise RuntimeError(f"Fail to connect: {resp.message}")
|
||||||
log.info("logged in")
|
log.info("logged in")
|
||||||
|
self.user_id = self.__client.user_id
|
||||||
|
|
||||||
async def resolve_room(
|
async def resolve_room(
|
||||||
self,
|
self,
|
||||||
|
@ -283,6 +290,18 @@ class Client(Aobject):
|
||||||
for room_id in invites:
|
for room_id in invites:
|
||||||
await self.__invite_queue.put((room_id, invites[room_id]))
|
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(
|
async def run(
|
||||||
self,
|
self,
|
||||||
sync_timeout:int=30
|
sync_timeout:int=30
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
|
from __future__ import annotations
|
||||||
"""
|
"""
|
||||||
Utilities for the bot.
|
Utilities for the bot.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
from dataclasses import (
|
from dataclasses import (
|
||||||
dataclass,
|
dataclass,
|
||||||
field
|
field
|
||||||
)
|
)
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from .client import Client
|
||||||
|
|
||||||
RoomAlias = str
|
RoomAlias = str
|
||||||
RoomId = str
|
RoomId = str
|
||||||
|
@ -17,3 +21,18 @@ class Room:
|
||||||
id: RoomId
|
id: RoomId
|
||||||
aliases: set[RoomAlias] = field(default_factory=set)
|
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
|
||||||
|
|
|
@ -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
|
import asyncio
|
||||||
|
@ -12,10 +12,15 @@ from matrix_bot.invite_policy import (
|
||||||
DeclineAll,
|
DeclineAll,
|
||||||
WhiteList
|
WhiteList
|
||||||
)
|
)
|
||||||
|
from matrix_bot.utils import ignore_client_message
|
||||||
from getpass import getpass
|
from getpass import getpass
|
||||||
|
|
||||||
logging.basicConfig(format="%(levelname)s: %(message)s", level=logging.DEBUG)
|
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():
|
async def main():
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
client = await Client(
|
client = await Client(
|
||||||
|
@ -23,25 +28,18 @@ async def main():
|
||||||
os.environ["HOMESERVER"],
|
os.environ["HOMESERVER"],
|
||||||
os.environ["PASSWD"],
|
os.environ["PASSWD"],
|
||||||
)
|
)
|
||||||
|
client.add_message_callback(callback)
|
||||||
withelisted_room_names = os.environ["ROOMS"].split(",")
|
withelisted_room_names = os.environ["ROOMS"].split(",")
|
||||||
whitelist_policy = await WhiteList(client, withelisted_room_names)
|
whitelist_policy = await WhiteList(client, withelisted_room_names)
|
||||||
room_name = withelisted_room_names[0]
|
room_name = withelisted_room_names[0]
|
||||||
client.set_invite_policy(whitelist_policy)
|
client.set_invite_policy(whitelist_policy)
|
||||||
await client.send_message(room_name, "Beware of Greeks bearing gifts")
|
await client.send_message(room_name, "Beware of Greeks bearing gifts")
|
||||||
await asyncio.sleep(5)
|
await asyncio.sleep(1)
|
||||||
await client.send_formated_message(
|
await client.send_formated_message(
|
||||||
room_name,
|
room_name,
|
||||||
"<b><font color='red'>Beware of Greeks bearing gifts</font></b>",
|
"<b><font color='red'>Beware of Greeks bearing gifts</font></b>",
|
||||||
"Beware of Greeks bearing gifts"
|
"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()
|
await client.run()
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue