# app/main.py - FastAPI Application Entry Point from contextlib import asynccontextmanager from datetime import datetime from fastapi import FastAPI, Request from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse, HTMLResponse, Response from fastapi.templating import Jinja2Templates import time from app.config import settings from app.agents.orchestrator import orchestrator from app.api.routes import api_router, enforcement_router, guvi_router from app.utils.logger import setup_logging setup_logging() templates = Jinja2Templates(directory="app/templates") BANNER = """ ██╗ ██╗ ██████╗ ███╗ ██╗███████╗██╗ ██╗██████╗ ██████╗ ████████╗ ██║ ██║██╔═══██╗████╗ ██║██╔════╝╚██╗ ██╔╝██╔══██╗██╔═══██╗╚══██╔══╝ ███████║██║ ██║██╔██╗ ██║█████╗ ╚████╔╝ ██████╔╝██║ ██║ ██║ ██╔══██║██║ ██║██║╚██╗██║██╔══╝ ╚██╔╝ ██╔═══╝ ██║ ██║ ██║ ██║ ██║╚██████╔╝██║ ╚████║███████╗ ██║ ██║ ╚██████╔╝ ██║ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ 🍯 Scam Honeypot System """ @asynccontextmanager async def lifespan(app: FastAPI): """Initialize and cleanup application resources.""" print(BANNER) print("Starting API...") # Initialize database from app.database.db import init_db, close_db await init_db() # Initialize orchestrator await orchestrator.initialize() print("System initialized") yield print("Shutting down...") await orchestrator.shutdown() await close_db() app = FastAPI( title="Scam Honeypot API", description="AI-powered honeypot for scam detection and intelligence extraction", version=settings.VERSION, docs_url="/docs", redoc_url="/redoc", lifespan=lifespan ) # CORS middleware app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Rate limiting middleware (DDoS protection) from app.middleware.rate_limiter import RateLimitMiddleware app.add_middleware(RateLimitMiddleware) @app.middleware("http") async def add_process_time_header(request: Request, call_next): """Add processing time to response headers.""" start_time = time.time() response = await call_next(request) process_time = time.time() - start_time response.headers["X-Process-Time"] = str(round(process_time * 1000, 2)) return response @app.get("/favicon.ico", include_in_schema=False) async def favicon(): return Response(content="\U0001F36F", media_type="image/x-icon") @app.get("/apple-touch-icon{path:path}.png", include_in_schema=False) async def apple_touch_icon(): return Response(content="\U0001F36F", media_type="image/png") @app.get("/", response_class=HTMLResponse, tags=["Info"]) async def root(request: Request): """Landing page.""" return templates.TemplateResponse( "index.html", {"request": request, "banner": BANNER, "version": settings.VERSION} ) @app.get("/api/v1/info", tags=["Info"]) async def api_info(): """API information endpoint.""" return { "message": "Scam Honeypot API", "version": settings.VERSION, "agents": ["ScamDetector", "PersonaEngine", "IntelExtractor", "AdaptiveStrategy", "ThreatEngine", "RiskScorer"], "endpoints": { "analyze": "/api/v1/analyze", "guvi_analyze": "/api/guvi/analyze", "scam_types": "/api/v1/scam-types", "personas": "/api/v1/personas", "stats": "/api/v1/stats", "campaigns": "/api/v1/campaigns", "docs": "/docs" } } @app.get("/health", tags=["Health"]) async def health_check(): """Health check endpoint.""" return { "status": "healthy", "timestamp": datetime.utcnow().isoformat(), "version": settings.VERSION, "llm_available": orchestrator.llm_client.is_available if orchestrator.llm_client else False } # Register routers app.include_router(api_router) app.include_router(enforcement_router) app.include_router(guvi_router) from app.decoys.fake_endpoints import router as decoy_router app.include_router(decoy_router) @app.exception_handler(Exception) async def global_exception_handler(request: Request, exc: Exception): """Global exception handler.""" return JSONResponse( status_code=500, content={"status": "error", "message": str(exc), "path": str(request.url)} ) if __name__ == "__main__": import uvicorn uvicorn.run("app.main:app", host="0.0.0.0", port=8000, reload=True)