#main.py from fastapi import FastAPI, HTTPException, Depends, status from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel, Field from sqlalchemy.orm import Session import models from database import engine, SessionLocal from ml_utils import ScamDetectionService from typing import Optional import time from datetime import datetime # Create FastAPI app app = FastAPI( title="Multilingual Scam Detection API", description="Simple API to detect scams in text messages and URLs", version="1.0.0" ) # Add CORS middleware # app.add_middleware( # CORSMiddleware, # allow_origins=["*"], # Configure for production # allow_credentials=True, # allow_methods=["*"], # allow_headers=["*"], # ) # Create database tables models.Base.metadata.create_all(bind=engine) # Initialize scam detection service scam_service = ScamDetectionService() # Database dependency def get_db(): db = SessionLocal() try: yield db finally: db.close() # Pydantic models for requests/responses class TextAnalysisRequest(BaseModel): text: str = Field(min_length=1, max_length=5000) language: Optional[str] = Field(default=None, description="Language code (en, es, fr)") class URLAnalysisRequest(BaseModel): url: str = Field(min_length=1) context: Optional[str] = Field(default="", description="Additional context") class ScamAnalysisResponse(BaseModel): risk_level: str confidence: float reasoning: str detected_language: Optional[str] = None processing_time: float timestamp: datetime class URLAnalysisResponse(ScamAnalysisResponse): url_status: str domain: str # Root endpoint @app.get("/") def root(): return { "message": "Multilingual Scam Detection API", "version": "1.0.0", "endpoints": { "analyze_text": "/analyze/text/", "analyze_url": "/analyze/url/", "health": "/health/", "analytics": "/analytics/summary/" } } # Health check @app.get("/health/") def health_check(): return { "status": "healthy", "timestamp": datetime.now(), "database": "connected", "ml_service": "active" } # Text analysis endpoint @app.post("/analyze/text/", response_model=ScamAnalysisResponse) def analyze_text(request: TextAnalysisRequest, db: Session = Depends(get_db)): """Analyze text message for scam indicators""" start_time = time.time() try: # Detect language if not provided detected_language = request.language or scam_service.detect_language(request.text) # Analyze for scam analysis = scam_service.analyze_text_scam( text=request.text, language=detected_language ) processing_time = time.time() - start_time # Save to database scam_record = models.ScamAnalysis( content=request.text, content_type="text", risk_level=analysis["risk_level"], confidence=analysis["confidence"], reasoning=analysis["reasoning"], detected_language=detected_language, processing_time=processing_time ) db.add(scam_record) db.commit() return ScamAnalysisResponse( risk_level=analysis["risk_level"], confidence=analysis["confidence"], reasoning=analysis["reasoning"], detected_language=detected_language, processing_time=round(processing_time, 3), timestamp=datetime.now() ) except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Analysis failed: {str(e)}" ) # URL analysis endpoint @app.post("/analyze/url/", response_model=URLAnalysisResponse) def analyze_url(request: URLAnalysisRequest, db: Session = Depends(get_db)): """Analyze URL for phishing/malicious behavior""" start_time = time.time() try: # Analyze URL analysis = scam_service.analyze_url_scam( url=request.url, context=request.context ) processing_time = time.time() - start_time # Save to database scam_record = models.ScamAnalysis( content=request.url, content_type="url", risk_level=analysis["risk_level"], confidence=analysis["confidence"], reasoning=analysis["reasoning"], processing_time=processing_time, additional_data={"domain": analysis["domain"], "url_status": analysis["url_status"]} ) db.add(scam_record) db.commit() return URLAnalysisResponse( risk_level=analysis["risk_level"], confidence=analysis["confidence"], reasoning=analysis["reasoning"], url_status=analysis["url_status"], domain=analysis["domain"], processing_time=round(processing_time, 3), timestamp=datetime.now() ) except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"URL analysis failed: {str(e)}" ) # Language detection endpoint @app.post("/detect/language/") def detect_language(text: str): """Detect language of input text""" try: detected_lang = scam_service.detect_language(text) confidence = scam_service.get_language_confidence(text) return { "text_preview": text[:100] + "..." if len(text) > 100 else text, "detected_language": detected_lang, "confidence": confidence, "supported_languages": ["en", "es", "fr"] } except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Language detection failed: {str(e)}" ) # Basic analytics @app.get("/analytics/summary/") def get_analytics(db: Session = Depends(get_db)): """Get basic analytics summary""" try: total_analyses = db.query(models.ScamAnalysis).count() # Count by risk level safe_count = db.query(models.ScamAnalysis).filter( models.ScamAnalysis.risk_level == "Safe" ).count() suspicious_count = db.query(models.ScamAnalysis).filter( models.ScamAnalysis.risk_level == "Suspicious" ).count() scam_count = db.query(models.ScamAnalysis).filter( models.ScamAnalysis.risk_level == "Scam" ).count() # Count by content type text_count = db.query(models.ScamAnalysis).filter( models.ScamAnalysis.content_type == "text" ).count() url_count = db.query(models.ScamAnalysis).filter( models.ScamAnalysis.content_type == "url" ).count() return { "total_analyses": total_analyses, "risk_distribution": { "Safe": safe_count, "Suspicious": suspicious_count, "Scam": scam_count }, "content_distribution": { "text": text_count, "url": url_count }, "supported_languages": ["en", "es", "fr"] } except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Analytics failed: {str(e)}" ) # Recent analyses @app.get("/history/recent/") def get_recent_analyses(limit: int = 10, db: Session = Depends(get_db)): """Get recent scam analyses""" try: recent = db.query(models.ScamAnalysis).order_by( models.ScamAnalysis.created_at.desc() ).limit(limit).all() return { "recent_analyses": [ { "id": analysis.id, "content_type": analysis.content_type, "risk_level": analysis.risk_level, "confidence": analysis.confidence, "detected_language": analysis.detected_language, "created_at": analysis.created_at, "content_preview": ( analysis.content[:50] + "..." if len(analysis.content) > 50 else analysis.content ) } for analysis in recent ], "total_shown": len(recent) } except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"History retrieval failed: {str(e)}" ) # Test endpoint with sample data @app.get("/test/samples/") def test_samples(): """Test with sample scam messages""" samples = [ { "text": "URGENT! Your bank account will be suspended. Click here: bit.ly/urgent-bank", "expected_risk": "Scam" }, { "text": "Hello, how are you today? Hope you're doing well!", "expected_risk": "Safe" }, { "text": "Congratulations! You've won $1000. Click to claim your prize now!", "expected_risk": "Suspicious" } ] results = [] for sample in samples: analysis = scam_service.analyze_text_scam(sample["text"]) results.append({ "text": sample["text"], "expected": sample["expected_risk"], "detected": analysis["risk_level"], "confidence": analysis["confidence"], "reasoning": analysis["reasoning"] }) return { "test_results": results, "total_tests": len(results) } if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)