a
    7ñ»jê- ã                   @  s*  d dl mZ d dlZd dlZd dlZd dl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 d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZmZmZmZmZ ddlmZ  ddlm!Z! ddlm"Z# ddlm$Z$ ddl%m&Z&m'Z' d dl(Z)e *e+¡Z,G dd„ de&ƒZ-dS )é    )ÚannotationsN)Úsuppress)ÚAsyncFileLock)Úconfig)Ú	constants)Újs_utils)Ú
page_utils)Úshared_utils)ÚDictÚListÚUnionÚOptionalÚTupleé   )Úbrowser)Úelement)Úcdp_util)ÚPathLike)Ú
ConnectionÚProtocolExceptionc                      sÈ  e Zd ZU dZded< dZded< dÞddd	d
œ‡ fdd„Zdd„ Zdd„ Ze	dd„ ƒZ
dd„ Zdd„ Zdßdddddœdd„Zdàdddd œd!d"„Zdáddd#d$œd%d&„Zdâddd#d œd'd(„Zdãddd*œd+d,„Zdäd-d.„Zdådd/d0œd1d2„Zdædd3d0œd4d5„Zdd#d6œd7d8„Zdçdd9d9d:d;œd<d=„Zd>d?„ Zd@dA„ ZdBdC„ ZdDdE„ ZdFdG„ ZdHdI„ ZdJdK„ Zdèd9dLdMœdNdO„ZdéddPœdQdR„Zdêdd9dSdTœdUdV„Z dWdX„ Z!dYdZœd[d\„Z"d]d^„ Z#d_d`„ Z$dadb„ Z%dcdd„ Z&dedf„ Z'dëdjdk„Z(dìdldm„Z)dndo„ Z*dpdq„ Z+dídtdu„Z,dîdwdx„Z-dïdydz„Z.dðdLdLd|dd}œd~d„Z/d€d�„ Z0d‚dƒ„ Z1dñdd„d…œd†d‡„Z2dòd„dLd9ddŠœd‹dŒ„Z3dód„dd�œdŽd�„Z4d�d‘œd’d“„Z5d”dZœd•d–„Z6dôddZœd—d˜„Z7d™dš„ Z8d›dœ„ Z9d�dž„ Z:dŸd „ Z;dõd¡d¢„Z<d£d¤„ Z=d¥d¦„ Z>d§d¨„ Z?d©dª„ Z@d«d¬„ ZAd­d®„ ZBdöd°d±„ZCd²d³„ ZDd÷d´dµ„ZEd¶d·„ ZFd¸d¹„ ZGdºd»„ ZHdød¼d½„ZIdùd¾d¿„ZJdúdÀdÁ„ZKdûdÂdÃ„ZLdüdÄdÅ„ZMdÆdÇ„ ZNdÈdÉ„ ZOdÊdË„ ZPdÌdÍ„ ZQdÎdÏ„ ZRdÐdÑœdÒdÓ„ZSdýdLdLd|dÔœdÕdÖ„ZTd d×œdØdÙ„ZUdÚdÛ„ ZVdÜdÝ„ ZW‡  ZXS )þÚTaba‚  
    :ref:`tab` is the controlling mechanism/connection to a 'target',
    for most of us 'target' can be read as 'tab'. However it could also
    be an iframe, serviceworker or background script for example,
    although there isn't much to control for those.
    If you open a new window by using
        :py:meth:`browser.get(..., new_window=True)`
    Your url will open a new window. This window is a 'tab'.
    When you browse to another page, the tab will be the same (browser view).
    It's important to keep some reference to tab objects, in case you're
    done interacting with elements and want to operate on the page level again.

    Custom CDP commands
    ---------------------------
    Tab object provide many useful and often-used methods. It is also possible
    to utilize the included cdp classes to to something totally custom.

    The cdp package is a set of so-called "domains" with each having methods,
    events and types.
    To send a cdp method, for example :py:obj:`cdp.page.navigate`,
    you'll have to check whether the method accepts any parameters
    and whether they are required or not.

    You can use:

    ```python
    await tab.send(cdp.page.navigate(url='https://Your-URL-Here'))
    ```

    So tab.send() accepts a generator object,
    which is created by calling a cdp method.
    This way you can build very detailed and customized commands.
    (Note: Finding correct command combos can be a time-consuming task.
     A whole bunch of useful methods have been added,
     preferably having the same apis or lookalikes, as in selenium.)

    Some useful, often needed and simply required methods
    ===================================================================

    :py:meth:`~find`  |  find(text)
    ----------------------------------------
    Finds and returns a single element by text match.
    By default, returns the first element found.
    Much more powerful is the best_match flag,
    although also much more expensive.
    When no match is found, it will retry for <timeout> seconds (default: 10),
    so this is also suitable to use as wait condition.

    :py:meth:`~find` |  find(text, best_match=True) or find(text, True)
    -----------------------------------------------------------------------
    Much more powerful (and expensive) than the above is
    the use of the `find(text, best_match=True)` flag.
    It will still return 1 element, but when multiple matches are found,
    it picks the one having the most similar text length.
    How would that help?
    For example, you search for "login",
    you'd probably want the "login" button element,
    and not thousands of scripts/meta/headings,
    which happens to contain a string of "login".

    When no match is found, it will retry for <timeout> seconds (default: 10),
    so this is also suitable to use as wait condition.

    :py:meth:`~select` | select(selector)
    ----------------------------------------
    Finds and returns a single element by css selector match.
    When no match is found, it will retry for <timeout> seconds (default: 10),
    so this is also suitable to use as wait condition.

    :py:meth:`~select_all` | select_all(selector)
    ------------------------------------------------
    Finds and returns all elements by css selector match.
    When no match is found, it will retry for <timeout> seconds (default: 10),
    so this is also suitable to use as wait condition.

    await :py:obj:`Tab`
    ---------------------------
    Calling `await tab` will do a lot of stuff under the hood,
    and ensures all references are up to date.
    Also it allows for the script to "breathe",
    as it is oftentime faster than your browser or webpage.
    So whenever you get stuck and things crashes or element could not be found,
    you should probably let it "breathe" by calling `await page`
    and/or `await page.sleep()`.

    It ensures :py:obj:`~url` will be updated to the most recent one,
    which is quite important in some other methods.

    Using other and custom CDP commands
    ======================================================
    Using the included cdp module, you can easily craft commands,
    which will always return an generator object.
    This generator object can be easily sent to the :py:meth:`~send` method.

    :py:meth:`~send`
    ---------------------------
    This is probably the most important method,
    although you won't ever call it, unless you want to go really custom.
    The send method accepts a :py:obj:`cdp` command.
    Each of which can be found in the cdp section.

    When you import * from this package, cdp will be in your namespace,
    and contains all domains/actions/events you can act upon.
    zcdp_browser.Browserr   Nz	List[str]Ú_download_behaviorÚstrzcdp.target.TargetInfozOptional['cdp_browser.Browser'])Úwebsocket_urlÚtargetr   c                   s.   t ƒ j|||fi |¤Ž || _d | _d | _d S ©N)ÚsuperÚ__init__r   Z_domZ
_window_id)Úselfr   r   r   Úkwargs©Ú	__class__© úLE:\soccer\ml_env\Lib\site-packages\seleniumbase/undetected/cdp_driver/tab.pyr   ‰   s    zTab.__init__c                 Ã  s   | S r   r"   ©r   r"   r"   r#   Ú
__aenter__•   s    zTab.__aenter__c                 Ã  s"   |   ¡ I d H  |r|r||ƒ‚d S r   )Úaclose)r   Úexc_typeÚexc_valÚexc_tbr"   r"   r#   Ú	__aexit__˜   s    zTab.__aexit__c                 C  s,   d| j jj› d| j jj› d| jdd… › �S )zÄ
        Get the inspector url.
        This url can be used in another browser to show you
        the devtools interface for current tab.
        Useful for debugging and headless mode.
        zhttp://ú:z/devtools/inspector.html?ws=é   N)r   r   ÚhostÚportr   r$   r"   r"   r#   Úinspector_url�   s    zTab.inspector_urlc                 C  s   dd l }|j| jdd� d S )Nr   é   )Únew©Ú
webbrowserÚopenr/   ©r   r3   r"   r"   r#   Úinspector_open§   s    zTab.inspector_openc                 Ã  s   ddl }| | j¡ dS )zŸ
        Opens the system's browser containing the devtools inspector page
        for this tab. Could be handy, especially to debug in headless mode.
        r   Nr2   r5   r"   r"   r#   Úopen_external_inspector¬   s    zTab.open_external_inspectorFTé
   ÚboolzUnion[int, float])ÚtextÚ
