iwm_browser/iwm_browser/main.py
2022-10-30 17:18:37 +01:00

181 lines
5.8 KiB
Python

from typing import Union
from fastapi.staticfiles import StaticFiles
from fastapi.responses import HTMLResponse
from fastapi import FastAPI, Form
import jinja2
import uvicorn
import httpx
import json
import os
import re
from . import utils
basedir = os.path.dirname(__file__)
app = FastAPI()
app.mount("/static", StaticFiles(directory=basedir + "/static"), name="static")
template_env = jinja2.Environment(
loader=jinja2.PackageLoader("iwm_browser", "templates"),
auto_reload=True
)
template_env.globals['convert_times'] = utils.convert_times
BASE_URL = "http://make.fangam.es"
THUMB_URL = "https://images.make.fangam.es"
# Matches level code.
# \S[A-Z0-9]{4}\-[A-Z0-9]{4} = With dash, no whitespace
# \S[A-Z0-9]{8} = without dash, no whitespace
level_code_regex = re.compile("[A-Z0-9]{4}\-[A-Z0-9]{4}|[A-Z0-9]{8}")
error_template = template_env.get_template("error.html")
@app.get("/", response_class=HTMLResponse)
async def root():
template = template_env.get_template("home.html")
return template.render()
@app.get("/search", response_class=HTMLResponse)
async def search(
q: Union[str, None] = None,
p: int = 0,
sort: str = "average_Rating",
dir: str = "desc",
date: int = -1
):
template = template_env.get_template("search.html")
limit = 10
if p is None:
p = 0
searchResults = None
if q is not None:
if level_code_regex.match(q):
levelCode = q.upper().replace("-", "")
searchValue = q
entryNumber = -1
try:
rq = httpx.get(BASE_URL + "/api/v1/map", params={
"code": levelCode,
}, timeout=10)
searchResults = rq.json()
print(rq.url, p * limit)
except httpx.ReadTimeout:
return "Server timed out"
else:
author = {}
min_diff = 0.00
max_diff = 5.00
params = re.findall("[a-z\-\_]*:[a-zA-Z0-9._\-]*", q)
search = re.sub("\S[a-z\-\_]*:[a-zA-Z0-9._\-]*", "", q).lstrip().rstrip()
for i in params:
split = i.split(':')
if split[0] == "author":
author = {"author": split[1]}
elif split[0] == "min_diff":
min_diff = float(split[1])
elif split[0] == "max_diff":
max_diff = float(split[1])
order = {"Dir": dir, "Name": sort}
if date == -1:
last_x_hours = {}
else:
last_x_hours = {"last_x_hours": date}
searchValue = q
try:
rq = httpx.get(BASE_URL + "/api/v1/map", params={
"start": p * limit,
"limit": limit,
"min_diff": min_diff,
"max_diff": max_diff,
"order": json.dumps([order]),
"name": search,
**last_x_hours, **author
}, timeout=10)
if rq.status_code == 503:
return error_template.render(reason="Server is unavailable right now.")
searchResults = rq.json()
print(rq.url, p * limit)
except httpx.ReadTimeout:
return error_template.render(reason="Server timed out")
except json.decoder.JSONDecodeError:
return error_template.render(reason="Failed to parse server response.", details=rq.text)
except Exception as exc:
return error_template.render(reason="Uncaught exception", details=exc)
entryNumber=len(searchResults)
else:
searchValue = ''
entryNumber = None
return template.render(
searchValue=searchValue,
searchPage=p,
searchResults=searchResults,
THUMB_URL=THUMB_URL,
entryLimit=limit,
entryNumber=entryNumber
)
@app.get("/level/{level_id}", response_class=HTMLResponse)
async def showLevel(level_id: int):
template = template_env.get_template("levelInfo.html")
try:
rq = httpx.get(BASE_URL + "/api/v1/map/" + str(level_id), timeout=10)
if rq.status_code == 503:
return error_template.render(reason="Server is unavailable right now")
searchResults = rq.json()
print(rq.url)
except httpx.ReadTimeout:
return error_template.render(reason="Server timed out")
except json.decoder.JSONDecodeError:
return error_template.render(reason="Failed to parse server response.", details=rq.text)
except Exception as exc:
return error_template.render(reason="Uncaught exception", details=exc)
return template.render(
map=searchResults,
THUMB_URL=THUMB_URL,
)
@app.get("/user/{user_id}", response_class=HTMLResponse)
async def showUser(user_id: int):
template = template_env.get_template("userInfo.html")
try:
rq = httpx.get(BASE_URL + "/api/v1/user/" + str(user_id), timeout=10)
if rq.status_code == 503:
return error_template.render(reason="Server is unavailable right now")
searchResults = rq.json()
print(rq.url)
except httpx.ReadTimeout:
return error_template.render(reason="Server timed out")
except json.decoder.JSONDecodeError:
return error_template.render(reason="Failed to parse server response.", details=rq.text)
except Exception as exc:
print(exc)
return error_template.render(reason="Uncaught exception", details=exc)
return template.render(
user=searchResults,
THUMB_URL=THUMB_URL,
)
def start():
"""Launched with `poetry run start` at root level"""
uvicorn.run("iwm_browser.main:app", host="0.0.0.0", port=7775, reload=True)