Ë
    :§Õj<!  ã                   óJ  — 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mZmZ ddlm	Z	 	 ej                  j                  dd¬«       ddlZ e	e«      j                  «       j                   j                   ZdZd	Zd
ZdZdZ G d„ de«      Zd„ Zd„ Zd„ Z G d„ d«      Zy# e$ r Y Œ^w xY w)aý  
Cliente HTTP ligero (con cache) para la Danbooru API.

Solo metadata: NUNCA descarga imagenes. Respeta la politica de uso de Danbooru
(User-Agent identificable, delay educado entre peticiones, respeta 429/Retry-After)
y guarda la respuesta JSON cruda en disco para no repetir inferencia de red.

    cache/<sha1(path + sorted(params))>.json = {"url", "fetched", "data"}

Uso:
    from danbooru_client import DanbooruClient
    c = DanbooruClient()
    c.posts("beach rating:general", min_score=20, limit=50)
é    N)ÚdatetimeÚtimezone)ÚPathúutf-8Úbackslashreplace)ÚencodingÚerrorszhttps://danbooru.donmai.usz9plumloom-danbooru/1.0 (+contact: set DANBOORU_USER_AGENT)g      ð?é   é   c                   ó   — e Zd ZdZy)ÚDanbooruErrorz3Error de red, HTTP o cache del cliente de Danbooru.N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__© ó    ú7C:\Users\Usuario\Downloads\SD\Engine\danbooru_client.pyr   r   '   s   „ Ú=r   r   c                  óP   — t         j                  j                  d«      xs t        S )z?User-Agent identificable; configurable con DANBOORU_USER_AGENT.ÚDANBOORU_USER_AGENT)ÚosÚenvironÚgetÚDEFAULT_USER_AGENTr   r   r   Údefault_user_agentr   +   s   € ä�:‰:�>‰>Ð/Ó0ÒFÔ4FÐFr   c                 óŒ   — t         j                  j                  | «      }|�|dk(  r|S 	 t        |«      S # t        $ r |cY S w xY w©NÚ )r   r   r   ÚfloatÚ
ValueError)ÚnameÚdefaultÚraws      r   Ú
_env_floatr$   0   sG   € Ü
�*‰*�.‰.˜Ó
€CØ
€{�c˜R’iØˆðÜ�S‹zÐøÜò ØŠðús   ª
5 µAÁAc                 ó†   — t         j                  j                  | «      }|�|dk(  ry 	 t        |«      S # t        $ r Y y w xY wr   )r   r   r   Úintr    )r!   r#   s     r   Ú_env_int_or_noner'   :   sB   € Ü
�*‰*�.‰.˜Ó
€CØ
€{�c˜R’iØðÜ�3‹xˆøÜò Ùðús   ©
4 ´	A ¿A c                   ót   — e Zd Zddddeddfd„Zdd„Zd„ Zd„ Zd„ Zd„ Z	e
d	„ «       Zd
„ Ze
d„ «       Zd„ Zd„ Zy)ÚDanbooruClientNFc                 ó  — |xs
 t        «       | _        |xs t        j                  d«      | _        |€t        dt        «      n
t        |«      | _        |€t        d«      n
t        |«      | _        t        |«      | _        t        | _        |€t         dz  dz  dz  }t#        |«      | _        | j$                  j'                  dd¬«       |€-t)        j*                  «       }| j                  |j,                  d	<   || _        d | _        y )
NÚ/ÚDANBOORU_DELAYÚDANBOORU_CACHE_TTLÚArchivosÚdanbooruÚcacheT©ÚparentsÚexist_okz
User-Agent)r   Ú
user_agentÚBASE_URLÚrstripÚbase_urlr$   ÚDEFAULT_DELAYr   Údelayr'   r&   ÚttlÚboolÚofflineÚDEFAULT_TIMEOUTÚtimeoutÚBASE_DIRr   Ú	cache_dirÚmkdirÚrequestsÚSessionÚheadersÚsessionÚ_last_request)Úselfr4   r@   r9   r:   r7   r<   rE   s           r   Ú__init__zDanbooruClient.__init__E   sà   € à$Ò<Ô(:Ó(<ˆŒØ!Ò-¤X×5Ñ5°cÓ:ˆŒØDIÀM”ZÐ 0´-Ô@ÔW\Ð]bÓWcˆŒ
Ø=@¸[Ô#Ð$8Ô9ÌcÐRUËhˆŒÜ˜G“}ˆŒÜ&ˆŒàÐÜ  :Ñ-°
Ñ:¸WÑDˆIÜ˜i›ˆŒØ�‰×Ñ T°DÐÔ9àˆ?Ü×&Ñ&Ó(ˆGØ,0¯O©OˆG�O‰O˜LÑ)ØˆŒà!ˆÕr   c                 ó€  — |r|gng }|r|j                  d|› �«       |�|j                  dt        |«      › �«       |r|j                  d|› �«       dj                  d„ |D «       «      t        |«      dœ}| j                  d|«      }|€g S t	        |t
        «      s!t        dt        |«      j                  › �«      ‚|S )	z=Posts que casan con `tags`. Devuelve la lista cruda de dicts.zrating:zscore:>=zorder:Ú c              3   ó&   K  — | ]	  }|sŒ|–— Œ y ­w)Nr   )Ú.0Úps     r   Ú	<genexpr>z'DanbooruClient.posts.<locals>.<genexpr>e   s   è ø€ Ð"9©e¨²q¤1©eùs   ‚Š)ÚtagsÚlimitz/posts.jsonz%Respuesta inesperada de /posts.json: )	Úappendr&   ÚjoinÚ_requestÚ
