fooder-api/fooder/utils/product_finder.py
2026-04-07 16:49:30 +02:00

54 lines
1.4 KiB
Python

from dataclasses import dataclass
from logging import getLogger
import httpx
logger = getLogger(__name__)
class NotFound(Exception):
pass
class ParseError(Exception):
pass
@dataclass
class ExternalProduct:
name: str
kcal: float
fat: float
protein: float
carb: float
fiber: float
async def find(barcode: str) -> ExternalProduct:
async with httpx.AsyncClient() as client:
response = await client.get(
f"https://world.openfoodfacts.org/api/v2/product/{barcode}.json",
headers={"User-Agent": "fooder/1.0"},
)
if response.status_code == 404:
raise NotFound()
try:
data = response.json()
product_data = data["product"]
name = product_data.get("product_name_pl") or product_data.get("product_name")
if brands := product_data.get("brands"):
name = f"{brands} {name}"
n = product_data["nutriments"]
return ExternalProduct(
name=name,
kcal=n.get("energy-kcal_100g") or 0.0,
fat=n.get("fat_100g") or 0.0,
protein=n.get("proteins_100g") or 0.0,
carb=n.get("carbohydrates_100g") or 0.0,
fiber=n.get("fiber_100g") or 0.0,
)
except (KeyError, TypeError) as e:
logger.error("Failed to parse product %s: %s", barcode, e)
raise ParseError() from e