{tiles_html(tiles,p) if tiles else ''}
{footer(ins,p)}
"""
def genre_ranking(ins, p):
bars = ins.get("bars") or []
maxv = max([b[1] for b in bars] or [1])
rows = ""
for b in bars:
label, val, vtxt = b[0], b[1], b[2]
sub = b[3] if len(b) > 3 else ""
w = max(8, int(100*val/maxv))
rows += f"""
{esc(label)}{esc(vtxt)}
{f'
{esc(sub)}
' if sub else ''}
"""
return f"""
{hdr(ins,p)}
{esc(ins['headline_label'])}
{rows}
{footer(ins,p)}
"""
def genre_spotlight(ins, p):
prod = ins.get("product") or {}
img = prod.get("image_data") or ""
chips = "".join(f'{esc(c)}' for c in (prod.get("meta") or []))
price = prod.get("price","")
return f"""
{esc(ins['label'].upper())} · À DÉCOUVRIR · {today_str().upper()}
KA
{esc(prod.get('title',''))}
{esc(prod.get('subtitle',''))}
{chips}
{f'
{esc(price)}
' if price else ''}
{esc(ins.get('tagline',''))}
{footer(ins,p)}
"""
def genre_list(ins, p):
items = ins.get("list") or []
rows = ""
for it in items[:5]:
img = it.get("image_data") or ""
thumb = '' if img else ''
price = esc(it.get("price", "") or "")
pr = ('
')
GENRES = {"hero":genre_hero, "ranking":genre_ranking, "spotlight":genre_spotlight,
"list":genre_list, "deal":genre_hero, "pulse":genre_hero}
def build_html(ins):
p = pal(ins["site"])
genre = ins.get("genre","hero")
if genre == "ranking" and not ins.get("bars"): genre = "hero"
if genre == "spotlight" and not (ins.get("product") or {}).get("image_data"): genre = "hero"
if genre == "list" and not ins.get("list"): genre = "hero"
body = GENRES.get(genre, genre_hero)(ins, p)
return f"""
{body}
""", genre
def render(ins, out_dir):
os.makedirs(out_dir, exist_ok=True)
# télécharger la photo produit en data-uri (robuste, pas de hotlink)
prod = ins.get("product")
if prod and prod.get("image") and not prod.get("image_data"):
du = data_uri(prod["image"])
if du: prod["image_data"] = du
for it in (ins.get("list") or []):
if it.get("image") and not it.get("image_data"):
du = data_uri(it["image"])
if du: it["image_data"] = du
html, genre = build_html(ins)
key = hashlib.md5((ins["site"]+ins.get("insight_id","")+genre).encode()).hexdigest()[:8]
html_path = os.path.join(out_dir, f"card-{ins['site']}-{key}.html")
big = os.path.join(out_dir, f"_big-{key}.png")
out = os.path.join(out_dir, f"card-{ins['site']}-{ins.get('insight_id','x')}-{genre}.png")
open(html_path,"w",encoding="utf-8").write(html)
chrome = find_chrome()
subprocess.run([chrome,"--headless","--disable-gpu","--hide-scrollbars",
"--force-device-scale-factor=2","--window-size=1080,1350",
f"--screenshot={big}","--virtual-time-budget=9000","--run-all-compositor-stages-before-draw",
f"file://{html_path}"], capture_output=True, timeout=60)
if not os.path.exists(big):
raise SystemExit("chrome screenshot a échoué")
# downscale 2x → 1080x1350 (texte net) via sips
subprocess.run(["/usr/bin/sips","-z","1350","1080",big,"--out",out],capture_output=True)
try: os.remove(big); os.remove(html_path)
except: pass
return out
if __name__ == "__main__":
ins = json.load(sys.stdin)
out_dir = sys.argv[1] if len(sys.argv)>1 else "/tmp/ka-social-cards"
print(render(ins, out_dir))