app.py 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. #!/usr/bin/env python3
  2. import pickle
  3. import atexit
  4. import datetime
  5. from flask import Flask, Blueprint, jsonify, request, abort
  6. from flask_cors import CORS
  7. DB_FILE = "vacation.db"
  8. last_update = datetime.datetime.now()
  9. try:
  10. with open(DB_FILE, "rb") as infile:
  11. db = pickle.load(infile)
  12. except FileNotFoundError:
  13. db = {}
  14. @atexit.register
  15. def save_db(prefix=""):
  16. with open(prefix + DB_FILE, "wb") as outfile:
  17. pickle.dump(db, outfile)
  18. def backup_db():
  19. save_db(f"backup-{datetime.datetime.now().isoformat()}-")
  20. bp = Blueprint("vacation", __name__)
  21. @bp.route("/")
  22. def health():
  23. return jsonify({"status": "healthy"})
  24. @bp.route("/availability", methods=["GET", "POST"])
  25. def status():
  26. global last_update
  27. if request.method == "POST":
  28. body = request.get_json()
  29. if body is None:
  30. abort(400)
  31. name = body.get("name", None)
  32. availability = body.get("availability", None)
  33. if not isinstance(name, str) or not isinstance(availability, list):
  34. abort(400)
  35. transaction = []
  36. for a in availability:
  37. month = a.get("month", None)
  38. day = a.get("day", None)
  39. status = a.get("status", None)
  40. if (month, day) not in db or status not in ("yes", "no", "maybe", "unknown"):
  41. abort(400)
  42. transaction.append((month, day, status))
  43. last_update = datetime.datetime.now()
  44. for (month, day, status) in transaction:
  45. db[(month, day)][name] = status
  46. return jsonify({
  47. "lastUpdated": last_update.isoformat(),
  48. "availability": [
  49. {
  50. "month": month,
  51. "day": day,
  52. "availability": [{
  53. "name": name,
  54. "status": status,
  55. } for (name, status) in avail.items()],
  56. } for (month, day), avail in db.items()
  57. ],
  58. })
  59. app = Flask(__name__)
  60. CORS(app)
  61. app.register_blueprint(bp, url_prefix="/vacation-planner/api")
  62. app.url_map.strict_slashes = False
  63. if __name__ == "__main__":
  64. app.run("0.0.0.0", 5000, debug=True)