Ë
     y!jÐ~  ã                   óT  — d Z ddlZddlZddlZddlZddlZddlZddlmZ ddl	m
Z
mZmZmZ  ej                  e«      Zddddd	d
ddddddddddœZdedeeef   fd„ZdRd„ZdRd„Zd„ Zd„ Zdedefd„Zdedefd„Zdedz  fd„Zdedefd „Zdededefd!„Zdededefd"„Z dRd#ed$edz  defd%„Z!d&„ Z"d'„ Z#d(„ Z$d)edefd*„Z%d)ed+e&ed,f   defd-„Z'dede&ed,f   fd.„Z(dede&ed,f   fd/„Z)dede&ed,f   fd0„Z*ddd1œdeded2edz  d$edz  de+e   f
d3„Z,d4e+e   defd5„Z-deded6edefd7„Z.d8ed9ed:ed;edef
d<„Z/d=ede+e&eef      fd>„Z0d?edefd@„Z1d=edefdA„Z2d=ededefdB„Z3d=ededefdC„Z4dSdDededefdE„Z5dDede+fdF„Z6dDedefdG„Z7d=edHe+de+fdI„Z8dJedefdK„Z9dddLdMœdNedOed$efdP„Z:dQ„ Z;y)TuK   Content Service â€” Generates full SEO-optimized blog articles with Claude.é    N)Úsettings)ÚBlogArticleÚBlogArticleImageÚBlogGenerationLogÚBlogSettingsé<   é    é   é   éÜ  éÄ	  é�  éX  é   é   éx  éÐ  éà.  )Úmeta_title_maxÚmeta_description_maxÚkeyword_density_minÚkeyword_density_maxÚword_count_minÚword_count_maxÚfaq_word_budget_minÚfaq_word_budget_maxÚmin_main_h2_countÚmin_faq_if_present_shortÚmin_faq_if_present_midÚmin_faq_if_present_longÚword_band_shortÚword_band_longÚmax_output_tokensÚlanguageÚreturnc                 ól   — | xs dj                  «       j                  d«      r	dddddddœS dd	d
ddddœS )z2Localized section headings for SEO body structure.ÚdeÚenzKey takeawayszFrequently asked questionszCommon mistakes to avoidu/   End with ## [Brand] â€” [short action headline])Útakeaways_h2Úfaq_h2Úmistakes_h2Úcta_hintÚtakeaways_altÚfaq_altzWichtigste Erkenntnisseu   HÃ¤ufig gestellte Fragenu   HÃ¤ufige Fehler vermeidenzFEnde mit ## Jetzt bei [Brand] starten (oder passende CTA-Ueberschrift))ÚlowerÚ
startswith©r$   s    úD/var/www/html/shopify_to_digistore/blogs/services/content_service.pyÚ	_seo_copyr3   #   sX   € àÒ�D×ÑÓ!×,Ñ,¨TÔ2à+Ø2Ø5ØIØ,Ø3ñ
ð 	
ð 2Ø,Ø2Ø\Ø(Ø/ñð ó    c                 óR   — t         j                  j                  | |||xs i ¬«       y )N©ÚarticleÚstepÚstatusÚdetails)r   ÚobjectsÚcreater6   s       r2   Ú	_log_stepr=   8   s(   € Ü×Ñ×$Ñ$Ø˜d¨6¸7º=Àbð %õ r4   c                 óˆ  — | j                  dg «      }|rdj                  d„ |D «       «      nd}t        }|j                  dd«      }|j                  dd«      }|j                  d	d
«      }|j                  dd«      }d}	|r¦d|j                  dd«      › d|j                  dd«      › d|j                  dd«      › d|j                  dd«      › d|j                  dd«      › ddj                  |j                  dg «      «      › d dj                  |j                  d!g «      «      › d�}	| j                  d"d#«      }
|
d#k(  rd$nd%}| j                  d&d«      }|rd'|› �nd}t        |
«      }dj                  g d(‘| d)   › ‘d*‘|› ‘d+‘| d)   › ‘d,‘| j                  d-d.«      › ‘d/‘| j                  d0d1«      › ‘d2‘|› ‘d3‘| j                  d4d5«      › ‘d‘|	› ‘d6‘|› ‘d7‘|d8   › ‘d9‘|d:   › ‘d;‘|d<   › ‘d=‘| d)   › ‘d>‘|d?   › ‘d@‘|› ‘dA‘| d)   › ‘dB‘|› ‘dC‘|› ‘dD‘|dEz
  › ‘dF‘|› ‘dG‘|› ‘dF‘|› ‘dH‘|› ‘dI‘| d)   › ‘dJ‘|› ‘«      S )KzJBuild the dynamic system prompt from BlogSettings / website configuration.Úexisting_articlesÚ
c              3   óz   K  — | ]3  }t        |t        «      r!|j                  d «      rd|d   › d|d    › �–— Œ5 y­w)Úurlz  - Útitlez -> N)Ú
isinstanceÚdictÚget)Ú.0Úas     r2   Ú	<genexpr>z'_build_system_prompt.<locals>.<genexpr>B   sA   è ø€ ð 
á&�Ü˜!œTÔ" q§u¡u¨U¤|ð �1�W‘:�,˜d 1 U¡8 *Ô-Ù&ùs   ‚9;z  Keine vorhandenr   r
   r   r   r   r   r   r	   Ú z9
Stil-Referenz (aus Analyse bestehender Artikel):
- Ton: ÚtonezNicht analysiertz
- Vokabular: Úvocabulary_levelÚmittelz
- Satzstruktur: Úsentence_styleÚGemischtz
- Absatzlaenge: Úparagraph_lengthÚkurzz
- Besonderheiten: Úunique_characteristicsÚKeinez
- Typische Elemente: ú, Útypical_elementsz
- Formatierung: Úformatting_preferencesr$   r'   zSprache: DeutschzSprache: EnglischÚdomainz+ Link: z#Du bist ein SEO-Content-Autor fuer Únamez (zl).
Du erstellst Blog-Artikel, die organischen Traffic generieren und Leser zu Aktionen konvertieren.

Ueber z	:
- Was: ÚdescriptionzKeine Beschreibungz
- Zielgruppe: Útarget_audiencezNicht definiertz
- Website: z
- Tonalitaet: Útone_descriptionzProfessionell und informativz™

Format & Struktur (Pflicht-Reihenfolge im Markdown-Body):
- Gesamtlaenge: 1.500-2.500 Woerter (Opening + Takeaways + Hauptteil + optional FAQ + CTA)
- a)  
- KEIN # H1 im Body (Titel kommt aus Frontmatter/planning; Body startet mit Fliesstext)
- Absaetze: Kurz und scanbar. Bullet Points wo sinnvoll.

Pflicht-Gliederung (exakte Reihenfolge nach YAML-Frontmatter):
1) Opening: 1-2 kurze Absaetze (max ~120 Woerter). Haupt-Keyword im ersten Satz.
2) ## r)   z÷: 4-6 Bullet-Punkte, je ein praegnanter Satz.
3) Hauptteil: 6-10 Abschnitte als ## H2 (Frage-Titel bevorzugt, z.B. "Was ist ...?", "Wie funktioniert ...?").
   Mindestens ein H2 mit Haupt-Keyword. Nutze ### H3 fuer Unterpunkte.
   Pflicht-H2: "## r+   u  " (oder sehr Ã¤hnliche Formulierung).
   Mindestens 2 interne Links in diesem Hauptteil (nicht nur in FAQ).
   Wenn FAQ geplant ist: Hauptteil etwas kuerzer halten, damit das Gesamtwortlimit eingehalten wird.
