
    }i{{                        d 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 ddl	m
Z
 ddlmZ dZdZg d	Zi d
ddd
dddddiidddddddddddddddddiiddddddddddd d!d"iidd#dddddd$ddd$d%d"iidd&dddd'dd(ddd
d)d"iid*ddddddd+ddd+d,d"iid-d.dddddd/ddd/ddd0ddiidd1d0dddd'dd2ddd2d3d4d5d6d7d8iid9d:ddd'ddd;ddd;d<d=d>d5d?d@dAiidBdCddd'd'ddDdddDdEdFd5dGdHiidIdJddd'd'ddKdddKdLdFd5dGdHiidMd6ddd'd'ddNdddNdOd4d5d6d7d8iid9dFdOddd'd'ddPdddPdQdFd5dGdHiidRdSddd'd'ddTdddTdUdFd5dGdHiidVdIidd'd'ddWdddWdXdYd4dZd[d\d]iid^d_dd`d'd'ddadddadbdYd4dZd[d\d]iidcddddd'd'ddedddedLdYd\dZd[dfiidgdhddd'd'ddddidUdYd4dZd[d\d]iidVd^id`d'd'ddddjdkdldmiiddndddd'ddddodpddldqiiddrdddd'ddddsdtd"iidduddd'd'ddvZdwZ ej$                  e      j(                  j+                         dxz  Zej.                  j1                  edy      Zdzed{efd|Zd}eeef   fd~Z G d d      Zy)zThis module is designed to interact with the innertube API.

This module is NOT intended to be used directly by end users, as each of the
interfaces returns raw results. These should instead be parsed to extract
the useful information for the end user.
    N)Tuple)parse)request)reset_cachezH861556708454-d6dlm3lh05idd8npek18k6be8ba3oc68.apps.googleusercontent.comSboVhoG9s0rNafixCSGGKXAT)'AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8'AIzaSyCtkvNIR1HCEwzsqK6JuE6KqpyjusIRI30z'AIzaSyA8eiZmM1FaDVjRy-df2KTyQ_vz_yYM39w'AIzaSyC8UYZpvA2eknNex0Pjid0_eTLJoDu6los'AIzaSyCjc_pVEDi4qsv5MtC2dMXzpIaDoRFLsxw'AIzaSyDHQ9ipnphqTzDqZsbtd8_Ru4_kiKVQe2kWEBcontextclientWindowsz10.0z2.20251021.01.00DESKTOP)
