"""Normalisation des URLs d'images recettes pour un rendu direct (Telegram, etc.). L'API recettes renvoie des URLs CloudFront du type https://d3hvwccx09j84u.cloudfront.net/0,0/image/HF_....jpg qui répondent en 502 au téléchargement direct (hotlink protégé). Le CDN servable est https://img.hellofresh.com//hellofresh_s3/image/HF_....jpg où le segment `0,0` (largeur,hauteur) de CloudFront est remplacé par une transformation Cloudinary (`f_auto,fl_lossy,q_auto,w_1200`) et le chemin préfixé par `hellofresh_s3`. Confirmé par probe (2026-06) : la variante img.hellofresh.com/.../hellofresh_s3/… renvoie 206 + image/jpeg, alors que l'URL CloudFront brute renvoie 502. Hôte/transfo configurables via config/endpoints.json (`image_cdn_host`, `image_cdn_transform`, `image_cdn_source_hosts`). """ from __future__ import annotations import json import re from functools import lru_cache from urllib.parse import urlsplit from . import auth _ENDPOINTS_PATH = auth.ROOT / "config" / "endpoints.json" # Segment de dimensionnement CloudFront en tête de chemin, ex. "/0,0/" ou "/200,200/". _SIZE_SEG = re.compile(r"^/\d+,\d+(?=/)") _DEFAULTS = { "image_cdn_host": "img.hellofresh.com", "image_cdn_transform": "f_auto,fl_lossy,q_auto,w_1200", "image_cdn_source_hosts": ["d3hvwccx09j84u.cloudfront.net"], } @lru_cache(maxsize=1) def _cfg() -> tuple[str, str, tuple[str, ...]]: """(host cible, transfo, hôtes source) lus depuis endpoints.json, avec défauts.""" data: dict = {} try: data = json.loads(_ENDPOINTS_PATH.read_text(encoding="utf-8")) except Exception: pass host = str(data.get("image_cdn_host") or _DEFAULTS["image_cdn_host"]) transform = str(data.get("image_cdn_transform") or _DEFAULTS["image_cdn_transform"]) sources = tuple(data.get("image_cdn_source_hosts") or _DEFAULTS["image_cdn_source_hosts"]) return host, transform, sources def fix_image_url(url: str) -> str: """Réécrit une URL d'image CloudFront HelloFresh vers le CDN servable. - URL vide → "". - Déjà sur un hôte hellofresh.com → renvoyée telle quelle. - Hôte CloudFront connu (ou *.cloudfront.net) → host remplacé, segment de taille retiré, chemin préfixé par `hellofresh_s3` et la transformation insérée. - Tout autre hôte → renvoyée telle quelle (on ne casse rien). """ if not url: return "" host, transform, sources = _cfg() parts = urlsplit(url) netloc = parts.netloc.lower() if "hellofresh.com" in netloc: # déjà servable (img/media.hellofresh.com) return url if netloc not in sources and not netloc.endswith(".cloudfront.net"): return url path = _SIZE_SEG.sub("", parts.path) # "/0,0/image/X.jpg" -> "/image/X.jpg" if not path.startswith("/"): path = "/" + path rest = path if path.startswith("/hellofresh_s3/") else "/hellofresh_s3" + path return f"https://{host}/{transform}{rest}"