
    F9j_                         d 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 ddlm	Z	 ddl
mZ  ej                  dej                        Zde	d	efd
Zded	e	fdZ G d de      Zy)u  Cacheo en disco para cualquier proveedor.

Envuelve a otro TweetProvider y guarda en disco (por handle) los tweets traídos,
con un TTL. Así la app no vuelve a pedir a X en cada recarga, lo que es CLAVE con
Scweet para no agotar la cuota de la cuenta secundaria (rate-limit).

Cachea un conjunto amplio por handle (sin filtrar por fecha) y filtra por la
ventana en lectura, de modo que una misma caché sirve para cualquier 'window'.
    N)datetimetimezone)List)Tweet)TweetProvider)tztreturnc                     | j                   | j                  | j                  | j                  j	                         | j
                  | j                  | j                  | j                  | j                  | j                  d
S )N
idauthortext
created_atlikesretweetsrepliesquotesviewsurl)r   r   r   r   	isoformatr   r   r   r   r   r   r	   s    agent/providers/cached.py_tweet_to_dictr      sU    ddahhll,,.ajjQYY((QWWQUU	     dc                 *   t        | d   | d   | d   t        j                  | d         | j                  dd      | j                  dd      | j                  dd      | j                  d	d      | j                  d
d      | j                  dd      
      S )Nr   r   r   r   r   r   r   r   r   r   r    r   )r   r   fromisoformatget)r   s    r   _tweet_from_dictr!       s    T71X;QvY))!L/:eeGQ!%%
A*>i#AEE(A,>eeGQQUU5"%5 r   c            
           e Zd ZddededefdZdedefdZdedefd	Z	e
d
ee   dededee   fd       Zddedededee   fdZddZy)CachedProviderinner	cache_dirttl_minutesc                     || _         || _        t        |      dz  | _        t	        j
                  |d       i | _        y )N<   T)exist_ok)r$   r%   floatttlosmakedirs	last_meta)selfr$   r%   r&   s       r   __init__zCachedProvider.__init__+   s6    
"%*
I-r   handler
   c                     |j                  d      j                         j                  dd      j                  dd      }t        j                  j                  | j                  | d      S )N@/_\.json)lstriplowerreplacer,   pathjoinr%   )r/   r1   safes      r   _pathzCachedProvider._path2   sR    }}S!'')11#s;CCD#Nww||DNNtfEN;;r   metac                     |j                  d      }t        |t              r	 i |dt        j                  |      i}|| j                  |j                  d      <   y # t
        $ r i |dd i}Y 2w xY w)Nnewestr3   )r    
isinstancestrr   r   
ValueErrorr.   r8   )r/   r1   r?   rA   s       r   	_set_metazCachedProvider._set_meta6   sv    (#fc"0I$I(*@*@*HI .2v}}S)*  0/$/$/0s   A A10A1tweetssincelimitc                 |    | D cg c]  }|j                   |k\  s| }}|j                  d d       |d | S c c}w )Nc                     | j                   S )N)r   r   s    r   <lambda>z(CachedProvider._window.<locals>.<lambda>B   s    q||r   T)keyreverse)r   sort)rF   rG   rH   r	   outs        r   _windowzCachedProvider._window?   sC     :&QALLE$9q&:+T:6E{ ;s   99c           
         | j                  |      }t        j                  j                  |      r	 t	        |d      5 }t        j                  |      }d d d        t        j                         j                  dd      z
  | j                  k  rf| j                  |t        |j                  di                    |j                  dg       D cg c]  }t        |       }}| j                  |||      S 	 | j                  j!                  |t"        |      }t        t%        | j                  di       j                  |j'                  d	      i             }	|	| j(                  |j'                  d	      <   |r	 t        |	      }
t+        |
j                  d
      t,              r|
d
   j/                         |
d
<   t	        |dd      5 }t        j0                  t        j                         |D cg c]  }t3        |       c}|
d|d       d d d        | j                  |||      S # 1 sw Y   xY wc c}w # t        $ r Y Ow xY wc c}w # 1 sw Y   CxY w# t        $ r Y Qw xY w)Nzutf-8)encoding
fetched_atr   r?   rF   )rG   rH   r.   r3   rA   w)rS   rF   r?   F)ensure_ascii)r>   r,   r;   existsopenjsonloadtimer    r+   rE   dictr!   rP   	Exceptionr$   fetch_user_tweets_EPOCHgetattrr8   r.   rB   r   r   dumpr   )r/   r1   rG   rH   r;   fblobr   rF   r?   	meta_saver	   s               r   r]   z CachedProvider.fetch_user_tweetsE   s	   zz&! 77>>$$1Q99Q<D 299;,!::TXXENN640D+EF;?88Hb;QR;Qa.q1;QFR<<u== F --fF%-PGDJJR8<<V]]3=OQSTU-1v}}S)*  J	immH5x@*3H*=*G*G*IIh'$g6!II'+yy{?E#Fv!N1$5v#F!*, 	 7 ||FE511? 21 S $ $G 76  sr   H; H)A;H; H6"H; :AI 'I/III )H3.H; ;	IIIII 	I('I(Nc                 ^   t         j                  j                  | j                        sy t        j                  | j                        D ]R  }|j                  d      s	 t        j                  t         j                  j                  | j                  |             T y # t        $ r Y aw xY w)Nr7   )	r,   r;   isdirr%   listdirendswithremover<   OSError)r/   fns     r   clearzCachedProvider.clearl   st    ww}}T^^,**T^^,B{{7#IIbggll4>>2>? -  s    =B  	B,+B,)r(   )2   )r
   N)__name__
__module____qualname__r   rC   r*   r0   r>   r[   rE   staticmethodr   r   r   intrP   r]   rk    r   r   r#   r#   *   s    m  % <C <C <2 24 2 U H S T%[  
%2 %2H %2S %2RVW\R] %2Nr   r#   )__doc__rX   r,   rZ   r   r   typingr   agent.modelsr   agent.providers.baser   fromtimestamputcr^   r[   r   r!   r#   rr   r   r   <module>ry      sm     	  '   .			hll	3e    J] Jr   