move restock to its own sttings

restock-tag
dgtlmoon 5 months ago
parent 0b5de0ed2f
commit f67e748975

@ -59,6 +59,10 @@ class Watch(BaseWatch):
super().__init__(*arg, **kw) super().__init__(*arg, **kw)
self['restock'] = Restock(kw['default']['restock']) if kw.get('default') and kw['default'].get('restock') else Restock() self['restock'] = Restock(kw['default']['restock']) if kw.get('default') and kw['default'].get('restock') else Restock()
self['restock_settings'] = kw['default']['restock_settings'] if kw.get('default',{}).get('restock_settings') else {
'follow_price_changes': True
}
def clear_watch(self): def clear_watch(self):
super().clear_watch() super().clear_watch()
self.update({'restock': Restock()}) self.update({'restock': Restock()})

@ -4,10 +4,12 @@ from wtforms import (
validators, validators,
FloatField FloatField
) )
from wtforms.fields.form import FormField
from wtforms.form import Form
from changedetectionio.forms import processor_text_json_diff_form from changedetectionio.forms import processor_text_json_diff_form
class RestockSettingsForm(Form):
class processor_settings_form(processor_text_json_diff_form): # Could be both, "in_stock_only" either
in_stock_only = BooleanField('Only trigger when product goes BACK to in-stock', default=True) in_stock_only = BooleanField('Only trigger when product goes BACK to in-stock', default=True)
price_change_min = FloatField('Minimum amount to trigger notification', [validators.Optional()], price_change_min = FloatField('Minimum amount to trigger notification', [validators.Optional()],
render_kw={"placeholder": "No limit", "size": "10"}) render_kw={"placeholder": "No limit", "size": "10"})
@ -19,7 +21,12 @@ class processor_settings_form(processor_text_json_diff_form):
validators.NumberRange(min=0, max=100, message="Should be between 0 and 100"), validators.NumberRange(min=0, max=100, message="Should be between 0 and 100"),
], render_kw={"placeholder": "0%", "size": "5"}) ], render_kw={"placeholder": "0%", "size": "5"})
follow_price_changes = BooleanField('Follow price changes', default=False) follow_price_changes = BooleanField('Follow price changes', default=True)
class processor_settings_form(processor_text_json_diff_form):
restock_settings = FormField(RestockSettingsForm)
def extra_tab_content(self): def extra_tab_content(self):
return 'Restock & Price Detection' return 'Restock & Price Detection'
@ -33,29 +40,28 @@ class processor_settings_form(processor_text_json_diff_form):
}); });
</script> </script>
<fieldset id="restock-fieldset-price-group"> <fieldset id="restock-fieldset-price-group">
<div class="pure-control-group"> <div class="pure-control-group">
<fieldset class="pure-group"> <fieldset class="pure-group">
{{ render_checkbox_field(form.in_stock_only) }} {{ render_checkbox_field(form.restock_settings.in_stock_only) }}
<span class="pure-form-message-inline">Only trigger re-stock notification when page changes from <strong>out of stock</strong> to <strong>back in stock</strong></span> <span class="pure-form-message-inline">Only trigger re-stock notification when page changes from <strong>out of stock</strong> to <strong>back in stock</strong></span>
</fieldset> </fieldset>
<fieldset class="pure-group"> <fieldset class="pure-group">
{{ render_checkbox_field(form.follow_price_changes) }} {{ render_checkbox_field(form.restock_settings.follow_price_changes) }}
<span class="pure-form-message-inline">Changes in price should trigger a notification</span> <span class="pure-form-message-inline">Changes in price should trigger a notification</span>
<br> <br>
<span class="pure-form-message-inline">When OFF - Only care about restock detection</span> <span class="pure-form-message-inline">When OFF - Only care about restock detection</span>
</fieldset> </fieldset>
<fieldset class="pure-group price-change-minmax"> <fieldset class="pure-group price-change-minmax">
{{ render_field(form.price_change_min, placeholder=watch['restock'].get('price')) }} {{ render_field(form.restock_settings.price_change_min, placeholder=watch['restock'].get('price')) }}
<span class="pure-form-message-inline">Minimum amount, only trigger a change when the price is less than this amount.</span> <span class="pure-form-message-inline">Minimum amount, only trigger a change when the price is less than this amount.</span>
</fieldset> </fieldset>
<fieldset class="pure-group price-change-minmax"> <fieldset class="pure-group price-change-minmax">
{{ render_field(form.price_change_max, placeholder=watch['restock'].get('price')) }} {{ render_field(form.restock_settings.price_change_max, placeholder=watch['restock'].get('price')) }}
<span class="pure-form-message-inline">Maximum amount, only trigger a change when the price is more than this amount.</span> <span class="pure-form-message-inline">Maximum amount, only trigger a change when the price is more than this amount.</span>
</fieldset> </fieldset>
<fieldset class="pure-group price-change-minmax"> <fieldset class="pure-group price-change-minmax">
{{ render_field(form.price_change_threshold_percent) }} {{ render_field(form.restock_settings.price_change_threshold_percent) }}
<span class="pure-form-message-inline">Price must change more than this % to trigger a change.</span><br> <span class="pure-form-message-inline">Price must change more than this % to trigger a change.</span><br>
<span class="pure-form-message-inline">For example, If the product is $1,000 USD originally, <strong>2%</strong> would mean it has to change more than $20 since the first check.</span><br> <span class="pure-form-message-inline">For example, If the product is $1,000 USD originally, <strong>2%</strong> would mean it has to change more than $20 since the first check.</span><br>
</fieldset> </fieldset>

