Files
SIA/tools/itb/bin/itb_input
2025-03-02 22:01:24 +01:00

168 lines
6.1 KiB
Python
Executable File

#!/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.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
class InputController:
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)
def log(self, msg: str):
"""Log message if verbose mode is enabled"""
if self.verbose:
print(f"DEBUG: {msg}", file=sys.stderr)
def focus_element(self, element_id: str = None):
"""Focus on an input element"""
try:
if element_id:
element = self.driver.find_element(By.ID, element_id)
else:
# Get currently focused element
element = self.driver.switch_to.active_element
element.click()
return element
except Exception as e:
self.log(f"Failed to focus element: {str(e)}")
return None
def enter_text(self, text: str, element_id: str = None, append: bool = False):
"""Enter text into an input element"""
try:
element = self.focus_element(element_id)
if not element:
return False
if not append:
# Clear existing text first
if element.tag_name.lower() in ['input', 'textarea']:
element.clear()
else:
# For contenteditable elements
element.send_keys(Keys.CONTROL + 'a')
element.send_keys(Keys.DELETE)
# Type the text
element.send_keys(text)
return True
except Exception as e:
self.log(f"Failed to enter text: {str(e)}")
return False
def set_caret_position(self, position: int, element_id: str = None):
"""Set the text cursor position"""
try:
element = self.focus_element(element_id)
if not element:
return False
# Use JavaScript to set caret position
self.driver.execute_script(
"""
const el = arguments[0];
const pos = arguments[1];
if (el.setSelectionRange) {
el.setSelectionRange(pos, pos);
} else if (el.createTextRange) {
const range = el.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
""",
element, position
)
return True
except Exception as e:
self.log(f"Failed to set caret position: {str(e)}")
return False
def select_text(self, start: int, end: int, element_id: str = None):
"""Select text range in an input element"""
try:
element = self.focus_element(element_id)
if not element:
return False
# Use JavaScript to set selection
self.driver.execute_script(
"""
const el = arguments[0];
const start = arguments[1];
const end = arguments[2];
if (el.setSelectionRange) {
el.setSelectionRange(start, end);
} else if (el.createTextRange) {
const range = el.createTextRange();
range.collapse(true);
range.moveStart('character', start);
range.moveEnd('character', end);
range.select();
}
""",
element, start, end
)
return True
except Exception as e:
self.log(f"Failed to select text: {str(e)}")
return False
def main():
parser = argparse.ArgumentParser(description='Control text input in Chrome')
parser.add_argument('debug_port', type=int, help='Chrome debug port')
parser.add_argument('-i', '--id', help='Element ID')
parser.add_argument('-t', '--text', help='Text to input')
parser.add_argument('--append', action='store_true', help='Append text instead of replacing')
parser.add_argument('--caret', type=int, help='Set caret position')
parser.add_argument('--select-start', type=int, help='Text selection start')
parser.add_argument('--select-end', type=int, help='Text selection end')
parser.add_argument('-v', '--verbose', action='store_true', help='Enable debug output')
args = parser.parse_args()
# Validate args
if args.select_start is not None and args.select_end is None:
print("Must specify both --select-start and --select-end", file=sys.stderr)
sys.exit(1)
if args.select_end is not None and args.select_start is None:
print("Must specify both --select-start and --select-end", file=sys.stderr)
sys.exit(1)
try:
controller = InputController(args.debug_port, args.verbose)
success = False
if args.text is not None:
success = controller.enter_text(args.text, args.id, args.append)
elif args.caret is not None:
success = controller.set_caret_position(args.caret, args.id)
elif args.select_start is not None:
success = controller.select_text(args.select_start, args.select_end, args.id)
else:
success = controller.focus_element(args.id) is not None
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()