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