best_matchÚreturn_enclosing_elementÚtimeoutc              	   Ã  s˜   t  ¡ }| ¡ }| ¡ }d}z|  |||¡I dH }W n ttfyJ   Y n0 |s”|  |||¡I dH }| ¡ | |kr‚t  d| ¡‚|  d¡I dH  qL|S )a  
        Find single element by text.
        Can also be used to wait for such element to appear.
        :param text:
         Text to search for. Note: Script contents are also considered text.
        :type text: str
        :param best_match:  :param best_match:
         When True (default), it will return the element which has the most
         comparable string length. This could help a lot. Eg:
         If you search for "login", you probably want the login button element,
         and not thousands of tags/scripts containing a "login" string.
         When False, it returns just the first match (but is way faster).
        :type best_match: bool
        :param return_enclosing_element:
            Since we deal with nodes instead of elements,
            the find function most often returns so called text nodes,
            which is actually a element of plain text,
            which is the somehow imaginary "child" of a "span", "p", "script"
            or any other elements which have text between their opening
            and closing tags.
            Most often when we search by text, we actually aim for the
            element containing the text instead of a lousy plain text node,
            so by default the containing element is returned.
            There are exceptions. Eg:
            Elements that use the "placeholder=" property.
        :type return_enclosing_element: bool
        :param timeout:
         Raise timeout exception when after this many seconds nothing is found.
        :type timeout: float,int
        Nú$Time ran out while waiting for: {%s}ç      à?)	ÚasyncioÚget_running_loopÚtimeÚstripÚfind_element_by_textÚ	ExceptionÚ	TypeErrorÚTimeoutErrorÚsleep)r   r:   r;   r<   r=   ÚloopÚ
start_timeÚitemr"   r"   r#   Úfindµ   s(    %ÿÿ
ÿzTab.findzelement.Element)Úselectorr=   Úreturnc                 Ã  s   | j ||d�I dH S )a|  
        Find a single element by css selector.
        Can also be used to wait for such an element to appear.
        :param selector: css selector,
         eg a[href], button[class*=close], a > img[src]
        :type selector: str
        :param timeout:
         Raise timeout exception when after this many seconds nothing is found.
        :type timeout: float,int
        )rM   r=   N©Úwait_for)r   rM   r=   r"   r"   r#   Úselectï   s    z
Tab.selectzList[element.Element])r:   r=   rN   c              	   Ã  sš   t  ¡ }| ¡ }| ¡ }g }z|  |¡I dH }W n ttfyF   Y n0 |s–| I dH  |  |¡I dH }| ¡ | |kr„t  d| ¡‚|  d¡I dH  qH|S )aq  
        Find multiple elements by text.
        Can also be used to wait for such elements to appear.
        :param text: Text to search for.
        Note: Script contents are also considered text.
        :type text: str
        :param timeout:
         Raise timeout exception when after this many seconds nothing is found.
        :type timeout: float,int
        Nr>   r?   )	r@   rA   rB   rC   Úfind_elements_by_textrE   rF   rG   rH   )r   r:   r=   rI   ÚnowÚitemsr"   r"   r#   Úfind_all   s"    
ÿzTab.find_allc           	      Ã  s¸   t  ¡ }| ¡ }| ¡ }g }|rP|  d¡I dH }|D ]}| | |¡I dH ¡ q4| |  |¡I dH ¡ |s´| I dH  |  |¡I dH }| ¡ | |kr¢t  d| ¡‚|  d¡I dH  qf|S )aä  
        Find multiple elements by CSS Selector.
        Can also be used to wait for such elements to appear.
        :param selector: css selector,
         eg a[href], button[class*=close], a > img[src]
        :type selector: str
        :param timeout:
         Raise timeout exception when after this many seconds nothing is found.
        :type timeout: float,int
        :param include_frames: Whether to include results in iframes.
        :type include_frames: bool
        ÚiframeNr>   r?   )r@   rA   rB   rC   Úquery_selector_allÚextendrG   rH   )	r   rM   r=   Zinclude_framesrI   rS   rT   ÚframesÚfrr"   r"   r#   Ú
select_all!  s$    
ÿzTab.select_allúabout:blank©Únew_tabÚ
new_windowc                 Ë  sÐ   | j stdƒ‚|r|sd}|r|ttddƒs:ttddƒdv rZ| j j|fdddœ|¤ŽI dH S | j j|fdddœ|¤ŽI dH S nP|s¬|  tj |¡¡I dH ^}}}| I dH  | S | j j|fdddœ|¤ŽI dH S dS )	a›  
        Top level get. Utilizes the first tab to retrieve the given url.
        This is a convenience function known from selenium.
        This function handles waits/sleeps and detects when DOM events fired,
        so it's the safest way of navigating.
        :param url: the url to navigate to
        :param new_tab: open new tab
        :param new_window: open new window
        :return: Page
        z>This page/tab has no browser attribute, so you can't use get()TZ	incognitoNÚ_cdp_browser)ÚcometZatlasFr]   )	r   ÚAttributeErrorÚgetattrÚ	sb_configÚgetÚsendÚcdpÚpageZnavigate)r   Úurlr^   r_   r   Zframe_idZ	loader_idÚ_r"   r"   r#   re   G  sP    ÿ
ÿ
ÿýÿÿÿÿÿÿ
ÿ
ÿÿÿzTab.getc                 Ã  s   | j |d�I d H S )N)ri   )re   )r   ri   r"   r"   r#   r4   z  s    zTab.openz0Optional[Union[cdp.dom.Node, 'element.Element']])rM   Ú_nodec           	   
   ƒ  sT  |s |   tj dd¡¡I dH }n|}|jdkr4|j}g }z |   tj |j|¡¡I dH }W n¦ tyþ } zŽ|durÒd|j	 
¡ v rêt|ddƒrž|`g W  Y d}~S | ¡ I dH  d|_|  ||¡I dH W  Y d}~S n|   tj ¡ ¡I dH  ‚ W Y d}~n
d}~0 0 |�s
g S g }|D ]<‰ t |‡ fdd„¡}|�s4�qt || |¡}| |¡ �q|S )	a‰  
        Equivalent of JavaScript "document.querySelectorAll".
        This is considered one of the main methods to use in this package.
        It returns all matching :py:obj:`element.Element` objects.
        :param selector: css selector.
         (first time? => https://www.w3schools.com/cssref/css_selectors.php )
        :type selector: str
        :param _node: internal use
        éÿÿÿÿTNÚIFRAMEúcould not find nodeÚ__lastc                   s
   | j ˆ kS r   ©Únode_id©Ún©Únidr"   r#   Ú<lambda>«  ó    z(Tab.query_selector_all.<locals>.<lambda>)rf   rg   ÚdomÚget_documentÚ	node_nameÚcontent_documentrW   rq   r   ÚmessageÚlowerrc   Ú
_Tab__lastÚupdateÚdisableÚutilÚfilter_recurser   ÚcreateÚappend)	r   rM   rk   ÚdocÚnode_idsÚerT   ÚnodeÚelemr"   rt   r#   rW   }  s@    
ÿÿ zTab.query_selector_allz.Optional[Union[cdp.dom.Node, element.Element]]c              
   ƒ  s@  |  ¡ }|s(|  tj dd¡¡I dH }n|}|jdkr<|j}d‰ z |  tj |j|¡¡I dH ‰ W n¨ t	�y } zŽ|durÜd|j
 ¡ v rôt|ddƒr¨|`g W  Y d}~S | ¡ I dH  d|_|  ||¡I dH W  Y d}~S n|  tj ¡ ¡I dH  ‚ W Y d}~n
d}~0 0 ˆ �sdS t |‡ fdd„¡}|�s2dS t || |¡S )	zŒ
        Find a single element based on a CSS Selector string.
        :param selector: CSS Selector(s)
        :type selector: str
        rl   TNrm   rn   ro   c                   s
   | j ˆ kS r   rp   rr   rp   r"   r#   rv   Ü  rw   z$Tab.query_selector.<locals>.<lambda>)rC   rf   rg   rx   ry   rz   r{   Úquery_selectorrq   r   r|   r}   rc   r~   r   r€   r�   r‚   r   rƒ   )r   rM   rk   r…   r‡   rˆ   r"   rp   r#   rŠ   ³  s:    