4) FAQ (NUR wenn include_faq: true im Frontmatter â€” siehe unten):
   ## r*   aÒ   mit 3-6 Eintraegen (### Frage mit ?, Antwort 2-4 Saetze).
   Wortbudget fuer FAQ: ca. 400-600 Woerter. Bei Gesamtlaenge ~1.500 Woerter: 3-4 FAQs;
   bei ~2.000+ Woertern: 4-6 FAQs.
   include_faq: true bei Erklaer-/Ratgeber-Themen (Was ist, Wie funktioniert, Guide, Tipps, Vergleich).
   include_faq: false bei sehr kurzen/promo-artigen Beitraegen oder wenn Nutzerfragen redundant waeren.
5) CTA: Letzter Abschnitt als ## mit kurzer Ueberschrift + Absatz + Link zu z.
   r,   Ú a{  

- Ueberschriften: H2 und H3, keyword-optimiert
- Bilder: 3-6 Bildplatzhalter mit detaillierter Beschreibung im Alt-Text.
  Format: [IMAGE: Alt-Text-Beschreibung]
  Das ERSTE [IMAGE: ...] ist nur das Beitragsbild (Featured Image) und darf NICHT im Fliesstext stehen.
  Weitere [IMAGE: ...] gehoeren in den Artikeltext.
  WICHTIG: Beschreibungen sollen KEINE Text-Elemente, Labels oder Produktnamen enthalten
  (AI-Bildgeneratoren halluzinieren Text). Stattdessen: Nahaufnahmen von Zutaten,
  abstrakte Illustrationen, Lifestyle-Fotos, Haende mit Produkten (ohne Label sichtbar).
- CTA: Jeder Artikel endet mit einem Call-to-Action zu z
  zU

SEO-Pflichtfelder (am Anfang des Artikels als YAML-Frontmatter):
- meta_title: Max z6 Zeichen, Haupt-Keyword am Anfang
- meta_description: é
   Ú-uR   Zeichen, mit Keyword und CTA
- include_faq: true oder false (Pflichtfeld â€” entscheide nach Thema)
- tags: 5-8 relevante Tags, kommasepariert
- slug: URL-freundlich, kurz, keyword-relevant

Kein Breadcrumb, keine Sidebar, kein Autorenblock, kein "Weitere Artikel"-Block im Body.

SEO-Checkliste (immer einhalten):
- Haupt-Keyword in: Titel (H1), Meta-Title, Meta-Description, erstem Absatz, mindestens einer H2
- 2-3 sekundaere Keywords natuerlich im Text verteilt
- Interne Verlinkung: Mindestens 2 Links zu bestehenden Artikeln
- Keyword-Dichte: Natuerlich, nicht spammy. Haupt-Keyword ca. zAx im gesamten Text.

Bestehende Artikel fuer interne Verlinkung:
z

CTA-Text: Jetzt bei z	 starten )rF   ÚjoinÚDEFAULT_SEO_RULESr3   )ÚwebsiteÚstyle_analysisr?   Ú
links_textÚ	seo_rulesr   r   r   Úmeta_desc_maxÚstyle_sectionr$   Úlang_instructionrW   Úcta_link_hintÚcopys                  r2   Ú_build_system_promptrj   >   s¬  € àŸ™Ð$7¸Ó<Ðñ ð 	�	‰	ñ 
á&ó
ô 	
ð !ð ô "€IØ#Ÿ-™-Ð(=¸qÓAÐØ#Ÿ-™-Ð(=¸qÓAÐØ—]‘]Ð#3°RÓ8€NØ—M‘MÐ"8¸#Ó>€Mà€MÙðà×Ñ˜6Ð#5Ó6Ð7ð 8Ø× Ñ Ð!3°XÓ>Ð?ð @Ø×#Ñ#Ð$4°jÓAÐBð CØ×#Ñ#Ð$6¸Ó?Ð@ð AØ!×%Ñ%Ð&>ÀÓHÐIð JØ—i‘i × 2Ñ 2Ð3EÀrÓ JÓKÐLð MØ—‘˜>×-Ñ-Ð.FÈÓKÓLÐMð Nð	ˆð �{‰{˜: tÓ,€HØ-5¸Ò-=Ñ)ÐCVÐØ�[‰[˜ 2Ó&€FÙ+1�h˜v˜hÑ'°r€MÜ�XÓ€D÷>Aó >AÐ2ð >A°7¸6±?Ð2Cð >AÀ2ð >AÀfÀXð >Að Nð >Að ˆv�Ðð>Aðð>Að 	�‰�MÐ#7Ó8Ð9ð	>Að:ð	>Að
 �{‰{Ð,Ð.?Ó@ÐAð>Að
Bð>Að ˆ8ð>Aðð>Að �{‰{Ð-Ð/MÓNÐOð>AðPð>Að €ð>Aðð>Að Ðð>Aðð>Að$ ˆNÑÐð%>Að$ð%>Að* ˜Ñ'Ð(ð+>Að*)ð+>Að2 ˆH�~Ðð3>Að2Mð3>Að< NUÐU[É_ÐL]ð=>Að<^ð=>Að> 	ˆÑÐð?>Að> ð?>Að> %�oð?>Að>
&8ð?>AðR 9@À¹Ð7HðS>AðRIðS>AðT €/ðU>AðTðU>AðZ "Ð"ð[>AðZ#ð[>Að\ # RÑ'Ð(ð]>Að\ )*ð]>Að\ +8¨ð]>Að\9?ð]>Aðr @SÐ>Sðs>Aðr TUðs>Aðr ViÐTiðs>Aðrjðs>Aðx €ðy>Aðxðy>Að| ˜V‘_Ð%ð}>Að| &/ð}>Að| 0=¨oô}>Að >Ar4   c                 ó:  — t        j                  «       }t        |j                  xs | j                  xs d«      }| j
                  xs g }|rddj                  |«      › �nd}d| j                  xs d› d| j                  xs d› |› d|d	   › d
|d   › d|d   › d�S )Nr'   z
Sekundaere Keywords: rT   rJ   z=Erstelle den vollstaendigen Artikel zum Thema:

Titel/Thema: z
Kein Titelz
Haupt-Keyword: z4

Anforderungen:
1. Pflicht-Reihenfolge: Opening -> r)   z -> H2-Hauptteil inkl. r+   a   -> (FAQ nur wenn include_faq: true) -> CTA
2. Kein # H1 im Markdown-Body
3. 3-6 Bildplatzhalter im Hauptteil (KEINE Text-Elemente in Bildbeschreibungen!)
4. Mindestens 2 interne Links im Hauptteil
5. Setze include_faq: true nur wenn echte Nutzerfragen sinnvoll sind; dann ## r*   aÇ   mit 3-6 ###-Fragen
6. Gesamt 1.500-2.500 Woerter; bei FAQ das Hauptteil-Wortbudget reduzieren, FAQ nicht weglassen wegen Laenge wenn include_faq: true

WICHTIG: Beginne mit YAML-Frontmatter:
```
---
meta_title: "..."
meta_description: "..."
include_faq: true
tags: ["tag1", "tag2", ...]
slug: "..."
---
```

Dann der Markdown-Body in der Pflicht-Reihenfolge.
WICHTIG: Keine ``` Zeilen vor oder nach dem Body (kein Code-Fence um Frontmatter oder Artikel).)	r   Úloadr3   r$   ÚlocaleÚsecondary_keywordsr_   rC   Útarget_keyword)r7   Úsettings_objri   Úsecondary_kwÚsecondary_texts        r2   Ú_build_user_promptrs   ¥   sÖ   € Ü×$Ñ$Ó&€LÜ�\×*Ñ*ÒD¨g¯n©nÒDÀÓE€DØ×-Ñ-Ò3°€Lá?KÐ
! $§)¡)¨LÓ"9Ð!:Ñ;ÐQSð ðà�m‰mÒ+˜|Ð,ð -Ø×&Ñ&Ò,¨"Ð-¨nÐ-=ð >$ð %)¨Ñ$8Ð#9Ð9PÐQUÐVcÑQdÐPeð fOð PTÐT\É~ÐN^ð _`ðcð cr4   c                 óÊ  — | xs dj                  «       } t        j                  d| t        j                  t        j                  z  «      }|r|j                  d«      j                  «       S | j                  d«      rf| j                  d«      }|d   j                  d«      r|dd  }|r|d   j                  «       dk(  r|d d }dj                  |«      j                  «       S | S )NrJ   z/^```(?:yaml|yml|markdown|md)?\s*\n(.*)\n```\s*$é   ú```r@   r   éÿÿÿÿ)	ÚstripÚreÚmatchÚDOTALLÚ
IGNORECASEÚgroupr0   Úsplitr_   )ÚtextÚfencedÚliness      r2   Ú_strip_code_fencesr‚   É   sÈ   € ØŠJ�B×ÑÓ€DÜ�X‰XØ:ØÜ
�	‰	”B—M‘MÑ!ó€Fñ
 Ø�|‰|˜A‹×$Ñ$Ó&Ð&Ø‡��uÔØ—
‘
˜4Ó ˆØ�‰8×Ñ˜uÔ%Ø˜!˜"�IˆEÙ�U˜2‘Y—_‘_Ó&¨%Ò/Ø˜#˜2�JˆEØ�y‰y˜Ó×%Ñ%Ó'Ð'Ø€Kr4   Úbodyc                 ó²  — | xs dj                  «       }|rbt        j                  d|d   j                  «       «      r;|j	                  d«       |r(t        j                  d|d   j                  «       «      rŒ;|r?|d   j                  «       dk(  r)|j	                  «        |r|d   j                  «       dk(  rŒ)dj                  |«      j                  «       S )zž
    Remove leftover ``` lines Claude often adds after YAML frontmatter.
    Without this, markdown renders them as <p>```</p> at the top of the article.
    rJ   z^```\w*\s*$r   rw   rv   r@   )Ú
