@@ -649,12 +649,144 @@ def uc_gui_write(driver, text):
649
649
pyautogui .write (text )
650
650
651
651
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 ):
653
696
source = driver .get_page_source ()
654
697
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
657
700
):
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 ):
658
790
return
659
791
install_pyautogui_if_missing (driver )
660
792
import pyautogui
@@ -696,6 +828,8 @@ def uc_gui_handle_cf(driver, frame="iframe"):
696
828
except Exception :
697
829
pass
698
830
reconnect_time = (float (constants .UC .RECONNECT_TIME ) / 2.0 ) + 0.5
831
+ if IS_LINUX :
832
+ reconnect_time = constants .UC .RECONNECT_TIME
699
833
driver .reconnect (reconnect_time )
700
834
701
835
@@ -4027,6 +4161,16 @@ def get_local_driver(
4027
4161
driver , * args , ** kwargs
4028
4162
)
4029
4163
)
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
+ )
4030
4174
driver .uc_gui_handle_cf = (
4031
4175
lambda * args , ** kwargs : uc_gui_handle_cf (
4032
4176
driver , * args , ** kwargs
0 commit comments