isinstanceÚlistr   Útyper   )	rG   rO   ÚratingÚ	min_scorerP   ÚorderÚpartsÚparamsÚdatas	            r   ÚpostszDanbooruClient.posts\   s»   € á�‘ BˆÙØ�L‰L˜7 6 (Ð+Ô,ØÐ Ø�L‰L˜8¤C¨	£NÐ#3Ð4Ô5ÙØ�L‰L˜6 % Ð)Ô*ØŸ(™(Ñ"9©eÓ"9Ó9ÄCÈÃJÑOˆØ�}‰}˜]¨FÓ3ˆØˆ<ØˆIÜ˜$¤Ô%ÜÐ"GÌÈTË
×H[ÑH[ÐG\Ð ]Ó^Ð^Øˆr   c                 ó´   — | j                  d|ddœ«      }t        |t        «      r|sy|D ]+  }t        |t        «      sŒ|j	                  d«      |k(  sŒ)|c S  y)z1Metadata de un tag concreto, o None si no existe.z
/tags.jsoné   )zsearch[name_matches]rP   Nr!   )rS   rT   rU   Údictr   )rG   r!   r\   Úitems       r   ÚtagzDanbooruClient.tagm   sU   € à�}‰}˜\ÀDÐSTÑ+UÓVˆÜ˜$¤Ô%©TØÛˆDÜ˜$¤Õ%¨$¯(©(°6Ó*:¸dÓ*BØ’ð ð r   c                 óî   — |t        j                  t        |j                  «       «      dd¬«      z   }t	        j
                  |j                  d«      «      j                  «       }| j                  |› d�z  S )NTF)Ú	sort_keysÚensure_asciir   z.json)	ÚjsonÚdumpsÚsortedÚitemsÚhashlibÚsha1ÚencodeÚ	hexdigestr@   )rG   Úpathr[   ÚsrcÚdigests        r   Ú_cache_pathzDanbooruClient._cache_pathy   s[   € Ø”T—Z‘Z¤ v§|¡|£~Ó 6À$ÐUZÔ[Ñ[ˆÜ—‘˜cŸj™j¨Ó1Ó2×<Ñ<Ó>ˆØ�~‰~ 6 (¨%Ð 0Ñ0Ð0r   c                 óÔ   — 	 |j                  d¬«      5 }t        j                  |«      }d d d «       t        t        «      rd|vry |S # 1 sw Y   Œ xY w# t        t        f$ r Y y w xY w)Nr   )r   r\   )Úopenrf   ÚloadÚOSErrorr    rT   r`   )rG   Ú
cache_pathÚfÚentrys       r   Ú_read_cachezDanbooruClient._read_cache~   sc   € ð	Ø—‘¨'�Ô2°aÜŸ	™	 !›�÷ 3ô ˜%¤Ô&¨&¸Ñ*=ØØˆ÷ 3Ð2ûäœÐ$ò 	Ùð	ús'   ‚A ”A	ªA Á	AÁA ÁA'Á&A'c                 ó„  — |t        j                  t        j                  «      j	                  «       |dœ}| j
                  j                  dd¬«       |j                  |j                  dz   z  }|j                  ddd¬«      5 }t        j                  ||d	¬
