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

162 lines
5.8 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.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class RefreshController:
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 = ""
with open(os.path.join(js_dir, "viewport.js")) as f:
self.js_code = f.read()
def log(self, msg: str):
"""Log message if verbose mode is enabled"""
if self.verbose:
print(f"DEBUG: {msg}", file=sys.stderr)
def get_page_state(self) -> dict:
"""Get current page state for comparison"""
return {
'url': self.driver.current_url,
'title': self.driver.title,
'scroll_position': self.driver.execute_script(
self.js_code + "; return getViewportInfo();"
)
}
def wait_for_page_change(self, original_state: dict, timeout: int = 30) -> bool:
"""Wait for page to refresh and stabilize"""
try:
start_time = time.time()
while time.time() - start_time < timeout:
current_state = self.get_page_state()
# Check if page has reloaded
if (current_state['url'] == original_state['url'] and
current_state['title'] == original_state['title']):
# Check if DOM has finished updating
is_stable = self.driver.execute_script("""
return (typeof window._lastMutation === 'undefined' ||
Date.now() - window._lastMutation > 1000);
""")
if is_stable:
return True
time.sleep(0.1)
self.log("Timeout waiting for page to stabilize")
return False
except Exception as e:
self.log(f"Error waiting for page change: {str(e)}")
return False
def setup_mutation_tracking(self):
"""Setup mutation observer to track DOM changes"""
self.driver.execute_script("""
// Track last mutation time
window._lastMutation = Date.now();
// Create mutation observer
const observer = new MutationObserver(() => {
window._lastMutation = Date.now();
});
// Observe entire document for any changes
observer.observe(document, {
childList: true,
subtree: true,
attributes: true,
characterData: true
});
""")
def refresh(self, hard: bool = False, timeout: int = 30) -> bool:
"""
Refresh the current page
Args:
hard (bool): If True, bypass cache with Ctrl+F5
timeout (int): Maximum time to wait for refresh in seconds
Returns:
bool: True if refresh was successful
"""
try:
# Get initial page state
original_state = self.get_page_state()
self.log(f"Original page state: {original_state}")
# Setup mutation tracking
self.setup_mutation_tracking()
if hard:
# Force reload bypassing cache
self.log("Executing hard refresh (Ctrl+F5)")
self.driver.execute_script("""
window.location.reload(true);
""")
else:
# Normal reload
self.log("Executing normal refresh")
self.driver.refresh()
# Wait for page to stabilize
success = self.wait_for_page_change(original_state, timeout)
if success:
# Restore scroll position
self.driver.execute_script(
"window.scrollTo(arguments[0], arguments[1]);",
original_state['scroll_position']['scroll_x'],
original_state['scroll_position']['scroll_y']
)
# Final verification
new_state = self.get_page_state()
self.log(f"New page state: {new_state}")
return True
return False
except Exception as e:
self.log(f"Refresh failed: {str(e)}")
return False
def main():
parser = argparse.ArgumentParser(description='Refresh page in Chrome')
parser.add_argument('debug_port', type=int, help='Chrome debug port')
parser.add_argument('--hard', action='store_true', help='Force refresh bypassing cache')
parser.add_argument('--timeout', type=int, default=30, help='Refresh timeout in seconds')
parser.add_argument('-v', '--verbose', action='store_true', help='Enable debug output')
args = parser.parse_args()
try:
controller = RefreshController(args.debug_port, args.verbose)
success = controller.refresh(args.hard, args.timeout)
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()