clientNameosName	osVersionclientVersionplatformzMozilla/5.01)
User-AgentX-Youtube-Client-NamezX-Youtube-Client-Versionr   T)innertube_contextheaderapi_keyrequire_js_playerrequire_po_token	WEB_EMBEDWEB_EMBEDDED_PLAYERz2.20240530.02.00EMBED)r   r   r   r   clientScreen56)r   r   	WEB_MUSIC	WEB_REMIXz1.20251013.03.00)r   r   67WEB_CREATORz1.20220726.00.0062F
WEB_SAFARIz2.20240726.00.00zMozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Safari/605.1.15,gzip(gfe)MWEBz2.20251014.06.00zMozilla/5.0 (iPad; CPU OS 16_7_10 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1,gzip(gfe)2WEB_KIDSz2.20241125.00.0076ANDROIDz19.44.38MOBILEAndroid1434)r   r   r   r   r   androidSdkVersionzcom.google.android.youtube/3
ANDROID_VRz1.60.19OculuszQuest 312L32)r   r   
deviceMakedeviceModelr   r   r3   ztcom.google.android.apps.youtube.vr.oculus/1.60.19 (Linux; U; Android 12L; eureka-user Build/SQ3A.220605.009.A1) gzip28ANDROID_MUSICz7.27.523011)r   r   r3   r   r   zIcom.google.android.apps.youtube.music/7.27.52 (Linux; U; Android 11) gzip21ANDROID_CREATORz	24.45.100zMcom.google.android.apps.youtube.creator/24.45.100 (Linux; U; Android 11) gzipANDROID_TESTSUITEz1.9ANDROID_PRODUCERz0.111.1zLcom.google.android.apps.youtube.producer/0.111.1 (Linux; U; Android 11) gzip91ANDROID_KIDSz7.36.1r   IOSz19.45.4AppleiPhonez18.1.0.22B83z
iPhone16,2)r   r   r9   r   r   r   r:   zMcom.google.ios.youtube/19.45.4 (iPhone16,2; U; CPU iOS 18_1_0 like Mac OS X;)5z'AIzaSyB-63vPrdThhKuerbB2N_l7Kwwcxj6yUAc	IOS_MUSICz7.27.0zQcom.google.ios.youtubemusic/7.27.0 (iPhone16,2; U; CPU iOS 18_1_0 like Mac OS X;)26IOS_CREATOR)r   r   r9   r:   r   r   zQcom.google.ios.ytcreator/24.45.100 (iPhone16,2; U; CPU iOS 18_1_0 like Mac OS X;)15IOS_KIDSTVHTML5z7.20240813.07.00TV)r   r   r   7TVHTML5_SIMPLY_EMBEDDED_PLAYERz2.0)r   r   r"   r   85MEDIA_CONNECT_FRONTENDz0.195)rM   rO   TV_EMBEDMEDIA_CONNECTi  	__cache__ztokens.jsonverification_url	user_codec                 <    t        d|  d|        t        d       y)z> Default `print(...)` and `input(...)` for oauth verification zPlease open z and input code z.Press enter when you have completed this step.N)printinput)rX   rY   s     >/usr/local/lib/python3.12/dist-packages/pytubefix/innertube.py_default_oauth_verifierr^     s#    	L)**:9+
FG	
:;    returnc                  p    t        d       t        t        d            } t        t        d            }| |fS )zr
    Requests the visitorData and po_token with an input and returns a tuple[visitorData: str, po_token: str]
    z_You can use the tool: https://github.com/YunzheZJU/youtube-po-token-generator, to get the tokenzEnter with your visitorData: zEnter with your po_token: )r[   strr\   )visitor_datapo_tokens     r]   _default_po_token_verifierre     s8     

klu<=>L5567H!!r_   c                       e Zd ZdZ	 	 	 	 	 	 	 ddZd ZddZd Zdeddfd	Z	dded
eddfdZ
ddZedefd       Zedefd       Zed        Zd ZddZd Zd Zd ZddedefdZd ZddZd Zd Zy) 	InnerTubez.Object for interacting with the innertube API.Nc                 F   || _         t        |   d   | _        t        |   d   | _        t        |   d   | _        t        |   d   | _        t        |   d   | _        d| _        d| _        d| _	        d| _
        || _        || _        |xs t        | _        d| _        || _        |xs t"        | _        | j                  s
t'                |xs t(        | _        | j                  r| j                  rt,        j.                  j1                  | j*                        rft3        | j*                        5 }t5        j6                  |      }	|	d   r.|	d   | _        |	d   | _        |	d	   | _        | j9                          ddd       | j                   r| j                  rrt,        j.                  j1                  | j*                        rHt3        | j*                        5 }t5        j6                  |      }	|	d
   | _
        |	d   | _	        ddd       yyyy# 1 sw Y   xY w# 1 sw Y   yxY w)a  Initialize an InnerTube object.

        :param str client:
            Client to use for the object.
            The default is ANDROID_TESTSUITE because there is no need to decrypt the
            signature cipher and throttling parameter.
        :param bool use_oauth:
            (Optional) Whether or not to authenticate to YouTube.
        :param bool allow_cache:
            (Optional) Allows caching of oauth tokens on the machine.
        :param str token_file:
            (Optional) Path to the file where the OAuth and Po tokens will be stored.
            Defaults to None, which means the tokens will be stored in the pytubefix/__cache__ directory.
        :param Callable oauth_verifier:
            (Optional) Verifier to be used for getting outh tokens.
            Verification URL and User-Code will be passed to it respectively. 
            (if passed, else default verifier will be used)
        :param bool use_po_token:
            (Optional) Whether or not to use po_token to bypass YouTube bot detector.
            It must be sent with the API along with the linked visitorData and
            then passed as a `po_token` query parameter to affected clients.
        :param Callable po_token_verifier:
            (Optional) Verified used to obtain the visitorData and po_token.
            The verifier will return the visitorData and po_token respectively.
            (if passed, else default verifier will be used)
        r   r   r   r   r   Naccess_tokenrefresh_tokenexpiresvisitorDatard   )client_name_default_clientsr   r   r   r   r   ri   rj   access_po_tokenaccess_visitorData	use_oauthallow_cacher^   oauth_verifierrk   use_po_tokenre   po_token_verifierr   _token_file