ÿÿ zTab.query_selector)r:   rN   c              	   ƒ  sÖ  ˆ  ¡ ‰ˆ tj dd¡¡I dH }ˆ tj ˆd¡¡I dH \}}|sHg S |rjˆ tj |d|¡¡I dH }ng }ˆ tj |¡¡I dH  g }|D ]¨‰t 	|‡fdd„¡}|sÊˆ tjj
ˆd�¡I dH }|sÊqŽzt |ˆ|¡}W n tyò   Y qŽY n0 |jdk�r,|j�s| ¡ I dH  | |j�p$|¡ qŽqŽ| |¡ qŽt |d	d„ ¡}	|	�r¶‡fd
d„|	D ƒ}
|
D ]P‰ ˆ j�rdt ˆ ‡fdd„¡}|�rd‡ ‡fdd„|D ƒ}| dd„ |D ƒ¡ �qdˆ tj ¡ ¡I dH  |�pÔg S )zÓ
        Returns element which match the given text.
        Note: This may (or will) also return any other element
        (like inline scripts), which happen to contain that text.
        :param text:
        rl   TNr   c                   s
   | j ˆ kS r   rp   rr   rt   r"   r#   rv   û  rw   z+Tab.find_elements_by_text.<locals>.<lambda>rp   é   c                 S  s
   | j dkS ©Nrm   ©rz   ©rˆ   r"   r"   r#   rv     rw   c                   s   g | ]}t  |ˆ |j¡‘qS r"   ©r   rƒ   r{   ©Ú.0rV   r$   r"   r#   Ú
<listcomp>!  s   ÿz-Tab.find_elements_by_text.<locals>.<listcomp>c                   s   | j dkoˆ  ¡ | j ¡ v S ©Nr‹   ©Ú	node_typer}   Z
node_valuerŽ   ©r:   r"   r#   rv   )  s   
c                   s   g | ]}t  |ˆˆ j¡‘qS r"   ©r   rƒ   Útree©r‘   Z	text_node©Úiframe_elemr   r"   r#   r’   -  s   ÿc                 s  s   | ]}|j V  qd S r   ©Úparentr™   r"   r"   r#   Ú	<genexpr>1  s   z,Tab.find_elements_by_text.<locals>.<genexpr>)rC   rf   rg   rx   ry   Úperform_searchÚget_search_resultsÚdiscard_search_resultsr�   r‚   Zresolve_noder   rƒ   ÚBaseExceptionr•   r�   r   r„   Úfilter_recurse_allr{   rX   r€   )r   r:   r…   Ú	search_idÚnresultr†   rT   rˆ   r‰   ÚiframesÚiframes_elemsÚiframe_text_nodesÚiframe_text_elemsr"   ©r›   ru   r   r:   r#   rR   á  sl    
ÿÿ

ÿÿ
þ
þþ
ÿzTab.find_elements_by_textzOptional[bool]zUnion[element.Element, None])r:   r;   r<   rN   c              
   ƒ  sT  ˆ  tj dd¡¡I dH }ˆ ¡ ‰ˆ  tj ˆd¡¡I dH \}}|sHdS ˆ  tj |d|¡¡I dH }ˆ  tj |¡¡I dH  |s„g }g }|D ]€‰t 	|‡fdd„¡}	zt
 |	ˆ|¡}
W n tyÌ   Y qŒY n0 |
jdk�r|
jsî|
 ¡ I dH  | |
jpú|
¡ qŒqŒ| |
¡ qŒt |dd„ ¡}|�r„‡fd	d
„|D ƒ}|D ]H‰ t ˆ ‡fdd„¡}|�r:‡ ‡fdd
„|D ƒ}| dd„ |D ƒ¡ �q:z²|�s¨W ˆ  tj ¡ ¡I dH  dS |�rìt|‡fdd„d�}|�pÎ|d }
|
W ˆ  tj ¡ ¡I dH  S |D ],}
|
�rð|
  W ˆ  tj ¡ ¡I dH  S �qðW ˆ  tj ¡ ¡I dH  nˆ  tj ¡ ¡I dH  0 dS )aë  
        Finds and returns the first element containing <text>, or best match.
        :param text:
        :param best_match:
            When True, which is MUCH more expensive (thus much slower),
            will find the closest match based on length.
            When searching for "login", you probably want the button element,
            and not thousands of tags/scripts containing the "login" string.
        :type best_match: bool
        :param return_enclosing_element:
        rl   TNr   c                   s
   | j ˆ kS r   rp   rr   rt   r"   r#   rv   W  rw   z*Tab.find_element_by_text.<locals>.<lambda>r‹   c                 S  s
   | j dkS rŒ   r�   rŽ   r"   r"   r#   rv   p  rw   c                   s   g | ]}t  |ˆ |j¡‘qS r"   r�   r�   r$   r"   r#   r’   s  s   ÿz,Tab.find_element_by_text.<locals>.<listcomp>c                   s   | j dkoˆ  ¡ | j ¡ v S r“   r”   rŽ   r–   r"   r#   rv   z  s   
c                   s   g | ]}t  |ˆˆ j¡‘qS r"   r—   r™   rš   r"   r#   r’   ~  s   ÿc                 s  s   | ]}|j V  qd S r   rœ   r™   r"   r"   r#   rž   ‚  s   z+Tab.find_element_by_text.<locals>.<genexpr>c                   s   t tˆ ƒt| jƒ ƒS r   )ÚabsÚlenZtext_all)Úelr–   r"   r#   rv   Š  rw   )Úkey)rf   rg   rx   ry   rC   rŸ   r    r¡   r�   r‚   r   rƒ   r¢   r•   r�   r   r„   r£   rX   r€   Úmin)r   r:   r;   r<   r…   r¤   r¥   r†   rT   rˆ   r‰   r¦   r§   r¨   r©   Zclosest_by_lengthr"   rª   r#   rD   7  s„    ÿÿ

ÿÿ
þ
þþ
ÿóÿùþzTab.find_element_by_textc                 Ã  s   |   tj d¡¡I dH  dS )zHistory backzwindow.history.back()N©rf   rg   ÚruntimeÚevaluater$   r"   r"   r#   Úback–  s    zTab.backc                 Ã  s   |   tj d¡¡I dH  dS )zHistory forwardzwindow.history.forward()Nr°   r$   r"   r"   r#   Úforwardš  s    zTab.forwardc                 Ã  s   |   tj ¡ ¡I dH S )zGet Navigation HistoryN)rf   rg   rh   Úget_navigation_historyr$   r"   r"   r#   rµ   ž  s    zTab.get_navigation_historyc                 Ã  s   |   d¡I dH S )zGet User Agent Stringznavigator.userAgentN©r²   r$   r"   r"   r#   Úget_user_agent¢  s    zTab.get_user_agentc                 Ã  s   |   d¡I dH S )zGet Cookie Stringzdocument.cookieNr¶   r$   r"   r"   r#   Úget_cookie_string¦  s    zTab.get_cookie_stringc                 Ã  s   |   d¡I dH S )zGet Locale Codez,navigator.language || navigator.languages[0]Nr¶   r$   r"   r"   r#   Úget_locale_codeª  s    ÿzTab.get_locale_codec                 Ã  s   |   d¡I dH S )z&Determine if connected to the Internetznavigator.onLineNr¶   r$   r"   r"   r#   Ú	is_online°  s    zTab.is_onlinezOptional[str]©Úignore_cacheÚscript_to_evaluate_on_loadc                 Ã  s    |   tjj||d�¡I dH  dS )zÔ
        Reloads the page
        :param ignore_cache: When set to True (default),
         it ignores cache, and re-downloads the items.
        :param script_to_evaluate_on_load: Script to run on load.
        r»   N)rf   rg   rh   Úreload)r   r¼   r½   r"   r"   r#   r¾   ´  s    þÿz
Tab.reload)Ú
expressionc              	   Ã  sb   |   tjj|d||dd�¡I d H \}}|r2t|ƒ‚|r^|rL|jd ur^|jS n|jd ur^|jjS d S )NT)r¿   Zuser_gestureÚawait_promiseÚreturn_by_valueÚ allow_unsafe_eval_blocked_by_csp)rf   rg   r±   r²   r   ÚvalueZdeep_serialized_value)r   r¿   rÀ   rÁ   Úremote_objectÚerrorsr"   r"   r#   r²   Æ  s$    ûÿ	

