""" FastAPI URL Blink Application Production-grade API for receiving encrypted user data, decrypting it, and storing in SQLite database. """ import os import logging from contextlib import asynccontextmanager from fastapi import FastAPI, Request from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse from core.database import init_db, DB_FILENAME from routers import auth, blink, contact, credits, general, gemini, payments from services.drive_service import DriveService # Configure logging logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s" ) logger = logging.getLogger(__name__) # Initialize Drive Service drive_service = DriveService() @asynccontextmanager async def lifespan(app: FastAPI): """ Application lifespan manager. Initializes database on startup. """ logger.info("Starting up - initializing database...") # Check for RESET_DB environment variable if os.getenv("RESET_DB", "").lower() == "true": logger.warning(f"RESET_DB is set to true. Skipping download and clearing local database ({DB_FILENAME}).") if os.path.exists(DB_FILENAME): os.remove(DB_FILENAME) logger.info("Local database deleted.") else: # Startup: Download DB from Drive ONLY if local file doesn't exist if not os.path.exists(DB_FILENAME): logger.info("Startup: Local DB missing. Attempting to download from Google Drive...") drive_service.download_db() else: logger.info("Startup: Local DB found. Skipping download to preserve data.") await init_db() logger.info("Database initialized successfully") # Start background job worker from services.gemini_job_worker import start_worker, stop_worker await start_worker() logger.info("Background job worker started") yield # Stop background job worker await stop_worker() logger.info("Background job worker stopped") # Shutdown: Upload DB to Drive logger.info("Shutdown: Uploading database to Google Drive...") drive_service.upload_db() logger.info("Shutting down...") # Create FastAPI application app = FastAPI( title="APIGateway", description="API for receiving and processing encrypted user data", version="1.0.0", lifespan=lifespan ) # Configure CORS app.add_middleware( CORSMiddleware, allow_origins=["*"], # Configure appropriately for production allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Include Routers app.include_router(general.router) app.include_router(auth.router) app.include_router(blink.router) app.include_router(gemini.router) app.include_router(credits.router) app.include_router(payments.router) app.include_router(contact.router) @app.exception_handler(Exception) async def global_exception_handler(request: Request, exc: Exception): """ Global exception handler for unhandled errors. """ logger.error(f"Unhandled exception: {exc}") return JSONResponse( status_code=500, content={"detail": "Internal server error"} ) if __name__ == "__main__": import uvicorn uvicorn.run( "app:app", host="0.0.0.0", port=8000, reload=True, log_level="info" )