diff --git a/article_server.py b/article_server.py index 91b0fc9..7a6c0e8 100644 --- a/article_server.py +++ b/article_server.py @@ -181,13 +181,15 @@ def _get_unpublished_articles() -> list[dict]: return articles[:50] # Max 50 SKIP_PATTERNS = [ - r'^ddg\d*\.html', r'^google', r'^bgg_(search|thread|game|price)', + r'^ddg\\d*\\.html', r'^google', r'^bgg_(search|thread|game|price)', r'^bk_', r'^backerkit', r'^brave_search', r'^fb_post', r'^reddit', r'^rp_mg', r'^rp_gladbach', r'^spiegel', r'^sportschau', r'^transfermarkt', r'^tm_', r'^kicker', r'^brettspielbox', r'^bsg_', r'^bbb_', r'^envyborn', r'^brettspiel_news_newsletter', r'^boardgamewire', r'^ddg_', r'^blocked', r'^error', r'^just.a.moment', r'^duckduckgo', r'^update.regarding', + r'deals', r'kennerspiele', r'kombi_deals', r'top_deals', + r'kinderspiele_deals', r'amazon_deals', r'amazon_primeday', ] @@ -1435,8 +1437,11 @@ h1{color:#c0392b;}p{color:#888;} article_body = re.sub(r']*>.*?\s*', '', article_body, flags=re.DOTALL) article_body = re.sub(r']*>.*?

\s*', '', article_body, flags=re.DOTALL) article_body = re.sub(r']*>.*?

\s*', '', article_body, flags=re.DOTALL) + # ── Fallback: strip any remaining h1 or meta (edge cases) ── + article_body = re.sub(r']*>.*?\s*', '', article_body, flags=re.DOTALL | re.IGNORECASE) + article_body = re.sub(r']*\bclass\s*=\s*"[^"]*\bmeta\b[^"]*"[^>]*>.*?

\s*', '', article_body, flags=re.DOTALL | re.IGNORECASE) # ── Umbruch vor Überschriften (Daniel 19.06.: bessere Lesbarkeit) ── - article_body = re.sub(r'()\\s*(\\n\\3', article_body) + article_body = re.sub(r'()\s*(\n\2', article_body) # ── Remove
after read-more (muss NACH Umbruch-Insertion laufen!) ── article_body = re.sub( r'()\s*\s*', @@ -1528,9 +1533,34 @@ h1{color:#c0392b;}p{color:#888;} fulltext = article_body.strip() sr_match = re.search(r'', article_body, re.IGNORECASE) if sr_match: - split_idx = sr_match.end() + split_idx = sr_match.start() introtext = article_body[:split_idx].strip() fulltext = article_body[split_idx:].strip() + # Remove the
from fulltext start + # (Joomla inserts its own read-more between introtext and fulltext) + fulltext = re.sub(r'^\s*', '', fulltext) + + # ── CSS aus in fulltext injizieren ────────────────── + # Problem: ', html_content, re.DOTALL) + if style_match: + style_css = style_match.group(1).strip() + fulltext = f'\n\n{fulltext}' + + # ── target="_blank" für externe Links erzwingen ────── + # Daniel 24.06.: Alle externen Links müssen _blank sein, + # damit brettspiel-news.de nicht verlassen wird. + def add_target_blank(m): + href = m.group(1) + rest = m.group(2) + if 'brettspiel-news.de' in href: + return m.group(0) # interne Links unverändert + if 'target=' in rest: + return m.group(0) # hat bereits target + return f'' + fulltext = re.sub(r']*)>', add_target_blank, fulltext) + introtext = re.sub(r']*)>', add_target_blank, introtext) article_payload = { "title": title, @@ -1593,7 +1623,15 @@ h1{color:#c0392b;}p{color:#888;} # Joomla requires relative + joomlaImage pseudo-protocol # Format: images/Spiele/2026/file.jpg#joomlaImage://local-images/Spiele/2026/file.jpg # image_intro braucht images/ prefix, joomlaImage NICHT - image_intro_value = f"images/{j_img_path}#joomlaImage://local-images/{j_img_path}" + # ── Bild-Dimensionen erkennen (Joomla 6 braucht ?width=&height=) ── + try: + from PIL import Image + img_pil = Image.open(image_path) + iw, ih = img_pil.size + img_pil.close() + except: + iw, ih = 1920, 1080 # Fallback: Standard-BSN-Bildmaße + image_intro_value = f"images/{j_img_path}#joomlaImage://local-images/{j_img_path}?width={iw}&height={ih}" article_payload["images"] = { "image_intro": image_intro_value, "image_intro_alt": title, @@ -1679,6 +1717,7 @@ h1{color:#c0392b;}p{color:#888;} self._json_reply(200 if published > 0 else 500, { "ok": published > 0, + "error": None if published > 0 else (errors[0] if errors else "Unbekannter Fehler beim Veröffentlichen"), "published": published, "published_ids": published_ids, "live_mode": allow_live,