zTab.evaluatezJUnion[Dict, Tuple[cdp.runtime.RemoteObject, cdp.runtime.ExceptionDetails]])Úobj_namerÁ   rN   c                 Ã  s†   d| }d| }|   tjj|d|dd�¡I dH \}}|r\|   tjj|d|dd�¡I dH \}}|rht|ƒ‚|rz|jr‚|jS n||fS dS )aU  
        Dump Given js object with its properties and values as a dict.
        Note: Complex objects might not be serializable,
        therefore this method is not a "source of truth"
        :param obj_name: the js object to dump
        :type obj_name: str
        :param return_by_value: If you want an tuple of cdp objects
         (returnvalue, errors), then set this to False.
        :type return_by_value: bool

        Example
        -------

        x = await self.js_dumps('window')
        print(x)
            '...{
            'pageYOffset': 0,
            'visualViewport': {},
            'screenX': 10,
            'screenY': 10,
            'outerWidth': 1050,
            'outerHeight': 832,
            'devicePixelRatio': 1,
            'screenLeft': 10,
            'screenTop': 10,
            'styleMedia': {},
            'onsearch': None,
            'isSecureContext': True,
            'trustedTypes': {},
            'performance': {'timeOrigin': 1707823094767.9,
            'timing': {'connectStart': 0,
            'navigationStart': 1707823094768,
            ]...
        að	  
            function ___dump(obj, _d = 0) {
                let _typesA = ['object', 'function'];
                let _typesB = ['number', 'string', 'boolean'];
                if (_d == 2) {
                    console.log('maxdepth reached for ', obj);
                    return
                }
                let tmp = {}
                for (let k in obj) {
                    if (obj[k] == window) continue;
                    let v;
                    try {
                        if (obj[k] === null
                            || obj[k] === undefined
                            || obj[k] === NaN) {
                            console.log('obj[k] is null or undefined or Nan',
                            k, '=>', obj[k])
                            tmp[k] = obj[k];
                            continue
                        }
                    } catch (e) {
                        tmp[k] = null;
                        continue
                    }
                    if (_typesB.includes(typeof obj[k])) {
                        tmp[k] = obj[k]
                        continue
                    }
                    try {
                        if (typeof obj[k] === 'function') {
                            tmp[k] = obj[k].toString()
                            continue
                        }
                        if (typeof obj[k] === 'object') {
                            tmp[k] = ___dump(obj[k], _d + 1);
                            continue
                        }
                    } catch (e) {}
                    try {
                        tmp[k] = JSON.stringify(obj[k])
                        continue
                    } catch (e) {
                    }
                    try {
                        tmp[k] = obj[k].toString();
                        continue
                    } catch (e) {}
                }
                return tmp
            }
            function ___dumpY(obj) {
                var objKeys = (obj) => {
                    var [target, result] = [obj, []];
                    while (target !== null) {
                        result = result.concat(
                            Object.getOwnPropertyNames(target)
                        );
                        target = Object.getPrototypeOf(target);
                    }
                    return result;
                }
                return Object.fromEntries(
                    objKeys(obj).map(_ => [_, ___dump(obj[_])]))
            }
            ___dumpY( %s )
            a6  
            ((obj, visited = new WeakSet()) => {
                 if (visited.has(obj)) {
                     return {}
                 }
                 visited.add(obj)
                 var result = {}, _tmp;
                 for (var i in obj) {
                         try {
                             if (i === 'enabledPlugin'
                                 || typeof obj[i] === 'function') {
                                 continue;
                             } else if (typeof obj[i] === 'object') {
                                 _tmp = recurse(obj[i], visited);
                                 if (Object.keys(_tmp).length) {
                                     result[i] = _tmp;
                                 }
                             } else {
                                 result[i] = obj[i];
                             }
                         } catch (error) {
                             // console.error('Error:', error);
                         }
                     }
                return result;
            })(%s)
        T)rÀ   rÁ   rÂ   N)rf   rg   r±   r²   r   rÃ   )r   rÆ   rÁ   Z	js_code_aZ	js_code_brÄ   Zexception_detailsr"   r"   r#   Újs_dumpsÝ  s>    )C½ÿGåÿüÿüÿzTab.js_dumpsc                 Ã  sN   | j rJ| j jrJ|  tj j| j jd�¡I dH  |  ¡ I dH  t d¡I dH  dS )z.Close the current target (ie: tab,window,page))Ú	target_idNçš™™™™™¹?)r   rÈ   rf   rg   Zclose_targetr&   r@   rH   r$   r"   r"   r#   Úclose„  s    ÿ
z	Tab.closez/Tuple[cdp.browser.WindowID, cdp.browser.Bounds])rN   c                 Ã  s&   |   tj | j¡¡I dH \}}||fS )zGet the window BoundsN)rf   rg   r   Zget_window_for_targetrÈ   )r   Ú	window_idÚboundsr"   r"   r#   Ú
get_window�  s    ÿzTab.get_windowc                 Ã  s8   |   tj dd¡¡I dH }|   tjj|jdd�¡I dH S )z+Gets the current page source content (html)rl   TN)Úbackend_node_idZinclude_shadow_dom)rf   rg   rx   ry   Zget_outer_htmlrÎ   )r   r…   r"   r"   r#   Úget_content–  s    þÿzTab.get_contentc                 Ã  s   | j dd�I dH S )zMaximize page/tab/windowÚmaximize©ÚstateN©Úset_window_stater$   r"   r"   r#   rÐ      s    zTab.maximizec                 Ã  s   | j dd�I dH S )úMinimize page/tab/windowÚminimizerÑ   NrÓ   r$   r"   r"   r#   rÖ   ¤  s    zTab.minimizec                 Ã  s   | j dd�I dH S )rÕ   Ú
fullscreenrÑ   NrÓ   r$   r"   r"   r#   r×   ¨  s    zTab.fullscreenc                 Ã  s   | j dd�I d H S )NÚnormalrÑ   rÓ   r$   r"   r"   r#   Úmedimize¬  s    zTab.medimizer   é   é   c                 Ã  s   |   ||||¡I dH S )aW  
        Set window size and position.
        :param left:
         Pixels from the left of the screen to the window top-left corner.
        :param top:
         Pixels from the top of the screen to the window top-left corner.
        :param width: width of the window in pixels
        :param height: height of the window in pixels
        NrÓ   ©r   ÚleftÚtopÚwidthÚheightr"   r"   r#   Úset_window_size¯  s    
zTab.set_window_sizec                 Ã  s   |   ||||¡I dH S )z>Same as set_window_size(). Uses a different naming convention.NrÓ   rÜ   r"   r"   r#   Úset_window_rect»  s    zTab.set_window_rectc                 Ã  s    |   tj | jj¡¡I dH  dS )z*Active this target (Eg: tab, window, page)N)rf   rg   r   Zactivate_targetrÈ   r$   r"   r"   r#   Úactivate¿  s    zTab.activatec                 Ã  s   |   ¡ I dH  dS )zAlias to self.activateN)rã   r$   r"   r"   r#   Úbring_to_frontÃ  s    zTab.bring_to_frontéÐ  rØ   c           
      ƒ  sÖ   g d¢}|   ¡ I dH \}}|D ]"‰ t‡ fdd„| ¡ D ƒƒr qXqtdd |¡|f ƒ‚ttjjˆ  	¡ tjjj
ƒ}	|	tjjj
kr–tj |||||	¡}n | jdd�I dH  tjj|	d	�}|  tjj||d
�¡I dH  dS )a�  
        Sets the window size or state.
        For state you can provide the full name like minimized, maximized,
        normal, fullscreen, or something which leads to either of those,
        like min, mini, mi,  max, ma, maxi, full, fu, no, nor.
        In case state is set other than "normal",
        the left, top, width, and height are ignored.
        :param left:
            desired offset from left, in pixels
        :type left: int
        :param top:
            desired offset from the top, in pixels
        :type top: int
        :param width:
            desired width in pixels
        :type width: int
        :param height:
            desired height in pixels
        :type height: int
        :param state:
            can be one of the following strings:
                - normal
                - fullscreen
                - maximized
                - minimized
        :type state: str
        )Z	minimizedZ	maximizedr×   rØ   Nc                 3  s   | ]}|ˆ v V  qd S r   r"   )r‘   Úx©Z
