import cgi import datetime import pytz import html import traceback 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 documentation 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 = "

400 Bad Request

\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 = "

400 Bad Request

\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 = "

400 Bad Request

\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 = "

400 Bad Request

\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 = "

500 Internal Server Error

\n" if "debug" in req.args: content += traceback.format_exc().replace("\n", "
") 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 = "

400 Bad Request

\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 = "

500 Internal Server Error

\n" if "debug" in req.args: content += traceback.format_exc().replace("\n", "
") 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 = "

400 Bad Request

\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 = "

400 Bad Request

\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 = "

500 Internal Server Error

" if "debug" in req.args: content += traceback.format_exc().replace("\n", "
") 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 = "

500 Internal Server Error

\n" if "debug" in req.args: content += traceback.format_exc().replace("\n", "
") 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 = "

400 Bad Request

\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 = "

400 Bad Request

\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 = "

400 Bad Request

\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 = "

500 Internal Server Error

\n" if "debug" in req.args: content += traceback.format_exc().replace("\n", "
") return Response(HTTP500, HTML, content) return Response(HTTP200, JSON if req.json else XML, content) def doNot(req): content = "

400 Bad Request

" 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