«       d d d «       |j                  |«       y # 1 sw Y   ŒxY w)N)ÚurlÚfetchedr\   Tr1   z.tmpÚwr   Ú
)r   ÚnewlineF)re   )r   Únowr   ÚutcÚ	isoformatr@   rA   Úparentr!   rs   rf   ÚdumpÚreplace)rG   rv   r{   r\   rx   Útmprw   s          r   Ú_write_cachezDanbooruClient._write_cacheˆ   s˜   € àÜ—|‘|¤H§L¡LÓ1×;Ñ;Ó=Øñ
ˆð
 	�‰×Ñ T°DÐÔ9Ø×Ñ :§?¡?°VÑ#;Ñ<ˆØ�X‰X�c G°TˆXÔ:¸aÜ�I‰I�e˜Q¨UÕ3÷ ;à�‰�JÕ÷ ;Ð:ús   ÂB6Â6B?c                 ó8  — |€y	 t        j                  | d   «      }|j                  € |j                  t        j
                  ¬«      }t        j                  t        j
                  «      |z
  j                  «       }||k  S # t        t        t        f$ r Y yw xY w)NTr|   )ÚtzinfoF)r   Úfromisoformatr‰   r…   r   r�   ÚKeyErrorr    Ú	TypeErrorr€   Útotal_seconds)rx   r:   r|   Úages       r   Ú	_is_freshzDanbooruClient._is_fresh”   s‰   € àˆ;Øð	Ü×,Ñ,¨U°9Ñ-=Ó>ˆGØ�~‰~Ð%Ø!Ÿ/™/´·±˜/Ó>�ô �|‰|œHŸL™LÓ)¨GÑ3×BÑBÓDˆØ�S‰yÐøô œ*¤iÐ0ò 	Ùð	ús   …AB ÂBÂBc           	      ó’  — |xs i }| j                  ||«      }| j                  |«      }|�2| j                  r|d   S | j                  || j                  «      r|d   S | j                  r(t        d|› dt        |j                  «       «      › �«      ‚| j                  |z   }| j                  |||«      }| j                  |||«       |S )z@Cache -> red -> cache. Devuelve el JSON (list/dict) ya parseado.r\   z!offline=True y no hay cache para rJ   )rq   ry   r<   r�   r:   r   rh   ri   r7   Ú_fetch_with_retryr‡   )rG   rn   r[   rv   Úcachedr{   r\   s          r   rS   zDanbooruClient._request£   sË   € à’˜2ˆØ×%Ñ% d¨FÓ3ˆ
Ø×!Ñ! *Ó-ˆàÐØ�|Š|Ø˜f‘~Ð%Ø�~‰~˜f d§h¡hÔ/Ø˜f‘~Ð%à�<Š<ÜØ3°D°6¸¼6À&Ç,Á,Ã.Ó;QÐ:RÐSóð ð �m‰m˜dÑ"ˆØ×%Ñ% c¨6°4Ó8ˆØ×Ñ˜* c¨4Ô0Øˆr   c                 óÄ   — d }	 | j                   j                  d«      }|r	 t        |«      }t	        d|«      S |S # t        $ r d }Y Œ)w xY w# t
        t        f$ r Y |S w xY w)NzRetry-Afterg        )rD   r   ÚAttributeErrorr   ÚmaxrŒ   r    )ÚrespÚfallbackr#   Úvalues       r   Ú_retry_afterzDanbooruClient._retry_after¹   sy   € àˆð	Ø—,‘,×"Ñ" =Ó1ˆCñ ðÜ˜c›
�Ü˜3 “Ð&ð ˆøô ò 	ØŠCð	ûô œzÐ*ò ØØˆðús    „; ¢A »A	ÁA	ÁAÁAc                 óâ   — | j                   �| j                  dk  ry t        j                  «       | j                   z
  }|| j                  k  r#t        j                  | j                  |z
  «       y y )Nr   )rF   r9   ÚtimeÚ	monotonicÚsleep)rG   Úelapseds     r   Ú	_throttlezDanbooruClient._throttleÈ   sX   € Ø×ÑÐ%¨¯©°qªØÜ—.‘.Ó" T×%7Ñ%7Ñ7ˆØ�T—Z‘ZÒÜ�J‰J�t—z‘z GÑ+Õ,ð  r   c           	      óò  — d }t        t        «      D �]G  }|dk(  r| j                  «        	 t        j                  «       | _        | j                  j                  ||| j                  ¬«      }|j                  }|dk(  rXd}|t        dz
  k  r2| j                  || j                  «      }	t        j                  |	«       Œ¬t        |› d|› d	t        › d