state_namer"   r#   rž   ê  rw   z'Tab.set_window_state.<locals>.<genexpr>z-could not determine any of %s from input '%s'ú,rØ   rÑ   )Úwindow_state)rÌ   )rÍ   Úallr}   Ú	NameErrorÚjoinrc   rg   r   ZWindowStateÚupperZNORMALZBoundsrÔ   rf   Zset_window_bounds)
r   rÝ   rÞ   rß   rà   rÒ   Zavailable_statesrË   rÌ   ré   r"   rç   r#   rÔ   Ç  s0    ÿÿý
ÿÿzTab.set_window_stateé   c                 Ã  sJ   |   ¡ I dH \}}|  tjjdd|j|d   dddddd�¡I dH  dS )z´
        Scrolls the page down.
        :param amount: Number in percentage.
         25 is a quarter of page, 50 half, and 1000 is 10x the page.
        :type amount: int
        Nr   éd   Téa  )ræ   ÚyÚ
y_distanceZy_overscrollÚx_overscrollÚprevent_flingÚrepeat_delay_msÚspeed©rÍ   rf   rg   Zinput_Zsynthesize_scroll_gesturerà   ©r   ÚamountrË   rÌ   r"   r"   r#   Úscroll_down  s    	øÿzTab.scroll_downc                 Ã  sF   |   ¡ I dH \}}|  tjjdd|j|d  ddddd�¡I dH  dS )z²
        Scrolls the page up.
        :param amount: Number in percentage.
         25 is a quarter of page, 50 half, and 1000 is 10x the page.
        :type amount: int
        Nr   rï   Trð   )ræ   rñ   rò   ró   rô   rõ   rö   r÷   rø   r"   r"   r#   Ú	scroll_up  s    	ùÿzTab.scroll_upÚ zOptional[Union[int, float]])rM   r:   r=   rN   c                 Ã  sÌ   t  ¡ }| ¡ }|rl|  |¡I dH }|sh|  |¡I dH }| ¡ | |krVt  d| ¡‚|  d¡I dH  q$|S |rÈ|  |¡I dH }|sÄ|  |¡I dH }| ¡ | |kr²t  d| ¡‚|  d¡I dH  q€|S dS )aÃ  
        Variant on query_selector_all and find_elements_by_text.
        This variant takes either selector or text,
        and will block until the requested element(s) are found.
        It will block for a maximum of <timeout> seconds,
        after which a TimeoutError will be raised.
        :param selector: css selector
        :param text: text
        :param timeout:
        :return: Element
        :raises: asyncio.TimeoutError
        Nr>   gœÄ °rh±?)r@   rA   rB   rŠ   rG   rH   rD   )r   rM   r:   r=   rI   rS   rK   r"   r"   r#   rP   1  s,    ÿÿzTab.wait_forc                 Ã  sÈ   t  |¡}t |¡}t  |¡}t |¡}| d¡rfttƒ� t |d¡}W d  ƒ n1 s\0    Y  |}t  |¡}t |¡}d|||f }ttƒ�  |  |¡I dH  W d  ƒ n1 sº0    Y  dS )a  This method uses JavaScript to set/update a common attribute.
        All matching selectors from querySelectorAll() are used.
        Example => (Make all links on a website redirect to Google):
        self.set_attributes("a", "href", "https://google.com"))ú/z./ú(ZxpathNzÉvar $elements = document.querySelectorAll('%s');
            var index = 0, length = $elements.length;
            for(; index < length; index++){
            $elements[index].setAttribute('%s','%s');})	ÚreÚescaper   Úescape_quotes_if_neededÚ
startswithr   rE   Zconvert_to_css_selectorr²   )r   rM   Ú	attributerÃ   Zcss_selectorZjs_coder"   r"   r#   Úset_attributesZ  s&    





*

ýýÿ

zTab.set_attributesc                 Ã  s   |   ddd¡I dH  dS )zqAll `target="_blank"` links become `target="_self"`.
        This prevents those links from opening in a new tab.z[target="_blank"]r   Ú_selfN)r  r$   r"   r"   r#   Úinternalize_linksv  s    zTab.internalize_linkszOptional[PathLike])ri   Úfilenamec                 Ã  sÀ   | j s@tj ¡ d }|jdd� |  |¡I dH  t d|› �¡ |s`| d¡d }| 	d¡d	 }d
||f }|  
d¡I dH d	 }| ¡ I dH  |  tjj||jtjj|jd�gd�¡I dH  dS )zÖ
        Downloads the file by the given url.
        :param url: The URL of the file.
        :param filename: The name for the file.
         If not specified, the name is composed from the url file name
        Z	downloadsT)Úexist_okNz9No download path set, so creating and using a default of rý   rl   ú?r   a   
         (elem) => {
            async function _downloadFile(
              imageSrc,
              nameOfDownload,
            ) {
              const response = await fetch(imageSrc);
              const blobImage = await response.blob();
              const href = URL.createObjectURL(blobImage);
              const anchorElement = document.createElement('a');
              anchorElement.href = href;
              anchorElement.download = nameOfDownload;
              document.body.appendChild(anchorElement);
              anchorElement.click();
              setTimeout(() => {
                document.body.removeChild(anchorElement);
                window.URL.revokeObjectURL(href);
                }, 500);
            }
            _downloadFile('%s', '%s')
            }
            Úbody)Ú	object_id)r  Ú	arguments)r   ÚpathlibÚPathÚcwdÚmkdirÚset_download_pathÚwarningsÚwarnÚrsplitÚsplitrW   r   rf   rg   r±   Zcall_function_onr  ZCallArgument)r   ri   r  Zdirectory_pathÚcoder
  r"   r"   r#   Údownload_file{  s4    	ÿÿþëýÿzTab.download_fileÚautoÚpng)r  ÚformatÚ	full_pagerN   c                 Ã  s"  |   ¡ I dH  d}| ¡ dv r(d}d}n| ¡ dv r<d}d}|rH|dkr²tj | jj¡}|j d	¡}|d
 }| 	dd¡d }t
j
 ¡  d¡}	|j› d|› d|	› �}
t |
| ¡}n
t |¡}|jjddd� |  tjj||d�¡I dH }|sôtdƒ‚t |¡}|�std| ƒ‚| |¡ t|ƒS )aN  
        Saves a screenshot of the page.
        This is not the same as :py:obj:`Element.save_screenshot`,
        which saves a screenshot of a single element only.
        :param filename: uses this as the save path
        :type filename: PathLike
        :param format: jpeg or png (defaults to jpeg)
        :type format: str
        :param full_page:
         When False (default), it captures the current viewport.
         When True, it captures the entire page.
        :type full_page: bool
        :return: The path/filename of the saved screenshot.
        :rtype: str
        N)ZjpgÚjpegz.jpgr  )r  z.pngr  r  rý   rl   r	  r   r   ú%Y-%m-%d_%H-%M-%SÚ__rj   T©Úparentsr  )Zformat_Zcapture_beyond_viewportzXCould not take screenshot. Most possible cause is the page has not finished loading yet.úInvalid filename or path: '%s')rH   r}   ÚurllibÚparseÚurlparser   ri   Úpathr  r  ÚdatetimerS   ÚstrftimeÚhostnamer  r  r�   r  rf   rg   rh   Zcapture_screenshotr   Úbase64Ú	b64decodeÚRuntimeErrorÚwrite_bytesr   )r   r  r  r  r%  ÚextÚparsedÚpartsÚ	last_partÚdt_strÚ	candidateÚdataÚ
data_bytesr"   r"   r#   Úsave_screenshot³  s@    
ÿÿ
ÿ

zTab.save_screenshot)r  rN   c                 Ã  sø   |   ¡ I dH  d}d}|r"|dkrŒtj | jj¡}|j d¡}|d }| dd¡d }t	j	 
¡  d	¡}|j› d
|› d|› �}t || ¡}n
t |¡}|jjddd� |  tj ¡ ¡I dH \}	}
|	sÌtdƒ‚t |	¡}|sætd| ƒ‚| |¡ t|ƒS )zÐ
        Saves a webpage as a PDF.
        :param filename: uses this as the save path
        :type filename: PathLike
        :return: The path/filename of the saved screenshot.
        :rtype: str
        Nz.pdfr  rý   rl   r	  r   r   r  r  rj   Tr  zCould not save PDF.r!  )rH   r"  r#  r$  r   ri   r%  r  r  r&  rS   r'  r(  r  r  r�   r  rf   rg   rh   Úprint_to_pdfr   r)  r*  r+  r,  r   )r   r  r%  r-  r.  r/  r0  r1  r2  r3  rj   r4  r"   r"   r#   r6  ì  s*    


