mirror of
https://github.com/dgtlmoon/changedetection.io.git
synced 2026-08-29 01:27:30 +00:00
WIP
This commit is contained in:
@@ -144,46 +144,49 @@ def construct_blueprint(datastore):
|
||||
@login_optionally_required
|
||||
def verify_condition_single_rule(watch_uuid):
|
||||
"""Verify a single condition rule against the current snapshot"""
|
||||
|
||||
from changedetectionio.processors.text_json_diff import prepare_filter_prevew
|
||||
from flask import request, jsonify
|
||||
from copy import deepcopy
|
||||
|
||||
ephemeral_data = {}
|
||||
|
||||
# Get the watch data
|
||||
watch = datastore.data['watching'].get(watch_uuid)
|
||||
if not watch:
|
||||
return jsonify({'status': 'error', 'message': 'Watch not found'}), 404
|
||||
|
||||
# Get the rule data from the request
|
||||
rule_data = request.json
|
||||
if not rule_data:
|
||||
return jsonify({'status': 'error', 'message': 'No rule data provided'}), 400
|
||||
|
||||
# Create ephemeral data with the current snapshot
|
||||
ephemeral_data = {}
|
||||
|
||||
# Get the current snapshot if available
|
||||
if watch.history_n and watch.get_last_fetched_text_before_filters():
|
||||
ephemeral_data['text'] = watch.get_last_fetched_text_before_filters()
|
||||
else:
|
||||
return jsonify({
|
||||
'status': 'error',
|
||||
'message': 'No snapshot available for verification. Please fetch content first.'
|
||||
}), 400
|
||||
|
||||
# Test the rule
|
||||
result = False
|
||||
try:
|
||||
# Create a temporary structure with just this rule
|
||||
temp_watch_data = {
|
||||
"conditions": [rule_data],
|
||||
"conditions_match_logic": "ALL" # Single rule, so use ALL
|
||||
}
|
||||
|
||||
# Create a temporary application data structure
|
||||
# First use prepare_filter_prevew to process the form data
|
||||
# This will return text_after_filter which is after all current form settings are applied
|
||||
# Create ephemeral data with the text from the current snapshot
|
||||
|
||||
try:
|
||||
# Call prepare_filter_prevew to get a processed version of the content with current form settings
|
||||
# We'll ignore the returned response and just use the datastore which is modified by the function
|
||||
|
||||
# this should apply all filters etc so then we can run the CONDITIONS against the final output text
|
||||
result = prepare_filter_prevew(datastore=datastore,
|
||||
form_data=request.form,
|
||||
watch_uuid=watch_uuid)
|
||||
|
||||
ephemeral_data['text'] = result.get('after_filter', '')
|
||||
# Create a temporary watch data structure with this single rule
|
||||
tmp_watch_data = deepcopy(datastore.data['watching'].get(watch_uuid))
|
||||
|
||||
# Override the conditions in the temporary watch
|
||||
rule_json = request.args.get("rule")
|
||||
rule = json.loads(rule_json) if rule_json else None
|
||||
tmp_watch_data['conditions'] = [rule]
|
||||
tmp_watch_data['conditions_match_logic'] = "ALL" # Single rule, so use ALL
|
||||
|
||||
|
||||
# Create a temporary application data structure for the rule check
|
||||
temp_app_data = {
|
||||
'watching': {
|
||||
watch_uuid: temp_watch_data
|
||||
watch_uuid: tmp_watch_data
|
||||
}
|
||||
}
|
||||
|
||||
# Execute the rule against the current snapshot
|
||||
# Execute the rule against the current snapshot with form data
|
||||
result = execute_ruleset_against_all_plugins(
|
||||
current_watch_uuid=watch_uuid,
|
||||
application_datastruct=temp_app_data,
|
||||
|
||||
@@ -1382,8 +1382,10 @@ def changedetection_app(config=None, datastore_o=None):
|
||||
@login_optionally_required
|
||||
def watch_get_preview_rendered(uuid):
|
||||
'''For when viewing the "preview" of the rendered text from inside of Edit'''
|
||||
from flask import jsonify
|
||||
from .processors.text_json_diff import prepare_filter_prevew
|
||||
return prepare_filter_prevew(watch_uuid=uuid, datastore=datastore)
|
||||
result = prepare_filter_prevew(watch_uuid=uuid, form_data=request.form, datastore=datastore)
|
||||
return jsonify(result)
|
||||
|
||||
|
||||
@app.route("/form/add/quickwatch", methods=['POST'])
|
||||
|
||||
@@ -28,13 +28,13 @@ def _task(watch, update_handler):
|
||||
return text_after_filter
|
||||
|
||||
|
||||
def prepare_filter_prevew(datastore, watch_uuid):
|
||||
def prepare_filter_prevew(datastore, watch_uuid, form_data):
|
||||
'''Used by @app.route("/edit/<string:uuid>/preview-rendered", methods=['POST'])'''
|
||||
from changedetectionio import forms, html_tools
|
||||
from changedetectionio.model.Watch import model as watch_model
|
||||
from concurrent.futures import ProcessPoolExecutor
|
||||
from copy import deepcopy
|
||||
from flask import request, jsonify
|
||||
from flask import request
|
||||
import brotli
|
||||
import importlib
|
||||
import os
|
||||
@@ -50,12 +50,12 @@ def prepare_filter_prevew(datastore, watch_uuid):
|
||||
|
||||
if tmp_watch and tmp_watch.history and os.path.isdir(tmp_watch.watch_data_dir):
|
||||
# Splice in the temporary stuff from the form
|
||||
form = forms.processor_text_json_diff_form(formdata=request.form if request.method == 'POST' else None,
|
||||
data=request.form
|
||||
form = forms.processor_text_json_diff_form(formdata=form_data if request.method == 'POST' else None,
|
||||
data=form_data
|
||||
)
|
||||
|
||||
# Only update vars that came in via the AJAX post
|
||||
p = {k: v for k, v in form.data.items() if k in request.form.keys()}
|
||||
p = {k: v for k, v in form.data.items() if k in form_data.keys()}
|
||||
tmp_watch.update(p)
|
||||
blank_watch_no_filters = watch_model()
|
||||
blank_watch_no_filters['url'] = tmp_watch.get('url')
|
||||
@@ -103,13 +103,12 @@ def prepare_filter_prevew(datastore, watch_uuid):
|
||||
|
||||
logger.trace(f"Parsed in {time.time() - now:.3f}s")
|
||||
|
||||
return jsonify(
|
||||
{
|
||||
return ({
|
||||
'after_filter': text_after_filter,
|
||||
'before_filter': text_before_filter.decode('utf-8') if isinstance(text_before_filter, bytes) else text_before_filter,
|
||||
'duration': time.time() - now,
|
||||
'trigger_line_numbers': trigger_line_numbers,
|
||||
'ignore_line_numbers': ignore_line_numbers,
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -49,16 +49,7 @@ $(document).ready(function () {
|
||||
alert("Please fill in all fields (Field, Operator, and Value) before verifying.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract the watch UUID from the URL
|
||||
const url = window.location.pathname;
|
||||
const uuidMatch = url.match(/\/edit\/([^\/]+)/);
|
||||
if (!uuidMatch || !uuidMatch[1]) {
|
||||
alert("Could not determine the watch UUID. Please save your changes first.");
|
||||
return;
|
||||
}
|
||||
|
||||
const watchUuid = uuidMatch[1];
|
||||
|
||||
|
||||
// Create a rule object
|
||||
const rule = {
|
||||
@@ -72,13 +63,38 @@ $(document).ready(function () {
|
||||
const originalHTML = $button.html();
|
||||
$button.html("⌛").prop("disabled", true);
|
||||
|
||||
// Collect form data - similar to request_textpreview_update() in watch-settings.js
|
||||
let formData = new FormData();
|
||||
$('#edit-text-filter textarea, #edit-text-filter input').each(function() {
|
||||
const $element = $(this);
|
||||
const name = $element.attr('name');
|
||||
if (name) {
|
||||
if ($element.is(':checkbox')) {
|
||||
formData.append(name, $element.is(':checked') ? $element.val() : false);
|
||||
} else {
|
||||
formData.append(name, $element.val());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Also collect select values
|
||||
$('#edit-text-filter select').each(function() {
|
||||
const $element = $(this);
|
||||
const name = $element.attr('name');
|
||||
if (name) {
|
||||
formData.append(name, $element.val());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Send the request to verify the rule
|
||||
$.ajax({
|
||||
url: `/conditions/${watchUuid}/verify-condition-single-rule`,
|
||||
url: verify_condition_rule_url+"?"+ new URLSearchParams({ rule: JSON.stringify(rule) }).toString(),
|
||||
type: "POST",
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify(rule),
|
||||
success: function(response) {
|
||||
data: formData,
|
||||
processData: false, // Prevent jQuery from converting FormData to a string
|
||||
contentType: false, // Let the browser set the correct content type
|
||||
success: function (response) {
|
||||
if (response.status === "success") {
|
||||
if (response.result) {
|
||||
alert("✅ Condition PASSES verification against current snapshot!");
|
||||
@@ -90,7 +106,7 @@ $(document).ready(function () {
|
||||
}
|
||||
$button.html(originalHTML).prop("disabled", false);
|
||||
},
|
||||
error: function(xhr) {
|
||||
error: function (xhr) {
|
||||
let errorMsg = "Error verifying condition.";
|
||||
if (xhr.responseJSON && xhr.responseJSON.message) {
|
||||
errorMsg = xhr.responseJSON.message;
|
||||
|
||||
@@ -286,6 +286,9 @@ Math: {{ 1 + 1 }}") }}
|
||||
{% if watch['processor'] == 'text_json_diff' %}
|
||||
|
||||
<div class="tab-pane-inner" id="conditions">
|
||||
<script>
|
||||
const verify_condition_rule_url="{{url_for('conditions.verify_condition_single_rule', watch_uuid=uuid)}}";
|
||||
</script>
|
||||
<style>
|
||||
.verifyRuleRow {
|
||||
background-color: #4caf50;
|
||||
|
||||
Reference in New Issue
Block a user