#!/root/venvs/itb/bin/python import sys import os import time import argparse from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.actions.action_builder import ActionBuilder from selenium.webdriver.common.actions.mouse_button import MouseButton class CursorController: def __init__(self, debug_port: int, verbose: bool = False): """Initialize connection to Chrome instance""" self.verbose = verbose options = webdriver.ChromeOptions() options.add_experimental_option("debuggerAddress", f"127.0.0.1:{debug_port}") self.driver = webdriver.Chrome(options=options) # Load JavaScript files js_dir = os.path.join(os.path.dirname(__file__), "..", "js") self.js_code = "" for filename in ["viewport.js", "mouse.js"]: with open(os.path.join(js_dir, filename)) as f: self.js_code += f.read() + "\n" def log(self, msg: str): """Log message if verbose mode is enabled""" if self.verbose: print(f"DEBUG: {msg}", file=sys.stderr) def get_viewport_info(self): """Get viewport dimensions and scroll position""" return self.driver.execute_script(self.js_code + "; return getViewportInfo();") def get_mouse_position(self): """Get current mouse coordinates""" return self.driver.execute_script(self.js_code + "; return getMousePosition();") def scroll_to_target(self, x: int, y: int): """Scroll viewport to make target coordinates visible""" viewport = self.get_viewport_info() self.driver.execute_script( "window.scrollTo(arguments[0], arguments[1]);", max(0, x - viewport['width'] // 2), max(0, y - viewport['height'] // 2) ) time.sleep(0.5) # Wait for scroll to complete def get_element_at_position(self, x: int, y: int): """Get the element at specified coordinates""" return self.driver.execute_script( self.js_code + "; return document.elementFromPoint(arguments[0], arguments[1]);", x, y ) def move_cursor(self, x: int, y: int, perform_click: bool = False, double_click: bool = False, right_click: bool = False, element_id: str = None) -> bool: """Move cursor to specified coordinates and optionally perform click actions""" try: self.log(f"Moving cursor to ({x}, {y})") if element_id: # Try to find element by ID first try: element = self.driver.find_element(By.ID, element_id) self.log(f"Found element by ID: {element_id}") except: self.log(f"Failed to find element by ID: {element_id}") return False else: # Scroll to make target visible self.scroll_to_target(x, y) # Get element at position element = self.get_element_at_position(x, y) if not element: self.log(f"No element found at coordinates ({x}, {y})") return False # Create action chain actions = ActionChains(self.driver) if element_id: actions.move_to_element(element) else: actions.move_by_offset(x, y) if perform_click: actions.click() elif double_click: actions.double_click() elif right_click: actions.context_click() # Execute the action chain actions.perform() return True except Exception as e: self.log(f"Error moving cursor: {str(e)}") return False def main(): parser = argparse.ArgumentParser(description='Control mouse cursor in Chrome') parser.add_argument('debug_port', type=int, help='Chrome debug port') parser.add_argument('-x', type=int, help='Target X coordinate') parser.add_argument('-y', type=int, help='Target Y coordinate') parser.add_argument('--click', action='store_true', help='Perform click') parser.add_argument('--double', action='store_true', help='Perform double click') parser.add_argument('--right', action='store_true', help='Perform right click') parser.add_argument('--id', help='Element ID to target') parser.add_argument('-v', '--verbose', action='store_true', help='Enable debug output') args = parser.parse_args() if args.double and args.right: print("Cannot specify both --double and --right", file=sys.stderr) sys.exit(1) if not args.id and (args.x is None or args.y is None): print("Must specify either element ID or both x and y coordinates", file=sys.stderr) sys.exit(1) try: controller = CursorController(args.debug_port, args.verbose) success = controller.move_cursor( x=args.x if args.x is not None else 0, y=args.y if args.y is not None else 0, perform_click=args.click, double_click=args.double, right_click=args.right, element_id=args.id ) sys.exit(0 if success else 1) except Exception as e: if args.verbose: print(f"Fatal error: {str(e)}", file=sys.stderr) sys.exit(1) if __name__ == "__main__": main()