diff --git a/changedetectionio/content_fetchers/base.py b/changedetectionio/content_fetchers/base.py index 73b69a18a..942a372f9 100644 --- a/changedetectionio/content_fetchers/base.py +++ b/changedetectionio/content_fetchers/base.py @@ -87,6 +87,8 @@ class Fetcher(): favicon_blob = None instock_data = None instock_data_js = "" + # Original response bytes (needed for PDF etc), fetchers that can't provide them leave this as None + raw_content = None screenshot_format = None status_code = None webdriver_js_execute_code = None @@ -151,8 +153,7 @@ class Fetcher(): Call this after content has been saved to disk. """ self.content = None - if hasattr(self, 'raw_content'): - self.raw_content = None + self.raw_content = None self.screenshot = None self.xpath_data = None # Keep headers and status_code as they're small diff --git a/changedetectionio/processors/text_json_diff/processor.py b/changedetectionio/processors/text_json_diff/processor.py index 13de489e2..0b9efb9ad 100644 --- a/changedetectionio/processors/text_json_diff/processor.py +++ b/changedetectionio/processors/text_json_diff/processor.py @@ -43,6 +43,11 @@ class PDFToHTMLToolNotFound(ValueError): ValueError.__init__(self, msg) +class PDFNotAvailableFromFetcher(ValueError): + def __init__(self, msg): + ValueError.__init__(self, msg) + + class FilterConfig: """Consolidates all filter and rule configurations from watch, tags, and global settings.""" @@ -481,6 +486,12 @@ class perform_site_check(difference_detection_processor): # PDF preprocessing if watch.is_pdf or stream_content_type.is_pdf: + # Browsers show PDFs in their built-in viewer, so a fetcher may only have the viewer's HTML + if not self.fetcher.raw_content or b'%PDF' not in self.fetcher.raw_content[:1024]: + raise PDFNotAvailableFromFetcher( + "Content is a PDF but this fetcher could not provide the original PDF file, " + "try the 'Basic fast Plaintext/HTTP Client' fetcher instead." + ) content = content_processor.preprocess_pdf(raw_content=self.fetcher.raw_content) stream_content_type.is_html = True