splitlinesry   rz   rx   Úpopr_   )rƒ   r�   s     r2   Ú_strip_orphan_fence_linesr‡   Ü   s¦   € ð
 ŠZ�R×#Ñ#Ó%€EÙ
”B—H‘H˜^¨U°1©X¯^©^Ó-=Ô>Ø�	‰	�!Œñ ”B—H‘H˜^¨U°1©X¯^©^Ó-=Õ>á
�E˜"‘I—O‘OÓ%¨Ò.Ø�	‰	Œñ �E˜"‘I—O‘OÓ%¨Ó.à�9‰9�UÓ×!Ñ!Ó#Ð#r4   Úrawc                 ó&
  — | ddg ddddœ}t        | «      } t        j                  d| t        j                  «      }|�rÍ|j	                  d«      }t        |j	                  d«      «      |d<   	 t        j                  |«      }t        |t        «      �r€t        |j                  d«      xs d«      j                  «       |d<   t        |j                  d	«      xs d«      j                  «       |d	<   t        |j                  d
«      xs d«      j                  «       j                  d«      |d
<   |j                  d«      }t        |t        «      rE|D �cg c]5  }t        |«      j                  «       sŒt        |«      j                  «       ‘Œ7 c}|d<   nat        |t        «      rQ|j                  «       rA|j                  d«      D �cg c]#  }|j                  «       sŒ|j                  «       ‘Œ% c}|d<   t        |j                  d«      «      |d<   |d   �s |j                  d«      D �]Ü  }|j                  «       }|j'                  d«      r6|j                  dd«      d   j                  «       j                  d«      |d<   Œ[|j'                  d«      r6|j                  dd«      d   j                  «       j                  d«      |d	<   Œ¢|j'                  d«      r6|j                  dd«      d   j                  «       j                  d«      |d
<   Œé|j'                  d«      r@t        |j                  dd«      d   j                  «       j                  d«      «      |d<   �Œ:|j'                  d«      s�ŒM|j                  dd«      d   j                  «       }|j'                  d«      r	 t)        j*                  |«      |d<   �Œœ|j                  d«      D �cg c]#  }|j                  «       sŒ|j                  «       ‘Œ% c}|d<   �Œß nt        | «      |d<   t        j.                  d|d   t        j0                  «      }	|	r"|	j	                  d«      j                  «       |d<   |S c c}w c c}w # t        j                   $ r t"        j%                  d«       Y �Œ‰w xY w# t(        j,                  $ rX |j                  d«      j                  d«      D �cg c]!  }|j                  «       j                  d«      ‘Œ# nc c}w c}|d<   Y �Œàw xY wc c}w )z8Parse Claude response: YAML frontmatter + markdown body.rJ   N)rƒ   Ú
meta_titleÚmeta_descriptionÚtagsÚslugrC   Úinclude_faqz^---\s*\n(.*?)\n---\s*\n(.*)ru   é   rƒ   rŠ   r‹   r�   Ú/rŒ   Ú,rŽ   z2YAML frontmatter parse failed, using line fallbackr@   zmeta_title:Ú:z"'zmeta_description:zslug:zinclude_faq:ztags:Ú[z[]z
^#\s+(.+)$rC   )r‚   ry   rz   r{   r}   r‡   ÚyamlÚ	safe_loadrD   rE   ÚstrrF   rx   Úlistr~   Ú_parse_include_faq_valueÚ	YAMLErrorÚloggerÚwarningr0   ÚjsonÚloadsÚJSONDecodeErrorÚsearchÚ	MULTILINE)
rˆ   ÚresultÚfrontmatter_matchÚfrontmatter_textÚdatarŒ   ÚtÚlineÚtags_strÚh1_matchs
             r2   Ú_parse_article_responser©   é   sH  € ð ØØØØØØñ€Fô ˜SÓ
!€CÜŸ™Ð!@À#ÄrÇyÁyÓQÐÚØ,×2Ñ2°1Ó5ÐÜ2Ð3D×3JÑ3JÈ1Ó3MÓNˆˆv‰ð	QÜ—>‘>Ð"2Ó3ˆDÜ˜$¤Õ%Ü'*¨4¯8©8°LÓ+AÒ+GÀRÓ'H×'NÑ'NÓ'P��|Ñ$Ü-0Ø—H‘HÐ/Ó0Ò6°Bó.ç‘%“'ð Ð)Ñ*ô "% T§X¡X¨fÓ%5Ò%;¸Ó!<×!BÑ!BÓ!D×!JÑ!JÈ3Ó!O��v‘Ø—x‘x Ó'�Ü˜d¤DÔ)Ù>BÓ%U¹d¸ÄcÈ!ÃfÇlÁlÅn¤c¨!£f§l¡l¥n¸dÑ%U�F˜6’NÜ ¤cÔ*¨t¯z©z¬|à+/¯:©:°c¬?ó&Ù+: a¸a¿g¹g½i˜Ÿ™�	¨?ñ&�F˜6‘Nô )AØ—H‘H˜]Ó+ó)��}Ñ%ð �lÓ#Ø(×.Ñ.¨t×4�Ø—z‘z“|�Ø—?‘? =Ô1àŸ
™
 3¨Ó*¨1Ñ-×3Ñ3Ó5×;Ñ;¸EÓBð ˜<Ò(ð —_‘_Ð%8Ô9àŸ
™
 3¨Ó*¨1Ñ-×3Ñ3Ó5×;Ñ;¸EÓBð Ð-Ò.ð —_‘_ WÔ-Ø%)§Z¡Z°°QÓ%7¸Ñ%:×%@Ñ%@Ó%B×%HÑ%HÈÓ%O�F˜6’NØ—_‘_ ^Ô4Ü,DØŸ