�«      ‚d|cxk  rdk  rSn nPd|› �}|t        dz
  k  r't        j                  | j                  d|z  z  «       �Œ
t        |› d|› d	t        › d
�«      ‚|dk\  rt        |› d|› �«      ‚	 |j!                  «       c S  t        |› d|xs d› �«      ‚# t        j                  $ rR}d|› �}|t        dz
  k  r+t        j                  | j                  d|z  z  «       Y d }~�Œ®t        |› d|› �«      |‚d }~ww xY w# t"        $ r}t        |› d�«      |‚d }~ww xY w)Nr   )r[   r>   zerror de red: r_   é   z: i­  zHTTP 429 (rate limited)z tras z	 intentosiô  iX  zHTTP i�  z: HTTP z: JSON invalidozfallo desconocido)ÚrangeÚMAX_ATTEMPTSrŸ   r›   rœ   rF   rE   r   r>   rB   ÚRequestExceptionr�   r9   r   Ústatus_coder™   rf   r    )
rG   r{   r[   rn   Ú
last_errorÚattemptr–   ÚexcÚstatusÚwaits
             r   r‘   z DanbooruClient._fetch_with_retryÏ   s  € Øˆ
Üœ\×*ˆGØ˜!Š|Ø—‘Ô ðFÜ%)§^¡^Ó%5�Ô"Ø—|‘|×'Ñ'¨°FÀDÇLÁLÐ'ÓQ�ð ×%Ñ%ˆFà˜Š}Ø6�
Øœ\¨AÑ-Ò-Ø×,Ñ,¨T°4·:±:Ó>�DÜ—J‘J˜tÔ$ØÜ# t f¨B¨z¨l¸&ÄÀÈiÐ$XÓYÐYà�fÔ"˜sÕ"Ø$ V HÐ-�
Øœ\¨AÑ-Ò-Ü—J‘J˜tŸz™z¨Q°'©\Ñ:Ô;ÙÜ# t f¨B¨z¨l¸&ÄÀÈiÐ$XÓYÐYà˜Š}Ü# t f¨G°F°8Ð$<Ó=Ð=ðGØ—y‘y“{Ò"ðE +ôL ˜t˜f B zÒ'HÐ5HÐ&IÐJÓKÐKøôA ×,Ñ,ò FØ-¨c¨UÐ3�
Øœ\¨AÑ-Ò-Ü—J‘J˜tŸz™z¨Q°'©\Ñ:Ô;ÝÜ# t f¨B¨z¨lÐ$;Ó<À#ÐEûðFûô: ò GÜ# t f¨OÐ$<Ó=À3ÐFûðGús6   ¬AE1Å
GÅ1GÆ6GÇ GÇGÇ	G6Ç"G1Ç1G6)Né   éÈ   Úscore)r   r   r   r5   rH   r]   rb   rq   ry   r‡   Ústaticmethodr�   rS   r™   rŸ   r‘   r   r   r   r)   r)   D   sh   „ Ø"&°$¸dÈØ"¨E¸4ó"ó.ò"ò1ò
ò
 ð ñ
ó ð
òð, ñó ðò-ó(Lr   r)   )r   rj   rf   r   Úsysr›   r   r   Úpathlibr   ÚstdoutÚreconfigureÚ	ExceptionrB   Ú__file__Úresolverƒ   r?   r5   r   r8   r=   r£   r   r   r$   r'   r)   r   r   r   Ú<module>r¶      sº   ðñó Û Û 	Û 
Û ß 'Ý ð	Ø‡J�J×Ñ GÐ4FÐÔGó á�‹>×!Ñ!Ó#×*Ñ*×1Ñ1€à'€ØPÐ Ø€Ø€Ø€ô>�Iô >òGò
ò÷sLò sLøðW ò 	Ùð	ús   ¦B ÂB"Â!B"