
    }i'                     |    d Z ddlZddlZddlmZmZ ddlmZmZ ddl	m
Z
  ej                  e      Z G d d      Zy)a%  
This module contains all the logic needed to find the signature functions.

YouTube's strategy to restrict downloading videos is to send a ciphered version
of the signature to the client, along with the decryption algorithm obfuscated
in JavaScript. For the clients to play the videos, JavaScript must take the
ciphered version, cycle it through a series of "transform functions," and then
signs the media URL with the output.

This module is responsible for (1) finding these "transformations
functions" (2) sends them to be interpreted by nodejs
    N)RegexMatchErrorInterpretationError)JSInterpreterextract_player_js_global_var)
NodeRunnerc                   z    e Zd ZdedefdZdefdZdedefdZdededefd	Zdedefd
Ze	dedede
fd       Zy)Cipherjsjs_urlc                    || _         || _        d | _        d | _        | j	                  ||      | _        | j                  ||      | _        t        |      | _	        | j                  j                  | j
                         t        |      | _        | j                  j                  | j                         d | _        t        |      | _        y )N)r   r
   _sig_param_val_nsig_param_valget_sig_function_namesig_function_nameget_nsig_function_namensig_function_namer   
runner_sigload_functionrunner_nsigcalculated_nr   js_interpreter)selfr
   r   s      ;/usr/local/lib/python3.12/dist-packages/pytubefix/cipher.py__init__zCipher.__init__   s    "#!%!;!;B!G"&"="=b&"I$R.%%d&<&<=%b>&&t'>'>? +B/    nc                    	 | j                   rA| j                   D ]1  }| j                  j                  ||g      }t        |t              s1 n n| j                  j                  |g      }dv sd|v st        |t              st        | j                  |      |S # t
        $ r}t        | j                  |      d}~ww xY w)a>  Interpret the function that transforms the signature parameter `n`.
            The lack of this signature generates the 403 forbidden error.
        :param str n:
            Contains the parameter that must be transformed.
        :rtype: str
        :returns:
            Returns the transformed value "n".
        r   reasonNerror_w8_)r   r   call
isinstancestr	Exceptionr   r   )r   r   paramnsiges        r   get_nsigzCipher.get_nsig,   s    	D##!11 E++00%<D%dC0  '',,aS1 d?fnJtS4I%T[[FF  	D%T[[CC	Ds   A)B 	C%B<<Cciphered_signaturereturnc                 N   	 | j                   r(| j                  j                  | j                   |g      }n| j                  j                  |g      }d|v st        |t              st	        | j
                  |      |S # t        $ r}t	        | j
                  |      d}~ww xY w)a<  interprets the function that signs the streams.
            The lack of this signature generates the 403 forbidden error.
        :param str ciphered_signature:
           Contains the signature that must be transformed.
        :rtype: str
        :returns:
           Returns the correct stream signature.
        r   Nr    )r   r   r"   r%   r   r   r#   r$   )r   r*   sigr(   s       r   get_sigzCipher.get_sigF   s    	D""oo**D,?,?AS+TUoo**,>+?@ c>C!5%T[[EE
  	D%T[[CC	Ds   AA? ?	B$BB$c                    g d}t         j                  d       |D ]  }t        j                  |      }|j	                  |      }|s,|j                  d      }t         j                  d|       t         j                  d|        d|j                         v r#|j                  d      }|rt        |      | _        |c S  t        dd| 	      )
