Ë
    Îfjž!  ã                   óŒ   — d Z ddlZddlmZmZmZmZ ddlmZm	Z	 ddl
mZ ddlmZmZ  ej                  e«      Z G d„ d«      Zy)	zGGenerate blog images (staged locally) and upload to Shopify at publish.é    N)ÚBlogArticleÚBlogArticleImageÚBlogGenerationLogÚBlogSettings)ÚBlogImageStorageÚis_shopify_cdn_url)ÚOpenAIImageClient)ÚShopifyFileAccessErrorÚShopifyFileServicec                   ó¨   — e Zd ZdZededefd„«       Zededefd„«       Zede	dede
dee
e
f   fd	„«       Zed
e
de
de
fd„«       Zededdfd„«       Zy)ÚBlogImageServicezEOrchestrates image generation, local staging, and Shopify CDN upload.Ú
article_idÚreturnc           	      óÖ  — t         j                  j                  |¬«      }t        j                  «       }|j
                  s|S t        |j                  j                  d¬«      j                  d«      «      }|s|S t        j                  j                  |dddt        |«      i¬«       |j                  xs d	d d
 }d\  }}d	}|D ]}  }		 | j                  |	||«      }
|
d   |	_        |
d   |	_        |
j                  dd	«      |	_        d|	_        |	j)                  g d¢¬«       |dz  }|	j$                  dk(  sŒr|	j*                  }Œ |r||_        |j)                  ddg¬«       | j3                  |«       t        j                  j                  |dd||dœ¬«       |S # t        $ rD t         j#                  d||	j$                  «       d|	_        |	j)                  dg¬«       |dz  }Y �Œ"w xY w)N)ÚpkÚpending©Úgeneration_statusÚpositionÚimage_generationÚstartedÚcount©ÚarticleÚstepÚstatusÚdetailsÚ éd   )r   r   zimage failed article=%s pos=%sÚfailedr   ©Úupdate_fieldsé   Úpreview_urlÚ
local_fileÚprompt_usedÚ	completed)Ú	image_urlr%   r&   r   ÚheaderÚfeatured_image_urlÚ
updated_at)Úokr    )r   ÚobjectsÚgetr   ÚloadÚinclude_imagesÚlistÚimagesÚfilterÚorder_byr   ÚcreateÚlenÚdescriptionÚ_generate_for_slotÚ	ExceptionÚloggerÚ	exceptionr   r   Úsaver(   r%   r&   r*   Ú"_inject_inline_images_into_content)Úclsr   r   Úsettings_objr   Únicher,   ÚfailÚfeatured_previewÚimgÚresults              úB/var/www/html/shopify_to_digistore/blogs/services/image_service.pyÚgenerate_for_articlez%BlogImageService.generate_for_article   s  € ä×%Ñ%×)Ñ)¨ZÐ)Ó8ˆÜ#×(Ñ(Ó*ˆØ×*Ò*ØˆNäØ�N‰N×!Ñ!°IÐ!Ó>×GÑGÈ
ÓSó
ˆñ ØˆNä×!Ñ!×(Ñ(ØØ#ØØœc '›lÐ+ð	 	)ô 	
ð ×)Ñ)Ò/¨R°°#Ð6ˆØ‰ˆˆDØÐãˆCð	Ø×/Ñ/°°W¸eÓD�ð # =Ñ1ˆCŒMØ# LÑ1ˆCŒNØ$Ÿj™j¨¸Ó;ˆCŒOØ$/ˆCÔ!Ø�H‰Hòð ô ð �!‰GˆBØ�|‰|˜xÓ'Ø#&§=¡=Ñ ð5 ñ8 Ø)9ˆGÔ&Ø�L‰LÐ(<¸lÐ'KˆLÔLà×.Ñ.¨wÔ7ä×!Ñ!×(Ñ(ØØ#ØØ¨Ñ.ð	 	)ô 	
ð ˆøôK ò Ü× Ñ Ø4°jÀ#Ç,Á,ôð )1�Ô%Ø—‘Ð(;Ð'<�Ô=Ø˜‘	�Úðús   Ã	FÆA	G(Ç'G(r   c                 ó’  — t        |j                  j                  d¬«      j                  d«      «      }t	        d„ |D «       «      s|S |j
                  xs d}|j                  }d}d}|D �]%  }|j                  dk(  �r|j                  s"t        |j                  «      r|j                  }ŒB|j                  }t        j                  |j                  «      }	t        j                  |j                  «      j                  }
|r|}Œ›	 t        j                   |	|
|j"                  xs |j$                  ¬	«      }||_
        |j                  }d|_        |j'                  d