token_fileospathexistsopenjsonloadrefresh_bearer_token)
selfr   rq   rr   rw   rs   rt   ru   fdatas
             r]   __init__zInnerTube.__init__  s   J "!1&!9:M!N&v.x8'/	:!1&!9:M!N 0 89K L !#"&"&,G0G (!2!P6PM %3>>d..277>>$//3Rdoo& 0!yy|'(,^(<D%)-o)>D&#'	?DL--/0 !1!1bggnnT__6Udoo& 8!yy|*.}*=''+J'7$8 8 7V!10 08 8s   .A	H*HHH c                    | j                   sy| j                  | j                  | j                  | j                  | j
                  d}t        j                  j                  | j                        }t        j                  j                  |      st        j                  |d       t        | j                  d      5 }t        j                  ||       ddd       y# 1 sw Y   yxY w)z Cache tokens to file if allowed.N)ri   rj   rk   rl   rd   T)exist_okw)rr   ri   rj   rk   rp   ro   rx   ry   dirnamerw   rz   makedirsr{   r|   dump)r   r   cacheDirr   s       r]   cache_tokenszInnerTube.cache_tokensh  s     !--!//||22,,
 77??4??3ww~~h'KK40$//3' 	1IIdA	 	 	s   =CC&c                    | j                   sy| j                  t        j                         kD  r|syt        t        j                         dz
        }t        t
        d| j                  d}t        j                  ddddi|	      }t        j                  |j                               }|d
   | _        ||d   z   | _        | j                          y)zxRefreshes the OAuth token if necessary.

        :param bool force:
            Force-refresh the bearer token.
        N   rj   )	client_idclient_secret
grant_typerj   #https://oauth2.googleapis.com/tokenPOSTContent-Typeapplication/jsonheadersr   ri   
expires_in)rq   rk   timeint
_client_id_client_secretrj   r   _execute_requestr|   loadsreadri   r   )r   force
start_timer   responseresponse_datas         r]   r~   zInnerTube.refresh_bearer_tokenz  s     ~~<<$))+%e r)*
#+)!//	
 ++1 2 
 

8==?3).9!M,$??r_   c                    t        t        j                         dz
        }t        dd}t        j                  ddddi|      }t        j                  |j                               }|d	   }|d
   }| j                  ||       t        t        |d   dd}t        j                  ddddi|      }t        j                  |j                               }|d   | _
        |d   | _        ||d   z   | _        | j                          y)zFetch an OAuth token.r   z'https://www.googleapis.com/auth/youtube)r   scopez)https://oauth2.googleapis.com/device/coder   r   r   r   rX   rY   device_codez,urn:ietf:params:oauth:grant-type:device_code)r   r   r   r   r   ri   rj   r   N)r   r   r   r   r   r|   r   r   rs   r   ri   rj   rk   r   )r   r   r   r   r   rX   rY   s          r]   fetch_bearer_tokenzInnerTube.fetch_bearer_token  s    r)*
#>
 ++7 2 
 

