from flask import Flask, jsonify, redirect, url_for, session, render_template from .db import engine from . import config from .helpers import register_filters from .models import UserSession, GlobalStatus, UserOnboarding from sqlmodel import Session, select from .modules import ( auth_routes, notifications_routes, schedule_routes, projects_routes, workshops_routes, files_routes, admin_routes, gitea_routes, feed_routes, onboarding_routes, dashboard_routes, ) app = Flask(__name__) app.secret_key = config.WEB_SECRET app.config['UPLOAD_FOLDER'] = '/var/lib/gitea/portal-files' app.config['MAX_CONTENT_LENGTH'] = 100 * 1024 * 1024 with app.app_context(): # Схему создаёт Alembic. Seed базового GlobalStatus — если пусто. try: with Session(engine) as db_session: if not db_session.exec(select(GlobalStatus)).first(): db_session.add(GlobalStatus(status="free", message="Вне расписания")) db_session.commit() except Exception as e: print(f"[main] seed GlobalStatus skipped: {e}", flush=True) @app.before_request def validate_session(): if "session_id" in session: with Session(engine) as db_session: db_sess = db_session.exec( select(UserSession).where(UserSession.session_token == session["session_id"]) ).first() if not db_sess: session.clear() return redirect(url_for("login")) register_filters(app) auth_routes.register(app) notifications_routes.register(app) schedule_routes.register(app) projects_routes.register(app) workshops_routes.register(app) files_routes.register(app) admin_routes.register(app) gitea_routes.register(app) feed_routes.register(app) onboarding_routes.register(app) dashboard_routes.register(app) @app.route("/healthz") def healthz(): try: from sqlalchemy import text from .llm_assistant import is_enabled as llm_is_enabled with engine.connect() as conn: conn.execute(text("SELECT 1")) return jsonify({"status": "ok", "db": "ok", "llm": "enabled" if llm_is_enabled() else "disabled"}) except Exception as e: return jsonify({"status": "error", "db": str(e)}), 503 @app.route("/") def index(): user_id = session.get("user_id") onboarding_completed = False if user_id: try: with Session(engine) as s: ob = s.exec(select(UserOnboarding).where(UserOnboarding.user_id == user_id)).first() onboarding_completed = bool(ob and ob.completed_at) except Exception: pass return render_template("index.html", onboarding_completed=onboarding_completed) @app.route("/api/public-status") def api_public_status(): with Session(engine) as s: gs = s.exec(select(GlobalStatus)).first() if not gs: return jsonify({"status": "free", "delay_minutes": 0, "message": None}) return jsonify({"status": gs.status, "delay_minutes": gs.delay_minutes or 0, "message": gs.message, "updated_at": gs.updated_at.isoformat() if gs.updated_at else None})