feat: autoayuno-api (FastAPI) — alimentos (OFF) y recetas
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
46
off.py
Normal file
46
off.py
Normal file
@@ -0,0 +1,46 @@
|
||||
"""Cliente de Open Food Facts: busca productos y los normaliza a la forma de
|
||||
alimento de la app. Tolerante a fallos: devuelve [] si algo va mal."""
|
||||
import httpx
|
||||
|
||||
_SEARCH = "https://world.openfoodfacts.org/cgi/search.pl"
|
||||
|
||||
|
||||
def search(q: str, limit: int = 12) -> list[dict]:
|
||||
"""Devuelve alimentos normalizados: {name, kcal_100g, off_id, barcode}."""
|
||||
try:
|
||||
resp = httpx.get(
|
||||
_SEARCH,
|
||||
params={
|
||||
"search_terms": q,
|
||||
"search_simple": 1,
|
||||
"action": "process",
|
||||
"json": 1,
|
||||
"page_size": limit,
|
||||
"fields": "product_name,nutriments,code",
|
||||
},
|
||||
timeout=6.0,
|
||||
headers={"User-Agent": "autoayuno/1.0 (self-hosted)"},
|
||||
)
|
||||
if resp.status_code != 200:
|
||||
return []
|
||||
out = []
|
||||
for p in resp.json().get("products", []):
|
||||
name = (p.get("product_name") or "").strip()
|
||||
kcal = p.get("nutriments", {}).get("energy-kcal_100g")
|
||||
if not name or kcal is None:
|
||||
continue
|
||||
try:
|
||||
kcal = float(kcal)
|
||||
except (TypeError, ValueError):
|
||||
continue
|
||||
if kcal <= 0:
|
||||
continue
|
||||
out.append({
|
||||
"name": name[:120],
|
||||
"kcal_100g": kcal,
|
||||
"off_id": p.get("code"),
|
||||
"barcode": p.get("code"),
|
||||
})
|
||||
return out
|
||||
except Exception:
|
||||
return []
|
||||
Reference in New Issue
Block a user