™
 3¨Ó*¨1Ñ-×3Ñ3Ó5×;Ñ;¸EÓBó-�F˜=Ó)ð —_‘_ WÖ-Ø#Ÿz™z¨#¨qÓ1°!Ñ4×:Ñ:Ó<�HØ×*Ñ*¨3Ô/ðÜ-1¯Z©Z¸Ó-A˜F 6›Nð 08¯~©~¸cÔ/Bó*Ù/B¨!ÀaÇgÁgÅi˜AŸG™G�IÐ/Bñ*˜˜v›ñ7 5ô> 3°3Ó7ˆˆv‰ä�y‰y˜¨¨v©¼¿¹ÓE€HÙØ"Ÿ.™.¨Ó+×1Ñ1Ó3ˆˆw‰à€Mùòc &Vùò&øô �~‰~ò 	QÜ�N‰NÐO×Pð	Qûô2  $×3Ñ3ò ð *2¯©¸Ó)=×)CÑ)CÀCÔ)Hó.á)H Að !"§¡£	§¡°Õ 6Ù)Hùô.˜F 6œNðüò*sg   Á-C'Q1 ÅQ'Å3Q'Æ:Q1 ÇQ,ÇQ,Ç0#Q1 Î,R ÏTÏ/TÑ'
Q1 Ñ1(RÒRÒ 5TÓ&S<Ó;TÔ
Tc                 óš   — | �| dk(  ry t        | t        «      r| S t        | «      j                  «       j	                  «       }|dv ry|dv ryy )NrJ   )ÚtrueÚyesÚ1ÚjaT)ÚfalseÚnoÚ0ÚneinF)rD   Úboolr–   rx   r/   )rˆ   Úss     r2   r˜   r˜   8  sS   € Ø
€{�c˜R’iØÜ�#”tÔØˆ
ÜˆC‹�‰Ó×ÑÓ €AØÐ&Ñ&ØØÐ(Ñ(ØØr4   Úbody_mdc                 ó  — t        j                  dd| xs dt         j                  ¬«      }t        j                  dd|«      }t        j                  dd|«      }t        j                  dd|«      }t        |j	                  «       «      S )Nú	^#+\s+.+$rJ   ©Úflagsú\[IMAGE:\s*.+?\]ú\[([^\]]+)\]\([^)]+\)ú\1ú[*_`#>|])ry   Úsubr    Úlenr~   )rµ   r   s     r2   Ú_count_markdown_wordsrÀ   E  sg   € Ü�6‰6�,  G¢M¨r¼¿¹ÔF€DÜ�6‰6Ð% r¨4Ó0€DÜ�6‰6Ð*¨E°4Ó8€DÜ�6‰6�+˜r 4Ó(€DÜˆt�z‰z‹|ÓÐr4   c                 óä   — d}d}| xs dj                  «       D ]T  }|j                  d«      r't        |dd  j                  «       t	        |«      «      }Œ;|sŒ>|j                  d«      sŒP|dz  }ŒV |S )Nr   FrJ   ú## r   z### ru   ©r…   r0   Ú_heading_matchesrx   Ú_faq_heading_patterns)rµ   r$   ÚcountÚin_faqr¦   s        r2   Ú_count_faq_itemsrÈ   M  so   € Ø€EØ€FØ’˜B×*Ñ*Ö,ˆØ�?‰?˜5Ô!Ü% d¨1¨2 h§n¡nÓ&6Ô8MÈhÓ8WÓXˆFØÚ�d—o‘o fÕ-Ø�Q‰J‰Eð -ð €Lr4   c                 óª   — | xs dj                  «       D ]<  }|j                  d«      sŒt        |dd  j                  «       t	        |«      «      sŒ< y y)NrJ   rÂ   r   TFrÃ   )rµ   r$   r¦   s      r2   Ú_has_faq_sectionrÊ   Y  sJ   € Ø’˜B×*Ñ*Ö,ˆØ�?‰?˜5Õ!Ü  Q R §¡Ó 0Ô2GÈÓ2QÕRÙð -ð r4   Ú
word_countrd   c                 óÖ   — |xs t         }| |j                  dd«      k\  r|j                  dd«      S | |j                  dd«      k\  r|j                  dd«      S |j                  d	d
«      S )Nr"   r   r    r
   r!   r   r   r   r   r   )r`   rF   )rË   rd   Úruless      r2   Ú_min_faq_for_word_countrÎ   a  sk   € ØÒ*Ô*€EØ�U—Y‘YÐ/°Ó6Ò6Ø�y‰yÐ2°AÓ6Ð6Ø�U—Y‘YÐ0°$Ó7Ò7Ø�y‰yÐ1°1Ó5Ð5Ø�9‰9Ð/°Ó3Ð3r4   c                 ó(  — t        j                  dd| t         j                  ¬«      }t        j                  dd|«      }t        j                  dd|«      }t        j                  dd|«      }t        d„ |j	                  d	«      D «       d«      }|d | S )
Nr·   rJ   r¸   rº   r»   r¼   r½   c              3   ó^   K  — | ]%  }|j                  «       sŒ|j                  «       –— Œ' y ­w©N)rx   )rG   Úps     r2   rI   z%_excerpt_from_body.<locals>.<genexpr>o  s!   è ø€ ÐDÑ$6˜q¸!¿'¹'½)�—‘—Ñ$6ùs   ‚-˜-z

)ry   r¾   r    Únextr~   )rƒ   Úmax_lenr   Úparas       r2   Ú_excerpt_from_bodyrÖ   j  sy   € Ü�6‰6�,  D´·±Ô=€DÜ�6‰6Ð% r¨4Ó0€DÜ�6‰6Ð*¨E°4Ó8€DÜ�6‰6�+˜r 4Ó(€DÜÑD D§J¡J¨vÔ$6ÓDÀbÓI€DØ��ˆ>Ðr4   c                 ó°  — g }| j                  d«      xs |j                  xs d}t        |j                  dd«      «      }t        |j                  dd«      «      }| j                  d«      s+|xs |j                  xs dd	| | d<   |j	                  d«       | j                  d
«      s>t        |xs |j                  xs d|j                  › �«      | d
<   |j	                  d
«       | j                  d«      sLt        | j                  d«      xs d|«      xs |j                  xs |xs dd	| | d<   |j	                  d«       | j                  d«      s|| d<   | j                  d«      sf|j                  r|j                  gng }|j                  |j                  xs g «       |D �cg c]  }|sŒ|‘Œ	 c}d	d | d<   |r|j	                  d«       |S c c}w )z?Derive SEO fields when the model omits or malforms frontmatter.rC   rJ   r   r   r   r	   rŠ   ÚBlogNr�   zarticle-r‹   rƒ   rŒ   r   )
rF   rC   Úintro   ÚappendÚ_generate_slugÚpkrÖ   Úextendrn   )	Úparsedr7   rd   Ú	fallbacksrC   ÚtmaxÚdmaxrŒ   r¥   s	            r2   Ú_fill_missing_metadatarâ   s  sÂ  € à€IØ�J‰J�wÓÒ6 7§=¡=Ò6°B€EÜˆy�}‰}Ð-¨rÓ2Ó3€DÜˆy�}‰}Ð3°SÓ9Ó:€Dà�:‰:�lÔ#Ø %Ò I¨×)?Ñ)?Ò IÀ6È5ÈDÐQˆˆ|ÑØ×Ñ˜Ô&Ø�:‰:�fÔÜ'ØÒF�W×+Ñ+ÒF°¸'¿*¹*¸Ð/Fó
ˆˆv‰ð 	×Ñ˜Ô Ø�:‰:Ð(Ô)Ü%7Ø�J‰J�vÓÒ$ " dó&
ò &<à×$Ñ$Ò3¨Ò3°°U°dÐ;ð 	Ð!Ñ"ð 	×ÑÐ+Ô,Ø�:‰:�gÔØˆˆw‰Ø�:‰:�fÔØ+2×+AÒ+A�×&Ñ&Ñ'ÀrˆØ�‰�G×.Ñ.Ò4°"Ô5Ù%)Ó/¡T ªQš! TÑ/°°Ð3ˆˆv‰ÙØ×Ñ˜VÔ$ØÐùò 0s   Æ)GÆ1Gc                 ól  — t        | ||«      }| j                  dd«      j                  «       st        d«      ‚t	        |j                  dd«      «      }t	        |j                  dd«      «      }| d   d | | d<   | d	   d | | d	<   t        | d
   xs | j                  d«      xs d«      | d
<   |r|| d<   | S )Nrƒ   rJ   z!Model returned empty article bodyr   r   r   r	   rŠ   r‹   r�   rC   Ú_metadata_fallbacks)râ   rF   rx   Ú
ValueErrorrÙ   rÛ   )rÞ   r7   rd   rß   rà   rá   s         r2   Ú_validate_metaræ   ’  sÅ   € Ü& v¨w¸	ÓB€IØ�:‰:�f˜bÓ!×'Ñ'Ô)ÜÐ<Ó=Ð=Üˆy�}‰}Ð-¨rÓ2Ó3€DÜˆy�}‰}Ð3°SÓ9Ó:€DØ! ,Ñ/°°Ð6€Fˆ<ÑØ!'Ð(:Ñ!;¸E¸TÐ!B€FÐÑÜ# F¨6¡NÒ$O°f·j±jÀÓ6IÒ$OÈRÓP€Fˆ6�NÙØ(1ˆÐ$Ñ%Ø€Mr4   r   c                 óp   — t        j                  dd| xs dj                  «       j                  «       «      S )Nz\s+r\   rJ   )ry   r¾   rx   r/   )r   s    r2   Ú_normalize_headingrè      s+   € Ü�6‰6�&˜# ¢
¨×1Ñ1Ó3×9Ñ9Ó;Ó<Ð<r4   Úpatterns.c                 óB   ‡— t        | «      Št        ˆfd„|D «       «      S )Nc              3   ó2   •K  — | ]  }|‰v xs ‰|v –— Œ y ­wrÑ   © )rG   rÒ   Únorms     €r2   rI   z#_heading_matches.<locals>.<genexpr>¦  s"   øè ø€ Ð8©x¨!ˆq�DˆyÒ%˜D A˜IÓ%©xùs   ƒ)rè   Úany)r   ré   rí   s     @r2   rÄ   rÄ   ¤  s   ø€ Ü˜dÓ#€DÜÓ8©xÓ8Ó8Ð8r4   c                 óT   — t        | «      }t        |d   «      t        |d   «      ddfS )Nr)   r-   zwichtigste erkenntnissezkey takeaways©r3   rè   ©r$   ri   s     r2   Ú_takeaway_heading_patternsrò   ©  s6   € Ü�XÓ€Dä˜4 Ñ/Ó0Ü˜4 Ñ0Ó1Ø!Øð	ð r4   c                 óV   — t        | «      }t        |d   «      t        |d   «      dddfS )Nr*   r.   u   hÃ¤ufig gestellte fragenzfrequently asked questionsÚfaqrð   rñ   s     r2   rÅ   rÅ   ³  s7   € Ü�XÓ€Dä˜4 ™>Ó*Ü˜4 	™?Ó+Ø"Ø$Øðð r4   c                 ó:   — t        | «      }t        |d   «      ddfS )Nr+   zcommon mistakesu   hÃ¤ufige fehlerrð   rñ   s     r2   Ú_mistakes_heading_patternsrö   ¾  s)   € Ü�XÓ€Dä˜4 Ñ.Ó/ØØðð r4   ©rŽ   rd   rŽ   c          	      óÜ  ‡— |xs t         }g }| xs dj                  «       s|j                  d«       |S t        | «      }|j	                  dd«      }|j	                  dd«      }||dz
  k  r|j                  d|› d	|› �«       n||d
z   kD  r|j                  d|› d|› �«       t        j                  d| t
        j                  «      r|j                  d«       t        | ‰«      }	|	rt        | ‰«      nd}
t        j                  d| «      s|j                  d«       nÙt        j                  d| «      }t        ˆfd„|D «       «      s|j                  d«       t        ˆfd„|D «       «      s|j                  d«       |D �cg c].  }t        |t        ‰«      «      st        |t        ‰«      «      s|‘Œ0 }}|j	                  dd«      }t        |«      |k  r |j                  dt        |«      › d	|› �«       |du r?|	s|j                  d«       |S t!        ||«      }|
|k  r|j                  d|
› d	|› �«       |S |dur*|	r(t!        ||«      }|
|k  r|j                  d|
› d	|› �«       |S c c}w )zIReturn warnings for SEO body structure (FAQ rules depend on include_faq).rJ   Ú
empty_bodyr   r   r   r   éÈ   zshort_article:Ú<i,  zlong_article:Ú>z	^#\s+[^#]Ú
h1_in_bodyr   z(?m)^##\s+.+Úno_h2_sectionsz(?m)^##\s+(.+)$c              3   óH   •K  — | ]  }t        |t        ‰«      «      –— Œ y ­wrÑ   )rÄ   rò   ©rG   r¥   r$   s     €r2   rI   z1_validate_content_structure_md.<locals>.<genexpr>ç  ó#   øè ø€ ð 
ÙOWÈ!Ô˜QÔ :¸8Ó D×EÉxùó   ƒ"Úmissing_key_takeawaysc              3   óH   •K  — | ]  }t        |t        ‰«      «      –— Œ y ­wrÑ   )rÄ   rö   r   s     €r2   rI   z1_validate_content_structure_md.<locals>.<genexpr>ë  r  r  Úmissing_mistakes_sectionr   r
   zfew_main_sections:TÚmissing_faq_sectionúfew_faq_items:F)r`   rx   rÚ   rÀ   rF   ry   rŸ   r    rÊ   rÈ   Úfindallrî   rÄ   rò   rÅ   r¿   rÎ   )rµ   r$   rŽ   rd   rÍ   ÚwarningsrË   ÚwminÚwmaxÚhas_faqÚ	faq_countÚh2_textsr¥   Úmain_h2Úmin_h2Úmin_faqs    `              r2   Ú_validate_content_structure_mdr  Ç  st  ø€ ð Ò*Ô*€EØ€HØŠM�r× Ñ Ô"Ø�‰˜Ô%Øˆä& wÓ/€JØ�9‰9Ð% tÓ,€DØ�9‰9Ð% tÓ,€DØ�D˜3‘JÒØ�‰˜.¨¨°A°d°VÐ<Õ=Ø	�d˜S‘jÒ	 Ø�‰˜-¨
 |°1°T°FÐ;Ô<ä	‡y�y�˜w¬¯©Ô5Ø�‰˜Ô%ä˜w¨Ó1€GÙ7>Ô  ¨(Ô3ÀA€Iä�9‰9�_ gÔ.Ø�‰Ð(Õ)ä—:‘:Ð0°'Ó:ˆÜó 
ÙOWó
ô 
ð �O‰OÐ3Ô4Üó 
ÙOWó
ô 
ð �O‰OÐ6Ô7ñ ó
á�Ü# AÔ'AÀ(Ó'KÔLÜ$ QÔ(=¸hÓ(GÔHò Øð 	ð 
ð —‘Ð.°Ó2ˆÜˆw‹<˜&Ò Ø�O‰OÐ0´°W³°¸aÀ¸xÐHÔIà�dÑÙØ�O‰OÐ1Ô2ð €Oô .¨j¸%Ó@ˆGØ˜7Ò"Ø—‘ .°°¸1¸W¸IÐ FÔGð €Oð 
˜EÑ	!¡gÜ)¨*°eÓ<ˆØ�wÒØ�O‰O˜n¨Y¨K°q¸¸	ÐBÔCà€Oùò-
s   Æ3I)r	  c                 ó&   — t        d„ | D «       «      S )Nc              3   óL   K  — | ]  }|d k(  xs |j                  d«      –— Œ y­w)r  r  N)r0   )rG   Úws     r2   rI   z._faq_structure_needs_repair.<locals>.<genexpr>	  s0   è ø€ ð áˆAð 	
Ð"Ñ"ÒD a§l¡lÐ3CÓ&DÓDÙùs   ‚"$)rî   )r	  s    r2   Ú_faq_structure_needs_repairr    s   € Üñ áóó ð r4   r  c                 óÄ   — t        |«      }t        j                  dd«      }t        j                  dd«      }t        | «      dkD  r| dd  n| }d|d   › d	|› d
|› d|› d|› d�S )Nr   r   r   r   ip  i�èÿÿzàDer Blog-Artikel unten hat include_faq: true, aber der FAQ-Abschnitt fehlt oder ist unvollstaendig.

Aufgabe: Gib den VOLLSTAENDIGEN Markdown-Body zurueck (ohne YAML-Frontmatter, kein # H1).
- Fuege oder vervollstaendige ## r*   z mit mindestens z¤ FAQ-Eintraegen.
- Jede Frage als ### (vollstaendige Frage mit ?), Antwort 2-4 Saetze.
- FAQ vor dem letzten CTA-##-Abschnitt einfuegen.
- Wortbudget fuer FAQ: ca. r^   z¢ Woerter; passe den Hauptteil leicht an, Gesamt 1.500-2.500 Woerter.
- Alle anderen Pflicht-Abschnitte (Takeaways, Hauptteil, Fehler, CTA) beibehalten.

Artikel:
r@   )r3   r`   rF   r¿   )rµ   r$   r  ri   ÚbudgetÚ
budget_maxÚ	body_tails          r2   Ú_build_faq_repair_promptr    s�   € Ü�XÓ€DÜ×"Ñ"Ð#8¸#Ó>€FÜ"×&Ñ&Ð'<¸cÓB€JÜ#& w£<°$Ò#6�˜˜‘¸G€Ið"ð #' x¡.Ð!1Ð1AÀ'Àð Kð #˜8 1 Z Lð 1ð €ð ðð r4   ÚmodelÚsystemÚuserÚ
max_tokensc                 ó˜   — | j                   j                  ||d|dœg|d¬«      }|j                  d   j                  j	                  «       S )Nr  )ÚroleÚcontentg      à?)r  r  Úmessagesr  Útemperaturer   )r#  r<   r"  r   rx   )Úclientr  r  r  r  Úresponses         r2   Ú_claude_messager'  "  sT   € Ø�‰×%Ñ%ØØØ!¨dÑ3Ð4ØØð &ó €Hð ×Ñ˜AÑ×#Ñ#×)Ñ)Ó+Ð+r4   Úhtmlc                 óŠ  — t        j                  d| t         j                  ¬«      }g }|D ]•  }|j                  «       }|sŒt        j                  d|t         j
                  t         j                  z  «      }|r2|j                  |j                  d«      |j                  d«      f«       Œ€|rŒƒ|j                  d|f«       Œ— |S )z1Return list of (h2_html, following_content_html).z(?=<h2[\s>])r¸   z(<h2[^>]*>.*?</h2>)(.*)ru   r�   rJ   )ry   r~   r|   rx   rz   r{   rÚ   r}   )r(  ÚpartsÚblocksÚpartÚms        r2   Ú_split_html_by_h2r.  -  s–   € ä�H‰H�_ d´"·-±-Ô@€EØ€FÛˆØ�z‰z‹|ˆÙØÜ�H‰HÐ/°´r·y±yÄ2Ç=Á=Ñ7PÓQˆÙØ�M‰M˜1Ÿ7™7 1›: q§w¡w¨q£zÐ2Õ3ÚØ�M‰M˜2˜t˜*Õ%ð ð €Mr4   Úh2_htmlc                 óT   — t        j                  dd| xs d«      j                  «       S )Nú<[^>]+>rJ   )ry   r¾   rx   )r/  s    r2   Ú_h2_inner_textr2  =  s"   € Ü�6‰6�*˜b '¢-¨RÓ0×6Ñ6Ó8Ð8r4   c                 óx   — d„ }t        j                  d|| t         j                  t         j                  z  ¬«      S )Nc                 ó
  — | j                  d«      xs d}| j                  d«      }t        j                  d|t        j                  «      r| j                  d«      S t	        t        d|› d�«      «      xs d}d	|› d
