73 lines
3.2 KiB
Python
73 lines
3.2 KiB
Python
from fastapi import APIRouter, HTTPException, Request
|
|
|
|
from app.services.kitchenowl import kitchenowl
|
|
from app.services.repository import repo
|
|
from app.services.store import JsonStore
|
|
|
|
|
|
router = APIRouter(prefix="/api/suggestions", tags=["suggestions"])
|
|
store = JsonStore()
|
|
|
|
|
|
def _bump(counter: dict, key: str, amount: int = 1) -> None:
|
|
counter[key] = int(counter.get(key, 0)) + amount
|
|
|
|
|
|
def _apply_learning(profile: dict, suggestion: dict, approved: bool) -> dict:
|
|
ingredients = suggestion.get("ingredients") or []
|
|
tags = suggestion.get("tags") or []
|
|
title = str(suggestion.get("title") or "").strip().lower()
|
|
ingredient_counter_key = "approved_ingredients" if approved else "rejected_ingredients"
|
|
tag_counter_key = "approved_tags" if approved else "rejected_tags"
|
|
title_counter_key = "approved_titles" if approved else "rejected_titles"
|
|
for ingredient in ingredients:
|
|
_bump(profile.setdefault(ingredient_counter_key, {}), ingredient)
|
|
for tag in tags:
|
|
_bump(profile.setdefault(tag_counter_key, {}), tag)
|
|
if title:
|
|
_bump(profile.setdefault(title_counter_key, {}), title)
|
|
return profile
|
|
|
|
|
|
@router.get("")
|
|
async def list_suggestions():
|
|
items = sorted(repo.list_suggestions(), key=lambda item: item.get("updated_at") or item.get("created_at") or "", reverse=True)
|
|
return {"items": items, "backend": repo.backend}
|
|
|
|
|
|
@router.post("/{suggestion_id}/decision")
|
|
async def decide(suggestion_id: str, request: Request):
|
|
payload = await request.json()
|
|
decision = str(payload.get("decision") or "").strip().lower()
|
|
current = next((item for item in repo.list_suggestions() if str(item.get("id")) == str(suggestion_id)), None)
|
|
if not current:
|
|
raise HTTPException(status_code=404, detail="Suggestion not found.")
|
|
if decision not in {"approve", "reject", "later"}:
|
|
raise HTTPException(status_code=400, detail="Decision must be approve, reject, or later.")
|
|
profile = repo.get_profile()
|
|
kitchenowl_result = None
|
|
if decision == "approve":
|
|
profile = _apply_learning(profile, current, approved=True)
|
|
import_now = bool(payload.get("import_to_kitchenowl", True))
|
|
already_linked = str(current.get("status") or "") == "approved" and str(current.get("kitchenowl_status") or "") in {"created", "duplicate", "updated"}
|
|
if import_now and kitchenowl.configured() and not already_linked:
|
|
kitchenowl_result = kitchenowl.create_recipe(current.get("payload") or {})
|
|
current_status = "approved"
|
|
elif decision == "reject":
|
|
profile = _apply_learning(profile, current, approved=False)
|
|
current_status = "rejected"
|
|
else:
|
|
current_status = "saved"
|
|
repo.save_profile(profile)
|
|
updated = repo.update_suggestion(
|
|
suggestion_id,
|
|
{
|
|
"status": current_status,
|
|
"updated_at": store.now(),
|
|
"decision_at": store.now(),
|
|
"kitchenowl_status": (kitchenowl_result or {}).get("status") if kitchenowl_result else current.get("kitchenowl_status", "not-imported"),
|
|
"kitchenowl_result": kitchenowl_result,
|
|
},
|
|
)
|
|
return {"status": "ok", "suggestion": updated, "profile": profile, "kitchenowl": kitchenowl_result}
|