zTab.print_to_pdfr   )r%  c                 Ã  s:   |   tjjdt| ¡ ƒd�¡I dH  dt| ¡ ƒg| _dS )zn
        Sets the download path.
        When not set, a default folder is used.
        :param path:
        Zallow)ZbehaviorÚdownload_pathN)rf   rg   r   Zset_download_behaviorr   Úresolver   )r   r%  r"   r"   r#   r    s    ÿÿ
zTab.set_download_pathzList['element.Element']c                 ƒ  s$   ˆ j dd�I dH }‡ fdd„|D ƒS )zAGet all elements of tag: link, a, img, scripts meta, video, audioúa,link,img,script,meta©rM   Nc                   s   g | ]}t  |ˆ ¡‘qS r"   )r   rƒ   )r‘   Úassetr$   r"   r#   r’      rw   z.Tab.get_all_linked_sources.<locals>.<listcomp>)rW   )r   Ú
all_assetsr"   r$   r#   Úget_all_linked_sources  s    ÿzTab.get_all_linked_sourcesc              	   ƒ  s¼   ddl }g }| jdd�I dH }|D ]”}|s>| |jp8|j¡ q"|j ¡ D ]l\}‰ |dv rHdˆ v rbqHt‡ fdd„d	D ƒƒszqH|j 	d
 
| j d
¡dd… ¡ˆ ¡}| d¡sªqH| |¡ qHq"|S )zó
        Convenience function, which returns all links (a,link,img,script,meta).
        :param absolute:
         Try to build all the links in absolute form
         instead of "as is", often relative.
        :return: List of URLs.
        r   Nr9  r:  )ÚsrcÚhrefú#c                   s   g | ]}|ˆ v ‘qS r"   r"   )r‘   rj   ©Úvr"   r#   r’   8  rw   z$Tab.get_all_urls.<locals>.<listcomp>)Úhttpú//rý   rý   r‹   )rC  rD  Úws)Úurllib.parserW   r„   r>  r?  ÚattrsrT   Úanyr#  Úurljoinrì   ri   r  r  )r   Úabsoluter"  Úresr<  r;  ÚkZabs_urlr"   rA  r#   Úget_all_urls"  s*    ÿÿ
zTab.get_all_urlsc                 Ã  s"   | j ddd�I d H }| ¡ I d H S )NÚhtmlr   ©r=   )rL   Zget_html_async)r   r   r"   r"   r#   Úget_htmlB  s    zTab.get_htmlc                 Ã  s   |   ¡ I d H S r   )rP  r$   r"   r"   r#   Úget_page_sourceF  s    zTab.get_page_sourcec                 Ã  s4   z| j |dd�I d H  W dS  ty.   Y dS 0 d S )Nç{®Gáz„?rO  TF)rQ   rE   )r   rM   r"   r"   r#   Úis_element_presentI  s
    zTab.is_element_presentc                 Ã  s   d|vrzz| j |dd�I d H }W n ty4   Y dS 0 |s>dS z$| ¡ I d H }|jdkp`|jdkW S  tyv   Y dS 0 n¢ttƒ�„ | d¡d  d¡d }| d¡d  d	¡d dd… }| j |dd�I d H }|sÚtƒ ‚|  |¡I d H }|� sötƒ ‚W d   ƒ d
S 1 �s0    Y  dS d S )Nú
:contains(rR  rO  Fr   ú rl   r   ú)T)rQ   rE   Úget_position_asyncrß   rà   r   r  rD   )r   rM   r   ÚpositionZtag_namer:   r"   r"   r#   Úis_element_visibleP  s.    

 "zTab.is_element_visiblec                 Ã  sn   |rt |ƒdk r.|  d¡I d H  |  ¡ I d H }d|v rFd|vrFd|vsfd|v sfd|v sfd|v sfd	|v rjd
S dS )Ni�  ç)\�Âõ(Ì?z data-callback="onCaptchaSuccess"útitle="reCAPTCHA"úid="recaptcha-token"z/challenge-platform/h/b/zid="challenge-widget-zchallenges.cloudfzcf-turnstile-TF)r¬   rH   rP  )r   Úsourcer"   r"   r#   Z__on_a_cf_turnstile_pagej  s&    þýüúùø	÷zTab.__on_a_cf_turnstile_pagec                 Ï  s   |   d¡I d H rdS dS )Nú"iframe[src*="Incapsula_Resource?"]TF©rY  ©r   Úargsr   r"   r"   r#   Z__on_an_incapsula_hcaptcha_page|  s    z#Tab.__on_an_incapsula_hcaptcha_pagec                 Ï  s   |   d¡I d H rdS dS )Núiframe[data--frc-frame-id]TFr_  r`  r"   r"   r#   Z__on_a_friendly_captcha_page�  s    z Tab.__on_a_friendly_captcha_pagec                 Ï  sr   |   d¡I d H  |  ¡ I d H }d|v s.d|v rR|  d¡I d H rR|   d¡I d H  dS d|v rn|   d¡I d H  dS d	S )
Ngš™™™™™Ù?r\  r[  úiframe[title="reCAPTCHA"]rÉ   Tzcom/recaptcha/api.jsg333333ó?F)rH   rP  rS  )r   ra  r   r]  r"   r"   r#   Z__on_a_g_recaptcha_page†  s    þýûzTab.__on_a_g_recaptcha_pagec              
   Ã  sÜ  d }|   d¡I d H rd}ndS |  d¡I d H  ttƒ��Ž | j|dd�I d H }|d }|d }|  ¡ I d H }|d }|d	 }|d
kr¼|dkr¼t|| ƒdk r¼t|| ƒdk r¼W d   ƒ dS | j|dd�I d H }|d }	|d }
d}d}t 	t
j¡I d H rþd}|	| }|
| }||ft_|  d¡I d H  ttjjƒ}|4 I d H š^ |  ¡ I d H  |  d¡I d H  | j|||dd�I d H  |  d¡I d H  W d   ƒI d H  �q¶1 I d H �s¬0    Y  W d   ƒ dS 1 �sÎ0    Y  dS )Nrc  Fr?   rÉ   rO  ræ   rñ   Ú
innerWidthÚinnerHeighti  i€  én   r   é   é#   é   ç)\�Âõ(¼?çš™™™™™©?rZ  T)rS  rH   r   rE   Úget_element_rectÚget_window_rectr«   Úget_gui_element_rectr@   Ú	to_threadr	   Ú
is_windowsrd   Ú_saved_cf_x_yr   r   ÚMultiBrowserÚPYAUTOGUILOCKrä   Úclick_with_offset)r   rM   Úelement_rectÚe_xÚe_yÚwindow_rectZ	win_widthZ
win_heightZgui_element_rectZgui_e_xZgui_e_yÚx_offsetÚy_offsetræ   rñ   Úgui_lockr"   r"   r#   Z__gui_click_recaptcha—  sX    ÿþýüÿ
ÿ>"zTab.__gui_click_recaptchac           
   	   Ã  s¬  d }|   d¡I d H rFd}d}|  |¡I d H }| |¡I d H }|sJdS ndS |  d¡I d H  d}d}d}ttjjƒ}|4 I d H šÐ |  ¡ I d H  |  d¡I d H  dt	j
v räd	| }	d
|vrÂd| }	nd|vrÒd| }	td|	||f ƒ ttƒ�: |j||dd�I d H  d}|  d¡I d H  W d   ƒ n1 �s.0    Y  W d   ƒI d H  �qf1 I d H �s\0    Y  |�r”|  d¡I d H  dt	j
v �r�tdƒ dS dt	j
v �r¨tdƒ dS )Nr^  ziframe[data-hcaptcha-widget-id]Fçš™™™™™á?é   é$   çyé&1¬¬?ú--debugú`%s`ú"ú"%s"ú'ú'%s'ú& <DEBUG> click_with_offset(%s, %s, %s)©ræ   rñ   ÚcenterTç333333³?ç      è?z <DEBUG> hCaptcha was clicked!z" <DEBUG> hCaptcha was NOT clicked!)rY  rD   Zquery_selector_asyncrH   r   r   rr  rs  rä   ÚsysÚargvÚprintr   rE   Úmouse_click_with_offset_async)
r   rM   Zouter_selectorZouter_elementr   ry  rz  Úwas_clickedr{  Údisplayed_selectorr"   r"   r#   Z__cdp_click_incapsula_hcaptchaÅ  sT    

ÿÿ
ÿ^z"Tab.__cdp_click_incapsula_hcaptchac              	   Ã  sŒ  d}|   d¡I d H r&|  |¡I d H }ndS |  d¡I d H  d}d}d}ttjjƒ}|4 I d H šÐ |  ¡ I d H  |  d¡I d H  dtj	v rÄd| }d	|vr¢d
| }nd|vr²d| }t
d|||f ƒ ttƒ�: |j||dd�I d H  d}|  d¡I d H  W d   ƒ n1 �s0    Y  W d   ƒI d H  �qF1 I d H �s<0    Y  |�rt|  d¡I d H  dtj	v �rpt
dƒ dS dtj	v �rˆt
dƒ dS )Nrb  Fr|  é   é"   r  r€  r�  r‚  rƒ  r„  r…  r†  r‡  Tr‰  rŠ  z& <DEBUG> Friendly Captcha was clicked!z* <DEBUG> Friendly Captcha was NOT clicked!)rY  rD   rH   r   r   rr  rs  rä   r‹  rŒ  r�  r   rE   rŽ  )r   rM   r   ry  rz  r�  r{  r�  r"   r"   r#   Z__gui_click_friendly_captchaò  sJ    