|› d|› d�S )Nru   rJ   r�   z\bid\s*=r   z<span>z</span>Úsectionz<h2 id="Ú"rü   z</h2>)r}   ry   rŸ   r|   rÛ   r2  )rz   ÚattrsÚinnerr�   s       r2   Úreplz_add_h2_ids.<locals>.replB  s{   € Ø—‘˜A“Ò$ "ˆØ—‘˜A“ˆÜ�9‰9�[ %¬¯©Ô7Ø—;‘;˜q“>Ð!Üœn¨v°e°W¸GÐ-DÓEÓFÒSÈ)ˆØ˜$˜˜q   q¨¨¨uÐ5Ð5r4   z<h2(\s[^>]*)?>(.*?)</h2>r¸   )ry   r¾   r|   r{   )r(  r9  s     r2   Ú_add_h2_idsr:  A  s3   € ò6ô �6‰6Ø#ØØÜ�m‰mœbŸi™iÑ'ô	ð r4   c                 ó¤  — t        | «      }|s| S |d   d   dk(  r|d   d   nd}|d   d   dk(  r|dd }|r|gng }t        |«      }t        |«      }|D ]j  \  }}t        |«      }	||z   }
t	        |	|«      r|j                  d|
› d�«       Œ8t	        |	|«      r|j                  d|
› d�«       ŒZ|j                  |
«       Œl dj                  |«      S )	z4Wrap key takeaways and FAQ blocks for theme styling.r   rJ   ru   Nz <div class="blog-key-takeaways">z</div>z<section class="blog-faq">z
</section>)r.  rò   rÅ   r2  rÄ   rÚ   r_   )r(  r$   r+  ÚprefixÚoutÚtakeaway_patternsÚfaq_patternsr/  Ú	body_htmlrC   Úchunks              r2   Ú_wrap_seo_sectionsrB  R  sí   € ä˜tÓ$€FÙØˆà# A™Y q™\¨RÒ/ˆV�A‰Y�qŠ\°R€FØˆa�y��|�rÒØ˜˜�ˆáˆ6‰( "€CÜ2°8Ó<ÐÜ(¨Ó2€Lã$Ñˆ�Ü˜wÓ'ˆØ˜)Ñ#ˆÜ˜EÐ#4Ô5Ø�J‰JÐ9¸%¸ÀÐGÕHÜ˜e \Ô2Ø�J‰JÐ3°E°7¸*ÐEÕFà�J‰J�uÕð %ð �7‰7�3‹<Ðr4   c                 ó0   — t        | «      } t        | |«      S rÑ   )r:  rB  )r(  r$   s     r2   Ú_finalize_article_htmlrD  m  s   € Ü�tÓ€DÜ˜d HÓ-Ð-r4   Úmd_textc                 óz   — t        j                  dd| «      } t        j                  | g d¢¬«      }t        ||«      S )z8Convert markdown to HTML, preserving image placeholders.ú\[IMAGE:\s*(.+?)\]zE<div class="image-placeholder" data-alt="\1"><!-- IMAGE: \1 --></div>)ÚextraÚ
sane_listsÚsmarty)Ú
extensions)ry   r¾   ÚmarkdownrD  )rE  r$   r(  s      r2   Ú_markdown_to_htmlrM  r  s@   € ä�f‰fØØPØó€Gô
 ×ÑØÚ4ô€Dô " $¨Ó1Ð1r4   c                 ó.   — t        j                  d| «      S )NrG  )ry   r  ©rE  s    r2   Ú_extract_image_placeholdersrP  €  s   € Ü�:‰:Ð+¨WÓ5Ð5r4   c                 ó4   — t        j                  dd| d¬«      S )zSBody markdown for HTML: excludes the first [IMAGE] (featured-only, not in content).z\[IMAGE:\s*.+?\]\s*rJ   ru   )rÆ   )ry   r¾   rO  s    r2   Ú"_body_without_featured_placeholderrR  „  s   € ä�6‰6Ð(¨"¨g¸QÔ?Ð?r4   r?   c                 ó¾   — g }|xs g D ]Q  }t        |t        «      sŒ|j                  dd«      }|sŒ)|| v sŒ.|j                  |j                  dd«      |dœ«       ŒS |S )NrB   rJ   rC   )rC   rB   )rD   rE   rF   rÚ   )r(  r?   ÚlinksÚartrB   s        r2   Ú_extract_internal_linksrV  ‰  sb   € Ø€EØ Ò& BÒ&ˆÜ˜#œtÔ$ØØ�g‰g�e˜RÓ ˆÚ�3˜$’;Ø�L‰L 3§7¡7¨7°BÓ#7ÀÑDÕEð 'ð €Lr4   rC   c                 ó  — | xs dj                  «       }dddddœ}|j                  «       D ]  \  }}|j                  ||«      }Œ t        j                  dd|«      }t        j                  d	d|«      j                  d«      }|d d
 S )NrJ   ÚaeÚoeÚueÚss)ô   Ã¤ô   Ã¶ô   Ã¼ô   ÃŸz[^a-z0-9\-]r^   z-+éP   )r/   ÚitemsÚreplacery   r¾   rx   )rC   r�   ÚreplacementsÚoldÚnews        r2   rÛ   rÛ   ”  s‹   € ØŠK�R×ÑÓ €DàØØØñ	€Lð !×&Ñ&Ö(‰ˆˆSØ�|‰|˜C Ó%‰ð )ä�6‰6�. # tÓ,€DÜ�6‰6�%˜˜dÓ#×)Ñ)¨#Ó.€DØ��ˆ9Ðr4   F©Úmeta_fallbacksÚstructure_warningsÚfaq_repairedrÞ   ra   c                ó@  — t        |d   «      }|r|d   nd}|dd }	|d   }
