oebb_py/main.py
2019-04-16 18:04:19 +00:00

234 lines
7.4 KiB
Python

import cgi
import datetime
import pytz
import html
import workers.conn
import workers.val
import workers.closest
import workers.radar
import workers.deparr
from classes.request import *
from classes.response import *
HTTP200 = "200 OK"
HTTP400 = "400 Bad Request"
HTTP405 = "405 Method Not Allowed"
HTTP500 = "500 Internal Server Error"
HTML = "text/html; charset=UTF-8"
JSON = "application/json; charset=UTF-8"
XML = "text/xml; charset=UTF-8"
DOCSTR = ' Check out the <a href="https://kumig.it/kumitterer/oebb_py#request">documentation</a> for usage instructions.'
def doConn(req):
try:
getfrm = req.cfrm if "cfrm" in dir(req) and req.cfrm else req.args["from"][0] if "from" in req.args else None
getto = req.cto if "cto" in dir(req) and req.cto else req.args["to"][0] if "to" in req.args else None
try:
frm = html.unescape(getfrm.encode("latin-1").decode("utf-8"))
to = html.unescape(getto.encode("latin-1").decode("utf-8"))
except UnicodeDecodeError:
frm = html.unescape(getfrm)
to = html.unescape(getto)
if not frm or not to:
raise ValueError()
except Exception:
content = "<h1>400 Bad Request</h1>\n"
content += "\"from\"and \"to\" values are required for this type of request."
return Response(HTTP400, HTML, content)
count = req.args["count"][0] if "count" in req.args and req.args["count"] else 6
date = req.args["date"][0] if "date" in req.args and req.args["date"] else datetime.datetime.strftime(datetime.datetime.now(pytz.timezone("Europe/Vienna")),"%d.%m.%Y")
time = req.args["time"][0] if "time" in req.args and req.args["time"] else datetime.datetime.strftime(datetime.datetime.now(pytz.timezone("Europe/Vienna")),"%H:%M")
mode = True if "mode" in req.args and req.args["mode"] and req.args["mode"][0].lower() == "arr" else False
details = True if "details" in req.args else False
try:
count = int(count)
if count < 0 or count > 10:
raise ValueError()
except:
content = "<h1>400 Bad Request</h1>\n"
content += "The \"count\" value must be a value between 0 and 10."
return Response(HTTP400, HTML, content)
try:
outtime = datetime.datetime.strptime("%s %s" % (date, time), "%d.%m.%Y %H:%M")
except:
content = "<h1>400 Bad Request</h1>\n"
content += "The \"date\" value must be in DD.MM.YYYY format, the \"time\" value must be in HH:MM format."
return Response(HTTP400, HTML, content)
via = list(req.args["via"]) if "via" in req.args else None
if via and len(via) > 3:
content = "<h1>400 Bad Request</h1>\n"
content += "It is not possible to route through more than three \"via\" stations."
return Response(HTTP400, HTML, content)
try:
content = workers.conn.worker(frm, to, count, outtime, mode, details, req.json, via)
except Exception as e:
content = "<h1>500 Internal Server Error</h1>\n"
if "debug" in req.args:
content += str(e)
return Response(HTTP500, HTML, content)
return Response(HTTP200, JSON if req.json else XML, content)
def doVal(req):
try:
try:
name = (req.cfrm or req.args["name"][0]).encode("latin-1").decode("utf-8")
except UnicodeDecodeError:
name = req.cfrm or req.args["name"][0]
if not name:
raise ValueError()
except Exception:
content = "<h1>400 Bad Request</h1>\n"
content += "A \"name\" value is required for this type of request."
return Response(HTTP400, HTML, content)
try:
content = workers.val.worker(name, req.json)
except Exception as e:
content = "<h1>500 Internal Server Error</h1>\n"
if "debug" in req.args:
content += str(e).encode()
return Response(HTTP500, HTML, content)
return Response(HTTP200, JSON if req.json else XML, content)
def doNearby(req):
try:
lat = float(req.args["lat"][0].replace(",", "."))
lon = float(req.args["lon"][0].replace(",", "."))
if (not lat and not lat == float(0)) or (not lon and not lon == float(0)):
raise ValueError()
except:
content = "<h1>400 Bad Request</h1>\n"
content += "\"lat\" and \"lon\" values are required for this type of request."
return Response(HTTP400, HTML, content)
distance = req.args["distance"][0] if "distance" in req.args and req.args["distance"] else 1000
try:
distance = int(distance)
if distance < 0 or distance > 10000:
raise ValueError()
except:
content = "<h1>400 Bad Request</h1>\n"
content += "\"distance\" must be a value between 0 and 10000."
return Response(HTTP400, HTML, content)
try:
content = workers.closest.worker(lat, lon, distance, req.json)
except Exception as e:
content = "<h1>500 Internal Server Error</h1>"
if "debug" in req.args:
content += repr(e)
return Response(HTTP500, HTML, content)
return Response(HTTP200, JSON if req.json else XML, content)
def doRadar(req):
trains = req.args["train"] if "train" in req.args else None
try:
content = workers.radar.worker(trains, req.json)
except Exception as e:
content = "<h1>500 Internal Server Error</h1>\n"
if "debug" in req.args:
content += repr(e)
return Response(HTTP500, HTML, content)
return Response(HTTP200, JSON if req.json else XML, content)
def doDepArr(req):
try:
name = req.args["name"][0]
try:
name = name.encode("latin-1").decode("utf-8")
except UnicodeDecodeError:
pass
except Exception:
content = "<h1>400 Bad Request</h1>\n"
content += "A \"name\" value is required for this type of request."
return Response(HTTP400, HTML, content)
count = req.args["count"][0] if "count" in req.args and req.args["count"] else 30
date = req.args["date"][0] if "date" in req.args and req.args["date"] else datetime.datetime.strftime(datetime.datetime.now(pytz.timezone("Europe/Vienna")),"%d.%m.%Y")
time = req.args["time"][0] if "time" in req.args and req.args["time"] else datetime.datetime.strftime(datetime.datetime.now(pytz.timezone("Europe/Vienna")),"%H:%M")
mode = True if req.rtype[:3] == "arr" else False
details = True
try:
count = int(count)
except:
content = "<h1>400 Bad Request</h1>\n"
content += "The \"count\" value must be a numeric value."
return Response(HTTP400, HTML, content)
try:
outtime = datetime.datetime.strptime("%s %s" % (date, time), "%d.%m.%Y %H:%M")
except:
content = "<h1>400 Bad Request</h1>\n"
content += "The \"date\" value must be in DD.MM.YYYY format, the \"time\" value must be in HH:MM format."
return Response(HTTP400, HTML, content)
try:
content = workers.deparr.worker(name, count, outtime, mode, details, req.json)
except Exception as e:
content = "<h1>500 Internal Server Error</h1>\n"
if "debug" in req.args:
content += str(e)
return Response(HTTP500, HTML, content)
return Response(HTTP200, JSON if req.json else XML, content)
def doNot(req):
content = "<h1>400 Bad Request</h1>"
content += "The request type you submitted is invalid."
return Response(HTTP400, HTML, content)
def application(env, re):
try:
req = Request(env)
if req.rtype in ["conn", "connection", "connections"]:
res = doConn(req)
elif req.rtype in ["val", "validate"]:
res = doVal(req)
elif req.rtype in ["closest", "close", "near", "nearby"]:
res = doNearby(req)
elif req.rtype in ["radar", "live", "trains"]:
res = doRadar(req)
elif req.rtype in ["dep", "arr", "departure", "arrival", "departures", "arrivals"]:
res = doDepArr(req)
else:
res = doNot(req)
except IllegalMethodException as e:
res = Response(HTTP405, HTML, str(e) + DOCSTR)
except InvalidArgumentException as e:
res = Response(HTTP400, HTML, str(e) + DOCSTR)
re(res.status, [("Content-Type", res.ctype)])
yield res.content.encode()
return