mirror of
https://github.com/dgtlmoon/changedetection.io.git
synced 2025-11-17 06:56:10 +00:00
Compare commits
3 Commits
0.49.0
...
apschedule
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
587ac0fe46 | ||
|
|
34fe88af67 | ||
|
|
4b7f7f8379 |
File diff suppressed because it is too large
Load Diff
@@ -19,11 +19,9 @@ from loguru import logger
|
|||||||
class update_worker(threading.Thread):
|
class update_worker(threading.Thread):
|
||||||
current_uuid = None
|
current_uuid = None
|
||||||
|
|
||||||
def __init__(self, q, notification_q, app, datastore, *args, **kwargs):
|
def __init__(self, app, *args, **kwargs):
|
||||||
self.q = q
|
|
||||||
self.app = app
|
self.app = app
|
||||||
self.notification_q = notification_q
|
|
||||||
self.datastore = datastore
|
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def queue_notification_for_watch(self, notification_q, n_object, watch):
|
def queue_notification_for_watch(self, notification_q, n_object, watch):
|
||||||
@@ -102,19 +100,19 @@ class update_worker(threading.Thread):
|
|||||||
v = watch.get(var_name)
|
v = watch.get(var_name)
|
||||||
if v and not watch.get('notification_muted'):
|
if v and not watch.get('notification_muted'):
|
||||||
if var_name == 'notification_format' and v == default_notification_format_for_watch:
|
if var_name == 'notification_format' and v == default_notification_format_for_watch:
|
||||||
return self.datastore.data['settings']['application'].get('notification_format')
|
return self.app.datastore.data['settings']['application'].get('notification_format')
|
||||||
|
|
||||||
return v
|
return v
|
||||||
|
|
||||||
tags = self.datastore.get_all_tags_for_watch(uuid=watch.get('uuid'))
|
tags = self.app.datastore.get_all_tags_for_watch(uuid=watch.get('uuid'))
|
||||||
if tags:
|
if tags:
|
||||||
for tag_uuid, tag in tags.items():
|
for tag_uuid, tag in tags.items():
|
||||||
v = tag.get(var_name)
|
v = tag.get(var_name)
|
||||||
if v and not tag.get('notification_muted'):
|
if v and not tag.get('notification_muted'):
|
||||||
return v
|
return v
|
||||||
|
|
||||||
if self.datastore.data['settings']['application'].get(var_name):
|
if self.app.datastore.data['settings']['application'].get(var_name):
|
||||||
return self.datastore.data['settings']['application'].get(var_name)
|
return self.app.datastore.data['settings']['application'].get(var_name)
|
||||||
|
|
||||||
# Otherwise could be defaults
|
# Otherwise could be defaults
|
||||||
if var_name == 'notification_format':
|
if var_name == 'notification_format':
|
||||||
@@ -129,7 +127,7 @@ class update_worker(threading.Thread):
|
|||||||
def send_content_changed_notification(self, watch_uuid):
|
def send_content_changed_notification(self, watch_uuid):
|
||||||
|
|
||||||
n_object = {}
|
n_object = {}
|
||||||
watch = self.datastore.data['watching'].get(watch_uuid)
|
watch = self.app.datastore.data['watching'].get(watch_uuid)
|
||||||
if not watch:
|
if not watch:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -156,17 +154,17 @@ class update_worker(threading.Thread):
|
|||||||
queued = True
|
queued = True
|
||||||
|
|
||||||
count = watch.get('notification_alert_count', 0) + 1
|
count = watch.get('notification_alert_count', 0) + 1
|
||||||
self.datastore.update_watch(uuid=watch_uuid, update_obj={'notification_alert_count': count})
|
self.app.datastore.update_watch(uuid=watch_uuid, update_obj={'notification_alert_count': count})
|
||||||
|
|
||||||
self.queue_notification_for_watch(notification_q=self.notification_q, n_object=n_object, watch=watch)
|
self.queue_notification_for_watch(notification_q=self.app.notification_q, n_object=n_object, watch=watch)
|
||||||
|
|
||||||
return queued
|
return queued
|
||||||
|
|
||||||
|
|
||||||
def send_filter_failure_notification(self, watch_uuid):
|
def send_filter_failure_notification(self, watch_uuid):
|
||||||
|
|
||||||
threshold = self.datastore.data['settings']['application'].get('filter_failure_notification_threshold_attempts')
|
threshold = self.app.datastore.data['settings']['application'].get('filter_failure_notification_threshold_attempts')
|
||||||
watch = self.datastore.data['watching'].get(watch_uuid)
|
watch = self.app.datastore.data['watching'].get(watch_uuid)
|
||||||
if not watch:
|
if not watch:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -179,8 +177,8 @@ class update_worker(threading.Thread):
|
|||||||
if len(watch['notification_urls']):
|
if len(watch['notification_urls']):
|
||||||
n_object['notification_urls'] = watch['notification_urls']
|
n_object['notification_urls'] = watch['notification_urls']
|
||||||
|
|
||||||
elif len(self.datastore.data['settings']['application']['notification_urls']):
|
elif len(self.app.datastore.data['settings']['application']['notification_urls']):
|
||||||
n_object['notification_urls'] = self.datastore.data['settings']['application']['notification_urls']
|
n_object['notification_urls'] = self.app.datastore.data['settings']['application']['notification_urls']
|
||||||
|
|
||||||
# Only prepare to notify if the rules above matched
|
# Only prepare to notify if the rules above matched
|
||||||
if 'notification_urls' in n_object:
|
if 'notification_urls' in n_object:
|
||||||
@@ -189,16 +187,16 @@ class update_worker(threading.Thread):
|
|||||||
'uuid': watch_uuid,
|
'uuid': watch_uuid,
|
||||||
'screenshot': None
|
'screenshot': None
|
||||||
})
|
})
|
||||||
self.notification_q.put(n_object)
|
self.app.notification_q.put(n_object)
|
||||||
logger.debug(f"Sent filter not found notification for {watch_uuid}")
|
logger.debug(f"Sent filter not found notification for {watch_uuid}")
|
||||||
else:
|
else:
|
||||||
logger.debug(f"NOT sending filter not found notification for {watch_uuid} - no notification URLs")
|
logger.debug(f"NOT sending filter not found notification for {watch_uuid} - no notification URLs")
|
||||||
|
|
||||||
def send_step_failure_notification(self, watch_uuid, step_n):
|
def send_step_failure_notification(self, watch_uuid, step_n):
|
||||||
watch = self.datastore.data['watching'].get(watch_uuid, False)
|
watch = self.app.datastore.data['watching'].get(watch_uuid, False)
|
||||||
if not watch:
|
if not watch:
|
||||||
return
|
return
|
||||||
threshold = self.datastore.data['settings']['application'].get('filter_failure_notification_threshold_attempts')
|
threshold = self.app.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),
|
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}}}} "
|
'notification_body': "Your configured browser step at position {} for {{{{watch_url}}}} "
|
||||||
"did not appear on the page after {} attempts, did the page change layout? "
|
"did not appear on the page after {} attempts, did the page change layout? "
|
||||||
@@ -209,8 +207,8 @@ class update_worker(threading.Thread):
|
|||||||
if len(watch['notification_urls']):
|
if len(watch['notification_urls']):
|
||||||
n_object['notification_urls'] = watch['notification_urls']
|
n_object['notification_urls'] = watch['notification_urls']
|
||||||
|
|
||||||
elif len(self.datastore.data['settings']['application']['notification_urls']):
|
elif len(self.app.datastore.data['settings']['application']['notification_urls']):
|
||||||
n_object['notification_urls'] = self.datastore.data['settings']['application']['notification_urls']
|
n_object['notification_urls'] = self.app.datastore.data['settings']['application']['notification_urls']
|
||||||
|
|
||||||
# Only prepare to notify if the rules above matched
|
# Only prepare to notify if the rules above matched
|
||||||
if 'notification_urls' in n_object:
|
if 'notification_urls' in n_object:
|
||||||
@@ -218,7 +216,7 @@ class update_worker(threading.Thread):
|
|||||||
'watch_url': watch['url'],
|
'watch_url': watch['url'],
|
||||||
'uuid': watch_uuid
|
'uuid': watch_uuid
|
||||||
})
|
})
|
||||||
self.notification_q.put(n_object)
|
self.app.notification_q.put(n_object)
|
||||||
logger.error(f"Sent step not found notification for {watch_uuid}")
|
logger.error(f"Sent step not found notification for {watch_uuid}")
|
||||||
|
|
||||||
|
|
||||||
@@ -226,7 +224,7 @@ class update_worker(threading.Thread):
|
|||||||
# All went fine, remove error artifacts
|
# All went fine, remove error artifacts
|
||||||
cleanup_files = ["last-error-screenshot.png", "last-error.txt"]
|
cleanup_files = ["last-error-screenshot.png", "last-error.txt"]
|
||||||
for f in cleanup_files:
|
for f in cleanup_files:
|
||||||
full_path = os.path.join(self.datastore.datastore_path, uuid, f)
|
full_path = os.path.join(self.app.datastore.datastore_path, uuid, f)
|
||||||
if os.path.isfile(full_path):
|
if os.path.isfile(full_path):
|
||||||
os.unlink(full_path)
|
os.unlink(full_path)
|
||||||
|
|
||||||
@@ -237,23 +235,23 @@ class update_worker(threading.Thread):
|
|||||||
update_handler = None
|
update_handler = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
queued_item_data = self.q.get(block=False)
|
queued_item_data = self.app.update_q.get(block=False)
|
||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
else:
|
else:
|
||||||
uuid = queued_item_data.item.get('uuid')
|
uuid = queued_item_data.item.get('uuid')
|
||||||
self.current_uuid = uuid
|
self.current_uuid = uuid
|
||||||
if uuid in list(self.datastore.data['watching'].keys()) and self.datastore.data['watching'][uuid].get('url'):
|
if uuid in list(self.app.datastore.data['watching'].keys()) and self.app.datastore.data['watching'][uuid].get('url'):
|
||||||
changed_detected = False
|
changed_detected = False
|
||||||
contents = b''
|
contents = b''
|
||||||
process_changedetection_results = True
|
process_changedetection_results = True
|
||||||
update_obj = {}
|
update_obj = {}
|
||||||
|
|
||||||
# Clear last errors (move to preflight func?)
|
# Clear last errors (move to preflight func?)
|
||||||
self.datastore.data['watching'][uuid]['browser_steps_last_error_step'] = None
|
self.app.datastore.data['watching'][uuid]['browser_steps_last_error_step'] = None
|
||||||
|
|
||||||
watch = self.datastore.data['watching'].get(uuid)
|
watch = self.app.datastore.data['watching'].get(uuid)
|
||||||
|
|
||||||
logger.info(f"Processing watch UUID {uuid} Priority {queued_item_data.priority} URL {watch['url']}")
|
logger.info(f"Processing watch UUID {uuid} Priority {queued_item_data.priority} URL {watch['url']}")
|
||||||
now = time.time()
|
now = time.time()
|
||||||
@@ -270,7 +268,7 @@ class update_worker(threading.Thread):
|
|||||||
print(f"Processor module '{processor}' not found.")
|
print(f"Processor module '{processor}' not found.")
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
update_handler = processor_module.perform_site_check(datastore=self.datastore,
|
update_handler = processor_module.perform_site_check(datastore=self.app.datastore,
|
||||||
watch_uuid=uuid
|
watch_uuid=uuid
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -294,7 +292,7 @@ class update_worker(threading.Thread):
|
|||||||
watch.save_screenshot(screenshot=e.screenshot)
|
watch.save_screenshot(screenshot=e.screenshot)
|
||||||
if e.xpath_data:
|
if e.xpath_data:
|
||||||
watch.save_xpath_data(data=e.xpath_data)
|
watch.save_xpath_data(data=e.xpath_data)
|
||||||
self.datastore.update_watch(uuid=uuid, update_obj={'last_error': e.message})
|
self.app.datastore.update_watch(uuid=uuid, update_obj={'last_error': e.message})
|
||||||
process_changedetection_results = False
|
process_changedetection_results = False
|
||||||
|
|
||||||
except content_fetchers_exceptions.ReplyWithContentButNoText as e:
|
except content_fetchers_exceptions.ReplyWithContentButNoText as e:
|
||||||
@@ -311,7 +309,7 @@ class update_worker(threading.Thread):
|
|||||||
else:
|
else:
|
||||||
extra_help = ", it's possible that the filters were found, but contained no usable text."
|
extra_help = ", it's possible that the filters were found, but contained no usable text."
|
||||||
|
|
||||||
self.datastore.update_watch(uuid=uuid, update_obj={
|
self.app.datastore.update_watch(uuid=uuid, update_obj={
|
||||||
'last_error': f"Got HTML content but no text found (With {e.status_code} reply code){extra_help}"
|
'last_error': f"Got HTML content but no text found (With {e.status_code} reply code){extra_help}"
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -343,15 +341,15 @@ class update_worker(threading.Thread):
|
|||||||
if e.page_text:
|
if e.page_text:
|
||||||
watch.save_error_text(contents=e.page_text)
|
watch.save_error_text(contents=e.page_text)
|
||||||
|
|
||||||
self.datastore.update_watch(uuid=uuid, update_obj={'last_error': err_text})
|
self.app.datastore.update_watch(uuid=uuid, update_obj={'last_error': err_text})
|
||||||
process_changedetection_results = False
|
process_changedetection_results = False
|
||||||
|
|
||||||
except FilterNotFoundInResponse as e:
|
except FilterNotFoundInResponse as e:
|
||||||
if not self.datastore.data['watching'].get(uuid):
|
if not self.app.datastore.data['watching'].get(uuid):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
err_text = "Warning, no filters were found, no change detection ran - Did the page change layout? update your Visual Filter if necessary."
|
err_text = "Warning, no filters were found, no change detection ran - Did the page change layout? update your Visual Filter if necessary."
|
||||||
self.datastore.update_watch(uuid=uuid, update_obj={'last_error': err_text})
|
self.app.datastore.update_watch(uuid=uuid, update_obj={'last_error': err_text})
|
||||||
|
|
||||||
# Filter wasnt found, but we should still update the visual selector so that they can have a chance to set it up again
|
# Filter wasnt found, but we should still update the visual selector so that they can have a chance to set it up again
|
||||||
if e.screenshot:
|
if e.screenshot:
|
||||||
@@ -365,7 +363,7 @@ class update_worker(threading.Thread):
|
|||||||
c = watch.get('consecutive_filter_failures', 0)
|
c = watch.get('consecutive_filter_failures', 0)
|
||||||
c += 1
|
c += 1
|
||||||
# Send notification if we reached the threshold?
|
# Send notification if we reached the threshold?
|
||||||
threshold = self.datastore.data['settings']['application'].get('filter_failure_notification_threshold_attempts', 0)
|
threshold = self.app.datastore.data['settings']['application'].get('filter_failure_notification_threshold_attempts', 0)
|
||||||
logger.debug(f"Filter for {uuid} not found, consecutive_filter_failures: {c} of threshold {threshold}")
|
logger.debug(f"Filter for {uuid} not found, consecutive_filter_failures: {c} of threshold {threshold}")
|
||||||
if c >= threshold:
|
if c >= threshold:
|
||||||
if not watch.get('notification_muted'):
|
if not watch.get('notification_muted'):
|
||||||
@@ -374,7 +372,7 @@ class update_worker(threading.Thread):
|
|||||||
c = 0
|
c = 0
|
||||||
logger.debug(f"Reset filter failure count back to zero")
|
logger.debug(f"Reset filter failure count back to zero")
|
||||||
|
|
||||||
self.datastore.update_watch(uuid=uuid, update_obj={'consecutive_filter_failures': c})
|
self.app.datastore.update_watch(uuid=uuid, update_obj={'consecutive_filter_failures': c})
|
||||||
else:
|
else:
|
||||||
logger.trace(f"{uuid} - filter_failure_notification_send not enabled, skipping")
|
logger.trace(f"{uuid} - filter_failure_notification_send not enabled, skipping")
|
||||||
|
|
||||||
@@ -386,20 +384,20 @@ class update_worker(threading.Thread):
|
|||||||
process_changedetection_results = False
|
process_changedetection_results = False
|
||||||
changed_detected = False
|
changed_detected = False
|
||||||
except content_fetchers_exceptions.BrowserConnectError as e:
|
except content_fetchers_exceptions.BrowserConnectError as e:
|
||||||
self.datastore.update_watch(uuid=uuid,
|
self.app.datastore.update_watch(uuid=uuid,
|
||||||
update_obj={'last_error': e.msg
|
update_obj={'last_error': e.msg
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
process_changedetection_results = False
|
process_changedetection_results = False
|
||||||
except content_fetchers_exceptions.BrowserFetchTimedOut as e:
|
except content_fetchers_exceptions.BrowserFetchTimedOut as e:
|
||||||
self.datastore.update_watch(uuid=uuid,
|
self.app.datastore.update_watch(uuid=uuid,
|
||||||
update_obj={'last_error': e.msg
|
update_obj={'last_error': e.msg
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
process_changedetection_results = False
|
process_changedetection_results = False
|
||||||
except content_fetchers_exceptions.BrowserStepsStepException as e:
|
except content_fetchers_exceptions.BrowserStepsStepException as e:
|
||||||
|
|
||||||
if not self.datastore.data['watching'].get(uuid):
|
if not self.app.datastore.data['watching'].get(uuid):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
error_step = e.step_n + 1
|
error_step = e.step_n + 1
|
||||||
@@ -417,7 +415,7 @@ class update_worker(threading.Thread):
|
|||||||
|
|
||||||
logger.debug(f"BrowserSteps exception at step {error_step} {str(e.original_e)}")
|
logger.debug(f"BrowserSteps exception at step {error_step} {str(e.original_e)}")
|
||||||
|
|
||||||
self.datastore.update_watch(uuid=uuid,
|
self.app.datastore.update_watch(uuid=uuid,
|
||||||
update_obj={'last_error': err_text,
|
update_obj={'last_error': err_text,
|
||||||
'browser_steps_last_error_step': error_step
|
'browser_steps_last_error_step': error_step
|
||||||
}
|
}
|
||||||
@@ -427,7 +425,7 @@ class update_worker(threading.Thread):
|
|||||||
c = watch.get('consecutive_filter_failures', 0)
|
c = watch.get('consecutive_filter_failures', 0)
|
||||||
c += 1
|
c += 1
|
||||||
# Send notification if we reached the threshold?
|
# Send notification if we reached the threshold?
|
||||||
threshold = self.datastore.data['settings']['application'].get('filter_failure_notification_threshold_attempts',
|
threshold = self.app.datastore.data['settings']['application'].get('filter_failure_notification_threshold_attempts',
|
||||||
0)
|
0)
|
||||||
logger.error(f"Step for {uuid} not found, consecutive_filter_failures: {c}")
|
logger.error(f"Step for {uuid} not found, consecutive_filter_failures: {c}")
|
||||||
if threshold > 0 and c >= threshold:
|
if threshold > 0 and c >= threshold:
|
||||||
@@ -435,26 +433,26 @@ class update_worker(threading.Thread):
|
|||||||
self.send_step_failure_notification(watch_uuid=uuid, step_n=e.step_n)
|
self.send_step_failure_notification(watch_uuid=uuid, step_n=e.step_n)
|
||||||
c = 0
|
c = 0
|
||||||
|
|
||||||
self.datastore.update_watch(uuid=uuid, update_obj={'consecutive_filter_failures': c})
|
self.app.datastore.update_watch(uuid=uuid, update_obj={'consecutive_filter_failures': c})
|
||||||
|
|
||||||
process_changedetection_results = False
|
process_changedetection_results = False
|
||||||
|
|
||||||
except content_fetchers_exceptions.EmptyReply as e:
|
except content_fetchers_exceptions.EmptyReply as e:
|
||||||
# Some kind of custom to-str handler in the exception handler that does this?
|
# 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)
|
err_text = "EmptyReply - try increasing 'Wait seconds before extracting text', Status Code {}".format(e.status_code)
|
||||||
self.datastore.update_watch(uuid=uuid, update_obj={'last_error': err_text,
|
self.app.datastore.update_watch(uuid=uuid, update_obj={'last_error': err_text,
|
||||||
'last_check_status': e.status_code})
|
'last_check_status': e.status_code})
|
||||||
process_changedetection_results = False
|
process_changedetection_results = False
|
||||||
except content_fetchers_exceptions.ScreenshotUnavailable as e:
|
except content_fetchers_exceptions.ScreenshotUnavailable as e:
|
||||||
err_text = "Screenshot unavailable, page did not render fully in the expected time or page was too long - try increasing 'Wait seconds before extracting text'"
|
err_text = "Screenshot unavailable, page did not render fully in the expected time or page was too long - try increasing 'Wait seconds before extracting text'"
|
||||||
self.datastore.update_watch(uuid=uuid, update_obj={'last_error': err_text,
|
self.app.datastore.update_watch(uuid=uuid, update_obj={'last_error': err_text,
|
||||||
'last_check_status': e.status_code})
|
'last_check_status': e.status_code})
|
||||||
process_changedetection_results = False
|
process_changedetection_results = False
|
||||||
except content_fetchers_exceptions.JSActionExceptions as e:
|
except content_fetchers_exceptions.JSActionExceptions as e:
|
||||||
err_text = "Error running JS Actions - Page request - "+e.message
|
err_text = "Error running JS Actions - Page request - "+e.message
|
||||||
if e.screenshot:
|
if e.screenshot:
|
||||||
watch.save_screenshot(screenshot=e.screenshot, as_error=True)
|
watch.save_screenshot(screenshot=e.screenshot, as_error=True)
|
||||||
self.datastore.update_watch(uuid=uuid, update_obj={'last_error': err_text,
|
self.app.datastore.update_watch(uuid=uuid, update_obj={'last_error': err_text,
|
||||||
'last_check_status': e.status_code})
|
'last_check_status': e.status_code})
|
||||||
process_changedetection_results = False
|
process_changedetection_results = False
|
||||||
except content_fetchers_exceptions.PageUnloadable as e:
|
except content_fetchers_exceptions.PageUnloadable as e:
|
||||||
@@ -465,26 +463,26 @@ class update_worker(threading.Thread):
|
|||||||
if e.screenshot:
|
if e.screenshot:
|
||||||
watch.save_screenshot(screenshot=e.screenshot, as_error=True)
|
watch.save_screenshot(screenshot=e.screenshot, as_error=True)
|
||||||
|
|
||||||
self.datastore.update_watch(uuid=uuid, update_obj={'last_error': err_text,
|
self.app.datastore.update_watch(uuid=uuid, update_obj={'last_error': err_text,
|
||||||
'last_check_status': e.status_code,
|
'last_check_status': e.status_code,
|
||||||
'has_ldjson_price_data': None})
|
'has_ldjson_price_data': None})
|
||||||
process_changedetection_results = False
|
process_changedetection_results = False
|
||||||
except content_fetchers_exceptions.BrowserStepsInUnsupportedFetcher as e:
|
except content_fetchers_exceptions.BrowserStepsInUnsupportedFetcher as e:
|
||||||
err_text = "This watch has Browser Steps configured and so it cannot run with the 'Basic fast Plaintext/HTTP Client', either remove the Browser Steps or select a Chrome fetcher."
|
err_text = "This watch has Browser Steps configured and so it cannot run with the 'Basic fast Plaintext/HTTP Client', either remove the Browser Steps or select a Chrome fetcher."
|
||||||
self.datastore.update_watch(uuid=uuid, update_obj={'last_error': err_text})
|
self.app.datastore.update_watch(uuid=uuid, update_obj={'last_error': err_text})
|
||||||
process_changedetection_results = False
|
process_changedetection_results = False
|
||||||
logger.error(f"Exception (BrowserStepsInUnsupportedFetcher) reached processing watch UUID: {uuid}")
|
logger.error(f"Exception (BrowserStepsInUnsupportedFetcher) reached processing watch UUID: {uuid}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Exception reached processing watch UUID: {uuid}")
|
logger.error(f"Exception reached processing watch UUID: {uuid}")
|
||||||
logger.error(str(e))
|
logger.error(str(e))
|
||||||
self.datastore.update_watch(uuid=uuid, update_obj={'last_error': "Exception: " + str(e)})
|
self.app.datastore.update_watch(uuid=uuid, update_obj={'last_error': "Exception: " + str(e)})
|
||||||
# Other serious error
|
# Other serious error
|
||||||
process_changedetection_results = False
|
process_changedetection_results = False
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Crash protection, the watch entry could have been removed by this point (during a slow chrome fetch etc)
|
# Crash protection, the watch entry could have been removed by this point (during a slow chrome fetch etc)
|
||||||
if not self.datastore.data['watching'].get(uuid):
|
if not self.app.datastore.data['watching'].get(uuid):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
update_obj['content-type'] = update_handler.fetcher.get_all_headers().get('content-type', '').lower()
|
update_obj['content-type'] = update_handler.fetcher.get_all_headers().get('content-type', '').lower()
|
||||||
@@ -498,14 +496,14 @@ class update_worker(threading.Thread):
|
|||||||
|
|
||||||
self.cleanup_error_artifacts(uuid)
|
self.cleanup_error_artifacts(uuid)
|
||||||
|
|
||||||
if not self.datastore.data['watching'].get(uuid):
|
if not self.app.datastore.data['watching'].get(uuid):
|
||||||
continue
|
continue
|
||||||
#
|
#
|
||||||
# Different exceptions mean that we may or may not want to bump the snapshot, trigger notifications etc
|
# Different exceptions mean that we may or may not want to bump the snapshot, trigger notifications etc
|
||||||
if process_changedetection_results:
|
if process_changedetection_results:
|
||||||
|
|
||||||
# Extract <title> as title if possible/requested.
|
# Extract <title> as title if possible/requested.
|
||||||
if self.datastore.data['settings']['application'].get('extract_title_as_title') or watch['extract_title_as_title']:
|
if self.app.datastore.data['settings']['application'].get('extract_title_as_title') or watch['extract_title_as_title']:
|
||||||
if not watch['title'] or not len(watch['title']):
|
if not watch['title'] or not len(watch['title']):
|
||||||
try:
|
try:
|
||||||
update_obj['title'] = html_tools.extract_element(find='title', html_content=update_handler.fetcher.content)
|
update_obj['title'] = html_tools.extract_element(find='title', html_content=update_handler.fetcher.content)
|
||||||
@@ -516,7 +514,7 @@ class update_worker(threading.Thread):
|
|||||||
# Now update after running everything
|
# Now update after running everything
|
||||||
timestamp = round(time.time())
|
timestamp = round(time.time())
|
||||||
try:
|
try:
|
||||||
self.datastore.update_watch(uuid=uuid, update_obj=update_obj)
|
self.app.datastore.update_watch(uuid=uuid, update_obj=update_obj)
|
||||||
|
|
||||||
|
|
||||||
# Also save the snapshot on the first time checked, "last checked" will always be updated, so we just check history length.
|
# Also save the snapshot on the first time checked, "last checked" will always be updated, so we just check history length.
|
||||||
@@ -554,7 +552,7 @@ class update_worker(threading.Thread):
|
|||||||
# Catch everything possible here, so that if a worker crashes, we don't lose it until restart!
|
# Catch everything possible here, so that if a worker crashes, we don't lose it until restart!
|
||||||
logger.critical("!!!! Exception in update_worker while processing process_changedetection_results !!!")
|
logger.critical("!!!! Exception in update_worker while processing process_changedetection_results !!!")
|
||||||
logger.critical(str(e))
|
logger.critical(str(e))
|
||||||
self.datastore.update_watch(uuid=uuid, update_obj={'last_error': str(e)})
|
self.app.datastore.update_watch(uuid=uuid, update_obj={'last_error': str(e)})
|
||||||
|
|
||||||
|
|
||||||
# Always record that we atleast tried
|
# Always record that we atleast tried
|
||||||
@@ -563,13 +561,13 @@ class update_worker(threading.Thread):
|
|||||||
# Record the 'server' header reply, can be used for actions in the future like cloudflare/akamai workarounds
|
# Record the 'server' header reply, can be used for actions in the future like cloudflare/akamai workarounds
|
||||||
try:
|
try:
|
||||||
server_header = update_handler.fetcher.headers.get('server', '').strip().lower()[:255]
|
server_header = update_handler.fetcher.headers.get('server', '').strip().lower()[:255]
|
||||||
self.datastore.update_watch(uuid=uuid,
|
self.app.datastore.update_watch(uuid=uuid,
|
||||||
update_obj={'remote_server_reply': server_header}
|
update_obj={'remote_server_reply': server_header}
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
self.datastore.update_watch(uuid=uuid, update_obj={'fetch_time': round(time.time() - now, 3),
|
self.app.datastore.update_watch(uuid=uuid, update_obj={'fetch_time': round(time.time() - now, 3),
|
||||||
'last_checked': round(time.time()),
|
'last_checked': round(time.time()),
|
||||||
'check_count': count
|
'check_count': count
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ pytest-flask ~=1.2
|
|||||||
# Anything 4.0 and up but not 5.0
|
# Anything 4.0 and up but not 5.0
|
||||||
jsonschema ~= 4.0
|
jsonschema ~= 4.0
|
||||||
|
|
||||||
|
apscheduler ~= 3.9
|
||||||
loguru
|
loguru
|
||||||
|
|
||||||
# For scraping all possible metadata relating to products so we can do better restock detection
|
# For scraping all possible metadata relating to products so we can do better restock detection
|
||||||
|
|||||||
Reference in New Issue
Block a user