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:
@@ -7,9 +7,12 @@ stable utilisée par le filtre et le serveur MCP.
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import re
|
||||||
from dataclasses import dataclass, field, asdict
|
from dataclasses import dataclass, field, asdict
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
_ISO_DURATION = re.compile(r"PT(?:(\d+)H)?(?:(\d+)M)?", re.IGNORECASE)
|
||||||
|
|
||||||
|
|
||||||
def _first(d: dict, *keys, default=None):
|
def _first(d: dict, *keys, default=None):
|
||||||
"""Renvoie la première clé présente et non vide parmi `keys`."""
|
"""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
|
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
|
@dataclass
|
||||||
class Recipe:
|
class Recipe:
|
||||||
id: str
|
id: str
|
||||||
@@ -89,11 +108,19 @@ class Recipe:
|
|||||||
return asdict(self)
|
return asdict(self)
|
||||||
|
|
||||||
def summary(self) -> dict[str, Any]:
|
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 {
|
return {
|
||||||
"id": self.id,
|
"id": self.id,
|
||||||
"name": self.name,
|
"name": self.name,
|
||||||
"headline": self.headline,
|
"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,
|
"contains_excluded": self.contains_excluded,
|
||||||
"matched_excludes": self.matched_excludes,
|
"matched_excludes": self.matched_excludes,
|
||||||
"score": self.score,
|
"score": self.score,
|
||||||
|
|||||||
Reference in New Issue
Block a user