#!/usr/bin/env python3 import pickle import atexit import datetime from flask import Flask, Blueprint, jsonify, request, abort from flask_cors import CORS DB_FILE = "vacation.db" last_update = datetime.datetime.now() since_backup = 0 try: with open(DB_FILE, "rb") as infile: db = pickle.load(infile) except FileNotFoundError: db = {} @atexit.register def save_db(prefix=""): with open(prefix + DB_FILE, "wb") as outfile: pickle.dump(db, outfile) def backup_db(): save_db(f"backup-{datetime.datetime.now().isoformat()}-") bp = Blueprint("vacation", __name__) @bp.route("/") def health(): return jsonify({"status": "healthy"}) @bp.route("/availability", methods=["GET", "POST"]) def status(): global last_update, since_backup if request.method == "POST": body = request.get_json() if body is None: abort(400) name = body.get("name", None) availability = body.get("availability", None) if not isinstance(name, str) or not isinstance(availability, list): abort(400) transaction = [] for a in availability: month = a.get("month", None) day = a.get("day", None) status = a.get("status", None) if (month, day) not in db or status not in ("yes", "no", "maybe", "unknown"): abort(400) transaction.append((month, day, status)) last_update = datetime.datetime.now() for (month, day, status) in transaction: db[(month, day)][name] = status since_backup += 1 if since_backup > 50: backup_db() return jsonify({ "lastUpdated": last_update.isoformat(), "availability": [ { "month": month, "day": day, "availability": [{ "name": name, "status": status, } for (name, status) in avail.items()], } for (month, day), avail in db.items() ], }) app = Flask(__name__) CORS(app) app.register_blueprint(bp, url_prefix="/vacation-planner/api") app.url_map.strict_slashes = False if __name__ == "__main__": app.run("0.0.0.0", 5000, debug=False, threaded=True)