8==?3();<!+.	,i8 $+(7H	
 ++1 2 
 

8==?3).9*?;!M,$??r_   rc   r`   c                 J    | j                   d   d   j                  d|i       y)z7
        Insert visitorData in the API request
        r   r   rl   N)r   update)r   rc   s     r]   insert_visitor_datazInnerTube.insert_visitor_data  s,     	y)(3::<<
 	r_   rd   c                     | j                  | j                  xs |       | j                  j                  dd| j                  xs |ii       y)zD
        Insert visitorData and po_token in the API request
        serviceIntegrityDimensionspoTokenN)r   rp   r   r   ro   )r   rc   rd   s      r]   insert_po_tokenzInnerTube.insert_po_token  sN     	  !8!8!HLI%%(4//;8+'
 	r_   c                 ~    | j                         \  | _        | _        | j                          | j	                          y)zh
        Requests visitorData and po_token, the default function is _default_po_token_verifier.
        N)ru   rp   ro   r   r   r   s    r]   fetch_po_tokenzInnerTube.fetch_po_token  s5     9=8N8N8P5!5r_   c                      y)z3Return the base url endpoint for the innertube API.z#https://www.youtube.com/youtubei/v1 r   s    r]   base_urlzInnerTube.base_url  s     5r_   c                     | j                   S )z;Return the base json data to transmit to the innertube API.)r   r   s    r]   	base_datazInnerTube.base_data  s     %%%r_   c                 
    ddiS )zBReturn the base query parameters to transmit to the innertube API.prettyPrintfalser   r   s    r]   base_paramszInnerTube.base_params  s     7
 	
r_   c                    | dt        j                  |       }ddi}| j                  r?| j                  r| j	                          n| j                          d| j                   |d<   | j                  r-| j                  r| j                          n| j                          |j                  | j                         t        j                  |d||      }t        j                  |j!                               S )zOMake a request to a given endpoint with the provided query parameters and data.?r   r   zBearer Authorizationr   r   )r   	urlencoderq   ri   r~   r   rt   ro   r   r   r   r   r   r   r|   r   r   )r   endpointqueryr   endpoint_urlr   r   s          r]   	_call_apizInnerTube._call_api  s     #1U__U%;$<=.
 >>  ))+''))01B1B0C'DGO$ ##$$&##%t{{#++	
 zz(--/**r_   c                     | j                    d}| j                  }|r| j                  j                  d|i       |r#| j                  d   d   j                  d|i       | j	                  ||| j                        S )a-  Make a request to the browse endpoint.

        :param str continuation:
            Continuation token if there is pagination
        :param str visitor_data:
            Visitor Data, required to get YouTube Shorts
        :rtype: dict
        :returns:
            Raw browse info results.
        z/browsecontinuationr   r   rl   r   r   r   r   r   )r   r   rc   r   r   s        r]   browsezInnerTube.browse  st     mm_G,  NN!!><"@ANN9%h/66|7TU~~ht~~>>r_   c                      y)z[Make a request to the reel endpoint.

        TODO: Figure out how we can use this
        Nr   r   s    r]   reelzInnerTube.reel.       	r_   c                      y)z]Make a request to the config endpoint.

        TODO: Figure out how we can use this
        Nr   r   s    r]   configzInnerTube.config7  r   r_   c                      y)z\Make a request to the guide endpoint.

        TODO: Figure out how we can use this
        Nr   r   s    r]   guidezInnerTube.guide@  r   r_   video_idr   c                     |r| j                   j                  d|i       |r| j                   j                  |dd       | j                   d}| j                  }| j	                  ||| j                         S )a%  Make a request to the next endpoint.

        :param str video_id:
            The video id to get player details for.
        :param str continuation:
            Continuation token if there is pagination
        :rtype: dict
        :returns:
            Raw player details results.
        r   truevideoIdcontentCheckOkz/next)r   r   r   r   r   )r   r   r   r   r   s        r]   nextzInnerTube.nextI  sj     NN!!><"@ANN!!h&"QRmm_E*  ~~ht~~>>r_   c                     | j                    d}| j                  }| j                  j                  |dd       | j	                  ||| j                        S )zMake a request to the player endpoint.

        :param str video_id:
            The video id to get player info for.
        :rtype: dict
        :returns:
            Raw player info results.
        z/playerr   r   r   )r   r   r   r   s       r]   playerzInnerTube.player`  sM     mm_G,  (fMN~~ht~~>>r_   c                     | j                    d}| j                  }|r|ni }| j                  j                  d|i       |r||d<   |j                  | j                         | j	                  |||      S )af  Make a request to the search endpoint.

        :param str search_query:
            The query to search.
        :param str continuation:
            Continuation token if there is pagination
        :param dict data:
            Additional data to send with the request.
        :rtype: dict
        :returns:
            Raw search query results.
        z/searchr   r   r   )r   search_queryr   r   r   r   s         r]   searchzInnerTube.searcho  so     mm_G,  tw56#/D DNN#~~ht44r_   c                     | j                    d}ddd|didd}|j                  | j                         | j                  || j                  |      }|S )a  Make a request to the age_verify endpoint.

        Notable examples of the types of video this verification step is for:
        * https://www.youtube.com/watch?v=QLdAhwSBZ3w
        * https://www.youtube.com/watch?v=hc0ZDaAZQT0

        :param str video_id:
            The video id to get player info for.
        :rtype: dict
        :returns:
            Returns information that includes a URL for bypassing certain restrictions.
        z/verify_agewatchEndpointT)racyCheckOkr   r   )nextEndpointsetControvercy)r   r   r   r   r   )r   r   r   r   results        r]   
