ewere / api /analysis_routes.py
andevs's picture
Create api/analysis_routes.py
1cf6ff4 verified
Raw
History Blame Contribute Delete
6.26 kB
from fastapi import APIRouter, HTTPException, Depends, UploadFile, File
from pydantic import BaseModel
from typing import List, Optional
from datetime import datetime
import base64
import io
from app import verify_token, db_service, skin_model, tone_analyzer
router = APIRouter()
class AnalysisRequest(BaseModel):
image_base64: Optional[str] = None
conditions: Optional[List[str]] = []
user_id: str
class AnalysisResponse(BaseModel):
id: str
conditions: List[dict]
pins: List[dict]
skin_tone: dict
recommendations: dict
dermatologist_warning: bool
disclaimer: str
@router.post("/analyze-skin", response_model=AnalysisResponse)
async def analyze_skin(
request: AnalysisRequest,
user_id: str = Depends(verify_token)
):
"""
Analyze skin from image or manual condition selection
"""
try:
analysis_id = f"analysis_{datetime.utcnow().timestamp()}"
# Initialize response
response = {
'id': analysis_id,
'conditions': [],
'pins': [],
'skin_tone': {},
'recommendations': {},
'dermatologist_warning': False,
'disclaimer': "These results are AI-generated. We recommend consulting a dermatologist or researching your skin condition to ensure accuracy."
}
# Process image if provided
if request.image_base64:
# Decode image
image_bytes = base64.b64decode(request.image_base64)
# Analyze skin conditions
analysis = skin_model.analyze_skin(image_bytes)
if 'error' in analysis:
raise HTTPException(status_code=400, detail=analysis['error'])
# Analyze skin tone
skin_tone = tone_analyzer.analyze_skin_tone(image_bytes)
response['conditions'] = analysis.get('conditions', [])
response['pins'] = analysis.get('pins', [])
response['skin_tone'] = skin_tone
response['dermatologist_warning'] = analysis.get('dermatologist_warning', False)
# Delete image after analysis (GDPR compliance)
# Image is already in memory, no need to delete
elif request.conditions:
# Manual condition selection
response['conditions'] = [
{'condition': c, 'severity': 'mild', 'confidence': 0}
for c in request.conditions
]
# Generate recommendations
from models.cosmetics_matcher import CosmeticMatcher
matcher = CosmeticMatcher()
recommendations = matcher.find_matches(
skin_tone=response['skin_tone'],
conditions=response['conditions']
)
response['recommendations'] = recommendations
# Save to database
db_service.save_analysis(
user_id=user_id,
analysis_id=analysis_id,
data=response
)
return response
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/update-pins")
async def update_analysis_pins(
analysis_id: str,
pins: List[dict],
user_id: str = Depends(verify_token)
):
"""
Update analysis based on user-modified pins
"""
try:
# Get existing analysis
analysis = db_service.get_analysis(analysis_id, user_id)
if not analysis:
raise HTTPException(status_code=404, detail="Analysis not found")
# Update pins
analysis['pins'] = pins
# Extract conditions from pins
conditions = [
{
'condition': pin['condition'],
'severity': pin.get('severity', 'mild'),
'confidence': pin.get('confidence', 0),
'position': pin.get('position')
}
for pin in pins
]
analysis['conditions'] = conditions
# Regenerate recommendations
from models.cosmetics_matcher import CosmeticMatcher
matcher = CosmeticMatcher()
recommendations = matcher.find_matches(
skin_tone=analysis['skin_tone'],
conditions=conditions
)
analysis['recommendations'] = recommendations
analysis['updated_at'] = datetime.utcnow().isoformat()
analysis['user_modified'] = True
# Save to database
db_service.update_analysis(analysis_id, user_id, analysis)
# Log privacy action
db_service.log_privacy_action({
'user_id': user_id,
'action': 'analysis_modified',
'details': f'User modified {len(pins)} pins',
'timestamp': datetime.utcnow().isoformat()
})
return analysis
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/history")
async def get_analysis_history(
limit: int = 10,
user_id: str = Depends(verify_token)
):
"""
Get user's analysis history
"""
try:
history = db_service.get_user_analyses(user_id, limit)
return {"history": history}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/{analysis_id}")
async def get_analysis(
analysis_id: str,
user_id: str = Depends(verify_token)
):
"""
Get specific analysis by ID
"""
try:
analysis = db_service.get_analysis(analysis_id, user_id)
if not analysis:
raise HTTPException(status_code=404, detail="Analysis not found")
return analysis
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.delete("/{analysis_id}")
async def delete_analysis(
analysis_id: str,
user_id: str = Depends(verify_token)
):
"""
Delete analysis (GDPR compliance)
"""
try:
db_service.delete_analysis(analysis_id, user_id)
return {"message": "Analysis deleted successfully"}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))