Carte recette dans summary() : image, prep_time + prep_minutes, allergènes

hf_get_menu/hf_propose exposent désormais de quoi composer une carte Telegram
(image_url Cloudfront directe, durée ISO + prep_minutes entier, allergènes) sans
appel supplémentaire — pour la mise en forme côté Hermes.
This commit is contained in:
jerem
2026-06-18 12:31:39 +02:00
parent e7776a539e
commit 4b1eb9f52c

View File

@@ -7,9 +7,12 @@ stable utilisée par le filtre et le serveur MCP.
from __future__ import annotations
import re
from dataclasses import dataclass, field, asdict
from typing import Any
_ISO_DURATION = re.compile(r"PT(?:(\d+)H)?(?:(\d+)M)?", re.IGNORECASE)
def _first(d: dict, *keys, default=None):
"""Renvoie la première clé présente et non vide parmi `keys`."""
@@ -20,6 +23,22 @@ def _first(d: dict, *keys, default=None):
return default
def _iso_duration_to_minutes(value: str) -> int | None:
"""Convertit une durée ISO 8601 ('PT1H30M', 'PT30M') en minutes entières.
Renvoie None si le format n'est pas reconnu (champ vide ou inattendu),
pour laisser le client distinguer « inconnu » de « 0 min ».
"""
if not value:
return None
m = _ISO_DURATION.fullmatch(value.strip())
if not m or not (m.group(1) or m.group(2)):
return None
hours = int(m.group(1) or 0)
minutes = int(m.group(2) or 0)
return hours * 60 + minutes
@dataclass
class Recipe:
id: str
@@ -89,11 +108,19 @@ class Recipe:
return asdict(self)
def summary(self) -> dict[str, Any]:
"""Version compacte pour les réponses MCP (moins de tokens)."""
"""Version compacte pour les réponses MCP (moins de tokens).
Inclut de quoi composer une carte (image, temps, allergènes) côté client
Telegram sans appel supplémentaire — cf. besoin de mise en forme Hermes.
"""
return {
"id": self.id,
"name": self.name,
"headline": self.headline,
"image_url": self.image_url,
"prep_time": self.prep_time,
"prep_minutes": _iso_duration_to_minutes(self.prep_time),
"allergens": self.allergens,
"contains_excluded": self.contains_excluded,
"matched_excludes": self.matched_excludes,
"score": self.score,