ÿÿ
ÿ^z Tab.__gui_click_friendly_captchar,   c           
      Ã  sz   | j ||d�I d H }d }d|v rV| ¡ I d H }|j}|j}|j}|j}	||||	dœ}n |  dt t	 
|¡¡ ¡I d H }|S )NrO  rT  )ræ   rñ   rß   rà   z4document.querySelector('%s').getBoundingClientRect())rQ   rW  ræ   rñ   rß   rà   rÇ   r   r  rÿ   r   )
r   rM   r=   r   ÚcoordinatesrX  ræ   rñ   rß   rà   r"   r"   r#   rl    s    ÿÿ
zTab.get_element_rectc                 Ã  s†  i }|   d¡I d H }|   d¡I d H }|   d¡I d H }|   d¡I d H }|   d¡I d H }|   d¡I d H }|   d¡I d H }|   d¡I d H }	|   d	¡I d H }
|   d
¡I d H }|   d¡I d H }|   d¡I d H }||d< ||d< ||d< ||d< ||d< ||d< |rü|nd|d< |�r|nd|d< |�r |nd|d< |	�r2|	nd|d< |
�rD|
nd|d< |�rV|nd|d< |�rh|nd|d< |�rz|nd|d< |S )Nzwindow.innerWidthzwindow.innerHeightzwindow.outerWidthzwindow.outerHeightzwindow.pageXOffsetzwindow.pageYOffsetzwindow.scrollXzwindow.scrollYzwindow.screenLeftzwindow.screenTopzwindow.screenXzwindow.screenYrd  re  Ú
outerWidthÚouterHeightrß   rà   r   ÚpageXOffsetÚpageYOffsetÚscrollXÚscrollYÚ
screenLeftÚ	screenTopræ   rñ   r¶   )r   r“  rd  re  r”  r•  r–  r—  r˜  r™  rš  r›  ræ   rñ   r"   r"   r#   rm  +  s8    zTab.get_window_rectc                 Ã  sæ   | j ||d�I dH }|d }|d }|  ¡ I dH }|d |d  }|d }|d |d  }	|| |d  }
|d }ttd	ƒr¸tjd
kr¸|d |d  }|dkr¤d}n|dk r°d}|	| }	|
| }
|	|d  }	|
|d  }
|||	|
dœS )z9(Coordinates are relative to the screen. Not the window.)rO  Nrß   rà   rñ   re  ræ   r—  r`   Zoperar”  rd  é8   é   r   r˜  r™  )rà   rß   ræ   rñ   )rl  rm  Úhasattrrd   r`   )r   rM   r=   ru  Ze_widthZe_heightrx  Z
w_bottom_yZviewport_heightræ   rñ   Zy_scroll_offsetry  r"   r"   r#   rn  I  s.    ÿþzTab.get_gui_element_rectc                 Ã  s   |   d¡I d H S )Nzdocument.titler¶   r$   r"   r"   r#   Ú	get_titled  s    zTab.get_titlec                 Ã  s   |   d¡I d H S )Nzwindow.location.hrefr¶   r$   r"   r"   r#   Úget_current_urlg  s    zTab.get_current_urlc                 Ã  s   |   d¡I d H S )Nzwindow.location.originr¶   r$   r"   r"   r#   Ú
get_originj  s    zTab.get_originc                 Ã  s(   | j ||d�I d H }| |¡I d H  d S ©NrO  )rL   Zsend_keys_async)r   rM   r:   r=   r   r"   r"   r#   Ú	send_keysm  s    zTab.send_keysc                 Ã  s   | j |||d�I d H  d S r¢  )r£  )r   rM   r:   r=   r"   r"   r#   Útypeq  s    zTab.typec                 Ã  s&   | j ||d�I d H }| ¡ I d H  d S r¢  )rL   Úclick_async)r   rM   r=   r   r"   r"   r#   Úclickt  s    z	Tab.clickc                 Ã  sú   |}d|v r t j|ddd�\}}|  |¡I d H r|ttƒ�2 | j|dd�I d H }| ¡ I d H  W d   ƒ qö1 sp0    Y  nz|dkrˆd S ttƒ�V | j||d�I d H  |  |¡I d H rØ| j|dd�I d H }| ¡ I d H  W d   ƒ n1 sì0    Y  d S )NrT  zcss selectorT)ZbyZxp_okrR  rO  r   )r   Zrecalculate_selectorrY  r   rE   rL   r¥  )r   rM   r=   Zoriginal_selectorrj   r   r"   r"   r#   Úclick_if_visiblex  s     ÿ

.
zTab.click_if_visiblec                 Ã  s<   | j ||d�I dH }| ¡ I dH  |j|||d�I dH  dS )z”Click an element at an {X,Y}-offset location.
        {0,0} is the top-left corner of the element.
        This method is used to click on CAPTCHAs.rO  Nr‡  )rL   Zscroll_into_view_asyncrŽ  )r   rM   ræ   rñ   rˆ  r=   r   r"   r"   r#   rt  ‹  s    zTab.click_with_offsetc              
   Ã  s0  |   d¡I dH  |  ¡ I dH }|  |¡I dH r0nf|  |¡I dH rR|  ¡ I dH }|S |  ¡ I dH rr|  ¡ I dH }|S |  ¡ I dH r’|  ¡ I dH }|S dS d}|  	d¡I dH r²d}�np|  	d¡I dH rÊd}�nX|  	d¡I dH râd}�n@|  	d¡I dH � rüd}�n&|  	d¡I dH �rd}�n|  	d	¡I dH �r.d	}nô|  	d
