Newer
Older
from aiohttp import web
import json
import os
import urllib.parse
from webargs import fields
from webargs.aiohttpparser import parser
from . import db
from . import serializers
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
STATIC_DIR = os.path.join(BASE_DIR, "static")
domain_filters = {
"up": fields.Bool(),
"open_registrations": fields.Bool(),
"anonymous_can_listen": fields.Bool(),
"federation_enabled": fields.Bool(),
}
def validate_domain(raw):
if not raw:
raise ValueError()
if not isinstance(raw, str):
raise ValueError()
url = f"http://{raw}/"
v = urllib.parse.urlparse(url).hostname
raise ValueError()
return v
async def index(request):
with open(os.path.join(BASE_DIR, "index.html"), "r") as f:
index_html = f.read()
return web.Response(
text=index_html.format(settings=settings), content_type="text/html"
)
async def domains(request):
if request.method == "GET":
filters = await parser.parse(domain_filters, request)
rows = await db.get_domains(request["conn"], private=False, **filters)
payload = {
"count": len(rows),
"previous": None,
"next": None,
"results": [
serializers.serialize_domain_from_check(check) for check in rows
],
}
return web.json_response(payload)
if request.method == "POST":
try:
payload = await request.json()
except json.decoder.JSONDecodeError:
payload = await request.post()
try:
payload = {"name": validate_domain(payload["name"])}
except (TypeError, KeyError, AttributeError, ValueError):
return web.json_response(
{"error": f"Invalid payload {payload}"}, status=400
)
try:
kwargs = crawler.get_session_kwargs()
async with aiohttp.ClientSession(**kwargs) as session:
await crawler.fetch_nodeinfo(session, payload["name"])
except (aiohttp.client_exceptions.ClientError, exceptions.CrawlerError) as e:
return web.json_response(
{"error": f"Invalid domain name {payload['name']}"}, status=400
)
domain = await serializers.create_domain(request["conn"], payload)
await request.app["crawler"].poll(payload["name"])
if domain:
payload = serializers.serialize_domain(domain)
return web.json_response(payload, status=201)
else:
# already exist
return web.json_response({}, status=204)
async def stats(request):
payload = await db.get_stats(request["conn"])
return web.json_response(payload)