@@ -649,12 +649,144 @@ def uc_gui_write(driver, text):
649649 pyautogui .write (text )
650650
651651
652- def uc_gui_handle_cf (driver , frame = "iframe" ):
652+ def get_gui_element_position (driver , selector ):
653+ element = driver .wait_for_element_present (selector , timeout = 3 )
654+ element_rect = element .rect
655+ window_rect = driver .get_window_rect ()
656+ window_bottom_y = window_rect ["y" ] + window_rect ["height" ]
657+ viewport_height = driver .execute_script ("return window.innerHeight;" )
658+ viewport_x = window_rect ["x" ] + element_rect ["x" ]
659+ viewport_y = window_bottom_y - viewport_height + element_rect ["y" ]
660+ return (viewport_x , viewport_y )
661+
662+
663+ def uc_gui_click_x_y (driver , x , y , timeframe = 0.25 , uc_lock = True ):
664+ install_pyautogui_if_missing (driver )
665+ import pyautogui
666+ pyautogui = get_configured_pyautogui (pyautogui )
667+ screen_width , screen_height = pyautogui .size ()
668+ if x > screen_width or y > screen_height :
669+ raise Exception (
670+ "PyAutoGUI cannot click on point (%s, %s)"
671+ " outside screen. (Width: %s, Height: %s)"
672+ % (x , y , screen_width , screen_height )
673+ )
674+ if uc_lock :
675+ gui_lock = fasteners .InterProcessLock (
676+ constants .MultiBrowser .PYAUTOGUILOCK
677+ )
678+ with gui_lock : # Prevent issues with multiple processes
679+ pyautogui .moveTo (x , y , timeframe , pyautogui .easeOutQuad )
680+ if timeframe >= 0.25 :
681+ time .sleep (0.0555 ) # Wait if moving at human-speed
682+ if "--debug" in sys .argv :
683+ print (" <DEBUG> pyautogui.click(%s, %s)" % (x , y ))
684+ pyautogui .click (x = x , y = y )
685+ else :
686+ # Called from a method where the gui_lock is already active
687+ pyautogui .moveTo (x , y , timeframe , pyautogui .easeOutQuad )
688+ if timeframe >= 0.25 :
689+ time .sleep (0.0555 ) # Wait if moving at human-speed
690+ if "--debug" in sys .argv :
691+ print (" <DEBUG> pyautogui.click(%s, %s)" % (x , y ))
692+ pyautogui .click (x = x , y = y )
693+
694+
695+ def on_a_cf_turnstile_page (driver ):
653696 source = driver .get_page_source ()
654697 if (
655- "//challenges.cloudflare.com" not in source
656- and 'aria-label="Cloudflare"' not in source
698+ "//challenges.cloudflare.com" in source
699+ or 'aria-label="Cloudflare"' in source
657700 ):
701+ return True
702+ return False
703+
704+
705+ def uc_gui_click_cf (driver , frame = "iframe" , retry = False , blind = False ):
706+ if not on_a_cf_turnstile_page (driver ):
707+ return
708+ install_pyautogui_if_missing (driver )
709+ import pyautogui
710+ pyautogui = get_configured_pyautogui (pyautogui )
711+ x = None
712+ y = None
713+ gui_lock = fasteners .InterProcessLock (
714+ constants .MultiBrowser .PYAUTOGUILOCK
715+ )
716+ with gui_lock : # Prevent issues with multiple processes
717+ needs_switch = False
718+ is_in_frame = js_utils .is_in_frame (driver )
719+ if is_in_frame and driver .is_element_present ("#challenge-stage" ):
720+ driver .switch_to .parent_frame ()
721+ needs_switch = True
722+ is_in_frame = js_utils .is_in_frame (driver )
723+ if not is_in_frame :
724+ # Make sure the window is on top
725+ page_actions .switch_to_window (
726+ driver , driver .current_window_handle , 2 , uc_lock = False
727+ )
728+ if not is_in_frame or needs_switch :
729+ # Currently not in frame (or nested frame outside CF one)
730+ try :
731+ i_x , i_y = get_gui_element_position (driver , "iframe" )
732+ driver .switch_to_frame (frame )
733+ except Exception :
734+ if driver .is_element_present ("iframe" ):
735+ i_x , i_y = get_gui_element_position (driver , "iframe" )
736+ driver .switch_to_frame ("iframe" )
737+ else :
738+ return
739+ try :
740+ selector = "span"
741+ element = driver .wait_for_element_present (selector , timeout = 2.5 )
742+ x = i_x + element .rect ["x" ] + int (element .rect ["width" ] / 2 ) + 1
743+ y = i_y + element .rect ["y" ] + int (element .rect ["height" ] / 2 ) + 1
744+ driver .switch_to .default_content ()
745+ except Exception :
746+ try :
747+ driver .switch_to .default_content ()
748+ except Exception :
749+ return
750+ driver .disconnect ()
751+ try :
752+ if x and y :
753+ sb_config ._saved_cf_x_y = (x , y )
754+ uc_gui_click_x_y (driver , x , y , timeframe = 0.842 , uc_lock = False )
755+ except Exception :
756+ pass
757+ reconnect_time = (float (constants .UC .RECONNECT_TIME ) / 2.0 ) + 0.5
758+ if IS_LINUX :
759+ reconnect_time = constants .UC .RECONNECT_TIME
760+ if not x or not y :
761+ reconnect_time = 1 # Make it quick (it already failed)
762+ driver .reconnect (reconnect_time )
763+ if blind :
764+ retry = True
765+ if retry and x and y and on_a_cf_turnstile_page (driver ):
766+ with gui_lock : # Prevent issues with multiple processes
767+ # Make sure the window is on top
768+ page_actions .switch_to_window (
769+ driver , driver .current_window_handle , 2 , uc_lock = False
770+ )
771+ driver .switch_to_frame ("iframe" )
772+ if driver .is_element_visible ("#success-icon" ):
773+ driver .switch_to .parent_frame ()
774+ return
775+ if blind :
776+ driver .uc_open_with_disconnect (driver .current_url , 3.8 )
777+ uc_gui_click_x_y (driver , x , y , timeframe = 1.05 , uc_lock = False )
778+ else :
779+ driver .uc_open_with_reconnect (driver .current_url , 3.8 )
780+ if on_a_cf_turnstile_page (driver ):
781+ driver .disconnect ()
782+ uc_gui_click_x_y (
783+ driver , x , y , timeframe = 1.05 , uc_lock = False
784+ )
785+ driver .reconnect (reconnect_time )
786+
787+
788+ def uc_gui_handle_cf (driver , frame = "iframe" ):
789+ if not on_a_cf_turnstile_page (driver ):
658790 return
659791 install_pyautogui_if_missing (driver )
660792 import pyautogui
@@ -696,6 +828,8 @@ def uc_gui_handle_cf(driver, frame="iframe"):
696828 except Exception :
697829 pass
698830 reconnect_time = (float (constants .UC .RECONNECT_TIME ) / 2.0 ) + 0.5
831+ if IS_LINUX :
832+ reconnect_time = constants .UC .RECONNECT_TIME
699833 driver .reconnect (reconnect_time )
700834
701835
@@ -4027,6 +4161,16 @@ def get_local_driver(
40274161 driver , * args , ** kwargs
40284162 )
40294163 )
4164+ driver .uc_gui_click_x_y = (
4165+ lambda * args , ** kwargs : uc_gui_click_x_y (
4166+ driver , * args , ** kwargs
4167+ )
4168+ )
4169+ driver .uc_gui_click_cf = (
4170+ lambda * args , ** kwargs : uc_gui_click_cf (
4171+ driver , * args , ** kwargs
4172+ )
4173+ )
40304174 driver .uc_gui_handle_cf = (
40314175 lambda * args , ** kwargs : uc_gui_handle_cf (
40324176 driver , * args , ** kwargs
0 commit comments