http.server → aiohttp.web

This commit is contained in:
Guilhem Saurel 2020-02-14 19:18:51 +01:00
parent 1b31e7bba9
commit a6fad80ca7
2 changed files with 44 additions and 37 deletions

View file

@ -3,7 +3,8 @@ FROM python:3.7-alpine
EXPOSE 4785
RUN pip3 install --no-cache-dir \
matrix-client
aiohttp \
matrix-nio
ADD matrix_webhook.py /

View file

@ -4,10 +4,11 @@ Matrix Webhook
Post a message to a matrix room with a simple HTTP POST
"""
import asyncio
import json
import os
from http.server import BaseHTTPRequestHandler, HTTPServer
from aiohttp import web
from matrix_client.client import MatrixClient
SERVER_ADDRESS = ('', int(os.environ.get('PORT', 4785)))
@ -16,47 +17,52 @@ MATRIX_ID = os.environ.get('MATRIX_ID', 'wwm')
MATRIX_PW = os.environ['MATRIX_PW']
API_KEY = os.environ['API_KEY']
client = MatrixClient(MATRIX_URL)
client.login(username=MATRIX_ID, password=MATRIX_PW)
rooms = client.get_rooms()
class MatrixWebhookServer(HTTPServer):
async def handler(request):
"""
an HTTPServer that embeds a matrix client
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.client = MatrixClient(MATRIX_URL)
self.client.login(username=MATRIX_ID, password=MATRIX_PW)
self.rooms = self.client.get_rooms()
class MatrixWebhookHandler(BaseHTTPRequestHandler):
"""
Class given to the server, st. it knows what to do with an HTTP request.
Coroutine given to the server, st. it knows what to do with an HTTP request.
This one handles a POST, checks its content, and forwards it to the matrix room.
"""
data = json.loads(request.read().decode())
status, ret = 400, 'I need a json dict with text & key'
if all(key in data for key in ['text', 'key']):
status, ret = 401, 'I need the good "key"'
if data['key'] == API_KEY:
status, ret = 404, 'I need the id of the room as a path, and to be in this room'
if request.rel_url[1:] not in rooms:
# try to see if this room has been joined recently
rooms = client.get_rooms()
if request.rel_url[1:] in rooms:
status, ret = 200, json.dumps(rooms[request.rel_url[1:]].send_text(data['text']))
def do_POST(self):
"""
get a json dict from the request, send a message to a matrix room
"""
length = int(self.headers.get('Content-Length'))
data = json.loads(self.rfile.read(length).decode())
status, ret = 400, 'I need a json dict with text & key'
if all(key in data for key in ['text', 'key']):
status, ret = 401, 'I need the good "key"'
if data['key'] == API_KEY:
status, ret = 404, 'I need the id of the room as a path, and to be in this room'
if self.path[1:] not in self.server.rooms:
# try to see if this room has been joined recently
self.server.rooms = self.server.client.get_rooms()
if self.path[1:] in self.server.rooms:
status, ret = 200, json.dumps(self.server.rooms[self.path[1:]].send_text(data['text']))
return web.Response(text='{"status": %i, "ret": "%a"}' % (status, ret),
content_type='application/json',
status=status)
self.send_response(status)
self.send_header('Content-Type', 'application/json')
self.end_headers()
self.wfile.write(b'{"status": %i, "ret": "%a"}' % (status, ret))
async def main():
server = web.Server(handler)
runner = web.ServerRunner(server)
await runner.setup()
site = web.TCPSite(runner, *SERVER_ADDRESS)
await site.start()
print("======= Serving ======")
# pause here for very long time by serving HTTP requests and
# waiting for keyboard interruption
await asyncio.sleep(100 * 3600)
if __name__ == '__main__':
MatrixWebhookServer(SERVER_ADDRESS, MatrixWebhookHandler).serve_forever()
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(main())
except KeyboardInterrupt:
pass
loop.close()