{% if visualselector_enabled %}
- {% if visualselector_data_is_ready %}
-
-
-
-
-
-
-
-
-
-
Currently: Loading...
-
- Beta! The Visual Selector is new and there may be minor bugs, please report pages that dont work, help us to improve this software!
+ The Visual Selector tool lets you select the text elements that will be used for the change detection ‐ after the Browser Steps has completed.
- {% else %}
-
Screenshot and element data is not available or not yet ready.
- {% endif %}
+
+
+
+
+
+
+
+
+
Currently: Loading...
{% else %}
Sorry, this functionality only works with Playwright/Chrome enabled watches.
Enable the Playwright Chrome fetcher, or alternatively try our very affordable subscription based service.
This is because Selenium/WebDriver can not extract full page screenshots reliably.
-
{% endif %}
diff --git a/changedetectionio/tests/fetchers/test_content.py b/changedetectionio/tests/fetchers/test_content.py
index d50d8210..b68e7123 100644
--- a/changedetectionio/tests/fetchers/test_content.py
+++ b/changedetectionio/tests/fetchers/test_content.py
@@ -5,7 +5,7 @@ from flask import url_for
from ..util import live_server_setup, wait_for_all_checks
import logging
-
+# Requires playwright to be installed
def test_fetch_webdriver_content(client, live_server):
live_server_setup(live_server)
diff --git a/changedetectionio/tests/visualselector/test_fetch_data.py b/changedetectionio/tests/visualselector/test_fetch_data.py
index 17dcfd9f..6bde6713 100644
--- a/changedetectionio/tests/visualselector/test_fetch_data.py
+++ b/changedetectionio/tests/visualselector/test_fetch_data.py
@@ -10,8 +10,9 @@ def test_visual_selector_content_ready(client, live_server):
import json
assert os.getenv('PLAYWRIGHT_DRIVER_URL'), "Needs PLAYWRIGHT_DRIVER_URL set for this test"
- live_server_setup(live_server)
time.sleep(1)
+ live_server_setup(live_server)
+
# Add our URL to the import page, because the docker container (playwright/selenium) wont be able to connect to our usual test url
test_url = "https://changedetection.io/ci-test/test-runjs.html"
@@ -35,7 +36,6 @@ def test_visual_selector_content_ready(client, live_server):
follow_redirects=True
)
assert b"unpaused" in res.data
- time.sleep(1)
wait_for_all_checks(client)
uuid = extract_UUID_from_client(client)
diff --git a/changedetectionio/update_worker.py b/changedetectionio/update_worker.py
index 4f2b144d..605c0ba9 100644
--- a/changedetectionio/update_worker.py
+++ b/changedetectionio/update_worker.py
@@ -113,6 +113,34 @@ class update_worker(threading.Thread):
self.notification_q.put(n_object)
print("Sent filter not found notification for {}".format(watch_uuid))
+ def send_step_failure_notification(self, watch_uuid, step_n):
+ watch = self.datastore.data['watching'].get(watch_uuid, False)
+ if not watch:
+ return
+ threshold = self.datastore.data['settings']['application'].get('filter_failure_notification_threshold_attempts')
+ n_object = {'notification_title': "Changedetection.io - Alert - Browser step at position {} could not be run".format(step_n+1),
+ 'notification_body': "Your configured browser step at position {} for {{watch['url']}} "
+ "did not appear on the page after {} attempts, did the page change layout? "
+ "Does it need a delay added?\n\nLink: {{base_url}}/edit/{{watch_uuid}}\n\n"
+ "Thanks - Your omniscient changedetection.io installation :)\n".format(step_n+1, threshold),
+ 'notification_format': 'text'}
+
+ if len(watch['notification_urls']):
+ n_object['notification_urls'] = watch['notification_urls']
+
+ elif len(self.datastore.data['settings']['application']['notification_urls']):
+ n_object['notification_urls'] = self.datastore.data['settings']['application']['notification_urls']
+
+ # Only prepare to notify if the rules above matched
+ if 'notification_urls' in n_object:
+ n_object.update({
+ 'watch_url': watch['url'],
+ 'uuid': watch_uuid
+ })
+ self.notification_q.put(n_object)
+ print("Sent step not found notification for {}".format(watch_uuid))
+
+
def cleanup_error_artifacts(self, uuid):
# All went fine, remove error artifacts
cleanup_files = ["last-error-screenshot.png", "last-error.txt"]
@@ -213,6 +241,32 @@ class update_worker(threading.Thread):
process_changedetection_results = True
+ except content_fetcher.BrowserStepsStepTimout as e:
+
+ if not self.datastore.data['watching'].get(uuid):
+ continue
+
+ err_text = "Warning, browser step at position {} could not run, target not found, check the watch, add a delay if necessary.".format(e.step_n+1)
+ self.datastore.update_watch(uuid=uuid, update_obj={'last_error': err_text,
+ # So that we get a trigger when the content is added again
+ 'previous_md5': ''})
+
+
+ if self.datastore.data['watching'][uuid].get('filter_failure_notification_send', False):
+ c = self.datastore.data['watching'][uuid].get('consecutive_filter_failures', 5)
+ c += 1
+ # Send notification if we reached the threshold?
+ threshold = self.datastore.data['settings']['application'].get('filter_failure_notification_threshold_attempts',
+ 0)
+ print("Step for {} not found, consecutive_filter_failures: {}".format(uuid, c))
+ if threshold > 0 and c >= threshold:
+ if not self.datastore.data['watching'][uuid].get('notification_muted'):
+ self.send_step_failure_notification(watch_uuid=uuid, step_n=e.step_n)
+ c = 0
+
+ self.datastore.update_watch(uuid=uuid, update_obj={'consecutive_filter_failures': c})
+ process_changedetection_results = False
+
except content_fetcher.EmptyReply as e:
# Some kind of custom to-str handler in the exception handler that does this?
err_text = "EmptyReply - try increasing 'Wait seconds before extracting text', Status Code {}".format(e.status_code)
diff --git a/docs/browsersteps-anim.gif b/docs/browsersteps-anim.gif
new file mode 100644
index 00000000..be2c5c3c
Binary files /dev/null and b/docs/browsersteps-anim.gif differ
diff --git a/requirements.txt b/requirements.txt
index 86d03afa..9fa11f7a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -57,4 +57,3 @@ jq~=1.3 ;python_version >= "3.8" and sys_platform == "linux"
# Any current modern version, required so far for screenshot PNG->JPEG conversion but will be used more in the future
pillow
# playwright is installed at Dockerfile build time because it's not available on all platforms
-