dg¬«       t        j(                  |«       |}|dz  }�Œ|j                  s�Œ&t        |j                  «      r�Œ=|j                  }t        j                  |j                  «      }	t        j                  |j                  «      j                  }
|r�Œ•	 t        j                   |	|
|j"                  xs |j$                  ¬	«      }|r||v r|j3                  ||«      }||_
        |j                  }d|_        |j'                  d
dg¬«       t        j(                  |«       |dz  }�Œ( |rG||_        ||_        |j'                  g d¢¬«       t4        j6                  j9                  |ddd|i¬«       |S # t*        $ r* |s t,        j/                  d|j0                  «       d}|}Y �Œ�w xY w# t*        $ r( |s t,        j/                  d|j0                  «       d}Y �ŒÚw xY w)zHUpload staged images to Shopify Files; rewrite inline URLs in body only.r'   r   r   c              3   ó4   K  — | ]  }|j                   –— Œ y ­w)N)r%   )Ú.0rC   s     rE   Ú	<genexpr>zCBlogImageService.upload_staged_images_to_shopify.<locals>.<genexpr>X   s   è ø€ Ð4©V c�3—>•>©Vùs   ‚r   r   Fr)   )ÚfilenameÚaltr(   r%   r!   r#   z�Shopify file upload denied for article=%s (reinstall OAuth with write_files). Featured image will use REST attachment at publish.TzrShopify file upload denied for article=%s (reinstall OAuth with write_files). Inline images will use preview URLs.)Úcontentr*   r+   Úshopify_image_uploadÚuploadedr   )r1   r2   r3   r4   ÚanyrM   r*   r   r%   r   r(   r   Ú
read_bytesÚresolve_pathÚnamer   Úupload_imageÚalt_textÚtitler<   Údeleter
   r:   Úwarningr   Úreplacer   r-   r5   )r>   r   r2   rM   Úfeatured_urlrO   Úuse_attachment_fallbackrC   r$   Úimage_bytesrK   Úshopify_urlr%   s                rE   Úupload_staged_images_to_shopifyz0BlogImageService.upload_staged_images_to_shopifyR   s  € ô Ø�N‰N×!Ñ!°KÐ!Ó@×IÑIÈ*ÓUó
ˆô Ñ4©VÓ4Ô4ØˆNà—/‘/Ò' RˆØ×1Ñ1ˆØˆØ"'ÐäˆCØ�|‰|˜xÓ'Ø—~’~Ü)¨#¯-©-Ô8Ø'*§}¡}˜ØØ!Ÿm™m�Ü.×9Ñ9¸#¿.¹.ÓI�Ü+×8Ñ8¸¿¹ÓH×MÑM�á*Ø#.�LØð/Ü"4×"AÑ"AØ#Ø!)ØŸL™LÒ9¨G¯M©Mô#�Kð
 %0�C”MØ!$§¡�JØ%'�C”NØ—H‘H¨K¸Ð+F�HÔGÜ$×+Ñ+¨JÔ7Ø#.�LØ ‘M�Hñ à—>’>Ùä! #§-¡-Ô0ÙàŸ-™-ˆKÜ*×5Ñ5°c·n±nÓEˆKÜ'×4Ñ4°S·^±^ÓD×IÑIˆHá&ÙðÜ0×=Ñ=ØØ%ØŸ™Ò5¨¯©ô�ñ ˜{¨gÑ5Ø!Ÿ/™/¨+°{ÓC�à'ˆCŒMØŸ™ˆJØˆCŒNØ�H‰H K°Ð#>ˆHÔ?Ü×#Ñ# JÔ/Ø˜‰MŠHðW ñZ Ø%ˆGŒOØ)5ˆGÔ&Ø�L‰LÚMð ô ô ×%Ñ%×,Ñ,ØØ+Ø"Ø# XÐ.ð	 -ô ð ˆøô .ò /Ù2ÜŸ™ð`à#ŸJ™Jôð
 /3Ð+Ø#.“Lð/ûô< *ò Ù.Ü—N‘NðMàŸ
™
ôð
 +/Ð'Úðús%   ÄA:KÈ0LË/LÌLÌ-MÍMrC   r@   c                 ój  — |j                   dk(  r!t        j                  |j                  |«      }n-t        j                  |j
                  xs |j                  «      }t        j                  |j                  |j                   |d   «      }|t        j                  |«      |j                  dd«      dœS )Nr)   r\   r&   r   )r%   r$   r&   )r   r	   Úgenerate_headerrV   Úgenerate_inlinerU   r   r<   r   r$   r.   )r>   rC   r   r@   rD   r%   s         rE   r8   z#BlogImageService._generate_for_slot¼   s’   € ð �<‰<˜8Ò#Ü&×6Ñ6°w·}±}ÀeÓL‰Fä&×6Ñ6°s·|±|Ò7TÀwÇ}Á}ÓUˆFä%×*Ñ*Ø�J‰J˜Ÿ™ f¨]Ñ&;ó
