
    }i                         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	 d dl
mZ  ej                  e      ZdZ G d d      Zy)    N)parse)RegexMatchErrorMaxRetriesExceeded)regex_searchi   c                        e Zd ZdZdZdZ fdZd Zd Zd Z	d Z
	 ddZdd	Zdd
ZddZddZddZd Zd Z xZS )AsyncHTTPClientzFSingleton Async HTTP Client with persistent session and handy methods.Nc                 \    | j                   t        | 	  |       | _         | j                   S N)	_instancesuper__new__)clsargskwargs	__class__s      F/usr/local/lib/python3.12/dist-packages/pytubefix/async_http_client.pyr   zAsyncHTTPClient.__new__   s'    == !GOC0CM}}    c                    K   | j                   | j                   j                  rt        j                         | _         | j                   S w)z-Ensure session is alive (recreate if closed).)_sessionclosedaiohttpClientSessionselfs    r   _get_sessionzAsyncHTTPClient._get_session   s6     == DMM$8$8#113DM}}s   AA
c                    K   | j                   r:| j                   j                  s#| j                   j                          d{    yyy7 w)zFClose the internal session (call at end of program or via async with).N)r   r   closer   s    r   r   zAsyncHTTPClient.close    s9     ==!5!5--%%''' "6='s   A AA
Ac                 B   K   | j                          d {    | S 7 wr
   )r   r   s    r   
__aenter__zAsyncHTTPClient.__aenter__%   s"     !!! 	"s   c                 @   K   | j                          d {    y 7 wr
   )r   )r   exc_typeexctbs       r   	__aexit__zAsyncHTTPClient.__aexit__)   s     jjls   c                    K   ddd}|r|j                  |       d }|Nt        |t        t        f      s$t	        j
                  |      j                  d      n|}|j                  dd       |j                         j                  d      st        d      | j                          d {   }	 |j                  |||||	       d {   }	|	S 7 %7 # t        $ r}
t        j                  d
|
         d }
~
ww xY ww)NzMozilla/5.0zen-US,en)z
User-Agentzaccept-languagezutf-8Content-Typeapplication/jsonhttpzInvalid URL)methodurlheadersdatatimeoutzHTTP error: )update
isinstancebytesstrjsondumpsencode
setdefaultlower
startswith
ValueErrorr   request	Exceptionloggererror)r   r*   r)   r+   r,   r-   base_headers	send_datasessionrespes              r   _execute_requestz AsyncHTTPClient._execute_request,   s     '4
S(	8B4%QT8V

4 ''0\`  ##N4FGyy{%%f-]++))++	 $ )  D K ,  	LL<s+,	sH   B(C>*C+C>0C 	C
C C>C 	C;C66C;;C>c                    K   | j                  |d||       d{   }|4 d{    |j                          d{   cddd      d{    S 7 87 /7 7 # 1 d{  7  sw Y   yxY ww)z#GET request, returns response text.GETr)   r+   r-   N)rB   text)r   r*   r+   r-   r@   s        r   getzAsyncHTTPClient.getH   sq     **3ugW^*__ 	% 	%$	% 	% 	% `	%$	% 	% 	% 	%sd   A1A
A1AA1AAAA1AA1A1AA1A."A%#A.*A1c                   K   |xs i }|j                  dd       | j                  |d|||       d{   }|4 d{    |j                          d{   cddd      d{    S 7 87 /7 7 # 1 d{  7  sw Y   yxY ww)z$POST request, returns response text.r&   r'   POST)r)   r+   r,   r-   N)r5   rB   rF   )r   r*   r+   r,   r-   r@   s         r   postzAsyncHTTPClient.postN   s     -R>+=>**dG + 
 
  	% 	%$	% 	% 	%
	%$	% 	% 	% 	%sh   2B
A-
B
A/ B
A5A1A5B
'A3(B
/B
1A53B
5B;A><BB
c                 6  K   | j                  |d||       d{   }|4 d{    |j                  j                         D ci c]  \  }}|j                         | c}}cddd      d{    S 7 \7 Sc c}}w 7 # 1 d{  7  sw Y   yxY ww)z&HEAD request, returns headers as dict.HEADrE   N)rB   r+   itemsr6   )r   r*   r+   r-   r@   kvs          r   headzAsyncHTTPClient.headX   s     **3vwX_*`` 	C 	C-1\\-?-?-ABTQAGGIqLB	C 	C 	C a	CB	C 	C 	C 	Csf   BA8
BA:BBA<#B&B2B3B:B<BBB
BBBc                  K   t         }d}||k  rt        |t         z   |      dz
  }d}d}	 |d|z   k\  r
