feat: added send_message and join_room methods
This commit is contained in:
parent
c3783253e1
commit
5710a71651
2 changed files with 78 additions and 18 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
import uuid
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
@ -6,10 +7,12 @@ from typing import Callable, Awaitable
|
||||||
from aiohttp import ClientSession, web
|
from aiohttp import ClientSession, web
|
||||||
|
|
||||||
from .matrix import Event, EventType
|
from .matrix import Event, EventType
|
||||||
|
from .utils import mx_message
|
||||||
|
|
||||||
class AppService:
|
class AppService:
|
||||||
_rx: web.Application
|
_site: web.TCPSite
|
||||||
_tx: ClientSession
|
_client: ClientSession
|
||||||
|
_app: web.Application
|
||||||
_callbacks: dict[EventType, dict[str, Callable]]
|
_callbacks: dict[EventType, dict[str, Callable]]
|
||||||
|
|
||||||
as_token: str
|
as_token: str
|
||||||
|
@ -29,7 +32,8 @@ class AppService:
|
||||||
server_name: str,
|
server_name: str,
|
||||||
logger: logging.Logger | None = None,
|
logger: logging.Logger | None = None,
|
||||||
):
|
):
|
||||||
self._rx = web.Application()
|
self._app = web.Application()
|
||||||
|
self._client = ClientSession()
|
||||||
self._callbacks = {}
|
self._callbacks = {}
|
||||||
|
|
||||||
self.as_token = as_token
|
self.as_token = as_token
|
||||||
|
@ -40,7 +44,7 @@ class AppService:
|
||||||
|
|
||||||
self.logger = logger if logger is not None else logging.getLogger(__file__)
|
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))
|
web.put('/transactions/{transaction}', lambda req: self.handler(req))
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -72,27 +76,47 @@ class AppService:
|
||||||
return func
|
return func
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
async def join_room(self):
|
async def join_room(self, room: str, mxid: str | None = None):
|
||||||
pass
|
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):
|
async def leave_room(self):
|
||||||
pass
|
raise NotImplementedError
|
||||||
|
|
||||||
async def send_message(self):
|
async def send_message(self, room: str, text: str, mxid: str | None = None) -> str:
|
||||||
pass
|
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):
|
async def redact_message(self):
|
||||||
pass
|
raise NotImplementedError
|
||||||
|
|
||||||
async def start(self, host: str = "localhost", port: int = 25511):
|
async def start(self, host: str = "localhost", port: int = 25511):
|
||||||
runner = web.AppRunner(self._rx)
|
runner = web.AppRunner(self._app)
|
||||||
await runner.setup()
|
await runner.setup()
|
||||||
site = web.TCPSite(runner, host, port)
|
self._site = web.TCPSite(runner, host, port)
|
||||||
await site.start()
|
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)
|
|
||||||
|
|
36
src/aioappsrv/utils.py
Normal file
36
src/aioappsrv/utils.py
Normal file
|
@ -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,
|
||||||
|
}
|
Loading…
Reference in a new issue