#!/usr/bin/python3 import os from dataclasses import dataclass from datetime import UTC, datetime from decimal import Decimal import flask import lxml.html import pytz app = flask.Flask(__name__) app.debug = True data_loc = os.path.expanduser("~/lib/data/eurotunnel") def get_filename(direction: str) -> tuple[datetime, str]: """Most recent list of outbound prices.""" end = f"_{direction}.html" most_recent = max([f for f in os.listdir(data_loc) if f.endswith(end)]) filename = os.path.join(data_loc, most_recent) timestamp = most_recent.removesuffix(end) dt_utc = datetime.strptime(timestamp, "%Y-%m-%d_%H%M%S").replace(tzinfo=UTC) dt = dt_utc.astimezone(pytz.timezone("Europe/London")) return (dt, filename) @dataclass class Train: """Eurostar train.""" dep: str arr: str price: Decimal | None = None def get_tickets(filename: str) -> list[Train]: """Get trains and prices.""" tree = lxml.html.parse(filename) root = tree.getroot() trains = [] by_time = {} for mission in root.findall(".//div[@data-mission]"): dep_text = mission.findtext(".//b") assert dep_text dep = dep_text.replace(":", "") arr_text = mission.findtext(".//small") assert arr_text arr = arr_text.removeprefix("Arrive ").replace(":", "") item = Train(dep=dep, arr=arr) trains.append(item) by_time[dep] = item for ticket in root.xpath("//div[contains(@class, 'ticket')]"): classes = ticket.get("class").split(" ") if "ticket" not in classes: continue ticket_class = classes[-1] if ticket_class != "standard": continue mission_time = ticket.getparent().getparent().get("data-mission-time") onclick = ticket.get("onclick").split(",") price = Decimal(onclick[2][1:-1]) by_time[mission_time].price = price return trains @app.route("/") def index() -> str: """Index.""" out_ts, out_filename = get_filename("outbound") out = get_tickets(out_filename) out = [t for t in out if t.dep > "0800" and "0700" < t.arr < "2200"] back_ts, back_filename = get_filename("return") back = get_tickets(back_filename) back = [t for t in back if t.dep > "1100" and "0700" < t.arr < "2200"] return flask.render_template( "index.html", out_ts=out_ts, out=out, back_ts=back_ts, back=back, ) if __name__ == "__main__": app.run(host="0.0.0.0")