verify_agezInnerTube.verify_age  sg     mm_K0  #'&*'" #	
 	DNN#$*:*:DAr_   c                     | j                    d}d|i}|j                  | j                         | j                  ||| j                        }|S )zMake a request to the get_transcript endpoint.

        This is likely related to captioning for videos, but is currently untested.
        z/get_transcriptr   )r   r   r   r   r   )r   r   r   r   r   s        r]   get_transcriptzInnerTube.get_transcript  sO    
 mm_O4x
 	T%%&%@r_   )r5   FTNNFN)F)NN)r`   N)__name__
__module____qualname____doc__r   r   r~   r   rb   r   r   r   propertyr   dictr   r   r   r   r   r   r   r   r   r   r   r   r   r_   r]   rg   rg     s    8  "M8^$ D(T  
3 
c 
4 
 5# 5 5 &4 & & 
 
"+H?,?S ?s ?.?5.8r_   rg   )r   r|   rx   pathlibr   typingr   urllibr   	pytubefixr   pytubefix.helpersr   r   r   	_api_keysrn   _token_timeoutPath__file__parentresolve
_cache_dirry   joinrv   rb   r^   re   rg   r   r_   r]   <module>r      s    	      ) X
+	_	"''!'%7 )

 (%((:

 =! '_. "7'!'%7$+

 (%)
 =! %/_X "-%7
 (%)
 =! Y_| "/%7
 (%)
 =!!}_` "'%7
 \%(
 =! a_D "(%7
 h%(
 =! E_h ",'!'%7 )

 (%)(:

 =!!'i_T "+%/ ('!%)-	
 8%(
 =" 'U_j ".%."*#,'!&)-

 Q%)
 ="!)k_X "1%.)-'!%

 f%)
 ="!%Y_B "3%0)-'!%

 j%)
 ="!%C_l "5%* ('!%)-	
 8%)(-

 ="!)m_Z "4%.)-'!%

 i%)
 ="!%[_D	 "0%-)-'!%

 e
 ="!#E	_l	 
"'%.") (&!/#/

 j%(
 ="!)m	_H "-%-") (&!/#/

 n%)
 ="!)I_v "/%0")#/&!/	
 n%)
 ="!'w_f ",%-") (&!/#/

 i
 ="!'0 "+%7 $
 (%(
 =!!!* "B%*$+ $		
 (%)
 =!!#, ":%*
 (%)
 ="!]_ @ W\\(#**224{B
ggll:}5<c <c <"E#s(O "W Wr_   