@ -132,6 +132,9 @@ class perform_site_check(difference_detection_processor):
update_obj['content_type'] = self.fetcher.headers.get('Content-Type', '') update_obj['content_type'] = self.fetcher.headers.get('Content-Type', '')
update_obj["last_check_status"] = self.fetcher.get_last_status_code() update_obj["last_check_status"] = self.fetcher.get_last_status_code()
# Which restock settings to compare against?
restock_settings = watch.get('restock_settings', {})
itemprop_availability = {} itemprop_availability = {}
try: try:
itemprop_availability = get_itemprop_availability(html_content=self.fetcher.content) itemprop_availability = get_itemprop_availability(html_content=self.fetcher.content)
@ -195,14 +198,14 @@ class perform_site_check(difference_detection_processor):
# out of stock -> back in stock only? # out of stock -> back in stock only?
if watch.get('restock') and watch['restock'].get('in_stock') != update_obj['restock'].get('in_stock'): if watch.get('restock') and watch['restock'].get('in_stock') != update_obj['restock'].get('in_stock'):
# Yes if we only care about it going to instock, AND we are in stock # Yes if we only care about it going to instock, AND we are in stock
if watch.get('in_stock_only') and update_obj['restock']['in_stock']: if restock_settings.get('in_stock_only') and update_obj['restock']['in_stock']:
changed_detected = True changed_detected = True
if not watch.get('in_stock_only'): if not restock_settings.get('in_stock_only'):
# All cases # All cases
changed_detected = True changed_detected = True
if watch.get('follow_price_changes') and watch.get('restock') and update_obj.get('restock') and update_obj['restock'].get('price'): if restock_settings.get('follow_price_changes') and watch.get('restock') and update_obj.get('restock') and update_obj['restock'].get('price'):
price = float(update_obj['restock'].get('price')) price = float(update_obj['restock'].get('price'))
# Default to current price if no previous price found # Default to current price if no previous price found
if watch['restock'].get('original_price'): if watch['restock'].get('original_price'):
@ -214,10 +217,10 @@ class perform_site_check(difference_detection_processor):
# Minimum/maximum price limit # Minimum/maximum price limit
if update_obj.get('restock') and update_obj['restock'].get('price'): if update_obj.get('restock') and update_obj['restock'].get('price'):
logger.debug( logger.debug(
f"{watch.get('uuid')} - Change was detected, 'price_change_max' is '{watch.get('price_change_max', '')}' 'price_change_min' is '{watch.get('price_change_min', '')}', price from website is '{update_obj['restock'].get('price', '')}'.") f"{watch.get('uuid')} - Change was detected, 'price_change_max' is '{restock_settings.get('price_change_max', '')}' 'price_change_min' is '{restock_settings.get('price_change_min', '')}', price from website is '{update_obj['restock'].get('price', '')}'.")
if update_obj['restock'].get('price'): if update_obj['restock'].get('price'):
min_limit = float(watch.get('price_change_min')) if watch.get('price_change_min') else None min_limit = float(restock_settings.get('price_change_min')) if restock_settings.get('price_change_min') else None
max_limit = float(watch.get('price_change_max')) if watch.get('price_change_max') else None max_limit = float(restock_settings.get('price_change_max')) if restock_settings.get('price_change_max') else None
price = float(update_obj['restock'].get('price')) price = float(update_obj['restock'].get('price'))
logger.debug(f"{watch.get('uuid')} after float conversion - Min limit: '{min_limit}' Max limit: '{max_limit}' Price: '{price}'") logger.debug(f"{watch.get('uuid')} after float conversion - Min limit: '{min_limit}' Max limit: '{max_limit}' Price: '{price}'")
@ -231,9 +234,9 @@ class perform_site_check(difference_detection_processor):
logger.trace(f"{watch.get('uuid')} {price} is NOT between {min_limit} and {max_limit}") logger.trace(f"{watch.get('uuid')} {price} is NOT between {min_limit} and {max_limit}")
# Price comparison by % # Price comparison by %
if watch['restock'].get('original_price') and changed_detected and watch.get('price_change_threshold_percent'): if watch['restock'].get('original_price') and changed_detected and restock_settings.get('price_change_threshold_percent'):
previous_price = float(watch['restock'].get('original_price')) previous_price = float(watch['restock'].get('original_price'))
pc = float(watch.get('price_change_threshold_percent')) pc = float(restock_settings.get('price_change_threshold_percent'))
change = abs((price - previous_price) / previous_price * 100) change = abs((price - previous_price) / previous_price * 100)
if change and change <= pc: if change and change <= pc:
logger.debug(f"{watch.get('uuid')} Override change-detected to FALSE because % threshold ({pc}%) was {change:.3f}%") logger.debug(f"{watch.get('uuid')} Override change-detected to FALSE because % threshold ({pc}%) was {change:.3f}%")

