mirror of
https://github.com/dgtlmoon/changedetection.io.git
synced 2025-11-14 21:46:14 +00:00
Compare commits
7 Commits
API-add-se
...
fix-mixed-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3078218cfb | ||
|
|
92ce7d29b6 | ||
|
|
06350b1a8c | ||
|
|
d632647574 | ||
|
|
40907f1658 | ||
|
|
8604ab57a8 | ||
|
|
52926efbd1 |
@@ -107,22 +107,22 @@ jobs:
|
|||||||
if: ${{ inputs.skip-pypuppeteer == false }}
|
if: ${{ inputs.skip-pypuppeteer == false }}
|
||||||
run: |
|
run: |
|
||||||
# Playwright via Sockpuppetbrowser fetch
|
# Playwright via Sockpuppetbrowser fetch
|
||||||
docker run --rm -e "FLASK_SERVER_NAME=cdio" -e "FAST_PUPPETEER_CHROME_FETCHER=True" -e "PLAYWRIGHT_DRIVER_URL=ws://sockpuppetbrowser:3000" --network changedet-network --hostname=cdio test-changedetectionio bash -c 'cd changedetectionio;pytest --live-server-host=0.0.0.0 --live-server-port=5004 tests/fetchers/test_content.py'
|
docker run --rm -e "FLASK_SERVER_NAME=cdio" -e "FAST_PUPPETEER_CHROME_FETCHER=True" -e "PLAYWRIGHT_DRIVER_URL=ws://sockpuppetbrowser:3000" --network changedet-network --hostname=cdio test-changedetectionio bash -c 'cd changedetectionio;pytest --live-server-host=0.0.0.0 --live-server-port=5004 --live-server-wait=20 tests/fetchers/test_content.py'
|
||||||
docker run --rm -e "FLASK_SERVER_NAME=cdio" -e "FAST_PUPPETEER_CHROME_FETCHER=True" -e "PLAYWRIGHT_DRIVER_URL=ws://sockpuppetbrowser:3000" --network changedet-network --hostname=cdio test-changedetectionio bash -c 'cd changedetectionio;pytest --live-server-host=0.0.0.0 --live-server-port=5004 tests/test_errorhandling.py'
|
docker run --rm -e "FLASK_SERVER_NAME=cdio" -e "FAST_PUPPETEER_CHROME_FETCHER=True" -e "PLAYWRIGHT_DRIVER_URL=ws://sockpuppetbrowser:3000" --network changedet-network --hostname=cdio test-changedetectionio bash -c 'cd changedetectionio;pytest --live-server-host=0.0.0.0 --live-server-port=5004 --live-server-wait=20 tests/test_errorhandling.py'
|
||||||
docker run --rm -e "FLASK_SERVER_NAME=cdio" -e "FAST_PUPPETEER_CHROME_FETCHER=True" -e "PLAYWRIGHT_DRIVER_URL=ws://sockpuppetbrowser:3000" --network changedet-network --hostname=cdio test-changedetectionio bash -c 'cd changedetectionio;pytest --live-server-host=0.0.0.0 --live-server-port=5004 tests/visualselector/test_fetch_data.py'
|
docker run --rm -e "FLASK_SERVER_NAME=cdio" -e "FAST_PUPPETEER_CHROME_FETCHER=True" -e "PLAYWRIGHT_DRIVER_URL=ws://sockpuppetbrowser:3000" --network changedet-network --hostname=cdio test-changedetectionio bash -c 'cd changedetectionio;pytest --live-server-host=0.0.0.0 --live-server-port=5004 --live-server-wait=20 tests/visualselector/test_fetch_data.py'
|
||||||
docker run --rm -e "FLASK_SERVER_NAME=cdio" -e "FAST_PUPPETEER_CHROME_FETCHER=True" -e "PLAYWRIGHT_DRIVER_URL=ws://sockpuppetbrowser:3000" --network changedet-network --hostname=cdio test-changedetectionio bash -c 'cd changedetectionio;pytest --live-server-host=0.0.0.0 --live-server-port=5004 tests/fetchers/test_custom_js_before_content.py'
|
docker run --rm -e "FLASK_SERVER_NAME=cdio" -e "FAST_PUPPETEER_CHROME_FETCHER=True" -e "PLAYWRIGHT_DRIVER_URL=ws://sockpuppetbrowser:3000" --network changedet-network --hostname=cdio test-changedetectionio bash -c 'cd changedetectionio;pytest --live-server-host=0.0.0.0 --live-server-port=5004 --live-server-wait=20 tests/fetchers/test_custom_js_before_content.py'
|
||||||
|
|
||||||
- name: Pyppeteer and SocketPuppetBrowser - Headers and requests checks
|
- name: Pyppeteer and SocketPuppetBrowser - Headers and requests checks
|
||||||
if: ${{ inputs.skip-pypuppeteer == false }}
|
if: ${{ inputs.skip-pypuppeteer == false }}
|
||||||
run: |
|
run: |
|
||||||
# Settings headers playwright tests - Call back in from Sockpuppetbrowser, check headers
|
# Settings headers playwright tests - Call back in from Sockpuppetbrowser, check headers
|
||||||
docker run --name "changedet" --hostname changedet --rm -e "FAST_PUPPETEER_CHROME_FETCHER=True" -e "FLASK_SERVER_NAME=changedet" -e "PLAYWRIGHT_DRIVER_URL=ws://sockpuppetbrowser:3000?dumpio=true" --network changedet-network test-changedetectionio bash -c 'cd changedetectionio; pytest --live-server-host=0.0.0.0 --live-server-port=5004 tests/test_request.py'
|
docker run --name "changedet" --hostname changedet --rm -e "FAST_PUPPETEER_CHROME_FETCHER=True" -e "FLASK_SERVER_NAME=changedet" -e "PLAYWRIGHT_DRIVER_URL=ws://sockpuppetbrowser:3000?dumpio=true" --network changedet-network test-changedetectionio bash -c 'cd changedetectionio; pytest --live-server-host=0.0.0.0 --live-server-port=5004 --live-server-wait=20 tests/test_request.py'
|
||||||
|
|
||||||
- name: Pyppeteer and SocketPuppetBrowser - Restock detection
|
- name: Pyppeteer and SocketPuppetBrowser - Restock detection
|
||||||
if: ${{ inputs.skip-pypuppeteer == false }}
|
if: ${{ inputs.skip-pypuppeteer == false }}
|
||||||
run: |
|
run: |
|
||||||
# restock detection via playwright - added name=changedet here so that playwright and sockpuppetbrowser can connect to it
|
# restock detection via playwright - added name=changedet here so that playwright and sockpuppetbrowser can connect to it
|
||||||
docker run --rm --name "changedet" -e "FLASK_SERVER_NAME=changedet" -e "FAST_PUPPETEER_CHROME_FETCHER=True" -e "PLAYWRIGHT_DRIVER_URL=ws://sockpuppetbrowser:3000" --network changedet-network test-changedetectionio bash -c 'cd changedetectionio;pytest --live-server-port=5004 --live-server-host=0.0.0.0 tests/restock/test_restock.py'
|
docker run --rm --name "changedet" -e "FLASK_SERVER_NAME=changedet" -e "FAST_PUPPETEER_CHROME_FETCHER=True" -e "PLAYWRIGHT_DRIVER_URL=ws://sockpuppetbrowser:3000" --network changedet-network test-changedetectionio bash -c 'cd changedetectionio;pytest --live-server-port=5004 --live-server-host=0.0.0.0 --live-server-wait=20 tests/restock/test_restock.py'
|
||||||
|
|
||||||
# SELENIUM
|
# SELENIUM
|
||||||
- name: Specific tests in built container for Selenium
|
- name: Specific tests in built container for Selenium
|
||||||
@@ -132,7 +132,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Specific tests in built container for headers and requests checks with Selenium
|
- name: Specific tests in built container for headers and requests checks with Selenium
|
||||||
run: |
|
run: |
|
||||||
docker run --name "changedet" --hostname changedet --rm -e "FLASK_SERVER_NAME=changedet" -e "WEBDRIVER_URL=http://selenium:4444/wd/hub" --network changedet-network test-changedetectionio bash -c 'cd changedetectionio; pytest --live-server-host=0.0.0.0 --live-server-port=5004 tests/test_request.py'
|
docker run --name "changedet" --hostname changedet --rm -e "FLASK_SERVER_NAME=changedet" -e "WEBDRIVER_URL=http://selenium:4444/wd/hub" --network changedet-network test-changedetectionio bash -c 'cd changedetectionio; pytest --live-server-host=0.0.0.0 --live-server-port=5004 --live-server-wait=20 tests/test_request.py'
|
||||||
|
|
||||||
# OTHER STUFF
|
# OTHER STUFF
|
||||||
- name: Test SMTP notification mime types
|
- name: Test SMTP notification mime types
|
||||||
|
|||||||
@@ -43,19 +43,19 @@ def customSequenceMatcher(
|
|||||||
yield before[alo:ahi]
|
yield before[alo:ahi]
|
||||||
elif include_removed and tag == 'delete':
|
elif include_removed and tag == 'delete':
|
||||||
if html_colour:
|
if html_colour:
|
||||||
yield [f'<span style="{REMOVED_STYLE}">{line}</span>' for line in same_slicer(before, alo, ahi)]
|
yield [f'<span class="cdio" style="{REMOVED_STYLE}">{line}</span>' for line in same_slicer(before, alo, ahi)]
|
||||||
else:
|
else:
|
||||||
yield [f"(removed) {line}" for line in same_slicer(before, alo, ahi)] if include_change_type_prefix else same_slicer(before, alo, ahi)
|
yield [f"(removed) {line}" for line in same_slicer(before, alo, ahi)] if include_change_type_prefix else same_slicer(before, alo, ahi)
|
||||||
elif include_replaced and tag == 'replace':
|
elif include_replaced and tag == 'replace':
|
||||||
if html_colour:
|
if html_colour:
|
||||||
yield [f'<span style="{REMOVED_STYLE}">{line}</span>' for line in same_slicer(before, alo, ahi)] + \
|
yield [f'<span class="cdio" style="{REMOVED_STYLE}">{line}</span>' for line in same_slicer(before, alo, ahi)] + \
|
||||||
[f'<span style="{ADDED_STYLE}">{line}</span>' for line in same_slicer(after, blo, bhi)]
|
[f'<span class="cdio" style="{ADDED_STYLE}">{line}</span>' for line in same_slicer(after, blo, bhi)]
|
||||||
else:
|
else:
|
||||||
yield [f"(changed) {line}" for line in same_slicer(before, alo, ahi)] + \
|
yield [f"(changed) {line}" for line in same_slicer(before, alo, ahi)] + \
|
||||||
[f"(into) {line}" for line in same_slicer(after, blo, bhi)] if include_change_type_prefix else same_slicer(before, alo, ahi) + same_slicer(after, blo, bhi)
|
[f"(into) {line}" for line in same_slicer(after, blo, bhi)] if include_change_type_prefix else same_slicer(before, alo, ahi) + same_slicer(after, blo, bhi)
|
||||||
elif include_added and tag == 'insert':
|
elif include_added and tag == 'insert':
|
||||||
if html_colour:
|
if html_colour:
|
||||||
yield [f'<span style="{ADDED_STYLE}">{line}</span>' for line in same_slicer(after, blo, bhi)]
|
yield [f'<span class="cdio" style="{ADDED_STYLE}">{line}</span>' for line in same_slicer(after, blo, bhi)]
|
||||||
else:
|
else:
|
||||||
yield [f"(added) {line}" for line in same_slicer(after, blo, bhi)] if include_change_type_prefix else same_slicer(after, blo, bhi)
|
yield [f"(added) {line}" for line in same_slicer(after, blo, bhi)] if include_change_type_prefix else same_slicer(after, blo, bhi)
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import threading
|
|||||||
import time
|
import time
|
||||||
import timeago
|
import timeago
|
||||||
|
|
||||||
|
from .html_tools import escape_mixed_content
|
||||||
from .processors import find_processors, get_parent_module, get_custom_watch_obj_for_processor
|
from .processors import find_processors, get_parent_module, get_custom_watch_obj_for_processor
|
||||||
from .safe_jinja import render as jinja_render
|
from .safe_jinja import render as jinja_render
|
||||||
from changedetectionio.strtobool import strtobool
|
from changedetectionio.strtobool import strtobool
|
||||||
@@ -539,6 +540,9 @@ def changedetection_app(config=None, datastore_o=None):
|
|||||||
import apprise
|
import apprise
|
||||||
import random
|
import random
|
||||||
from .apprise_asset import asset
|
from .apprise_asset import asset
|
||||||
|
from .notification import default_notification_format
|
||||||
|
from .update_worker import build_notification_object_for_watch
|
||||||
|
|
||||||
apobj = apprise.Apprise(asset=asset)
|
apobj = apprise.Apprise(asset=asset)
|
||||||
|
|
||||||
# so that the custom endpoints are registered
|
# so that the custom endpoints are registered
|
||||||
@@ -595,6 +599,8 @@ def changedetection_app(config=None, datastore_o=None):
|
|||||||
# Only use if present, if not set in n_object it should use the default system value
|
# Only use if present, if not set in n_object it should use the default system value
|
||||||
if 'notification_format' in request.form and request.form['notification_format'].strip():
|
if 'notification_format' in request.form and request.form['notification_format'].strip():
|
||||||
n_object['notification_format'] = request.form.get('notification_format', '').strip()
|
n_object['notification_format'] = request.form.get('notification_format', '').strip()
|
||||||
|
else:
|
||||||
|
n_object['notification_format'] = default_notification_format
|
||||||
|
|
||||||
if 'notification_title' in request.form and request.form['notification_title'].strip():
|
if 'notification_title' in request.form and request.form['notification_title'].strip():
|
||||||
n_object['notification_title'] = request.form.get('notification_title', '').strip()
|
n_object['notification_title'] = request.form.get('notification_title', '').strip()
|
||||||
@@ -610,9 +616,14 @@ def changedetection_app(config=None, datastore_o=None):
|
|||||||
else:
|
else:
|
||||||
n_object['notification_body'] = "Test body"
|
n_object['notification_body'] = "Test body"
|
||||||
|
|
||||||
n_object['as_async'] = False
|
n_object = build_notification_object_for_watch(watch, n_object, datastore.data['settings']['application'].get('notification_body'))
|
||||||
n_object.update(watch.extra_notification_token_values())
|
|
||||||
|
if n_object['notification_format'].startswith('HTML'):
|
||||||
|
n_object['notification_body'] = escape_mixed_content(n_object['notification_body'])
|
||||||
|
|
||||||
from .notification import process_notification
|
from .notification import process_notification
|
||||||
|
n_object['as_async'] = False
|
||||||
|
# Now we send the notification_body after everything is compiled
|
||||||
sent_obj = process_notification(n_object, datastore)
|
sent_obj = process_notification(n_object, datastore)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -500,3 +500,40 @@ def get_triggered_text(content, trigger_text):
|
|||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
return triggered_text
|
return triggered_text
|
||||||
|
|
||||||
|
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
import html
|
||||||
|
|
||||||
|
|
||||||
|
def escape_mixed_content(document):
|
||||||
|
import uuid
|
||||||
|
# Parse the document as HTML
|
||||||
|
|
||||||
|
# Generate a single random hash for placeholders
|
||||||
|
random_hash = f"__PLACEHOLDER_{uuid.uuid4().hex}__"
|
||||||
|
placeholder_map = []
|
||||||
|
|
||||||
|
# <br> to something else so we can preserve them
|
||||||
|
random_hash_br = f"__BR_{uuid.uuid4().hex}__"
|
||||||
|
document = document.replace('<br>', random_hash_br)
|
||||||
|
|
||||||
|
soup = BeautifulSoup(document, 'html.parser')
|
||||||
|
|
||||||
|
# Find all <span class="cdio"> and <br>/<br/>
|
||||||
|
for tag in soup.find_all("span", class_="cdio"):
|
||||||
|
placeholder_map.append(str(tag)) # Save the tag as a string
|
||||||
|
tag.replace_with(random_hash) # Replace tag with the placeholder
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Escape the entire document
|
||||||
|
escaped_html = html.escape(str(soup))
|
||||||
|
|
||||||
|
# Restore all occurrences of placeholders with the original tags
|
||||||
|
for original_tag in placeholder_map:
|
||||||
|
escaped_html = escaped_html.replace(random_hash, original_tag, 1) # Replace one occurrence at a time
|
||||||
|
|
||||||
|
escaped_html = escaped_html.replace( random_hash_br, "<br>")
|
||||||
|
return escaped_html
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from apprise import NotifyFormat
|
|||||||
import apprise
|
import apprise
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
|
from changedetectionio.html_tools import escape_mixed_content
|
||||||
|
|
||||||
valid_tokens = {
|
valid_tokens = {
|
||||||
'base_url': '',
|
'base_url': '',
|
||||||
@@ -85,6 +86,8 @@ def process_notification(n_object, datastore):
|
|||||||
n_body = n_body.replace("\n", '<br>')
|
n_body = n_body.replace("\n", '<br>')
|
||||||
|
|
||||||
n_title = jinja_render(template_str=n_object.get('notification_title', ''), **notification_parameters)
|
n_title = jinja_render(template_str=n_object.get('notification_title', ''), **notification_parameters)
|
||||||
|
if n_object['notification_format'].startswith('HTML'):
|
||||||
|
n_body = escape_mixed_content(n_body)
|
||||||
|
|
||||||
url = url.strip()
|
url = url.strip()
|
||||||
if url.startswith('#'):
|
if url.startswith('#'):
|
||||||
@@ -161,7 +164,6 @@ def process_notification(n_object, datastore):
|
|||||||
attach=n_object.get('screenshot', None)
|
attach=n_object.get('screenshot', None)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Returns empty string if nothing found, multi-line string otherwise
|
# Returns empty string if nothing found, multi-line string otherwise
|
||||||
log_value = logs.getvalue()
|
log_value = logs.getvalue()
|
||||||
|
|
||||||
|
|||||||
@@ -454,8 +454,18 @@ def test_global_send_test_notification(client, live_server, measure_memory_usage
|
|||||||
assert b"Error: You must have atleast one watch configured for 'test notification' to work" in res.data
|
assert b"Error: You must have atleast one watch configured for 'test notification' to work" in res.data
|
||||||
|
|
||||||
|
|
||||||
|
client.get(
|
||||||
|
url_for("form_delete", uuid="all"),
|
||||||
|
follow_redirects=True
|
||||||
|
)
|
||||||
|
|
||||||
def _test_color_notifications(client, notification_body_token):
|
def _test_color_notifications(client, notification_body_token):
|
||||||
|
|
||||||
|
client.get(
|
||||||
|
url_for("form_delete", uuid="all"),
|
||||||
|
follow_redirects=True
|
||||||
|
)
|
||||||
|
|
||||||
from changedetectionio.diff import ADDED_STYLE, REMOVED_STYLE
|
from changedetectionio.diff import ADDED_STYLE, REMOVED_STYLE
|
||||||
|
|
||||||
set_original_response()
|
set_original_response()
|
||||||
@@ -494,9 +504,9 @@ def _test_color_notifications(client, notification_body_token):
|
|||||||
wait_for_all_checks(client)
|
wait_for_all_checks(client)
|
||||||
|
|
||||||
set_modified_response()
|
set_modified_response()
|
||||||
|
|
||||||
|
|
||||||
res = client.get(url_for("form_watch_checknow"), follow_redirects=True)
|
res = client.get(url_for("form_watch_checknow"), follow_redirects=True)
|
||||||
|
|
||||||
assert b'1 watches queued for rechecking.' in res.data
|
assert b'1 watches queued for rechecking.' in res.data
|
||||||
|
|
||||||
wait_for_all_checks(client)
|
wait_for_all_checks(client)
|
||||||
@@ -504,7 +514,8 @@ def _test_color_notifications(client, notification_body_token):
|
|||||||
|
|
||||||
with open("test-datastore/notification.txt", 'r') as f:
|
with open("test-datastore/notification.txt", 'r') as f:
|
||||||
x = f.read()
|
x = f.read()
|
||||||
assert f'<span style="{REMOVED_STYLE}">Which is across multiple lines' in x
|
assert f'<span class="cdio" style="{REMOVED_STYLE}">Which is across multiple lines' in x
|
||||||
|
assert f'<br>' in x
|
||||||
|
|
||||||
|
|
||||||
client.get(
|
client.get(
|
||||||
|
|||||||
@@ -16,6 +16,77 @@ import time
|
|||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
|
def build_notification_object_for_watch(watch, n_object, default_app_settings_notification_format):
|
||||||
|
from changedetectionio import diff
|
||||||
|
from changedetectionio.notification import default_notification_format_for_watch
|
||||||
|
|
||||||
|
dates = []
|
||||||
|
trigger_text = ''
|
||||||
|
|
||||||
|
if watch:
|
||||||
|
watch_history = watch.history
|
||||||
|
dates = list(watch_history.keys())
|
||||||
|
trigger_text = watch.get('trigger_text', [])
|
||||||
|
|
||||||
|
# Add text that was triggered
|
||||||
|
if len(dates):
|
||||||
|
snapshot_contents = watch.get_history_snapshot(dates[-1])
|
||||||
|
else:
|
||||||
|
snapshot_contents = "No snapshot/history available, the watch should fetch atleast once."
|
||||||
|
|
||||||
|
# If we ended up here with "System default"
|
||||||
|
if n_object.get('notification_format') == default_notification_format_for_watch:
|
||||||
|
n_object['notification_format'] = default_app_settings_notification_format
|
||||||
|
|
||||||
|
html_colour_enable = False
|
||||||
|
# HTML needs linebreak, but MarkDown and Text can use a linefeed
|
||||||
|
if n_object.get('notification_format') == 'HTML':
|
||||||
|
line_feed_sep = "<br>"
|
||||||
|
# Snapshot will be plaintext on the disk, convert to some kind of HTML
|
||||||
|
snapshot_contents = snapshot_contents.replace('\n', line_feed_sep)
|
||||||
|
elif n_object.get('notification_format') == 'HTML Color':
|
||||||
|
line_feed_sep = "<br>"
|
||||||
|
# Snapshot will be plaintext on the disk, convert to some kind of HTML
|
||||||
|
snapshot_contents = snapshot_contents.replace('\n', line_feed_sep)
|
||||||
|
html_colour_enable = True
|
||||||
|
else:
|
||||||
|
line_feed_sep = "\n"
|
||||||
|
|
||||||
|
triggered_text = ''
|
||||||
|
if len(trigger_text):
|
||||||
|
from . import html_tools
|
||||||
|
triggered_text = html_tools.get_triggered_text(content=snapshot_contents, trigger_text=trigger_text)
|
||||||
|
if triggered_text:
|
||||||
|
triggered_text = line_feed_sep.join(triggered_text)
|
||||||
|
|
||||||
|
# Could be called as a 'test notification' with only 1 snapshot available
|
||||||
|
prev_snapshot = "Example text: example test\nExample text: change detection is cool\nExample text: some more examples\n"
|
||||||
|
current_snapshot = "Example text: example test\nExample text: change detection is fantastic\nExample text: even more examples\nExample text: a lot more examples"
|
||||||
|
|
||||||
|
if len(dates) > 1:
|
||||||
|
prev_snapshot = watch.get_history_snapshot(dates[-2])
|
||||||
|
current_snapshot = watch.get_history_snapshot(dates[-1])
|
||||||
|
|
||||||
|
n_object.update({
|
||||||
|
'current_snapshot': snapshot_contents,
|
||||||
|
'diff': diff.render_diff(prev_snapshot, current_snapshot, line_feed_sep=line_feed_sep, html_colour=html_colour_enable),
|
||||||
|
'diff_added': diff.render_diff(prev_snapshot, current_snapshot, include_removed=False, line_feed_sep=line_feed_sep),
|
||||||
|
'diff_full': diff.render_diff(prev_snapshot, current_snapshot, include_equal=True, line_feed_sep=line_feed_sep,
|
||||||
|
html_colour=html_colour_enable),
|
||||||
|
'diff_patch': diff.render_diff(prev_snapshot, current_snapshot, line_feed_sep=line_feed_sep, patch_format=True),
|
||||||
|
'diff_removed': diff.render_diff(prev_snapshot, current_snapshot, include_added=False, line_feed_sep=line_feed_sep),
|
||||||
|
'notification_timestamp': time.time(),
|
||||||
|
'screenshot': watch.get_screenshot() if watch and watch.get('notification_screenshot') else None,
|
||||||
|
'triggered_text': triggered_text,
|
||||||
|
'uuid': watch.get('uuid') if watch else None,
|
||||||
|
'watch_url': watch.get('url') if watch else None,
|
||||||
|
})
|
||||||
|
|
||||||
|
if watch:
|
||||||
|
n_object.update(watch.extra_notification_token_values())
|
||||||
|
|
||||||
|
return n_object
|
||||||
|
|
||||||
class update_worker(threading.Thread):
|
class update_worker(threading.Thread):
|
||||||
current_uuid = None
|
current_uuid = None
|
||||||
|
|
||||||
@@ -27,75 +98,8 @@ class update_worker(threading.Thread):
|
|||||||
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):
|
||||||
from changedetectionio import diff
|
|
||||||
from changedetectionio.notification import default_notification_format_for_watch
|
|
||||||
|
|
||||||
dates = []
|
|
||||||
trigger_text = ''
|
|
||||||
|
|
||||||
now = time.time()
|
now = time.time()
|
||||||
|
n_object = build_notification_object_for_watch(watch, n_object, self.datastore.data['settings']['application'].get('notification_format'))
|
||||||
if watch:
|
|
||||||
watch_history = watch.history
|
|
||||||
dates = list(watch_history.keys())
|
|
||||||
trigger_text = watch.get('trigger_text', [])
|
|
||||||
|
|
||||||
# Add text that was triggered
|
|
||||||
if len(dates):
|
|
||||||
snapshot_contents = watch.get_history_snapshot(dates[-1])
|
|
||||||
else:
|
|
||||||
snapshot_contents = "No snapshot/history available, the watch should fetch atleast once."
|
|
||||||
|
|
||||||
# If we ended up here with "System default"
|
|
||||||
if n_object.get('notification_format') == default_notification_format_for_watch:
|
|
||||||
n_object['notification_format'] = self.datastore.data['settings']['application'].get('notification_format')
|
|
||||||
|
|
||||||
html_colour_enable = False
|
|
||||||
# HTML needs linebreak, but MarkDown and Text can use a linefeed
|
|
||||||
if n_object.get('notification_format') == 'HTML':
|
|
||||||
line_feed_sep = "<br>"
|
|
||||||
# Snapshot will be plaintext on the disk, convert to some kind of HTML
|
|
||||||
snapshot_contents = snapshot_contents.replace('\n', line_feed_sep)
|
|
||||||
elif n_object.get('notification_format') == 'HTML Color':
|
|
||||||
line_feed_sep = "<br>"
|
|
||||||
# Snapshot will be plaintext on the disk, convert to some kind of HTML
|
|
||||||
snapshot_contents = snapshot_contents.replace('\n', line_feed_sep)
|
|
||||||
html_colour_enable = True
|
|
||||||
else:
|
|
||||||
line_feed_sep = "\n"
|
|
||||||
|
|
||||||
triggered_text = ''
|
|
||||||
if len(trigger_text):
|
|
||||||
from . import html_tools
|
|
||||||
triggered_text = html_tools.get_triggered_text(content=snapshot_contents, trigger_text=trigger_text)
|
|
||||||
if triggered_text:
|
|
||||||
triggered_text = line_feed_sep.join(triggered_text)
|
|
||||||
|
|
||||||
# Could be called as a 'test notification' with only 1 snapshot available
|
|
||||||
prev_snapshot = "Example text: example test\nExample text: change detection is cool\nExample text: some more examples\n"
|
|
||||||
current_snapshot = "Example text: example test\nExample text: change detection is fantastic\nExample text: even more examples\nExample text: a lot more examples"
|
|
||||||
|
|
||||||
if len(dates) > 1:
|
|
||||||
prev_snapshot = watch.get_history_snapshot(dates[-2])
|
|
||||||
current_snapshot = watch.get_history_snapshot(dates[-1])
|
|
||||||
|
|
||||||
n_object.update({
|
|
||||||
'current_snapshot': snapshot_contents,
|
|
||||||
'diff': diff.render_diff(prev_snapshot, current_snapshot, line_feed_sep=line_feed_sep, html_colour=html_colour_enable),
|
|
||||||
'diff_added': diff.render_diff(prev_snapshot, current_snapshot, include_removed=False, line_feed_sep=line_feed_sep),
|
|
||||||
'diff_full': diff.render_diff(prev_snapshot, current_snapshot, include_equal=True, line_feed_sep=line_feed_sep, html_colour=html_colour_enable),
|
|
||||||
'diff_patch': diff.render_diff(prev_snapshot, current_snapshot, line_feed_sep=line_feed_sep, patch_format=True),
|
|
||||||
'diff_removed': diff.render_diff(prev_snapshot, current_snapshot, include_added=False, line_feed_sep=line_feed_sep),
|
|
||||||
'notification_timestamp': now,
|
|
||||||
'screenshot': watch.get_screenshot() if watch and watch.get('notification_screenshot') else None,
|
|
||||||
'triggered_text': triggered_text,
|
|
||||||
'uuid': watch.get('uuid') if watch else None,
|
|
||||||
'watch_url': watch.get('url') if watch else None,
|
|
||||||
})
|
|
||||||
|
|
||||||
if watch:
|
|
||||||
n_object.update(watch.extra_notification_token_values())
|
|
||||||
|
|
||||||
logger.trace(f"Main rendered notification placeholders (diff_added etc) calculated in {time.time()-now:.3f}s")
|
logger.trace(f"Main rendered notification placeholders (diff_added etc) calculated in {time.time()-now:.3f}s")
|
||||||
logger.debug("Queued notification for sending")
|
logger.debug("Queued notification for sending")
|
||||||
notification_q.put(n_object)
|
notification_q.put(n_object)
|
||||||
|
|||||||
Reference in New Issue
Block a user