mirror of
https://github.com/dgtlmoon/changedetection.io.git
synced 2025-11-02 15:47:19 +00:00
Compare commits
1 Commits
0.45.18
...
2286-remov
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
895c443110 |
4
.github/dependabot.yml
vendored
4
.github/dependabot.yml
vendored
@@ -4,10 +4,6 @@ updates:
|
||||
directory: /
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
"caronc/apprise":
|
||||
versioning-strategy: "increase"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
groups:
|
||||
all:
|
||||
patterns:
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
# Read more https://github.com/dgtlmoon/changedetection.io/wiki
|
||||
|
||||
__version__ = '0.45.18'
|
||||
__version__ = '0.45.17'
|
||||
|
||||
from changedetectionio.strtobool import strtobool
|
||||
from distutils.util import strtobool
|
||||
from json.decoder import JSONDecodeError
|
||||
import os
|
||||
#os.environ['EVENTLET_NO_GREENDNS'] = 'yes'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import os
|
||||
from changedetectionio.strtobool import strtobool
|
||||
from distutils.util import strtobool
|
||||
|
||||
from flask_expects_json import expects_json
|
||||
from changedetectionio import queuedWatchMetaData
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#
|
||||
#
|
||||
|
||||
from changedetectionio.strtobool import strtobool
|
||||
from distutils.util import strtobool
|
||||
from flask import Blueprint, request, make_response
|
||||
import os
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
from changedetectionio.strtobool import strtobool
|
||||
from distutils.util import strtobool
|
||||
from flask import Blueprint, flash, redirect, url_for
|
||||
from flask_login import login_required
|
||||
from changedetectionio.store import ChangeDetectionStore
|
||||
|
||||
@@ -12,15 +12,9 @@ def construct_blueprint(datastore: ChangeDetectionStore):
|
||||
from .form import SingleTag
|
||||
add_form = SingleTag(request.form)
|
||||
sorted_tags = sorted(datastore.data['settings']['application'].get('tags').items(), key=lambda x: x[1]['title'])
|
||||
|
||||
from collections import Counter
|
||||
|
||||
tag_count = Counter(tag for watch in datastore.data['watching'].values() if watch.get('tags') for tag in watch['tags'])
|
||||
|
||||
output = render_template("groups-overview.html",
|
||||
available_tags=sorted_tags,
|
||||
form=add_form,
|
||||
tag_count=tag_count
|
||||
available_tags=sorted_tags,
|
||||
)
|
||||
|
||||
return output
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
{% from '_helpers.jinja' import render_field, render_checkbox_field, render_button %}
|
||||
{% from '_common_fields.jinja' import render_common_settings_form %}
|
||||
<script>
|
||||
const notification_base_url="{{url_for('ajax_callback_send_notification_test', mode="group-settings")}}";
|
||||
const notification_base_url="{{url_for('ajax_callback_send_notification_test', watch_uuid=uuid)}}";
|
||||
</script>
|
||||
|
||||
<script src="{{url_for('static_content', group='js', filename='tabs.js')}}" defer></script>
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th># Watches</th>
|
||||
<th>Tag / Label name</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
@@ -46,8 +45,7 @@
|
||||
<td class="watch-controls">
|
||||
<a class="link-mute state-{{'on' if tag.notification_muted else 'off'}}" href="{{url_for('tags.mute', uuid=tag.uuid)}}"><img src="{{url_for('static_content', group='images', filename='bell-off.svg')}}" alt="Mute notifications" title="Mute notifications" class="icon icon-mute" ></a>
|
||||
</td>
|
||||
<td>{{ "{:,}".format(tag_count[uuid]) if uuid in tag_count else 0 }}</td>
|
||||
<td class="title-col inline"> <a href="{{url_for('index', tag=uuid) }}">{{ tag.title }}</a></td>
|
||||
<td class="title-col inline">{{tag.title}}</td>
|
||||
<td>
|
||||
<a class="pure-button pure-button-primary" href="{{ url_for('tags.form_tag_edit', uuid=uuid) }}">Edit</a>
|
||||
<a class="pure-button pure-button-primary" href="{{ url_for('tags.delete', uuid=uuid) }}" title="Deletes and removes tag">Delete</a>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import sys
|
||||
from changedetectionio.strtobool import strtobool
|
||||
from distutils.util import strtobool
|
||||
from loguru import logger
|
||||
from changedetectionio.content_fetchers.exceptions import BrowserStepsStepException
|
||||
import os
|
||||
|
||||
@@ -6,7 +6,7 @@ import queue
|
||||
import threading
|
||||
import time
|
||||
from copy import deepcopy
|
||||
from changedetectionio.strtobool import strtobool
|
||||
from distutils.util import strtobool
|
||||
from functools import wraps
|
||||
from threading import Event
|
||||
|
||||
@@ -519,29 +519,26 @@ def changedetection_app(config=None, datastore_o=None):
|
||||
notification_urls = request.form['notification_urls'].strip().splitlines()
|
||||
|
||||
if not notification_urls:
|
||||
logger.debug("Test notification - Trying by group/tag in the edit form if available")
|
||||
# On an edit page, we should also fire off to the tags if they have notifications
|
||||
if request.form.get('tags') and request.form['tags'].strip():
|
||||
logger.debug("Test notification - Trying by group/tag")
|
||||
if request.form['tags'].strip():
|
||||
for k in request.form['tags'].split(','):
|
||||
tag = datastore.tag_exists_by_name(k.strip())
|
||||
notification_urls = tag.get('notifications_urls') if tag and tag.get('notifications_urls') else None
|
||||
|
||||
is_global_settings_form = request.args.get('mode', '') == 'global-settings'
|
||||
is_group_settings_form = request.args.get('mode', '') == 'group-settings'
|
||||
if not notification_urls and not is_global_settings_form and not is_group_settings_form:
|
||||
# In the global settings, use only what is typed currently in the text box
|
||||
if not notification_urls:
|
||||
logger.debug("Test notification - Trying by global system settings notifications")
|
||||
if datastore.data['settings']['application'].get('notification_urls'):
|
||||
notification_urls = datastore.data['settings']['application']['notification_urls']
|
||||
|
||||
|
||||
if not notification_urls:
|
||||
return 'No Notification URLs set/found'
|
||||
return make_response({'error': 'No Notification URLs set'}, 400)
|
||||
|
||||
for n_url in notification_urls:
|
||||
if len(n_url.strip()):
|
||||
if not apobj.add(n_url):
|
||||
return f'Error - {n_url} is not a valid AppRise URL.'
|
||||
message = '{} is not a valid AppRise URL.'.format(n_url)
|
||||
return make_response({'error': message}, 400)
|
||||
|
||||
try:
|
||||
# use the same as when it is triggered, but then override it with the form test values
|
||||
@@ -566,7 +563,7 @@ def changedetection_app(config=None, datastore_o=None):
|
||||
except Exception as e:
|
||||
return make_response({'error': str(e)}, 400)
|
||||
|
||||
return 'OK - Sent test notifications'
|
||||
return 'OK'
|
||||
|
||||
|
||||
@app.route("/clear_history/<string:uuid>", methods=['GET'])
|
||||
@@ -603,12 +600,6 @@ def changedetection_app(config=None, datastore_o=None):
|
||||
output = render_template("clear_all_history.html")
|
||||
return output
|
||||
|
||||
def _watch_has_tag_options_set(watch):
|
||||
"""This should be fixed better so that Tag is some proper Model, a tag is just a Watch also"""
|
||||
for tag_uuid, tag in datastore.data['settings']['application'].get('tags', {}).items():
|
||||
if tag_uuid in watch.get('tags', []) and (tag.get('include_filters') or tag.get('subtractive_selectors')):
|
||||
return True
|
||||
|
||||
@app.route("/edit/<string:uuid>", methods=['GET', 'POST'])
|
||||
@login_optionally_required
|
||||
# https://stackoverflow.com/questions/42984453/wtforms-populate-form-with-data-if-data-exists
|
||||
@@ -779,7 +770,6 @@ def changedetection_app(config=None, datastore_o=None):
|
||||
has_default_notification_urls=True if len(datastore.data['settings']['application']['notification_urls']) else False,
|
||||
has_empty_checktime=using_default_check_time,
|
||||
has_extra_headers_file=len(datastore.get_all_headers_in_textfile_for_watch(uuid=uuid)) > 0,
|
||||
has_special_tag_options=_watch_has_tag_options_set(watch=watch),
|
||||
is_html_webdriver=is_html_webdriver,
|
||||
jq_support=jq_support,
|
||||
playwright_enabled=os.getenv('PLAYWRIGHT_DRIVER_URL', False),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import os
|
||||
import re
|
||||
from changedetectionio.strtobool import strtobool
|
||||
from distutils.util import strtobool
|
||||
|
||||
from wtforms import (
|
||||
BooleanField,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from changedetectionio.strtobool import strtobool
|
||||
from distutils.util import strtobool
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
@@ -362,7 +362,6 @@ class model(dict):
|
||||
# @todo bump static cache of the last timestamp so we dont need to examine the file to set a proper ''viewed'' status
|
||||
return snapshot_fname
|
||||
|
||||
@property
|
||||
@property
|
||||
def has_empty_checktime(self):
|
||||
# using all() + dictionary comprehension
|
||||
|
||||
@@ -3,7 +3,7 @@ import os
|
||||
import hashlib
|
||||
import re
|
||||
from copy import deepcopy
|
||||
from changedetectionio.strtobool import strtobool
|
||||
from distutils.util import strtobool
|
||||
from loguru import logger
|
||||
|
||||
class difference_detection_processor():
|
||||
|
||||
@@ -45,7 +45,7 @@ $(document).ready(function() {
|
||||
}
|
||||
}).done(function(data){
|
||||
console.log(data);
|
||||
alert(data);
|
||||
alert('Sent');
|
||||
}).fail(function(data){
|
||||
console.log(data);
|
||||
alert('There was an error communicating with the server.');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from changedetectionio.strtobool import strtobool
|
||||
from distutils.util import strtobool
|
||||
|
||||
from flask import (
|
||||
flash
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Because strtobool was removed in python 3.12 distutils
|
||||
|
||||
_MAP = {
|
||||
'y': True,
|
||||
'yes': True,
|
||||
't': True,
|
||||
'true': True,
|
||||
'on': True,
|
||||
'1': True,
|
||||
'n': False,
|
||||
'no': False,
|
||||
'f': False,
|
||||
'false': False,
|
||||
'off': False,
|
||||
'0': False
|
||||
}
|
||||
|
||||
|
||||
def strtobool(value):
|
||||
try:
|
||||
return _MAP[str(value).lower()]
|
||||
except KeyError:
|
||||
raise ValueError('"{}" is not a valid bool value'.format(value))
|
||||
@@ -7,8 +7,7 @@
|
||||
<script>
|
||||
const browser_steps_available_screenshots=JSON.parse('{{ watch.get_browsersteps_available_screenshots|tojson }}');
|
||||
const browser_steps_config=JSON.parse('{{ browser_steps_config|tojson }}');
|
||||
<!-- Should be _external so that firefox and others load it more reliably -->
|
||||
const browser_steps_fetch_screenshot_image_url="{{url_for('browser_steps.browser_steps_fetch_screenshot_image', uuid=uuid, _external=True)}}";
|
||||
const browser_steps_fetch_screenshot_image_url="{{url_for('browser_steps.browser_steps_fetch_screenshot_image', uuid=uuid)}}";
|
||||
const browser_steps_last_error_step={{ watch.browser_steps_last_error_step|tojson }};
|
||||
const browser_steps_start_url="{{url_for('browser_steps.browsersteps_start_session', uuid=uuid)}}";
|
||||
const browser_steps_sync_url="{{url_for('browser_steps.browsersteps_ui_update', uuid=uuid)}}";
|
||||
@@ -32,7 +31,6 @@
|
||||
<script src="{{url_for('static_content', group='js', filename='browser-steps.js')}}" defer></script>
|
||||
{% endif %}
|
||||
|
||||
{% set has_tag_filters_extra="WARNING: Watch has tag/groups set with special filters\n" if has_special_tag_options else '' %}
|
||||
<script src="{{url_for('static_content', group='js', filename='recheck-proxy.js')}}" defer></script>
|
||||
|
||||
<div class="edit-form monospaced-textarea">
|
||||
@@ -282,7 +280,7 @@ User-Agent: wonderbra 1.0") }}
|
||||
<div class="pure-control-group">
|
||||
{% set field = render_field(form.include_filters,
|
||||
rows=5,
|
||||
placeholder=has_tag_filters_extra+"#example
|
||||
placeholder="#example
|
||||
xpath://body/div/span[contains(@class, 'example-class')]",
|
||||
class="m-d")
|
||||
%}
|
||||
@@ -318,7 +316,7 @@ xpath://body/div/span[contains(@class, 'example-class')]",
|
||||
</span>
|
||||
</div>
|
||||
<fieldset class="pure-control-group">
|
||||
{{ render_field(form.subtractive_selectors, rows=5, placeholder=has_tag_filters_extra+"header
|
||||
{{ render_field(form.subtractive_selectors, rows=5, placeholder="header
|
||||
footer
|
||||
nav
|
||||
.stockticker") }}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
{% from '_helpers.jinja' import render_field, render_checkbox_field, render_button %}
|
||||
{% from '_common_fields.jinja' import render_common_settings_form %}
|
||||
<script>
|
||||
const notification_base_url="{{url_for('ajax_callback_send_notification_test', mode="global-settings")}}";
|
||||
const notification_base_url="{{url_for('ajax_callback_send_notification_test', watch_uuid=uuid)}}";
|
||||
{% if emailprefix %}
|
||||
const email_notification_prefix=JSON.parse('{{emailprefix|tojson}}');
|
||||
{% endif %}
|
||||
|
||||
@@ -100,12 +100,6 @@ def test_setup_group_tag(client, live_server):
|
||||
assert b'Should be only this' in res.data
|
||||
assert b'And never this' not in res.data
|
||||
|
||||
res = client.get(
|
||||
url_for("edit_page", uuid="first"),
|
||||
follow_redirects=True
|
||||
)
|
||||
# 2307 the UI notice should appear in the placeholder
|
||||
assert b'WARNING: Watch has tag/groups set with special filters' in res.data
|
||||
|
||||
# RSS Group tag filter
|
||||
# An extra one that should be excluded
|
||||
|
||||
Reference in New Issue
Block a user