API HelloFresh réelle câblée + filtrage coco validé en local
- Endpoints découverts: menu (menus-service) + détails batch (recipes/recipes) - get_menu en 2 temps: menu (ids) -> batch détails (ingrédients/allergènes) - Fix faux positifs: exclusion sur ingrédients/allergènes/nom, plus sur les tags (HelloFresh pose un tag interne 'coconut' sur ~la moitié des recettes) - Token mis en cache (pas de navigateur si frais) - endpoints.json versionné (sans secret), semaine optionnelle (défaut = courante) - Testé: 4 recettes coco/85 détectées, shortlist classée, tous les outils MCP OK - set_selection (écriture) reste à découvrir sur un compte avec box active
This commit is contained in:
@@ -64,15 +64,27 @@ def load_prefs() -> dict:
|
||||
|
||||
|
||||
# --- application aux recettes ----------------------------------------------
|
||||
def _recipe_haystack(recipe: Recipe) -> str:
|
||||
parts = [recipe.name, recipe.headline, *recipe.ingredients, *recipe.allergens, *recipe.tags]
|
||||
def _exclusion_haystack(recipe: Recipe) -> str:
|
||||
"""Champs FAISANT FOI pour l'exclusion : ingrédients, allergènes, nom, accroche.
|
||||
|
||||
On EXCLUT volontairement les `tags` : HelloFresh y pose des tags internes non
|
||||
affichés (ex. un tag `coconut` présent sur des dizaines de recettes sans coco),
|
||||
ce qui provoquait des faux positifs massifs.
|
||||
"""
|
||||
parts = [recipe.name, recipe.headline, *recipe.ingredients, *recipe.allergens]
|
||||
return normalize(" | ".join(p for p in parts if p))
|
||||
|
||||
|
||||
def _pref_haystack(recipe: Recipe) -> str:
|
||||
"""Pour le scoring de préférences, les tags sont utiles (catégories de cuisine…)."""
|
||||
parts = [recipe.name, recipe.headline, *recipe.ingredients, *recipe.tags]
|
||||
return normalize(" | ".join(p for p in parts if p))
|
||||
|
||||
|
||||
def mark_excluded(recipe: Recipe, excludes: list[str] | None = None) -> Recipe:
|
||||
"""Remplit `contains_excluded` et `matched_excludes` sur la recette."""
|
||||
excludes = excludes if excludes is not None else load_excludes()
|
||||
hay = _recipe_haystack(recipe)
|
||||
hay = _exclusion_haystack(recipe)
|
||||
matched = [term for term in excludes if normalize(term) and normalize(term) in hay]
|
||||
recipe.matched_excludes = matched
|
||||
recipe.contains_excluded = bool(matched)
|
||||
@@ -81,7 +93,7 @@ def mark_excluded(recipe: Recipe, excludes: list[str] | None = None) -> Recipe:
|
||||
|
||||
def score(recipe: Recipe, prefs: dict | None = None) -> float:
|
||||
prefs = prefs or load_prefs()
|
||||
hay = _recipe_haystack(recipe)
|
||||
hay = _pref_haystack(recipe)
|
||||
s = 0.0
|
||||
for kw in prefs.get("liked", []):
|
||||
if normalize(kw) and normalize(kw) in hay:
|
||||
|
||||
Reference in New Issue
Block a user