Public Access
feat: feedback-driven recipe discovery (auto-ingest via Spoonacular)
This commit is contained in:
@@ -1,11 +1,18 @@
|
||||
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
from app.database import get_db
|
||||
from app.models import ScrapeLog, EmailLog, MealPlan
|
||||
from app.models import ScrapeLog, EmailLog, MealPlan, Recipe
|
||||
from app.security import require_admin
|
||||
from app.services.scraper_service import ScraperService, enqueue_scrape
|
||||
from app.services.feedback_analyzer import FeedbackAnalyzer
|
||||
from app.services.recipe_discovery import RecipeDiscoveryService
|
||||
from app.services.recipe_ingestion import RecipeIngestionService
|
||||
from typing import List, Optional
|
||||
from datetime import datetime, timedelta
|
||||
from uuid import UUID
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
router = APIRouter(dependencies=[Depends(require_admin)])
|
||||
|
||||
@@ -179,4 +186,50 @@ def get_stats(db: Session = Depends(get_db)):
|
||||
"recipes": recipe_count,
|
||||
"ingredients": ingredient_count,
|
||||
"meal_plans": plan_count
|
||||
}
|
||||
|
||||
|
||||
@router.post("/trigger-discovery", status_code=200)
|
||||
def trigger_discovery(
|
||||
family_profile_id: UUID,
|
||||
force: bool = False,
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
from uuid import UUID as UUIDType
|
||||
|
||||
profile = (
|
||||
db.query(FamilyProfile)
|
||||
.filter(FamilyProfile.id == family_profile_id)
|
||||
.first()
|
||||
)
|
||||
if not profile:
|
||||
raise HTTPException(status_code=404, detail="Family profile not found")
|
||||
|
||||
analyzer = FeedbackAnalyzer(lookback_weeks=4)
|
||||
analysis = analyzer.analyze(db, profile.id)
|
||||
|
||||
if not analysis.discovery_queries and not force:
|
||||
return {"status": "skipped", "reason": "No discovery queries and force=false"}
|
||||
|
||||
discovery = RecipeDiscoveryService()
|
||||
if not analysis.discovery_queries and force:
|
||||
queries = ["popular recipes"]
|
||||
else:
|
||||
queries = analysis.discovery_queries
|
||||
|
||||
candidates = discovery.discover(queries)
|
||||
if not candidates:
|
||||
return {"status": "no_candidates"}
|
||||
|
||||
ingestion = RecipeIngestionService()
|
||||
added = ingestion.ingest(
|
||||
db, profile.id, candidates, analysis.to_dict()
|
||||
)
|
||||
logger.info("Manual discovery: added %d recipes for family %s", added, profile.id)
|
||||
return {
|
||||
"status": "success",
|
||||
"candidates_found": len(candidates),
|
||||
"recipes_added": added,
|
||||
"discovery_queries": queries,
|
||||
"confidence": analysis.confidence,
|
||||
}
|
||||
Reference in New Issue
Block a user