import os import time import re from random import randint from loguru import logger from changedetectionio.content_fetchers import SCREENSHOT_MAX_HEIGHT_DEFAULT from changedetectionio.content_fetchers.base import get_playwright_bypass_csp, manage_user_agent from changedetectionio.jinja2_custom import render as jinja_render from changedetectionio.validate_url import validate_fetch_url_async def track_latest_navigation_response(page): """Record the latest main-frame document response seen on this page, and return the holder. Idempotent on purpose - every navigation would otherwise add another 'response' listener, and that event fires once per HTTP response (hundreds on a heavy page), so the callbacks are worth not duplicating. One tracker per page is installed and then shared by the fetcher and by every action_goto_url() call on it. Returns a dict that holds {'response': }, or None if the page does not support event listeners (the unit test stubs, mainly). """ if not hasattr(page, 'on'): return None existing = getattr(page, '_cdio_latest_navigation_response', None) if existing is not None: return existing latest = {} def _keep(response): try: if response.frame == page.main_frame and response.request.is_navigation_request(): latest['response'] = response except Exception as e: # Never let a bookkeeping listener break a fetch logger.debug(f"Could not record navigation response: {e}") page.on("response", _keep) page._cdio_latest_navigation_response = latest return latest def browser_steps_get_valid_steps(browser_steps: list): if browser_steps is not None and len(browser_steps): valid_steps = list(filter( lambda s: (s['operation'] and len(s['operation']) and s['operation'] != 'Choose one'),browser_steps)) # Just incase they selected Goto site by accident with older JS if valid_steps and valid_steps[0]['operation'] == 'Goto site': del(valid_steps[0]) return valid_steps return [] # Two flags, tell the JS which of the "Selector" or "Value" field should be enabled in the front end # 0- off, 1- on browser_step_ui_config = {'Choose one': '0 0', # 'Check checkbox': '1 0', # 'Click button containing text': '0 1', # 'Scroll to bottom': '0 0', # 'Scroll to element': '1 0', # 'Scroll to top': '0 0', # 'Switch to iFrame by index number': '0 1' # 'Uncheck checkbox': '1 0', # @todo 'Check checkbox': '1 0', 'Click X,Y': '0 1', 'Click element if exists': '1 0', 'Click element': '1 0', 'Click element containing text': '0 1', 'Click element containing text if exists': '0 1', 'Enter text in field': '1 1', 'Execute JS': '0 1', # 'Extract text and use as filter': '1 0', 'Goto site': '0 0', 'Goto URL': '0 1', 'Make all child elements visible': '1 0', 'Press Enter': '0 0', 'Select by label': '1 1', '