diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4e6a0c98..da3d99a9 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -2,7 +2,7 @@ Contributing is always welcome!
I am no professional flask developer, if you know a better way that something can be done, please let me know!
-Otherwise, it's always best to PR into the `dev` branch.
+Otherwise, it's always best to PR into the `master` branch.
Please be sure that all new functionality has a matching test!
diff --git a/MANIFEST.in b/MANIFEST.in
index b06768fc..003a69a8 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,8 +1,8 @@
recursive-include changedetectionio/api *
recursive-include changedetectionio/blueprint *
+recursive-include changedetectionio/content_fetchers *
recursive-include changedetectionio/model *
recursive-include changedetectionio/processors *
-recursive-include changedetectionio/res *
recursive-include changedetectionio/static *
recursive-include changedetectionio/templates *
recursive-include changedetectionio/tests *
diff --git a/README.md b/README.md
index e1b7ec1e..52aabe9e 100644
--- a/README.md
+++ b/README.md
@@ -91,6 +91,14 @@ We [recommend and use Bright Data](https://brightdata.grsm.io/n0r16zf7eivq) glob
Please :star: star :star: this project and help it grow! https://github.com/dgtlmoon/changedetection.io/
+### We have a Chrome extension!
+
+Easily add the current web page to your changedetection.io tool, simply install the extension and click "Sync" to connect it to your existing changedetection.io install.
+
+[](https://chromewebstore.google.com/detail/changedetectionio-website/kefcfmgmlhmankjmnbijimhofdjekbop)
+
+[Goto the Chrome Webstore to download the extension.](https://chromewebstore.google.com/detail/changedetectionio-website/kefcfmgmlhmankjmnbijimhofdjekbop)
+
## Installation
### Docker
diff --git a/changedetectionio/__init__.py b/changedetectionio/__init__.py
index e2bf5ddc..447dec27 100644
--- a/changedetectionio/__init__.py
+++ b/changedetectionio/__init__.py
@@ -2,7 +2,7 @@
# Read more https://github.com/dgtlmoon/changedetection.io/wiki
-__version__ = '0.45.14'
+__version__ = '0.45.16'
from distutils.util import strtobool
from json.decoder import JSONDecodeError
diff --git a/changedetectionio/content_fetchers/res/stock-not-in-stock.js b/changedetectionio/content_fetchers/res/stock-not-in-stock.js
index d669f285..b9529152 100644
--- a/changedetectionio/content_fetchers/res/stock-not-in-stock.js
+++ b/changedetectionio/content_fetchers/res/stock-not-in-stock.js
@@ -17,8 +17,9 @@ function isItemInStock() {
'as soon as stock is available',
'ausverkauft', // sold out
'available for back order',
- 'back-order or out of stock',
+ 'awaiting stock',
'back in stock soon',
+ 'back-order or out of stock',
'backordered',
'benachrichtigt mich', // notify me
'brak na stanie',
@@ -66,10 +67,11 @@ function isItemInStock() {
'we couldn\'t find any products that match',
'we do not currently have an estimate of when this product will be back in stock.',
'we don\'t know when or if this item will be back in stock.',
+ 'we were not able to find a match',
'zur zeit nicht an lager',
'品切れ',
- '已售完',
'已售',
+ '已售完',
'품절'
];
diff --git a/changedetectionio/flask_app.py b/changedetectionio/flask_app.py
index d9004a98..550a57e7 100644
--- a/changedetectionio/flask_app.py
+++ b/changedetectionio/flask_app.py
@@ -30,6 +30,7 @@ from flask_compress import Compress as FlaskCompress
from flask_login import current_user
from flask_paginate import Pagination, get_page_parameter
from flask_restful import abort, Api
+from flask_cors import CORS
from flask_wtf import CSRFProtect
from loguru import logger
@@ -53,6 +54,9 @@ app = Flask(__name__,
static_folder="static",
template_folder="templates")
+# Enable CORS, especially useful for the Chrome extension to operate from anywhere
+CORS(app)
+
# Super handy for compressing large BrowserSteps responses and others
FlaskCompress(app)
@@ -1427,6 +1431,13 @@ def changedetection_app(config=None, datastore_o=None):
update_q.put(queuedWatchMetaData.PrioritizedItem(priority=1, item={'uuid': uuid, 'skip_when_checksum_same': False}))
flash("{} watches queued for rechecking".format(len(uuids)))
+ elif (op == 'clear-errors'):
+ for uuid in uuids:
+ uuid = uuid.strip()
+ if datastore.data['watching'].get(uuid):
+ datastore.data['watching'][uuid]["last_error"] = False
+ flash(f"{len(uuids)} watches errors cleared")
+
elif (op == 'clear-history'):
for uuid in uuids:
uuid = uuid.strip()
diff --git a/changedetectionio/static/styles/scss/styles.scss b/changedetectionio/static/styles/scss/styles.scss
index e182cd35..aa5e7aa5 100644
--- a/changedetectionio/static/styles/scss/styles.scss
+++ b/changedetectionio/static/styles/scss/styles.scss
@@ -1096,3 +1096,16 @@ ul {
white-space: nowrap;
}
+#chrome-extension-link {
+ img {
+ height: 21px;
+ padding: 2px;
+ vertical-align: middle;
+ }
+
+ padding: 9px;
+ border: 1px solid var(--color-grey-800);
+ border-radius: 10px;
+ vertical-align: middle;
+}
+
diff --git a/changedetectionio/static/styles/styles.css b/changedetectionio/static/styles/styles.css
index b00df672..ae37c680 100644
--- a/changedetectionio/static/styles/styles.css
+++ b/changedetectionio/static/styles/styles.css
@@ -1180,3 +1180,13 @@ ul {
.restock-label.not-in-stock {
background-color: var(--color-background-button-cancel);
color: #777; }
+
+#chrome-extension-link {
+ padding: 9px;
+ border: 1px solid var(--color-grey-800);
+ border-radius: 10px;
+ vertical-align: middle; }
+ #chrome-extension-link img {
+ height: 21px;
+ padding: 2px;
+ vertical-align: middle; }
diff --git a/changedetectionio/templates/base.html b/changedetectionio/templates/base.html
index d8ec20e3..c4c664cb 100644
--- a/changedetectionio/templates/base.html
+++ b/changedetectionio/templates/base.html
@@ -147,7 +147,19 @@
{% if visualselector_enabled %}
- The Visual Selector tool lets you select the text elements that will be used for the change detection ‐ after the Browser Steps has completed.
+ The Visual Selector tool lets you select the text elements that will be used for the change detection ‐ after the Browser Steps has completed, this tool is a helper to manage filters in the "CSS/JSONPath/JQ/XPath Filters" box of the Filters & Triggers tab.
diff --git a/docs/chrome-extension-screenshot.png b/docs/chrome-extension-screenshot.png
new file mode 100644
index 00000000..1b3a0a9d
Binary files /dev/null and b/docs/chrome-extension-screenshot.png differ
diff --git a/requirements.txt b/requirements.txt
index 42cfb2e0..04bd2ec2 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -9,6 +9,7 @@ flask-login>=0.6.3
flask-paginate
flask_expects_json~=1.7
flask_restful
+flask_cors # For the Chrome extension to operate
flask_wtf~=1.2
flask~=2.3
inscriptis~=2.2
@@ -35,10 +36,12 @@ dnspython==2.3.0 # related to eventlet fixes
# jq not available on Windows so must be installed manually
# Notification library
-apprise~=1.7.1
+apprise~=1.7.4
# apprise mqtt https://github.com/dgtlmoon/changedetection.io/issues/315
-paho-mqtt
+# and 2.0.0 https://github.com/dgtlmoon/changedetection.io/issues/2241 not yet compatible
+# use v1.x due to https://github.com/eclipse/paho.mqtt.python/issues/814
+paho-mqtt < 2.0.0
# This mainly affects some ARM builds, which unlike the other builds ignores "ARG CRYPTOGRAPHY_DONT_BUILD_RUST=1"
# so without this pinning, the newer versions on ARM will forcefully try to build rust, which results in "rust compiler not found"
@@ -71,10 +74,7 @@ jq~=1.3; python_version >= "3.8" and sys_platform == "linux"
pillow
# playwright is installed at Dockerfile build time because it's not available on all platforms
-# experimental release
-pyppeteer-ng==2.0.0rc4
-# https://github.com/dgtlmoon/pyppeteerstealth
-pyppeteerstealth
+pyppeteer-ng==2.0.0rc5
# Include pytest, so if theres a support issue we can ask them to run these tests on their setup
pytest ~=7.2