|rt        |
«      }
|j                  d| j                  xs d«      }t	        |
|¬«      }t        j                  dd	|«      }t        |j                  «       «      }| j                  xs d	j                  «       }|r|j                  «       j                  |«      nd}t        |t        |d«      z  d
z  d«      }t        ||j                  dg «      «      }|j                  d«      xs | j                  | _        |j                  d«      xs% t!        |j                  d| j                  «      «      | _        || _        |d   | _        |d   | _        |j                  d«      xs g | _        || _        || _        || _        d	| _        | j5                  g d¢¬«       | j6                  j9                  «       j;                  «        |r#t<        j>                  jA                  | |dd¬«       tC        |	d¬«      D ]+  \  }}t<        j>                  jA                  | |d|› �d¬«       Œ- ||t        |«      |j                  d«      tE        |
|«      dœ}|r||d<   |r||d<   |rd|d<   | |t        |«      fS )z?Convert parsed markdown to HTML and save article + image slots.rƒ   r   Nru   r$   r'   r1   r1  rJ   éd   r�   r?   rC   r�   rŠ   r‹   rŒ   )rC   r�   r"  rŠ   r‹   rŒ   rË   Úkeyword_densityÚinternal_linksÚgeneration_errorÚ
updated_at©Úupdate_fieldsÚheaderÚpending)r7   Úalt_textÚpositionÚgeneration_status)Ústartzinline-rŽ   )rË   rl  Úimage_placeholdersrŽ   r  Úmetadata_fallbacksrh  Tri  )#rP  rR  rF   rm   rM  ry   r¾   r¿   r~   ro   r/   rÆ   ÚroundÚmaxrV  rC   rÛ   r�   r"  rŠ   r‹   rŒ   rË   rl  rm  rn  ÚsaveÚimagesÚallÚdeleter   r;   r<   Ú	enumeraterÈ   )r7   rÞ   ra   rd   rg  rh  ri  rx  Ú
header_altÚinline_altsrµ   r$   Úhtml_contentÚ
plain_textrË   ÚkeywordÚkeyword_countrl  rm  ÚiÚaltÚlog_detailss                         r2   Ú_persist_generated_articlerŠ  £  s¥  € ô 5°V¸F±^ÓDÐÙ*<Ð# AÒ&À$€JØ$ Q RÐ(€Kà�V‰n€GÙÜ4°WÓ=ˆà�{‰{˜: w§~¡~Ò'=¸Ó>€HÜ$ W°xÔ@€LÜ—‘˜
 B¨Ó5€JÜ�Z×%Ñ%Ó'Ó(€Jà×%Ñ%Ò+¨×2Ñ2Ó4€GÙ9@�J×$Ñ$Ó&×,Ñ,¨WÔ5Àa€MÜ˜M¬C°