t               	 | j                  | d| d| |       d{   }	 |t         k(  rb	 | j                  | d|       d{   }
|
4 d{    |
j                  j                  d      }|rt        |      }ddd      d{    |4 d{    	 |j                  j                          d{   }|sn|t        |      z  }| 9ddd      d{    ||k  ryy7 # t        j
                  $ r$}	t        j                  |	       |dz  }Y d}	~	nd}	~	ww xY w>7 7 7 # 1 d{  7  sw Y   xY w# t        $ r}	t        j                  |	       Y d}	~	d}	~	ww xY w7 7 7 # 1 d{  7  sw Y   xY ww)	zFAsync generator: stream file in chunks with retries and range support.r      Nz&range=-)r-   z&range=0-99999999999zContent-Length)default_range_sizeminr   rB   r   ClientErrorr;   r<   r+   rG   intr:   contentreadanylen)r   r*   r-   max_retries	file_size
downloadedstop_postriesresponserA   r@   content_lengthchunks                r   streamzAsyncHTTPClient.stream^   s    &	
9$:(::IFJHEHAO+,..%)%:%:%wzl!H:> &; &  H 
 ..	$!%!6!6%34g "7 " D  $ < <)-)9)9:J)K)(+N(;I< <      "*"2"2":":"<<E #e*,JK    9 9$  ** LLOQJE < < < < < ! $LLOO$ <       s  <GD. D,D. "
G-F E*
F E,F )E0>F 	E.
F GF0GF67F28F6GF4	G*G,D. .E%E G E%%G*F ,F .F 0F6E97F>F 	F-F(#G(F--G2F64G6G<F?=GGc                N  K   t        j                  |      }|j                   d|j                   d|j                   d}t        t        j                  |j                              }d|d<   |t        j                  |      z   }t               }| j                  |||      2 3 d{   }	|	 |j                  |	        7 6 t        j                  d      }
|
j                  |      }|st        d|
j                         d}|j#                  d	      D ]5  }t        j                  d|      }|st%        |j'                  d
            }7 t)        d
|d
z         D ]C  }||d<   |t        j                  |      z   }| j                  |||      2 3 d{  7  }	|	 6 E yw)z9Async generator: read sequential video segments in order.:///?r   sqN   Segment-Count: (\d+)
seq_stream   
rR   )r   urlsplitschemenetlocpathdict	parse_qslquery	urlencode	bytearrayrc   extendrecompilesearchr   patternsplitrW   grouprange)r   r*   r-   r[   	split_urlbase_urlqsurl_0bufferrb   segment_regexmsegment_countlinerh   seg_urls                   r   rj   zAsyncHTTPClient.seq_stream   s    NN3'	&&'s9+;+;*<Ainn=MQO%//)//2345??2..;;ug{C 	! 	!%KMM% 	!C 

#;<  (!,0E0EFFLL) 	0D		2D9A #AGGAJ	0
 =1,- 	BBtH!44G#{{7G[I  e  J	sJ   B!F%#C'C(C+F%CA-F%3AF%F!FF!F%c                 \   K   | j                  |       d{   }t        |d         S 7 w)z(Get file size via HEAD (Content-Length).Ncontent-length)rP   rW   )r   r*   	head_infos      r   filesizezAsyncHTTPClient.filesize   s,     ))C.(	9-.// )s   ,*,c                 b  K   d}t        j                  |      }|j                   d|j                   d|j                   d}t        t        j                  |j                              }d|d<   |t        j                  |      z   }| j                  |d       d{   }|4 d{    |j                          d{   }ddd      d{    |t              z  }d}	|j                  d	      D ]  }
	 t        t        d
|
d            }	 |	dk(  rt        dd
      t!        d|	dz         D ]I  }||d<   |t        j                  |      z   }| j#                  |       d{   }|t        |d         z  }K |S 7 7 7 7 # 1 d{  7  sw Y   xY w# t        $ r Y w xY w7 Ew)z,Get total file size for sequential segments.r   re   rf   rg   rh   rD   )r)   Nrk   ri   rR   seq_filesizer   )r   rl   rm   rn   ro   rp   rq   rr   rs   rB   readrZ   rz   rW   r   r   r|   rP   )r   r*   totalr}   r~   r   r   r@   r,   r   r   rh   r   r   s                 r   r   zAsyncHTTPClient.seq_filesize   s    NN3'	&&'s9+;+;*<Ainn=MQO%//)//2345??2..**5*?? 	% 	%$D	% 	%TJJw' 	D #L1I4QR$S T	
 A!.2JKK=1,- 	6BBtH!44G"ii00IS#3455E		6
 % @	%$	% 	% 	% 	% #  1s   BF/F
F/)F*F/-F	FF	F/F(F/;FAF/'F-(F/F/F	F/	FFFF/	F*'F/)F**F/)rD   NNN)NN)NNN)Nr   )__name__
__module____qualname____doc__r   r   r   r   r   r   r$   rB   rG   rJ   rP   rc   rj   r   r   __classcell__)r   s   @r   r   r      sZ    PIH(
 CG8%%C' R80
r   r   )r   asyncior2   loggingrv   urllibr   pytubefix.exceptionsr   r   pytubefix.helpersr   	getLoggerr   r;   rT   r    r   r   <module>r      sA        	  D *			8	$$ t tr   