# main.py import asyncio import sys import os from pathlib import Path from contextlib import asynccontextmanager # ✅ MUST be set FIRST before anything async-related imports. # On Windows, Uvicorn defaults to SelectorEventLoop which does NOT support # subprocess creation (needed by Playwright to launch the browser). # ProactorEventLoop supports subprocesses on Windows. if sys.platform.startswith("win"): asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy()) from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles # Import routers AFTER setting loop policy from routes.auth_routes import router as auth_router from routes.reports_routes import router as reports_router from routes.user_routes import user_router from routes.contact_routes import contact_router # Import SSL monitor from reports.ssl_monitor import start_ssl_monitor, stop_ssl_monitor # Import Gemini token tracker from reports.gemini_token_tracker import initialize_token_tracker # Import Website Down Detector from reports.website_down_detector import initialize_down_detector, stop_down_detector @asynccontextmanager async def lifespan(app: FastAPI): """ Application lifespan manager. Starts SSL monitor, token tracker, and website downtime detector on startup. Stops all services on shutdown. """ # Start SSL monitoring service try: start_ssl_monitor() print("✅ SSL Monitor initialized") except Exception as e: print(f"⚠️ Warning: Could not start SSL Monitor: {e}") # Initialize Gemini token tracker try: await initialize_token_tracker() except Exception as e: print(f"⚠️ Warning: Could not initialize Token Tracker: {e}") # Initialize Website Down Detector try: await initialize_down_detector() print("✅ Website Down Detector initialized (monitoring every 24h)") except Exception as e: print(f"⚠️ Warning: Could not initialize Website Down Detector: {e}") print("✨ Server is ready!\n") yield # Shutdown print("\n" + "="*60) print("🛑 Shutting down WebMentAI Backend API...") print("="*60) # Stop SSL monitoring service try: stop_ssl_monitor() print("✅ SSL Monitor stopped") except Exception as e: print(f"⚠️ Warning: Error stopping SSL Monitor: {e}") # Stop Website Down Detector try: await stop_down_detector() print("✅ Website Down Detector stopped") except Exception as e: print(f"⚠️ Warning: Error stopping Website Down Detector: {e}") print("="*60 + "\n") app = FastAPI( title="WebMentAI Backend API", lifespan=lifespan ) # Mount static files directory to serve assets (like logo) assets_path = Path(__file__).parent / "assets" if assets_path.exists(): app.mount("/assets", StaticFiles(directory=str(assets_path)), name="assets") app.include_router(reports_router) app.include_router(auth_router) app.include_router(user_router) app.include_router(contact_router) app.add_middleware( CORSMiddleware, allow_origins=["http://localhost:3000"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) @app.get("/") async def home(): return {"message": "Welcome to the WebMentAI!"}