@ -114,7 +114,7 @@ def test_itemprop_price_change(client, live_server):
set_original_response(props_markup=instock_props[0], price='120.45') set_original_response(props_markup=instock_props[0], price='120.45')
res = client.post( res = client.post(
url_for("edit_page", uuid="first"), url_for("edit_page", uuid="first"),
data={"follow_price_changes": "", "url": test_url, "tags": "", "headers": "", 'fetch_backend': "html_requests"}, data={"restock_settings-follow_price_changes": "", "url": test_url, "tags": "", "headers": "", 'fetch_backend': "html_requests"},
follow_redirects=True follow_redirects=True
) )
assert b"Updated watch." in res.data assert b"Updated watch." in res.data
@ -149,9 +149,9 @@ def test_itemprop_price_minmax_limit(client, live_server):
res = client.post( res = client.post(
url_for("edit_page", uuid="first"), url_for("edit_page", uuid="first"),
data={"follow_price_changes": "y", data={"restock_settings-follow_price_changes": "y",
"price_change_min": 900.0, "restock_settings-price_change_min": 900.0,
"price_change_max": 1100.10, "restock_settings-price_change_max": 1100.10,
"url": test_url, "url": test_url,
"tags": "", "tags": "",
"headers": "", "headers": "",
@ -221,8 +221,8 @@ def test_itemprop_percent_threshold(client, live_server):
res = client.post( res = client.post(
url_for("edit_page", uuid="first"), url_for("edit_page", uuid="first"),
data={"follow_price_changes": "y", data={"restock_settings-follow_price_changes": "y",
"price_change_threshold_percent": 5.0, "restock_settings-price_change_threshold_percent": 5.0,
"url": test_url, "url": test_url,
"tags": "", "tags": "",
"headers": "", "headers": "",

Loading…
Cancel
Save