"""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-a-licious: el endpoint de texto fiable de OFF (el legacy cgi/search.pl # devuelve 503 a IPs de datacenter). _SEARCH = "https://search.openfoodfacts.org/search" def search(q: str, limit: int = 12) -> list[dict]: """Devuelve alimentos normalizados: {name, kcal_100g, off_id, barcode}.""" try: resp = httpx.get( _SEARCH, params={ "q": q, "page_size": limit, "fields": "code,product_name,nutriments", }, timeout=6.0, headers={"User-Agent": "autoayuno/1.0 (self-hosted; carlos)"}, ) if resp.status_code != 200: return [] out = [] for h in resp.json().get("hits", []): name = (h.get("product_name") or "").replace("\n", " ").strip() kcal = (h.get("nutriments") or {}).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": h.get("code"), "barcode": h.get("code"), }) return out except Exception: return []