¸AÓ,>Ñ>ÀÑDÀaÓH€OÜ,Ø�g—k‘kÐ"5°rÓ:ó€Nð —J‘J˜wÓ'Ò8¨7¯=©=€G„MØ—:‘:˜fÓ%ò ¬Ø�
‰
�7˜GŸM™MÓ*ó*€G„Lð #€G„OØ Ñ-€GÔØ%Ð&8Ñ9€GÔØ—:‘:˜fÓ%Ò+¨€G„LØ#€GÔØ-€GÔØ+€GÔØ!€GÔØ‡L�Lò
ð ô ð  ‡N�N×ÑÓ×ÑÔ!ÙÜ× Ñ ×'Ñ'ØØØØ'ð	 	(ô 	
ô ˜K¨q×1‰ˆˆ3Ü× Ñ ×'Ñ'ØØØ˜q˜c�]Ø'ð	 	(õ 	
ð 2ð !Ø*Ü!Ð"4Ó5Ø—z‘z -Ó0Ü% g¨xÓ8ñ€Kñ Ø,:ˆÐ(Ñ)ÙØ,>ˆÐ(Ñ)ÙØ&*ˆ�NÑ#Ø�K¤Ð%7Ó!8Ð8Ð8r4   c           
      óª  — t         j                  j                  | ¬«      }t        j                  «       j                  «       }t        }t         j                  |_        |j                  ddg¬«       t        |dd«       t        t        dd«      }|st        d	«      ‚t        t        d
