Files
truenas-stacks/home/doris-kitchen/app/routes/api_suggestions.py
2026-05-16 20:22:45 +00:00

73 lines
3.0 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))
if import_now and kitchenowl.configured():
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}