¡I dH �rFd
}nÜ|  	d¡I dH �r^d}nÄ|  	d¡I dH �rvd}n¬|  	d¡I dH �rŽd}n”|  	d¡I dH �r¦d}n||  	d¡I dH �r¾d}nd|  	d¡I dH �rÖd}nL|  	d¡I dH �rîd}n4|  	d¡I dH �rd}n|  	d¡I dH �rd}ndS |�s,dS |  	d¡I dH �rÈ|  	d¡I dH �s†|  	d¡I dH �s†|  	d¡I dH �s†|  	d¡I dH �rÈd}t
tƒ�  |  |¡I dH  W d  ƒ n1 �sº0    Y  �n*|  	d¡I dH �r>|  	d¡I dH �sþ|  	d¡I dH �r>d}t
tƒ�  |  |¡I dH  W d  ƒ n1 �s20    Y  n´|  	d¡I dH �sb|  	d¡I dH �r¢d}t
tƒ�  |  |¡I dH  W d  ƒ n1 �s–0    Y  nP|  	d ¡I dH �ròd!}t
tƒ�  |  |¡I dH  W d  ƒ n1 �sè0    Y  t
tƒ�� |   d"¡I dH  | j|d#d$�I dH }|d% }|d& }d'}d(}	t tj¡I dH �rRd'}	|| }
||	 }|
|ft_|   d¡I dH  ttjjƒ}|4 I dH š^ |  ¡ I dH  |   d"¡I dH  | j|||	d#d$�I dH  |   d)¡I dH  W d  ƒI dH  �q
1 I dH �s 0    Y  W d  ƒ d*S 1 �s"0    Y  dS )+z®This method does a few things to click a CAPTCHA:
        1. Checks to see if a CAPTCHA is on the current page.
        2. If found, calls `click_with_offset(*)` to click it.rj  NFz[class="cf-turnstile"]z#challenge-form div > divz [style="display: grid;"] div divz[class*=spacer] + div divz.spacer div:not([class])z[data-testid*="challenge-"] divz%div#turnstile-widget div:not([class])zngx-turnstile div:not([class])z1form div:not([class]):has(input[name*="cf-turn"])zform div:not(:has(*))z#body > div#check > div:not([class])z.cf-turnstile-wrapperz"[id*="turnstile"] div:not([class])z%[class*="turnstile"] div:not([class])z"[data-callback="onCaptchaSuccess"]z[div:not([class]):not([id]):not([aria-label]) > div:not([class]):not([id]):not([aria-label])Úformzform[class*="center"]zform[class*="right"]zform div[class*="center"]zform div[class*="right"]aÔ  var $elements = document.querySelectorAll(
                'form[class], form div[class]');
                var index = 0, length = $elements.length;
                for(; index < length; index++){
                the_class = $elements[index].getAttribute('class');
                new_class = the_class.replaceAll('center', 'left');
                new_class = new_class.replaceAll('right', 'left');
                $elements[index].setAttribute('class', new_class);}zform div[style*="center"]zform div[style*="right"]aÔ  var $elements = document.querySelectorAll(
                'form[style], form div[style]');
                var index = 0, length = $elements.length;
                for(; index < length; index++){
                the_style = $elements[index].getAttribute('style');
                new_style = the_style.replaceAll('center', 'left');
                new_style = new_style.replaceAll('right', 'left');
                $elements[index].setAttribute('style', new_style);}z'form [id*="turnstile"] div:not([class])z*form [class*="turnstile"] div:not([class])a  var $elements = document.querySelectorAll(
                'form [id*="turnstile"]');
                var index = 0, length = $elements.length;
                for(; index < length; index++){
                $elements[index].setAttribute('align', 'left');}
                var $elements = document.querySelectorAll(
                'form [class*="turnstile"]');
                var index = 0, length = $elements.length;
                for(; index < length; index++){
                $elements[index].setAttribute('align', 'left');}z/[style*="text-align: center;"] div:not([class])a“  var $elements = document.querySelectorAll(
                '[style*="text-align: center;"]');
                var index = 0, length = $elements.length;
                for(; index < length; index++){
                the_style = $elements[index].getAttribute('style');
                new_style = the_style.replaceAll('center', 'left');
                $elements[index].setAttribute('style', new_style);}rk  r   rO  ræ   rñ   é   é    rZ  T)rH   rP  Ú_Tab__on_a_cf_turnstile_pageÚ_Tab__on_a_g_recaptcha_pageÚ_Tab__gui_click_recaptchaÚ#_Tab__on_an_incapsula_hcaptcha_pageÚ"_Tab__cdp_click_incapsula_hcaptchaÚ _Tab__on_a_friendly_captcha_pageÚ _Tab__gui_click_friendly_captcharS  r   rE   r²   rn  r@   ro  r	   rp  rd   rq  r   r   rr  rs  rä   rt  )r   r]  ÚresultrM   Úscriptru  rv  rw  ry  rz  ræ   rñ   r{  r"   r"   r#   Úsolve_captcha“  s   ÿÿÿÿÿÿÿÿÿýüûú
ÿ

4ÿýüÿ

2ÿÿÿü	ÿ
2ÿÿÿ	
0
ÿ>"zTab.solve_captchac                 Ã  s   |   ¡ I d H  d S r   )r´  r$   r"   r"   r#   Úclick_captchaC  s    zTab.click_captchac                 Ã  s   |   tj ¡ ¡I d H S r   )rf   rg   rx   ry   r$   r"   r"   r#   ry   F  s    zTab.get_documentc                 Ã  s   |   tj ¡ ¡I d H S r   )rf   rg   rx   Úget_flattened_documentr$   r"   r"   r#   r¶  I  s    zTab.get_flattened_documentc                 Ã  st   | j js| I dH  d | j dd¡dd… ¡}|  tj tjjd|d�¡¡I dH }i }|D ]}|d ||d < qZ|S )	zq
        Get local storage items as dict of strings.
        Proper deserialization may need to be done.
        Nrý   r‹   rl   T©Zis_local_storageZsecurity_originr   r   )	r   ri   rì   r  rf   rg   Údom_storageZget_dom_storage_itemsÚ	StorageId)r   ÚoriginrT   ÚretvalrK   r"   r"   r#   Úget_local_storageL  s    
ÿÿÿ
zTab.get_local_storageÚdict)rT   c                 ƒ  sV   ˆj jsˆI dH  d ˆj dd¡dd… ¡‰ tj‡ ‡fdd„| ¡ D ƒŽ I dH  dS )zç
        Set local storage.
        Dict items must be strings.
        Simple types will be converted to strings automatically.
        :param items: dict containing {key:str, value:str}
        :type items: dict[str,str]
        Nrý   r‹   rl   c              	     s<   g | ]4\}}ˆ  tjjtjjd ˆ d�t|ƒt|ƒd�¡‘qS )Tr·  )Z
storage_idr®   rÃ   )rf   rg   r¸  Zset_dom_storage_itemr¹  r   )r‘   r®   Úval©rº  r   r"   r#   r’   l  s   
÷ÿûÿz)Tab.set_local_storage.<locals>.<listcomp>)r   ri   rì   r  r@   ZgatherrT   )r   rT   r"   r¿  r#   Úset_local_storage`  s    

öÿzTab.set_local_storage)r:   rM   r=   c                 C  s   | j |||d�S )zÏ
        Alias to query_selector_all or find_elements_by_text,
        depending on whether text= is set or selector= is set.
        :param selector: css selector string
        :type selector: str
        )rM   r:   r=   rO   )r   r:   rM   r=   r"   r"   r#   Ú__call__z  s    ÿzTab.__call__)Úotherc              	   C  s,   z|j | j kW S  ttfy&   Y dS 0 d S )NF)r   rb   rF   )r   rÂ  r"   r"   r#   Ú__eq__Š  s    z
Tab.__eq__c                 C  s>   zt | j|ƒW S  ty8   td| jj› d�| ƒ‚Y n0 d S )Nr‚  z" has no attribute "%s")rc   Ú_targetrb   r!   Ú__name__)r   rK   r"   r"   r#   Ú__getattr__�  s    ÿzTab.__getattr__c              	   C  sH   d}| j jrd| j j› d�}dt| ƒj› d| j› d| j› d|› d�	}|S )	Nrü   z[url: ú]ú<z [z] [z] ú>)r   ri   r¤  rÅ  rÈ   Útype_)r   ÚextraÚsr"   r"   r#   Ú__repr__˜  s
    (zTab.__repr__)N)FTr8   )r8   )r8   )r8   F)r\   FF)r\   )N)N)FT)TN)FT)T)r   r   rÚ   rÛ   )r   r   rÚ   rÛ   )r   r   rÚ   rå   rØ   )rî   )rî   )rü   rü   r8   )N)r  r  F)r  )T)N)r,   )r,   )r,   )r,   )r,   )r   )Fr,   )rü   rü   r8   )YrÅ  Ú
__module__Ú__qualname__Ú__doc__Ú__annotations__r   r   r%   r*   Úpropertyr/   r6   r7   rL   rQ   rU   r[   re   r4   rW   rŠ   rR   rD   r³   r´   rµ   r·   r¸   r¹   rº   r¾   r²   rÇ   rÊ   rÍ   rÏ   rÐ   rÖ   r×   rÙ   rá   râ   rã   rä   rÔ   rú   rû   rP   r  r  r  r5  r6  r  r=  rM  rP  rQ  rS  rY  r«  r®  r°  r¬  r­  r¯  r±  rl  rm  rn  rŸ  r   r¡  r£  r¤  r¦  r§  rt  r´  rµ  ry   r¶  r¼  rÀ  rÁ  rÃ  rÆ  rÍ  Ú__classcell__r"   r"   r    r#   r      sì   
h ü
	   û= ý ý$  ü(   ü3
 ý9 ý.Y  ü_  ý ÿ ÿ (		


 ÿ
=

   ü) ÿ:   ü; þ" 
.-(






 1   ür   ).Ú
__future__r   r@   r)  r&  Úloggingr  rÿ   r‹  rF  r"  r  Ú
contextlibr   Úfilelockr   Zseleniumbaser   rd   Zseleniumbase.fixturesr   r   r   r	   Útypingr
   r   r   r   r   rü   r   Zcdp_browserr   r   r�   r   Ú
connectionr   r   Zmycdprg   Ú	getLoggerrÅ  Úloggerr   r"   r"   r"   r#   Ú<module>   s2   
