from __future__ import annotations from functools import lru_cache from pathlib import Path from flask import Blueprint, Response, current_app, redirect, send_from_directory, url_for from flask_login import current_user from ..models import User from ..services.calendar_feeds import build_calendar_feed bp = Blueprint("main", __name__) @bp.route("/") def index(): if current_user.is_authenticated: return redirect(url_for("tasks.my_tasks")) return redirect(url_for("auth.login")) @bp.route("/healthz") def healthz(): return {"status": "ok"}, 200 @bp.route("/manifest.json") def manifest(): return send_from_directory(current_app.static_folder, "manifest.json", mimetype="application/manifest+json") @bp.route("/service-worker.js") def service_worker(): response = send_from_directory(current_app.static_folder, "service-worker.js", mimetype="application/javascript") response.headers["Service-Worker-Allowed"] = "/" return response @bp.route("/uploads/") def uploads(filename: str): return send_from_directory(current_app.config["UPLOAD_FOLDER"], filename) @bp.route("/calendar-feed/.ics") def calendar_feed(token: str): user = User.query.filter_by(calendar_feed_token=token).first_or_404() body = build_calendar_feed(user, url_for("tasks.my_tasks", _external=True)) response = Response(body, content_type="text/calendar; charset=utf-8") response.headers["Content-Disposition"] = 'inline; filename="putzliga.ics"' response.headers["Cache-Control"] = "private, max-age=300" return response @lru_cache(maxsize=64) def load_icon_svg(name: str, static_folder: str) -> str: path = Path(static_folder) / "icons" / f"{name}.svg" return path.read_text(encoding="utf-8") if path.exists() else ""