#!/usr/bin/env python3 """Build Joomla article for children's games and POST to brettspiel-news.de.""" import json, base64, subprocess, sys, os import urllib.request, urllib.error # Load parsed deals with open("/tmp/kinderspiele_data.json") as f: data = json.load(f) deals = data["deals"] age_groups = data["age_groups"] # Joomla config JOOMLA_TOKEN = "sha256:794:cc64e486eddbb2e5a96a28be897034924f66f2722db0be3baab408e6b806e2b4" API_BASE = "https://www.brettspiel-news.de/api/index.php/v1" HEADERS = { "Accept": "application/vnd.api+json", "Content-Type": "application/json", "X-Joomla-Token": JOOMLA_TOKEN, } def api_post(endpoint, payload): url = f"{API_BASE}{endpoint}" data = json.dumps(payload).encode("utf-8") req = urllib.request.Request(url, data=data, headers=HEADERS, method="POST") try: with urllib.request.urlopen(req, timeout=30) as resp: return json.loads(resp.read()) except urllib.error.HTTPError as e: body = e.read().decode()[:500] print(f"HTTP {e.code}: {body}", file=sys.stderr) raise def api_patch(endpoint, payload): url = f"{API_BASE}{endpoint}" data = json.dumps(payload).encode("utf-8") req = urllib.request.Request(url, data=data, headers=HEADERS, method="PATCH") try: with urllib.request.urlopen(req, timeout=30) as resp: return json.loads(resp.read()) except urllib.error.HTTPError as e: body = e.read().decode()[:500] print(f"HTTP {e.code}: {body}", file=sys.stderr) raise # Step 1: Upload intro image to Joomla Media print("Uploading intro image...") with open("/tmp/monsterjaeger.jpg", "rb") as f: img_b64 = base64.b64encode(f.read()).decode() media_result = api_post("/media/files", { "path": "images/Spiele/2026/monsterjaeger_kinderspiele_2026-06-21.jpg", "content": img_b64, }) print(f"Media upload: {media_result.get('data', {}).get('id', 'OK')}") # Step 2: Build article HTML age_labels = { "2+": "Für die Kleinsten (ab 2–3 Jahre)", "3+": "Für die Kleinsten (ab 3 Jahre)", "4+": "Ab 4 Jahre", "5+": "Ab 5 Jahre", "6+": "Ab 6 Jahre", "7+": "Ab 7 Jahre", "Allgemein": "Weitere Kinderspiele", } age_order = ["2+", "3+", "4+", "5+", "6+", "7+", "Allgemein"] # Build deal blocks by age sections = [] for age in age_order: if age not in age_groups: continue games = age_groups[age] label = age_labels.get(age, age) blocks = [] for g in games: blocks.append(f"""
{g['title']}
{g['price']:.2f} € UVP {g['uvp']:.2f} € -{g['pct']}% ({g['saved']:.2f} € gespart)
Zu Amazon →
""") sections.append(f"

{label}

\n" + "\n".join(blocks)) total_count = len(deals) group_count = len(age_groups) # Summary stats summary_lines = [] for age in age_order: if age in age_groups: summary_lines.append(f"{age_labels.get(age, age)}: {len(age_groups[age])} Spiele") intro_html = f"""

Jeden Sonntag durchforsten wir Amazon nach den besten Kinderspiel-Angeboten – heute mit {total_count} reduzierten Titeln für kleine Spieler.

Die Angebote sind nach Altersgruppen sortiert: von den ersten Brettspielen für die Kleinsten bis zu spannenden Familienspielen für Schulkinder. Alle Preise inklusive Mehrwertsteuer, Stand 21. Juni 2026.

Unser Tipp: Monsterjäger von Schmidt Spiele ist heute mit 54 % Rabatt der absolute Preisknüller – nur 11,31 € statt 24,49 €!

""" # Build full HTML all_sections = "\n".join(sections) body_html = intro_html + all_sections + f"""

Preise und Verfugbarkeit konnen sich schnell andern. Uber die Links (Partner-Tag 60pro05-21) kauft ihr zum gleichen Preis – Amazon zahlt eine kleine Provision.

Brettspiel-News.de · (C) liegt beim jeweiligen Rechteinhaber

""" # Clean up extended chars for Joomla body_html = body_html.replace("ö", "ö").replace("ä", "ä").replace("ü", "ü").replace("ß", "ß") print(f"\nArticle body: {len(body_html)} chars, {total_count} games, {group_count} groups") # Step 3: POST article print("\nCreating Joomla article...") article = { "title": "🧒 Sonntags-Kinderspiele: Die 20 besten Angebote für kleine Spieler", "introtext": body_html, "fulltext": body_html, "catid": 61, "state": 0, "access": 6, "created_by": 560, "language": "de", "featured": 1, "metadesc": f"20 reduzierte Kinderspiele bei Amazon: Monsterjäger -54%, Pupsparade -42%, Sagaland -43% – sortiert nach Altersgruppen. Alle Deals mit Direktlinks.", "metakey": "Kinderspiele, Kinder Brettspiele, Angebote, Amazon Deals, Monsterjäger, Pupsparade, Sagaland, Kinderspiel des Jahres", "metadata": {"author": "Daniel Krause", "robots": "index, follow"}, "images": { "image_intro": "https://www.brettspiel-news.de/images/Spiele/2026/monsterjaeger_kinderspiele_2026-06-21.jpg#joomlaImage://local-images/Spiele/2026/monsterjaeger_kinderspiele_2026-06-21.jpg?width=&height=" }, } result = api_post("/content/articles", article) article_id = result["data"]["id"] print(f"\n✅ Article created! ID: {article_id}") print(f"URL: https://www.brettspiel-news.de/index.php?option=com_content&view=article&id={article_id}") print(f"Article server: http://185.162.249.159:8890/?key=br3ttsp1el-n3ws-2026") # Print summary print(f"\n=== KINDERSPIELE TOP 20 ===") print(f"Spiele: {total_count}") print(f"Altersgruppen: {group_count}") for line in summary_lines: print(f" {line}")