mirror of
				https://github.com/dgtlmoon/changedetection.io.git
				synced 2025-10-31 06:37:41 +00:00 
			
		
		
		
	Compare commits
	
		
			9 Commits
		
	
	
		
			reverse-26
			...
			refactor-t
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | d579e26cd6 | ||
|   | f8fe5c8d41 | ||
|   | bddf9af584 | ||
|   | 643a45b5e2 | ||
|   | e9f1cc91c7 | ||
|   | 080526eb65 | ||
|   | c9552d2319 | ||
|   | 3c14273021 | ||
|   | 547ab70ea3 | 
| @@ -619,7 +619,6 @@ def changedetection_app(config=None, datastore_o=None): | ||||
|         from .blueprint.browser_steps.browser_steps import browser_step_ui_config | ||||
|         from . import processors | ||||
|  | ||||
|         using_default_check_time = True | ||||
|         # More for testing, possible to return the first/only | ||||
|         if not datastore.data['watching'].keys(): | ||||
|             flash("No watches to edit", "error") | ||||
| @@ -644,10 +643,6 @@ def changedetection_app(config=None, datastore_o=None): | ||||
|         # be sure we update with a copy instead of accidently editing the live object by reference | ||||
|         default = deepcopy(datastore.data['watching'][uuid]) | ||||
|  | ||||
|         # Show system wide default if nothing configured | ||||
|         if all(value == 0 or value == None for value in datastore.data['watching'][uuid]['time_between_check'].values()): | ||||
|             default['time_between_check'] = deepcopy(datastore.data['settings']['requests']['time_between_check']) | ||||
|  | ||||
|         # Defaults for proxy choice | ||||
|         if datastore.proxy_list is not None:  # When enabled | ||||
|             # @todo | ||||
| @@ -685,18 +680,8 @@ def changedetection_app(config=None, datastore_o=None): | ||||
|  | ||||
|             if request.args.get('unpause_on_save'): | ||||
|                 extra_update_obj['paused'] = False | ||||
|             # Re #110, if they submit the same as the default value, set it to None, so we continue to follow the default | ||||
|             # Assume we use the default value, unless something relevant is different, then use the form value | ||||
|             # values could be None, 0 etc. | ||||
|             # Set to None unless the next for: says that something is different | ||||
|             extra_update_obj['time_between_check'] = dict.fromkeys(form.time_between_check.data) | ||||
|             for k, v in form.time_between_check.data.items(): | ||||
|                 if v and v != datastore.data['settings']['requests']['time_between_check'][k]: | ||||
|                     extra_update_obj['time_between_check'] = form.time_between_check.data | ||||
|                     using_default_check_time = False | ||||
|                     break | ||||
|  | ||||
|  | ||||
|             extra_update_obj['time_between_check'] = form.time_between_check.data | ||||
|  | ||||
|              # Ignore text | ||||
|             form_ignore_text = form.ignore_text.data | ||||
| @@ -777,7 +762,6 @@ def changedetection_app(config=None, datastore_o=None): | ||||
|                                      extra_title=f" - Edit - {watch.label}", | ||||
|                                      form=form, | ||||
|                                      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, | ||||
| @@ -863,11 +847,13 @@ def changedetection_app(config=None, datastore_o=None): | ||||
|                 flash("An error occurred, please see below.", "error") | ||||
|  | ||||
|         output = render_template("settings.html", | ||||
|                                  form=form, | ||||
|                                  hide_remove_pass=os.getenv("SALTED_PASS", False), | ||||
|                                  api_key=datastore.data['settings']['application'].get('api_access_token'), | ||||
|                                  emailprefix=os.getenv('NOTIFICATION_MAIL_BUTTON_PREFIX', False), | ||||
|                                  settings_application=datastore.data['settings']['application']) | ||||
|                                  form=form, | ||||
|                                  hide_remove_pass=os.getenv("SALTED_PASS", False), | ||||
|                                  min_system_recheck_seconds=int(os.getenv('MINIMUM_SECONDS_RECHECK_TIME', 3)), | ||||
|                                  settings_application=datastore.data['settings']['application'] | ||||
|                                  ) | ||||
|  | ||||
|         return output | ||||
|  | ||||
| @@ -1668,14 +1654,14 @@ def notification_runner(): | ||||
|             # Trim the log length | ||||
|             notification_debug_log = notification_debug_log[-100:] | ||||
|  | ||||
| # Thread runner to check every minute, look for new watches to feed into the Queue. | ||||
| # Threaded runner, look for new watches to feed into the Queue. | ||||
| def ticker_thread_check_time_launch_checks(): | ||||
|     import random | ||||
|     from changedetectionio import update_worker | ||||
|  | ||||
|     proxy_last_called_time = {} | ||||
|  | ||||
|     recheck_time_minimum_seconds = int(os.getenv('MINIMUM_SECONDS_RECHECK_TIME', 20)) | ||||
|     recheck_time_minimum_seconds = int(os.getenv('MINIMUM_SECONDS_RECHECK_TIME', 3)) | ||||
|     logger.debug(f"System env MINIMUM_SECONDS_RECHECK_TIME {recheck_time_minimum_seconds}") | ||||
|  | ||||
|     # Spin up Workers that do the fetching | ||||
| @@ -1729,9 +1715,7 @@ def ticker_thread_check_time_launch_checks(): | ||||
|                 continue | ||||
|  | ||||
|             # If they supplied an individual entry minutes to threshold. | ||||
|  | ||||
|             watch_threshold_seconds = watch.threshold_seconds() | ||||
|             threshold = watch_threshold_seconds if watch_threshold_seconds > 0 else recheck_time_system_seconds | ||||
|             threshold = recheck_time_system_seconds if watch.get('time_between_check_use_default') else watch.threshold_seconds() | ||||
|  | ||||
|             # #580 - Jitter plus/minus amount of time to make the check seem more random to the server | ||||
|             jitter = datastore.data['settings']['requests'].get('jitter_seconds', 0) | ||||
|   | ||||
| @@ -453,6 +453,7 @@ class watchForm(commonSettingsForm): | ||||
|     tags = StringTagUUID('Group tag', [validators.Optional()], default='') | ||||
|  | ||||
|     time_between_check = FormField(TimeBetweenCheckForm) | ||||
|     time_between_check_use_default = BooleanField('Use global settings for time between check', default=False) | ||||
|  | ||||
|     include_filters = StringListField('CSS/JSONPath/JQ/XPath Filters', [ValidateCSSJSONXPATHInput()], default='') | ||||
|  | ||||
|   | ||||
| @@ -12,7 +12,7 @@ from loguru import logger | ||||
| # file:// is further checked by ALLOW_FILE_URI | ||||
| SAFE_PROTOCOL_REGEX='^(http|https|ftp|file):' | ||||
|  | ||||
| minimum_seconds_recheck_time = int(os.getenv('MINIMUM_SECONDS_RECHECK_TIME', 60)) | ||||
| minimum_seconds_recheck_time = int(os.getenv('MINIMUM_SECONDS_RECHECK_TIME', 3)) | ||||
| mtable = {'seconds': 1, 'minutes': 60, 'hours': 3600, 'days': 86400, 'weeks': 86400 * 7} | ||||
|  | ||||
| from changedetectionio.notification import ( | ||||
| @@ -69,6 +69,7 @@ base_config = { | ||||
|     # Requires setting to None on submit if it's the same as the default | ||||
|     # Should be all None by default, so we use the system default in this case. | ||||
|     'time_between_check': {'weeks': None, 'days': None, 'hours': None, 'minutes': None, 'seconds': None}, | ||||
|     'time_between_check_use_default': True, | ||||
|     'title': None, | ||||
|     'trigger_text': [],  # List of text or regex to wait for until a change is detected | ||||
|     'url': '', | ||||
|   | ||||
| @@ -1,3 +1,17 @@ | ||||
| function toggleOpacity(checkboxSelector, fieldSelector) { | ||||
|     const checkbox = document.querySelector(checkboxSelector); | ||||
|     const fields = document.querySelectorAll(fieldSelector); | ||||
|     function updateOpacity() { | ||||
|         const opacityValue = checkbox.checked ? 0.6 : 1; | ||||
|         fields.forEach(field => { | ||||
|             field.style.opacity = opacityValue; | ||||
|         }); | ||||
|     } | ||||
|     // Initial setup | ||||
|     updateOpacity(); | ||||
|     checkbox.addEventListener('change', updateOpacity); | ||||
| } | ||||
|  | ||||
| $(document).ready(function () { | ||||
|     $('#notification-setting-reset-to-default').click(function (e) { | ||||
|         $('#notification_title').val(''); | ||||
| @@ -10,4 +24,7 @@ $(document).ready(function () { | ||||
|         e.preventDefault(); | ||||
|         $('#notification-tokens-info').toggle(); | ||||
|     }); | ||||
|  | ||||
|     toggleOpacity('#time_between_check_use_default', '#time_between_check'); | ||||
| }); | ||||
|  | ||||
|   | ||||
| @@ -928,23 +928,26 @@ body.full-width { | ||||
|       font-size: .875em; | ||||
|     } | ||||
|   } | ||||
|   .text-filtering { | ||||
|     h3 { | ||||
|       margin-top: 0; | ||||
|     } | ||||
|     border: 1px solid #ccc; | ||||
|     padding: 1rem; | ||||
|     border-radius: 5px; | ||||
|     margin-bottom: 1rem; | ||||
|     fieldset:last-of-type { | ||||
| } | ||||
|  | ||||
| .border-fieldset { | ||||
|   h3 { | ||||
|     margin-top: 0; | ||||
|   } | ||||
|   border: 1px solid #ccc; | ||||
|   padding: 1rem; | ||||
|   border-radius: 5px; | ||||
|   margin-bottom: 1rem; | ||||
|   fieldset:last-of-type { | ||||
|     padding-bottom: 0; | ||||
|     .pure-control-group { | ||||
|       padding-bottom: 0; | ||||
|       .pure-control-group { | ||||
|         padding-bottom: 0; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| ul { | ||||
|   padding-left: 1em; | ||||
|   padding-top: 0px; | ||||
|   | ||||
| @@ -1041,17 +1041,18 @@ body.full-width .edit-form { | ||||
|     color: var(--color-text-input-description); } | ||||
|     .edit-form .pure-form-message-inline code { | ||||
|       font-size: .875em; } | ||||
|   .edit-form .text-filtering { | ||||
|     border: 1px solid #ccc; | ||||
|     padding: 1rem; | ||||
|     border-radius: 5px; | ||||
|     margin-bottom: 1rem; } | ||||
|     .edit-form .text-filtering h3 { | ||||
|       margin-top: 0; } | ||||
|     .edit-form .text-filtering fieldset:last-of-type { | ||||
|  | ||||
| .border-fieldset { | ||||
|   border: 1px solid #ccc; | ||||
|   padding: 1rem; | ||||
|   border-radius: 5px; | ||||
|   margin-bottom: 1rem; } | ||||
|   .border-fieldset h3 { | ||||
|     margin-top: 0; } | ||||
|   .border-fieldset fieldset:last-of-type { | ||||
|     padding-bottom: 0; } | ||||
|     .border-fieldset fieldset:last-of-type .pure-control-group { | ||||
|       padding-bottom: 0; } | ||||
|       .edit-form .text-filtering fieldset:last-of-type .pure-control-group { | ||||
|         padding-bottom: 0; } | ||||
|  | ||||
| ul { | ||||
|   padding-left: 1em; | ||||
|   | ||||
| @@ -872,3 +872,16 @@ class ChangeDetectionStore: | ||||
|                         self.__data["watching"][awatch]['include_filters'][num] = 'xpath1:' + selector | ||||
|                     if selector.startswith('xpath:'): | ||||
|                         self.__data["watching"][awatch]['include_filters'][num] = selector.replace('xpath:', 'xpath1:', 1) | ||||
|  | ||||
|     # Use more obvious default time setting | ||||
|     def update_15(self): | ||||
|         for uuid in self.__data["watching"]: | ||||
|             if self.__data["watching"][uuid]['time_between_check'] == self.__data['settings']['requests']['time_between_check']: | ||||
|                 # What the old logic was, which was pretty confusing | ||||
|                 self.__data["watching"][uuid]['time_between_check_use_default'] = True | ||||
|             elif all(value is None or value == 0 for value in self.__data["watching"][uuid]['time_between_check'].values()): | ||||
|                 self.__data["watching"][uuid]['time_between_check_use_default'] = True | ||||
|             else: | ||||
|                 # Something custom here | ||||
|                 self.__data["watching"][uuid]['time_between_check_use_default'] = False | ||||
|  | ||||
|   | ||||
| @@ -87,15 +87,9 @@ | ||||
|                         {{ render_field(form.tags) }} | ||||
|                         <span class="pure-form-message-inline">Organisational tag/group name used in the main listing page</span> | ||||
|                     </div> | ||||
|                     <div class="pure-control-group"> | ||||
|                     <div class="pure-control-group time-between-check border-fieldset"> | ||||
|                         {{ render_field(form.time_between_check, class="time-check-widget") }} | ||||
|                         {% if has_empty_checktime %} | ||||
|                         <span class="pure-form-message-inline">Currently using the <a | ||||
|                                 href="{{ url_for('settings_page', uuid=uuid) }}">default global settings</a>, change to another value if you want to be specific.</span> | ||||
|                         {% else %} | ||||
|                         <span class="pure-form-message-inline">Set to blank to use the <a | ||||
|                                 href="{{ url_for('settings_page', uuid=uuid) }}">default global settings</a>.</span> | ||||
|                         {% endif %} | ||||
|                         {{ render_checkbox_field(form.time_between_check_use_default, class="use-default-timecheck") }} | ||||
|                     </div> | ||||
|                     <div class="pure-control-group"> | ||||
|                         {{ render_checkbox_field(form.extract_title_as_title) }} | ||||
| @@ -330,7 +324,7 @@ nav | ||||
|                         </ul> | ||||
|                       </span> | ||||
|                 </fieldset> | ||||
|                 <div class="text-filtering"> | ||||
|                 <div class="text-filtering border-fieldset"> | ||||
|                 <fieldset class="pure-group" id="text-filtering-type-options"> | ||||
|                     <h3>Text filtering</h3> | ||||
|                         Limit trigger/ignore/block/extract to;<br> | ||||
|   | ||||
| @@ -31,7 +31,7 @@ | ||||
|                 <fieldset> | ||||
|                     <div class="pure-control-group"> | ||||
|                         {{ render_field(form.requests.form.time_between_check, class="time-check-widget") }} | ||||
|                         <span class="pure-form-message-inline">Default time for all watches, when the watch does not have a specific time setting.</span> | ||||
|                         <span class="pure-form-message-inline">Default recheck time for all watches, current system minimum is <i>{{min_system_recheck_seconds}}</i> seconds (<a href="https://github.com/dgtlmoon/changedetection.io/wiki/Misc-system-settings#enviroment-variables">more info</a>).</span> | ||||
|                     </div> | ||||
|                     <div class="pure-control-group"> | ||||
|                         {{ render_field(form.requests.form.jitter_seconds, class="jitter_seconds") }} | ||||
|   | ||||
| @@ -54,102 +54,3 @@ def test_check_watch_field_storage(client, live_server): | ||||
|     assert b"woohoo" in res.data | ||||
|     assert b"curl: foo" in res.data | ||||
|  | ||||
|  | ||||
|  | ||||
| # Re https://github.com/dgtlmoon/changedetection.io/issues/110 | ||||
| def test_check_recheck_global_setting(client, live_server): | ||||
|  | ||||
|     res = client.post( | ||||
|         url_for("settings_page"), | ||||
|         data={ | ||||
|                "requests-time_between_check-minutes": 1566, | ||||
|                'application-fetch_backend': "html_requests" | ||||
|                }, | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|     assert b"Settings updated." in res.data | ||||
|  | ||||
|     # Now add a record | ||||
|  | ||||
|     test_url = "http://somerandomsitewewatch.com" | ||||
|  | ||||
|     res = client.post( | ||||
|         url_for("import_page"), | ||||
|         data={"urls": test_url}, | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|     assert b"1 Imported" in res.data | ||||
|  | ||||
|     # Now visit the edit page, it should have the default minutes | ||||
|  | ||||
|     res = client.get( | ||||
|         url_for("edit_page", uuid="first"), | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|  | ||||
|     # Should show the default minutes | ||||
|     assert b"change to another value if you want to be specific" in res.data | ||||
|     assert b"1566" in res.data | ||||
|  | ||||
|     res = client.post( | ||||
|         url_for("settings_page"), | ||||
|         data={ | ||||
|                "requests-time_between_check-minutes": 222, | ||||
|                 'application-fetch_backend': "html_requests" | ||||
|                }, | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|     assert b"Settings updated." in res.data | ||||
|  | ||||
|     res = client.get( | ||||
|         url_for("edit_page", uuid="first"), | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|  | ||||
|     # Should show the default minutes | ||||
|     assert b"change to another value if you want to be specific" in res.data | ||||
|     assert b"222" in res.data | ||||
|  | ||||
|     # Now change it specifically, it should show the new minutes | ||||
|     res = client.post( | ||||
|         url_for("edit_page", uuid="first"), | ||||
|         data={"url": test_url, | ||||
|               "time_between_check-minutes": 55, | ||||
|               'fetch_backend': "html_requests" | ||||
|               }, | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|  | ||||
|     res = client.get( | ||||
|         url_for("edit_page", uuid="first"), | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|     assert b"55" in res.data | ||||
|  | ||||
|     # Now submit an empty field, it should give back the default global minutes | ||||
|     res = client.post( | ||||
|         url_for("settings_page"), | ||||
|         data={ | ||||
|                "requests-time_between_check-minutes": 666, | ||||
|                 "application-fetch_backend": "html_requests" | ||||
|                }, | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|     assert b"Settings updated." in res.data | ||||
|  | ||||
|     res = client.post( | ||||
|         url_for("edit_page", uuid="first"), | ||||
|         data={"url": test_url, | ||||
|               "time_between_check-minutes": "", | ||||
|               'fetch_backend': "html_requests" | ||||
|               }, | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|  | ||||
|     assert b"Updated watch." in res.data | ||||
|  | ||||
|     res = client.get( | ||||
|         url_for("edit_page", uuid="first"), | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|     assert b"666" in res.data | ||||
|   | ||||
| @@ -54,7 +54,9 @@ services: | ||||
|   #         | ||||
|   #        Default number of parallel/concurrent fetchers | ||||
|   #      - FETCH_WORKERS=10 | ||||
|  | ||||
|   # | ||||
|   #        Absolute minimum seconds to recheck, overrides any watch minimum, change to 0 to disable | ||||
|   #      - MINIMUM_SECONDS_RECHECK_TIME=3 | ||||
|       # Comment out ports: when using behind a reverse proxy , enable networks: etc. | ||||
|       ports: | ||||
|         - 5000:5000 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user