diff --git a/changedetectionio/flask_app.py b/changedetectionio/flask_app.py index 35099d7f..f153714f 100644 --- a/changedetectionio/flask_app.py +++ b/changedetectionio/flask_app.py @@ -83,6 +83,10 @@ csrf = CSRFProtect() csrf.init_app(app) notification_debug_log=[] +# get locale ready +default_locale = locale.getdefaultlocale() +locale.setlocale(locale.LC_ALL, default_locale) + watch_api = Api(app, decorators=[csrf.exempt]) def init_app_secret(datastore_path): @@ -115,9 +119,7 @@ def get_css_version(): @app.template_filter('format_number_locale') def _jinja2_filter_format_number_locale(value: float) -> str: "Formats for example 4000.10 to the local locale default of 4,000.10" - default_locale = locale.getdefaultlocale() - locale.setlocale(locale.LC_ALL, default_locale) - # Format the number with two decimal places + # Format the number with two decimal places (locale format string will return 6 decimal) formatted_value = locale.format_string("%.2f", value, grouping=True) return formatted_value diff --git a/changedetectionio/processors/restock_diff/__init__.py b/changedetectionio/processors/restock_diff/__init__.py index 49e375b1..2405a124 100644 --- a/changedetectionio/processors/restock_diff/__init__.py +++ b/changedetectionio/processors/restock_diff/__init__.py @@ -4,7 +4,7 @@ import re from babel.numbers import parse_decimal class Restock(dict): - + def parse_currency(self, raw_value: str) -> float: # Clean and standardize the value standardized_value = raw_value @@ -51,6 +51,7 @@ class Restock(dict): if value and not self.get('original_price'): self['original_price'] = value + super().__setitem__(key, value) class Watch(BaseWatch): diff --git a/changedetectionio/processors/restock_diff/processor.py b/changedetectionio/processors/restock_diff/processor.py index d7eb24a8..a0a764d6 100644 --- a/changedetectionio/processors/restock_diff/processor.py +++ b/changedetectionio/processors/restock_diff/processor.py @@ -138,27 +138,19 @@ class perform_site_check(difference_detection_processor): else: update_obj['restock']['in_stock'] = False - # Used for the change detection, we store the real data separately, in the future this can implement some min,max threshold - # @todo if price is None? - self.fetcher.instock_data = f"{itemprop_availability.get('availability')} - {itemprop_availability.get('price')}" - - elif self.fetcher.instock_data: - # 'Possibly in stock' comes from stock-not-in-stock.js when no string found above in the metadata of the HTML - update_obj['restock'] = Restock({'in_stock': True if self.fetcher.instock_data == 'Possibly in stock' else False}) - - # @todo scrape price somehow - logger.debug( - f"Restock - using scraped browserdata - Watch UUID {watch.get('uuid')} restock check returned '{self.fetcher.instock_data}' from JS scraper.") - # Main detection method fetched_md5 = None - if self.fetcher.instock_data: - # 'Possibly in stock' comes from stock-not-in-stock.js when no string found above the fold. - update_obj["in_stock"] = True if self.fetcher.instock_data == 'Possibly in stock' else False - logger.debug(f"Watch UUID {watch.get('uuid')} restock check returned '{self.fetcher.instock_data}' from JS scraper.") - else: + + if not self.fetcher.instock_data and not itemprop_availability.get('availability'): raise UnableToExtractRestockData(status_code=self.fetcher.status_code) + # Nothing automatic in microdata found, revert to scraping the page + if self.fetcher.instock_data and itemprop_availability.get('availability') is None: + # 'Possibly in stock' comes from stock-not-in-stock.js when no string found above the fold. + # Careful! this does not really come from chrome/js when the watch is set to plaintext + update_obj['restock']["in_stock"] = True if self.fetcher.instock_data == 'Possibly in stock' else False + logger.debug(f"Watch UUID {watch.get('uuid')} restock check returned '{self.fetcher.instock_data}' from JS scraper.") + # Main detection method fetched_md5 = hashlib.md5(self.fetcher.instock_data.encode('utf-8')).hexdigest() @@ -217,4 +209,8 @@ class perform_site_check(difference_detection_processor): # Always record the new checksum update_obj["previous_md5"] = fetched_md5 - return changed_detected, update_obj, self.fetcher.instock_data.encode('utf-8').strip() + price = update_obj.get('restock').get('price') if update_obj.get('restock').get('price') else "" + # @todo store in DB? build graphs? + snapshot_content = f"{update_obj.get('restock').get('in_stock')} - {price}" + + return changed_detected, update_obj, snapshot_content.encode('utf-8').strip()