From 5710a7165184822130fc7157c66aab587e825cd7 Mon Sep 17 00:00:00 2001 From: alemi Date: Mon, 29 Jan 2024 18:42:03 +0100 Subject: [PATCH] feat: added send_message and join_room methods --- src/aioappsrv/app.py | 60 +++++++++++++++++++++++++++++------------- src/aioappsrv/utils.py | 36 +++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 18 deletions(-) create mode 100644 src/aioappsrv/utils.py diff --git a/src/aioappsrv/app.py b/src/aioappsrv/app.py index 5b3060d..a90ecad 100644 --- a/src/aioappsrv/app.py +++ b/src/aioappsrv/app.py @@ -1,3 +1,4 @@ +import uuid import asyncio import logging @@ -6,10 +7,12 @@ from typing import Callable, Awaitable from aiohttp import ClientSession, web from .matrix import Event, EventType +from .utils import mx_message class AppService: - _rx: web.Application - _tx: ClientSession + _site: web.TCPSite + _client: ClientSession + _app: web.Application _callbacks: dict[EventType, dict[str, Callable]] as_token: str @@ -29,7 +32,8 @@ class AppService: server_name: str, logger: logging.Logger | None = None, ): - self._rx = web.Application() + self._app = web.Application() + self._client = ClientSession() self._callbacks = {} self.as_token = as_token @@ -40,7 +44,7 @@ class AppService: self.logger = logger if logger is not None else logging.getLogger(__file__) - self._rx.add_routes([ + self._app.add_routes([ web.put('/transactions/{transaction}', lambda req: self.handler(req)) ]) @@ -72,27 +76,47 @@ class AppService: return func return wrapper - async def join_room(self): - pass + async def join_room(self, room: str, mxid: str | None = None): + async with self._client.request( + method="POST", + url=f"/join/{room}", + headers={ + "Authorization": f"Bearer {self.as_token}", + "Content-Type": "application/json", + }, + params={"user_id": mxid} if mxid else {}, + ) as res: + doc = await res.json() + self.logger.debug("joined room %s with %s : %s", room, mxid, doc) async def leave_room(self): - pass + raise NotImplementedError - async def send_message(self): - pass + async def send_message(self, room: str, text: str, mxid: str | None = None) -> str: + async with self._client.request( + method="PUT", + url=f"/rooms/{room}/send/m.room.message/{uuid.uuid4()}", + headers={ + "Authorization": f"Bearer {self.as_token}", + "Content-Type": "application/json", + }, + params={"user_id": mxid} if mxid else {}, + json=mx_message(text), + ) as res: + doc = await res.json() + self.logger.debug("sent message %s to %s as %s : %s", text, room, mxid, doc) + return doc["event_id"] async def redact_message(self): - pass + raise NotImplementedError async def start(self, host: str = "localhost", port: int = 25511): - runner = web.AppRunner(self._rx) + runner = web.AppRunner(self._app) await runner.setup() - site = web.TCPSite(runner, host, port) - await site.start() + self._site = web.TCPSite(runner, host, port) + await self._site.start() + async def stop(self): + await self._site.stop() + await self._tx.close() - -# utility function in case we need to block forever -async def idle(): - while True: - await asyncio.sleep(3600) diff --git a/src/aioappsrv/utils.py b/src/aioappsrv/utils.py new file mode 100644 index 0000000..f8d0cbd --- /dev/null +++ b/src/aioappsrv/utils.py @@ -0,0 +1,36 @@ +import asyncio +from io import StringIO +from html.parser import HTMLParser + +# thanks [stackoverflow](https://stackoverflow.com/questions/753052/strip-html-from-strings-in-python) +class MLStripper(HTMLParser): + def __init__(self): + super().__init__() + self.reset() + self.strict = False + self.convert_charrefs= True + self.text = StringIO() + def handle_data(self, d): + self.text.write(d) + def get_data(self): + return self.text.getvalue() + +# remove all html tags from given string +def strip_html(html: str) -> str: + s = MLStripper() + s.feed(html) + return s.get_data() + +# utility function in case we need to block forever +async def idle(): + while True: + await asyncio.sleep(3600) + +# wraps a HTML formatted message into its struct, stripping html +def mx_message(text: str) -> dict: + return { + "body": strip_html(text), + "msgtype": "m.text", + "format": "org.matrix.custom.html", + "formatted_body": text, + }