a&  Extract the name of the function responsible for computing the signature.
        :param str js:
            The contents of the base.js asset file.
        :param str js_url:
            Full base.js url
        :rtype: str
        :returns:
            Function name from regex match
        )z(?P<sig>[a-zA-Z0-9_$]+)\s*=\s*function\(\s*(?P<arg>[a-zA-Z0-9_$]+)\s*\)\s*{\s*(?P=arg)\s*=\s*(?P=arg)\.split\(\s*[a-zA-Z0-9_\$\"\[\]]+\s*\)\s*;\s*[^}]+;\s*return\s+(?P=arg)\.join\(\s*[a-zA-Z0-9_\$\"\[\]]+\s*\)z(?:\b|[^a-zA-Z0-9_$])(?P<sig>[a-zA-Z0-9_$]{2,})\s*=\s*function\(\s*a\s*\)\s*{\s*a\s*=\s*a\.split\(\s*""\s*\)(?:;[a-zA-Z0-9_$]{2}\.[a-zA-Z0-9_$]{2}\(a,\d+\))?z\b(?P<var>[a-zA-Z0-9_$]+)&&\((?P=var)=(?P<sig>[a-zA-Z0-9_$]{2,})\((?:(?P<param>\d+),decodeURIComponent|decodeURIComponent)\((?P=var)\)\)zX\b[cs]\s*&&\s*[adf]\.set\([^,]+\s*,\s*encodeURIComponent\s*\(\s*(?P<sig>[a-zA-Z0-9$]+)\(zg\b[a-zA-Z0-9]+\s*&&\s*[a-zA-Z0-9]+\.set\([^,]+\s*,\s*encodeURIComponent\s*\(\s*(?P<sig>[a-zA-Z0-9$]+)\(z;\bm=(?P<sig>[a-zA-Z0-9$]{2,})\(decodeURIComponent\(h\.s\)\)z0("|\')signature\1\s*,\s*(?P<sig>[a-zA-Z0-9$]+)\(z!\.sig\|\|(?P<sig>[a-zA-Z0-9$]+)\(zyt\.akamaized\.net/\)\s*\|\|\s*.*?\s*[cs]\s*&&\s*[adf]\.set\([^,]+\s*,\s*(?:encodeURIComponent\s*\()?\s*(?P<sig>[a-zA-Z0-9$]+)\(z>\b[cs]\s*&&\s*[adf]\.set\([^,]+\s*,\s*(?P<sig>[a-zA-Z0-9$]+)\(zS\bc\s*&&\s*[a-zA-Z0-9]+\.set\([^,]+\s*,\s*\([^)]*\)\s*\(\s*(?P<sig>[a-zA-Z0-9$]+)\(z!looking for signature cipher namer-   z"finished regex search, matched: %sz Signature cipher function name: r&   get_initial_function_namezmultiple in callerpattern)
loggerdebugrecompilesearchgroup	groupdictintr   r   )	r   r
   r   function_patternsr3   regexfunction_matchr-   r&   s	            r   r   zCipher.get_sig_function_name\   s    
 	89( 	GJJw'E"\\"-N$**51A7K?uEFn6688*009E.1%j+
	 .,vh8O
 	
r   c                    t         j                  d       	 d}t        j                  ||      }|r+|j	                  d      }t         j                  d|        |S t         j                  d|        t         j                  d       t        |      \  }}}|r|r|rt         j                  d|        t        |      j                  |i d      }t         j                  d	       t        |      D ]  \  }	}
|
j                  d
      st         j                  d|	        dt        j                  |      |	fz  }t        j                  ||      }|rD|j	                  d      }t         j                  d|        | j                  ||      | _        |c S t        d| d|        yyyy# t        $ r}|d}~ww xY w)aO  Extract the name of the function that transforms the signature parameter `n`.

        :param str js:
            The contents of the base.js asset file.
        :param str js_url:
            Full base.js url
        :rtype: str
        :returns:
            The name of the function used to compute the throttling parameter.
        zlooking for nsig namez?var\s*[a-zA-Z0-9$_]{3}\s*=\s*\[(?P<funcname>[a-zA-Z0-9$_]{3})\]funcnamezNfunc name: z#Failed to get Nfunc name. Pattern: z4Extracts the function name based on the global arrayzGlobal Obj name is: d   z&Successfully interpreted global objectr!   z_w8_ found in index a  (?xs)
                                    [;\n](?:
                                        (?P<f>function\s+)|
                                        (?:var\s+)?
                                    )(?P<funcname>[a-zA-Z0-9_$]+)\s*(?(f)|=\s*function\s*)
                                    \(\s*(?:[a-zA-Z0-9_$]+\s*,\s*)?(?P<argname>[a-zA-Z0-9_$]+)(?:\s*,\s*[a-zA-Z0-9_$]+)*\s*\)\s*\{
                                    (?:(?!(?<!\{)\};(?![\]\)])).)*
                                    \}\s*catch\(\s*[a-zA-Z0-9_$]+\s*\)\s*
                                    \{\s*(?:return\s+|[\w=]+)%s\[%d\]\s*\+\s*(?P=argname)\s*[\};].*?\s*return\s+[^}]+\}[;\n]
                                zNfunc name is: get_throttling_function_namez in r1   N)r4   r5   r6   r8   r9   r   r   interpret_expression	enumerateendswithescape_extract_nsig_param_valr   r   r%   )r   r
   r   r3   	func_namen_func
global_objvarnamecodekvr(   s               r   r   zCipher.get_nsig_function_name   s    	,-)	XG		'2.I"4|F845 B7)LMST,H,L)
GT'dLL#7y!AB!.r!2!G!GbRU!VJLL!IJ )* 5 1::f-"LL+?s)CD	'$ )+		'(:A'>	'?G )+		'2(>I()2)D &vh-G H7;7S7STVX^7_ 4'-"1'ERYQZZ^_e^fOg# )	 /3':6  	G	s,   AF2 B0F2 BF2 F2 2	G;F==GrL   rH   c                    t         j                  d       t        j                  dt        j                  |       dt        j
                        }g }|j                  |       D ]Z  }|j                  d      dk(  r"|j                  d      r|j                  d      n|j                  d      }|j                  |       \ t         j                  d|        |S )a$  Extract the control parameter from the signature function `n`.

        :param str code:
            The contents of the base.js asset file.
        :param str func_name:
            function name
        :rtype: list
        :returns:
            The list with the extracted values.
        z!Looking for the control parameterz(?<![A-Za-z0-9_$\.])(?P<func>zh)\s*\[\w\[\d+\]\]\(\s*(?P<arg1>[A-Za-z0-9_$]+)(?:\s*,\s*(?P<arg2>[A-Za-z0-9_$]+))?(?:\s*,\s*[^)]*)?\s*\)arg1thisarg2zParameters found: )	r4   r5   r6   r7   rF   	MULTILINEfinditerr9   append)rL   rH   r3   resultsmchosens         r   rG   zCipher._extract_nsig_param_val   s     	89 **9-. / LL

 !!$' 	#A()6(AaggfoQWWV_[\[b[bci[jFNN6"	# 	)'34r   N)__name__
__module____qualname__r$   r   r)   r.   r   r   staticmethodlistrG    r   r   r	   r	      s    03 0 0(# 4# # ,*
 *
S *
S *
X6 6c 6r !c !c !d ! !r   r	   )__doc__loggingr6   pytubefix.exceptionsr   r   pytubefix.jsinterpr   r   pytubefix.sig_nsig.node_runnerr   	getLoggerrY   r4   r	   r^   r   r   <module>re      s9     	 E J 5			8	$L Lr   