ˆ
ð %Ü+×7Ñ7¸
ÓCØ!Ÿ:™: m°RÓ8ñ
ð 	
ó    r(   rL   c                 ó   — d| › d|› d�S )Nz
<img src="z" alt="zI" loading="lazy" style="width:100%;border-radius:8px;margin:1.5rem 0;" />© )r(   rL   s     rE   Ú_img_tagzBlogImageService._img_tagÑ   s"   € ð ˜˜ 7¨3¨%ð 0Gð Hð	
rb   Nc                 ó¬  — |j                   xs d}d}|j                  j                  d¬«      j                  d¬«      j	                  d«      D ]f  }|j
                  sŒd|j                  xs d› d	�}| j                  |j
                  |j                  xs d«      }||v sŒS|j                  ||«      }d
}Œh |r||_         |j                  ddg¬«       yy)zPReplace inline image placeholders only (header is featured_image_url, not body).r   Fr'   r   r)   )r   r   z<!-- IMAGE: z -->TrM   r+   r!   N)
rM   r2   r3   Úexcluder4   r(   rU   re   rY   r<   )r>   r   rM   ÚchangedrC   ÚplaceholderÚtags          rE   r=   z3BlogImageService._inject_inline_images_into_contentØ   sÔ   € ð —/‘/Ò' RˆØˆà—>‘>×(Ñ(Ø)ð )ó 
ç
‰'˜8ˆ'Ó
$§X¡X¨jÓ%9ò:ˆCð —=’=ØØ(¨¯©Ò);¸Ð(<¸DÐAˆKØ—,‘,˜sŸ}™}¨c¯l©lÒ.@¸bÓAˆCØ˜gÒ%Ø!Ÿ/™/¨+°sÓ;�Ø‘ð:ñ Ø%ˆGŒOØ�L‰L¨	°<Ð'@ˆLÕAð rb   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚclassmethodÚintr   rF   r^   r   ÚstrÚdictr8   Ústaticmethodre   r=   rd   rb   rE   r   r      sÞ   „ ÙOàð?¨cð ?°kò ?ó ð?ðB ðg°kð gÀkò gó ðgðR ð
àð
ð ð
ð ð	
ð
 
ˆc�3ˆh‰ò
ó ð
ð( ð
˜Cð 
 cð 
¨cò 
ó ð
ð ðB¸ð BÈò Bó ñBrb   r   )rn   ÚloggingÚblogs.modelsr   r   r   r   Ú!blogs.services.blog_image_storager   r   Ú"blogs.services.openai_image_clientr	   Ú#blogs.services.shopify_file_servicer
   r   Ú	getLoggerrk   r:   r   rd   rb   rE   Ú<module>rz      s:   ðÙ Mã ç WÓ Wß RÝ @ß Zà	ˆ×	Ñ	˜8Ó	$€÷^Bò ^Brb   