d«      }t        t        t        dd«      xs |j                  dd«      «      }t        |«      }t!        |«      }	 t#        j$                  |¬«      }	t'        |	||||«      }
t        |dddt)        |
«      i«       t+        t-        |
«      ||«      }|j/                  dd«      }|j                  d|j0                  xs d«      }|j                  d«      }|d   }t3        ||||¬«      }d}|du rÁt5        |«      r¶t6        j9                  d| |«       t        |ddd|i«       t;        t=        |«      |«      }t'        |	||t?        |||«      |«      }t-        |«      }|j                  d«      xs ||d<   |j                  d«      �|d   |d<   d}t3        |d   |d|¬«      }t        |ddd|i«       tA        |||||||¬«      \  }}}|rt6        jC                  d | |«       t        |d!d|«       t6        j9                  d"| |j                  d#«      ||j                  d«      «       |S # tD        $ rn}t6        jG                  d$| «       t         jH                  |_        tK        |«      |_&        |j                  g d%¢¬«       t        |dd&d'tK        |«      i«       ‚ d}~ww xY w)(zEGenerate a full blog article using Claude (Django worker entrypoint).)rÜ   r9   ro  rp  Úcontent_generationÚstartedÚANTHROPIC_API_KEYrJ   z ANTHROPIC_API_KEY not configuredÚANTHROPIC_MODELzclaude-sonnet-4-20250514ÚBLOG_CONTENT_MAX_TOKENSNr#   r   )Úapi_keyÚ	completedÚ
raw_lengthrä   r$   r'   rŽ   rƒ   r÷   FTz#Article %s FAQ repair triggered: %sÚ
faq_repairr	  Úwarnings_afterrf  z!Article %s structure warnings: %sÚcontent_completez9Article %s generated: %s words, %s images, include_faq=%srË   z Article generation failed for %s)r9   rn  ro  ÚfailedÚerror)'r   r;   rF   r   rl   Úas_prompt_configr`   ÚSTATUS_GENERATINGr9   r|  r=   Úgetattrr   ÚRuntimeErrorrÙ   rj   rs   Ú	anthropicÚ	Anthropicr'  r¿   ræ   r©   r†   rm   r  r  rš   ÚinforÎ   rÀ   r  rŠ  r›   Ú	ExceptionÚ	exceptionÚSTATUS_FAILEDr–   rn  )Ú
article_idr7   ra   rd   Úkeyr  r  Úsystem_promptÚuser_promptr%  Úraw_contentrÞ   rg  r$   rŽ   rµ   rh  ri  r  Ú
repair_rawÚrepairedr‰  Ú	img_countÚexcs                           r2   Úgenerate_article_contentr¬  þ  sp  € ä×!Ñ!×%Ñ%¨Ð%Ó4€GÜ×ÑÓ!×2Ñ2Ó4€GÜ!€Iä ×2Ñ2€G„NØ‡L�L ¨,Ð7€LÔ8ÜˆgÐ+¨YÔ7ä
”(Ð/°Ó
4€CÙÜÐ=Ó>Ð>Ü”HÐ/Ð1KÓL€EÜÜ”Ð3°TÓ:ò 	5Ø�=‰=Ð,¨eÓ4ó€Jô
 )¨Ó1€MÜ$ WÓ-€Kð^Ü×$Ñ$¨SÔ1ˆÜ%Ø�E˜=¨+°zó
ˆô 	ØØ ØØœ3˜{Ó+Ð,ô		
ô  Ü# KÓ0°'¸9ó
ˆð  Ÿ™Ð$9¸4Ó@ˆà—;‘;˜z¨7¯>©>Ò+A¸TÓBˆØ—j‘j Ó/ˆØ˜‘.ˆÜ;ØØØ#Øô	
Ðð ˆØ˜$ÑÔ#>Ð?QÔ#RÜ�K‰KØ5ØØ"ôô
 �g˜|¨Y¸ÐEWÐ8XÔYÜ-Ô.CÀGÓ.LÈiÓXˆGÜ(ØØØÜ(¨°(¸GÓDØóˆJô /¨zÓ:ˆHØ%Ÿ\™\¨&Ó1Ò?°ZˆF�6‰NØ�|‰|˜MÓ*Ð6Ø(0°Ñ(?��}Ñ%ØˆLÜ!?Ø�v‘ØØ Ø#ô	"Ðô ØØØØ!Ð#5Ð6ô	ô +EØØØØØ)Ø1Ø%ô+
Ñ'ˆ�˜iñ Ü�N‰NØ3ØØ"ôô
 	�'Ð-¨{¸KÔHä�‰ØGØØ�O‰O˜LÓ)ØØ�O‰O˜MÓ*ô	
ð ˆøäò Ü×ÑÐ;¸ZÔHÜ$×2Ñ2ˆŒÜ#& s£8ˆÔ Ø�‰Ò#OˆÔPÜ�'Ð/°¸GÄSÈÃXÐ;NÔOØûðús   Ã3G'K Ë	MË$A)MÍMrÑ   )r'   )<Ú__doc__rœ   Úloggingry   r�  rL  r”   Údjango.confr   Úblogs.modelsr   r   r   r   Ú	getLoggerÚ__name__rš   r`   r–   rE   r3   r=   rj   rs   r‚   r‡   r©   r³   r˜   rÙ   rÀ   rÈ   rÊ   rÎ   rÖ   râ   ræ   rè   ÚtuplerÄ   rò   rÅ   rö   r—   r  r  r  r'  r.  r2  r:  rB  rD  rM  rP  rR  rV  rÛ   rŠ  r¬  rì   r4   r2   Ú<module>r´     sž  ðÙ Qã Û Û 	ã Û Û Ý  ç WÓ Wà	ˆ×	Ñ	˜8Ó	$€ð ØØØØØØØØØ !ØØ ØØØñÐ ð&˜ð   S¨# X¡ó ó*ódAòN!còHð&
$ Cð 
$¨Có 
$ðL ð L¨ó Lð^
 T¨D¡[ó 
ð 3ð ¨3ó ð	˜cð 	¨Sð 	°Só 	ð˜cð ¨Sð °Tó ñ4¨ð 4¸¸t¹ð 4Èsó 4òòò>ð=˜Sð = Só =ð9˜3ð 9¨%°°S°©/ð 9¸dó 9ð
¨ð °°s¸C°x±ó ð Cð ¨E°#°s°(©Oó ð¨ð °°s¸C°x±ó ð  $Ø!ò>Øð>àð>ð ˜‘ð	>ð
 �d‰{ð>ð 
ˆ#�Yó>ðB¨$¨s©)ð ¸ó ð cð °Sð À3ð È3ó ð&, 3ð ,°ð ,¸3ð ,ÈCð ,ÐTWó ,ð˜Cð  D¨¨s°C¨x©Ñ$9ó ð 9˜Cð 9 Có 9ð�cð ˜có ð"˜Sð ¨Cð °Có ð6. ð .°ð .¸ó .ñ
2˜sð 2¨cð 2¸Só 2ð6¨ð 6°ó 6ð@°ð @¸ó @ð
 #ð ¸$ð À4ó ð˜#ð  #ó ð* ØØòX9àðX9ð ðX9ð ó	X9óvtr4   