webchanges 3.37.0__tar.gz → 3.38.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. {webchanges-3.37.0/webchanges.egg-info → webchanges-3.38.0}/PKG-INFO +16 -9
  2. {webchanges-3.37.0 → webchanges-3.38.0}/README.rst +5 -1
  3. {webchanges-3.37.0 → webchanges-3.38.0}/pyproject.toml +13 -6
  4. {webchanges-3.37.0 → webchanges-3.38.0}/requirements.txt +0 -1
  5. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/__init__.py +2 -2
  6. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/_resources/config.schema.json +218 -54
  7. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/_resources/jobs.schema.json +313 -73
  8. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/_vendored/headers.py +3 -3
  9. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/_vendored/packaging_version.py +39 -18
  10. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/cli.py +157 -84
  11. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/command.py +129 -24
  12. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/config.py +11 -0
  13. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/differs.py +147 -126
  14. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/filters/_base.py +27 -10
  15. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/filters/_document.py +121 -51
  16. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/filters/_encoding.py +2 -0
  17. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/filters/_html.py +86 -29
  18. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/filters/_shell.py +2 -0
  19. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/filters/_text.py +20 -17
  20. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/handler.py +58 -28
  21. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/jobs/__init__.py +2 -0
  22. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/jobs/_base.py +175 -57
  23. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/jobs/_browser.py +74 -30
  24. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/jobs/_exceptions.py +14 -1
  25. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/jobs/_shell.py +3 -1
  26. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/jobs/_url.py +266 -102
  27. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/mailer.py +69 -13
  28. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/main.py +8 -0
  29. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/reporters/__init__.py +10 -1
  30. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/reporters/_base.py +189 -58
  31. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/reporters/_browser.py +2 -0
  32. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/reporters/_chat.py +97 -72
  33. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/reporters/_stdout.py +41 -17
  34. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/reporters/_system.py +2 -0
  35. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/reporters/_web.py +13 -10
  36. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/storage/_base.py +62 -14
  37. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/storage/_config.py +63 -44
  38. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/storage/_minidb.py +3 -1
  39. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/storage/_redis.py +10 -7
  40. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/storage/_sqlite3.py +10 -5
  41. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/storage/_ssdb.py +12 -5
  42. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/storage/_yaml.py +138 -41
  43. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/util.py +75 -50
  44. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/worker.py +20 -30
  45. {webchanges-3.37.0 → webchanges-3.38.0/webchanges.egg-info}/PKG-INFO +16 -9
  46. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges.egg-info/requires.txt +15 -5
  47. {webchanges-3.37.0 → webchanges-3.38.0}/LICENSE.md +0 -0
  48. {webchanges-3.37.0 → webchanges-3.38.0}/MANIFEST.in +0 -0
  49. {webchanges-3.37.0 → webchanges-3.38.0}/setup.cfg +0 -0
  50. {webchanges-3.37.0 → webchanges-3.38.0}/setup.py +0 -0
  51. {webchanges-3.37.0 → webchanges-3.38.0}/tools/get_manpages_parser.py +0 -0
  52. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/__main__.py +0 -0
  53. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/_resources/__init__.py +0 -0
  54. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/_vendored/__init__.py +0 -0
  55. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/_vendored/typeguard.py +0 -0
  56. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/filters/__init__.py +0 -0
  57. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/py.typed +0 -0
  58. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/reporters/_email.py +0 -0
  59. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/storage/__init__.py +0 -0
  60. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges/storage_minidb.py +0 -0
  61. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges.egg-info/SOURCES.txt +0 -0
  62. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges.egg-info/dependency_links.txt +0 -0
  63. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges.egg-info/entry_points.txt +0 -0
  64. {webchanges-3.37.0 → webchanges-3.38.0}/webchanges.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: webchanges
3
- Version: 3.37.0
3
+ Version: 3.38.0
4
4
  Summary: Web Changes Delivered. AI-Summarized. Totally Anonymous.
5
5
  Author-email: Mike Borsetti <mike+webchanges@borsetti.com>
6
6
  Maintainer-email: Mike Borsetti <mike+webchanges@borsetti.com>
@@ -21,10 +21,10 @@ Classifier: Operating System :: OS Independent
21
21
  Classifier: Programming Language :: Python
22
22
  Classifier: Programming Language :: Python :: 3
23
23
  Classifier: Programming Language :: Python :: 3 :: Only
24
- Classifier: Programming Language :: Python :: 3.11
25
24
  Classifier: Programming Language :: Python :: 3.12
26
25
  Classifier: Programming Language :: Python :: 3.13
27
26
  Classifier: Programming Language :: Python :: 3.14
27
+ Classifier: Programming Language :: Python :: 3.15
28
28
  Classifier: Programming Language :: Python :: Free Threading
29
29
  Classifier: Programming Language :: Python :: Free Threading :: 4 - Resilient
30
30
  Classifier: Programming Language :: Python :: Implementation :: CPython
@@ -34,10 +34,9 @@ Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
34
34
  Classifier: Topic :: System :: Monitoring
35
35
  Classifier: Topic :: Utilities
36
36
  Classifier: Typing :: Typed
37
- Requires-Python: >=3.11
37
+ Requires-Python: >=3.12
38
38
  Description-Content-Type: text/x-rst
39
39
  License-File: LICENSE.md
40
- Requires-Dist: colorama; sys_platform == "win32"
41
40
  Requires-Dist: cssselect
42
41
  Requires-Dist: h2
43
42
  Requires-Dist: html2text
@@ -64,7 +63,7 @@ Requires-Dist: html5lib; extra == "html5lib"
64
63
  Provides-Extra: ical2text
65
64
  Requires-Dist: vobject; extra == "ical2text"
66
65
  Provides-Extra: jq
67
- Requires-Dist: jq; os_name != "nt" and extra == "jq"
66
+ Requires-Dist: jq; extra == "jq"
68
67
  Provides-Extra: ocr
69
68
  Requires-Dist: pytesseract; extra == "ocr"
70
69
  Requires-Dist: Pillow; extra == "ocr"
@@ -75,10 +74,14 @@ Requires-Dist: pypdf; extra == "pypdf"
75
74
  Provides-Extra: pypdf-crypto
76
75
  Requires-Dist: pypdf; extra == "pypdf-crypto"
77
76
  Requires-Dist: cryptography; extra == "pypdf-crypto"
77
+ Provides-Extra: xmltodict
78
+ Requires-Dist: xmltodict; extra == "xmltodict"
78
79
  Provides-Extra: deepdiff
79
- Requires-Dist: deepdiff>=8.0; extra == "deepdiff"
80
+ Requires-Dist: deepdiff>=8.0; python_version < "3.15" and extra == "deepdiff"
81
+ Requires-Dist: deepdiff<9,>=8.0; python_version >= "3.15" and extra == "deepdiff"
80
82
  Provides-Extra: deepdiff-xml
81
- Requires-Dist: deepdiff>=8.0; extra == "deepdiff-xml"
83
+ Requires-Dist: deepdiff>=8.0; python_version < "3.15" and extra == "deepdiff-xml"
84
+ Requires-Dist: deepdiff<9,>=8.0; python_version >= "3.15" and extra == "deepdiff-xml"
82
85
  Requires-Dist: xmltodict; extra == "deepdiff-xml"
83
86
  Provides-Extra: imagediff
84
87
  Requires-Dist: Pillow; extra == "imagediff"
@@ -99,7 +102,7 @@ Requires-Dist: requests; extra == "requests"
99
102
  Provides-Extra: safe-password
100
103
  Requires-Dist: keyring; extra == "safe-password"
101
104
  Provides-Extra: all
102
- Requires-Dist: webchanges[beautify,bs4,curl_cffi,deepdiff_xml,html5lib,ical2text,imagediff,jq,matrix,ocr,pdf2text,pushbullet,pushover,pypdf_crypto,redis,requests,safe_password,use_browser,xmpp]; extra == "all"
105
+ Requires-Dist: webchanges[beautify,bs4,curl_cffi,deepdiff_xml,html5lib,ical2text,imagediff,jq,matrix,ocr,pdf2text,pushbullet,pushover,pypdf_crypto,redis,requests,safe_password,use_browser,xmltodict,xmpp]; extra == "all"
103
106
  Dynamic: license-file
104
107
 
105
108
  .. role:: underline
@@ -158,6 +161,10 @@ or with ``pip``:
158
161
 
159
162
  pip install webchanges
160
163
 
164
+ On Windows with Python 3.15, first run ``set PYYAML_FORCE_LIBYAML=0`` (in PowerShell:
165
+ ``$env:PYYAML_FORCE_LIBYAML = "0"``), as explained `here
166
+ <https://webchanges.readthedocs.io/en/stable/introduction.html#install-windows>`__.
167
+
161
168
  Other ways to run
162
169
  -----------------
163
170
  - In a `Docker <https://www.docker.com/>`__ container: a minimal implementation (no browser) is `here
@@ -247,7 +254,7 @@ Relationship with **urlwatch**
247
254
  ==============================
248
255
  This project is a fork of `urlwatch 2.21
249
256
  <https://github.com/thp/urlwatch/tree/346b25914b0418342ffe2fb0529bed702fddc01f>`__ and has since added many features;
250
- see the `comparison <https://webchanges.readthedocs.io/en/stable/_static/webchanges-vs-urlwatch.html>`__.
257
+ see the `comparison <https://webchanges.readthedocs.io/en/stable/upgrading.html>`__.
251
258
 
252
259
 
253
260
  .. |support| image:: https://img.shields.io/pypi/pyversions/webchanges.svg
@@ -54,6 +54,10 @@ or with ``pip``:
54
54
 
55
55
  pip install webchanges
56
56
 
57
+ On Windows with Python 3.15, first run ``set PYYAML_FORCE_LIBYAML=0`` (in PowerShell:
58
+ ``$env:PYYAML_FORCE_LIBYAML = "0"``), as explained `here
59
+ <https://webchanges.readthedocs.io/en/stable/introduction.html#install-windows>`__.
60
+
57
61
  Other ways to run
58
62
  -----------------
59
63
  - In a `Docker <https://www.docker.com/>`__ container: a minimal implementation (no browser) is `here
@@ -143,7 +147,7 @@ Relationship with **urlwatch**
143
147
  ==============================
144
148
  This project is a fork of `urlwatch 2.21
145
149
  <https://github.com/thp/urlwatch/tree/346b25914b0418342ffe2fb0529bed702fddc01f>`__ and has since added many features;
146
- see the `comparison <https://webchanges.readthedocs.io/en/stable/_static/webchanges-vs-urlwatch.html>`__.
150
+ see the `comparison <https://webchanges.readthedocs.io/en/stable/upgrading.html>`__.
147
151
 
148
152
 
149
153
  .. |support| image:: https://img.shields.io/pypi/pyversions/webchanges.svg
@@ -16,7 +16,7 @@ dynamic = ['version', 'dependencies']
16
16
  name = 'webchanges'
17
17
  description = 'Web Changes Delivered. AI-Summarized. Totally Anonymous.'
18
18
  readme = { file = 'README.rst', content-type = 'text/x-rst' }
19
- requires-python = '>=3.11'
19
+ requires-python = '>=3.12'
20
20
  license = "MIT AND BSD-3-Clause"
21
21
  license-files = ['LICENSE.md']
22
22
  authors = [{ name = 'Mike Borsetti', email = 'mike+webchanges@borsetti.com' }]
@@ -35,10 +35,10 @@ classifiers = [
35
35
  'Programming Language :: Python',
36
36
  'Programming Language :: Python :: 3',
37
37
  'Programming Language :: Python :: 3 :: Only',
38
- 'Programming Language :: Python :: 3.11',
39
38
  'Programming Language :: Python :: 3.12',
40
39
  'Programming Language :: Python :: 3.13',
41
40
  'Programming Language :: Python :: 3.14',
41
+ 'Programming Language :: Python :: 3.15',
42
42
  'Programming Language :: Python :: Free Threading',
43
43
  'Programming Language :: Python :: Free Threading :: 4 - Resilient',
44
44
  'Programming Language :: Python :: Implementation :: CPython',
@@ -70,15 +70,22 @@ beautify = ['beautifulsoup4', 'jsbeautifier', 'cssbeautifier']
70
70
  bs4 = ['beautifulsoup4']
71
71
  html5lib = ['html5lib']
72
72
  ical2text = ['vobject']
73
- jq = ['jq; os_name != "nt"']
73
+ jq = ['jq']
74
74
  ocr = ['pytesseract', 'Pillow']
75
75
  pdf2text = ['pdftotext']
76
76
  pypdf = ['pypdf']
77
77
  pypdf_crypto = ['pypdf', 'cryptography']
78
+ xmltodict = ['xmltodict'] # xmltojson and xmltoyaml filters
78
79
  # differs
79
80
  # deepdiff >= 8.0 is required for threshold_to_diff_deeper
80
- deepdiff = ['deepdiff >= 8.0']
81
- deepdiff_xml = ['deepdiff >= 8.0', 'xmltodict']
81
+ # deepdiff < 9 on Python >= 3.15: deepdiff 9 requires cachebox < 6, and cachebox 5.x has no 3.15 wheels and cannot be
82
+ # built for 3.15 (it uses PyO3 0.27, which supports Python only up to 3.14). Keep in sync with tests/requirements_*.txt
83
+ deepdiff = ['deepdiff >= 8.0; python_version < "3.15"', 'deepdiff >= 8.0, < 9; python_version >= "3.15"']
84
+ deepdiff_xml = [
85
+ 'deepdiff >= 8.0; python_version < "3.15"',
86
+ 'deepdiff >= 8.0, < 9; python_version >= "3.15"',
87
+ 'xmltodict',
88
+ ]
82
89
  imagediff = ['Pillow']
83
90
  # reporters
84
91
  matrix = ['matrix_client']
@@ -92,7 +99,7 @@ requests = ['requests']
92
99
  safe_password = ['keyring']
93
100
  # all
94
101
  all = [
95
- 'webchanges[use_browser,beautify,bs4,html5lib,ical2text,jq,ocr,pdf2text,pypdf_crypto,deepdiff_xml,imagediff,matrix,pushbullet,pushover,xmpp,curl_cffi,redis,requests,safe_password]',
102
+ 'webchanges[use_browser,beautify,bs4,html5lib,ical2text,jq,ocr,pdf2text,pypdf_crypto,xmltodict,deepdiff_xml,imagediff,matrix,pushbullet,pushover,xmpp,curl_cffi,redis,requests,safe_password]',
96
103
  ]
97
104
 
98
105
 
@@ -1,4 +1,3 @@
1
- colorama; sys_platform == 'win32'
2
1
  cssselect
3
2
  h2
4
3
  html2text
@@ -12,7 +12,7 @@ supported services. Can check the output of local commands as well.
12
12
 
13
13
  from __future__ import annotations
14
14
 
15
- __min_python_version__ = (3, 11) # minimum version of Python required to run; 3.11 supported until fall 2026
15
+ __min_python_version__ = (3, 12) # minimum version of Python required to run; 3.12 supported until 7 October 2027
16
16
 
17
17
 
18
18
  __project_name__ = str(__package__)
@@ -22,7 +22,7 @@ __project_name__ = str(__package__)
22
22
  # * MINOR version when you add functionality in a backwards compatible manner, and
23
23
  # * MICRO or PATCH version when you make backwards compatible bug fixes. We no longer use '0'
24
24
  # If unsure on increments, use pkg_resources.parse_version to parse
25
- __version__ = '3.37.0'
25
+ __version__ = '3.38.0'
26
26
  __description__ = (
27
27
  'Check web (or command output) for changes since last run and notify.\n\nAnonymously alerts you of web changes.'
28
28
  )
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "job_defaults": {
18
18
  "$ref": "#/$defs/_ConfigJobDefaults",
19
- "description": "Default directives applied to jobs by kind (all, url, browser, command)."
19
+ "description": "Default directives applied to jobs by kind (all_jobs, url_jobs, browser_jobs, command_jobs)."
20
20
  },
21
21
  "differ_defaults": {
22
22
  "$ref": "#/$defs/_ConfigDifferDefaults",
@@ -34,6 +34,16 @@
34
34
  "version_check": {
35
35
  "$ref": "#/$defs/_ConfigVersionCheck",
36
36
  "description": "Settings for the once-a-day check against PyPi for a newer release of webchanges."
37
+ },
38
+ "jobs": {
39
+ "anyOf": [{"type": "string"}, {"type": "array", "items": {"type": "string"}, "minItems": 1}, {"type": "null"}],
40
+ "description": "The jobs file(s) to use instead of the default jobs.yaml: a file, a glob pattern (e.g. 'jobs/**/*.yaml') or a directory (for all its *.yaml files, recursively), or a list of these. Relative paths are taken from the directory of this configuration file. Overridden by the --jobs command line argument. Set to null for the default.",
41
+ "default": null
42
+ },
43
+ "hooks": {
44
+ "anyOf": [{"type": "string"}, {"type": "array", "items": {"type": "string"}, "minItems": 1}, {"type": "null"}],
45
+ "description": "The hooks file(s) to use instead of the default hooks.py: a file, a glob pattern or a directory (for all its *.py files, recursively), or a list of these. Relative paths are taken from the directory of this configuration file. Overridden by the --hooks command line argument. Set to null for the default.",
46
+ "default": null
37
47
  }
38
48
  },
39
49
  "additionalProperties": false,
@@ -160,8 +170,11 @@
160
170
  "title": "stdout reporter",
161
171
  "description": "Display a text report on standard output (the console).",
162
172
  "type": "object",
163
- "required": ["enabled", "color"],
164
173
  "properties": {
174
+ "tags": {
175
+ "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
176
+ "description": "Restrict this reporter to the jobs having any of these tags in their 'tags' directive. If omitted, the reporter reports on every job."
177
+ },
165
178
  "enabled": {
166
179
  "type": "boolean",
167
180
  "description": "Enable the stdout reporter.",
@@ -178,8 +191,11 @@
178
191
  "title": "Browser reporter",
179
192
  "description": "Open the HTML report in the system's default web browser.",
180
193
  "type": "object",
181
- "required": ["enabled"],
182
194
  "properties": {
195
+ "tags": {
196
+ "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
197
+ "description": "Restrict this reporter to the jobs having any of these tags in their 'tags' directive. If omitted, the reporter reports on every job."
198
+ },
183
199
  "enabled": {
184
200
  "type": "boolean",
185
201
  "description": "Enable the browser reporter.",
@@ -191,8 +207,11 @@
191
207
  "title": "Discord reporter",
192
208
  "description": "Send the report as a message in a Discord channel via a webhook.",
193
209
  "type": "object",
194
- "required": ["enabled", "webhook_url", "embed", "subject", "colored", "max_message_length"],
195
210
  "properties": {
211
+ "tags": {
212
+ "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
213
+ "description": "Restrict this reporter to the jobs having any of these tags in their 'tags' directive. If omitted, the reporter reports on every job."
214
+ },
196
215
  "enabled": {
197
216
  "type": "boolean",
198
217
  "description": "Enable the Discord reporter.",
@@ -290,8 +309,11 @@
290
309
  "title": "Email reporter",
291
310
  "description": "Send the report via email, using either SMTP or the external sendmail program.",
292
311
  "type": "object",
293
- "required": ["enabled", "html", "to", "from", "subject", "method", "smtp", "sendmail"],
294
312
  "properties": {
313
+ "tags": {
314
+ "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
315
+ "description": "Restrict this reporter to the jobs having any of these tags in their 'tags' directive. If omitted, the reporter reports on every job."
316
+ },
295
317
  "enabled": {
296
318
  "type": "boolean",
297
319
  "description": "Enable the email reporter.",
@@ -330,20 +352,11 @@
330
352
  "title": "GitHub Issue reporter",
331
353
  "description": "Submit the Markdown report as a new issue on a GitHub repository. Requires a personal access token with 'public_repo' (public) or 'repo' (private) scope.",
332
354
  "type": "object",
333
- "required": [
334
- "enabled",
335
- "token",
336
- "owner",
337
- "repo",
338
- "title",
339
- "labels",
340
- "format_dt",
341
- "format_content",
342
- "assignees",
343
- "type",
344
- "milestone"
345
- ],
346
355
  "properties": {
356
+ "tags": {
357
+ "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
358
+ "description": "Restrict this reporter to the jobs having any of these tags in their 'tags' directive. If omitted, the reporter reports on every job."
359
+ },
347
360
  "enabled": {
348
361
  "type": "boolean",
349
362
  "description": "Enable the GitHub Issue reporter.",
@@ -407,8 +420,11 @@
407
420
  "title": "Gotify reporter",
408
421
  "description": "Send the Markdown report to a Gotify server. Requires an application token created on the Gotify server's Web-UI.",
409
422
  "type": "object",
410
- "required": ["enabled", "priority", "server_url", "title", "token"],
411
423
  "properties": {
424
+ "tags": {
425
+ "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
426
+ "description": "Restrict this reporter to the jobs having any of these tags in their 'tags' directive. If omitted, the reporter reports on every job."
427
+ },
412
428
  "enabled": {
413
429
  "type": "boolean",
414
430
  "description": "Enable the Gotify reporter.",
@@ -424,11 +440,16 @@
424
440
  "description": "Base URL of the Gotify server.",
425
441
  "default": ""
426
442
  },
427
- "title": {
443
+ "subject": {
428
444
  "type": "string",
429
- "description": "Message title.",
445
+ "description": "Message title; can contain the placeholders {count}, {jobs} and {jobs_files}. Empty for no title.",
430
446
  "default": ""
431
447
  },
448
+ "title": {
449
+ "type": "string",
450
+ "deprecated": true,
451
+ "description": "DEPRECATED: Replace key with 'subject'."
452
+ },
432
453
  "token": {
433
454
  "type": "string",
434
455
  "description": "Gotify application token.",
@@ -440,8 +461,11 @@
440
461
  "title": "IFTTT reporter",
441
462
  "description": "Send the text report as an IFTTT event via the Maker Webhooks service.",
442
463
  "type": "object",
443
- "required": ["enabled", "key", "event"],
444
464
  "properties": {
465
+ "tags": {
466
+ "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
467
+ "description": "Restrict this reporter to the jobs having any of these tags in their 'tags' directive. If omitted, the reporter reports on every job."
468
+ },
445
469
  "enabled": {
446
470
  "type": "boolean",
447
471
  "description": "Enable the IFTTT reporter.",
@@ -463,8 +487,11 @@
463
487
  "title": "Mailgun reporter",
464
488
  "description": "Send the text report via email using the Mailgun service.",
465
489
  "type": "object",
466
- "required": ["enabled", "region", "api_key", "domain", "from_mail", "from_name", "to", "subject"],
467
490
  "properties": {
491
+ "tags": {
492
+ "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
493
+ "description": "Restrict this reporter to the jobs having any of these tags in their 'tags' directive. If omitted, the reporter reports on every job."
494
+ },
468
495
  "enabled": {
469
496
  "type": "boolean",
470
497
  "description": "Enable the Mailgun reporter.",
@@ -511,8 +538,11 @@
511
538
  "title": "Matrix reporter",
512
539
  "description": "Send the report to a room using the Matrix protocol.",
513
540
  "type": "object",
514
- "required": ["enabled", "homeserver", "access_token", "room_id"],
515
541
  "properties": {
542
+ "tags": {
543
+ "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
544
+ "description": "Restrict this reporter to the jobs having any of these tags in their 'tags' directive. If omitted, the reporter reports on every job."
545
+ },
516
546
  "enabled": {
517
547
  "type": "boolean",
518
548
  "description": "Enable the Matrix reporter.",
@@ -567,8 +597,11 @@
567
597
  "title": "ntfy reporter",
568
598
  "description": "Send the text report to an ntfy server (https://ntfy.sh).",
569
599
  "type": "object",
570
- "required": ["enabled", "topic_url", "authorization", "priorities"],
571
600
  "properties": {
601
+ "tags": {
602
+ "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
603
+ "description": "Restrict this reporter to the jobs having any of these tags in their 'tags' directive. If omitted, the reporter reports on every job."
604
+ },
572
605
  "enabled": {
573
606
  "type": "boolean",
574
607
  "description": "Enable the ntfy reporter.",
@@ -591,8 +624,11 @@
591
624
  "title": "Prowl reporter",
592
625
  "description": "Send the text report via Prowl (iOS push notifications).",
593
626
  "type": "object",
594
- "required": ["enabled", "api_key", "priority", "application", "subject"],
595
627
  "properties": {
628
+ "tags": {
629
+ "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
630
+ "description": "Restrict this reporter to the jobs having any of these tags in their 'tags' directive. If omitted, the reporter reports on every job."
631
+ },
596
632
  "enabled": {
597
633
  "type": "boolean",
598
634
  "description": "Enable the Prowl reporter.",
@@ -624,8 +660,11 @@
624
660
  "title": "Pushbullet reporter",
625
661
  "description": "Send the text report via Pushbullet. Note: the underlying 'pushbullet' Python package has not been maintained since 2022.",
626
662
  "type": "object",
627
- "required": ["enabled", "api_key"],
628
663
  "properties": {
664
+ "tags": {
665
+ "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
666
+ "description": "Restrict this reporter to the jobs having any of these tags in their 'tags' directive. If omitted, the reporter reports on every job."
667
+ },
629
668
  "enabled": {
630
669
  "type": "boolean",
631
670
  "description": "Enable the Pushbullet reporter.",
@@ -642,8 +681,11 @@
642
681
  "title": "Pushover reporter",
643
682
  "description": "Send the text report via Pushover (https://pushover.net).",
644
683
  "type": "object",
645
- "required": ["enabled", "app", "device", "sound", "user", "priority"],
646
684
  "properties": {
685
+ "tags": {
686
+ "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
687
+ "description": "Restrict this reporter to the jobs having any of these tags in their 'tags' directive. If omitted, the reporter reports on every job."
688
+ },
647
689
  "enabled": {
648
690
  "type": "boolean",
649
691
  "description": "Enable the Pushover reporter.",
@@ -681,8 +723,11 @@
681
723
  "title": "run_command reporter",
682
724
  "description": "Run a local command receiving the text report. Substitutes {count}, {jobs}, and {text} in the command string and exposes the WEBCHANGES_REPORT_CONFIG_JSON and WEBCHANGES_CHANGED_JOBS_JSON environment variables.",
683
725
  "type": "object",
684
- "required": ["enabled", "command"],
685
726
  "properties": {
727
+ "tags": {
728
+ "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
729
+ "description": "Restrict this reporter to the jobs having any of these tags in their 'tags' directive. If omitted, the reporter reports on every job."
730
+ },
686
731
  "enabled": {
687
732
  "type": "boolean",
688
733
  "description": "Enable the run_command reporter.",
@@ -699,8 +744,11 @@
699
744
  "title": "Telegram reporter",
700
745
  "description": "Send the Markdown report via Telegram using the Bot API.",
701
746
  "type": "object",
702
- "required": ["enabled", "bot_token", "chat_id", "silent"],
703
747
  "properties": {
748
+ "tags": {
749
+ "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
750
+ "description": "Restrict this reporter to the jobs having any of these tags in their 'tags' directive. If omitted, the reporter reports on every job."
751
+ },
704
752
  "enabled": {
705
753
  "type": "boolean",
706
754
  "description": "Enable the Telegram reporter.",
@@ -736,8 +784,11 @@
736
784
  "title": "Webhook reporter",
737
785
  "description": "Send the report to a webhook endpoint (e.g. Slack, Mattermost).",
738
786
  "type": "object",
739
- "required": ["enabled", "markdown", "webhook_url", "rich_text", "max_message_length"],
740
787
  "properties": {
788
+ "tags": {
789
+ "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
790
+ "description": "Restrict this reporter to the jobs having any of these tags in their 'tags' directive. If omitted, the reporter reports on every job."
791
+ },
741
792
  "enabled": {
742
793
  "type": "boolean",
743
794
  "description": "Enable the webhook reporter.",
@@ -769,8 +820,11 @@
769
820
  "title": "XMPP reporter",
770
821
  "description": "Send the text report via the XMPP protocol. Use a dedicated XMPP account, never a primary one.",
771
822
  "type": "object",
772
- "required": ["enabled", "sender", "recipient", "insecure_password"],
773
823
  "properties": {
824
+ "tags": {
825
+ "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }],
826
+ "description": "Restrict this reporter to the jobs having any of these tags in their 'tags' directive. If omitted, the reporter reports on every job."
827
+ },
774
828
  "enabled": {
775
829
  "type": "boolean",
776
830
  "description": "Enable the XMPP reporter.",
@@ -829,49 +883,159 @@
829
883
  "text": { "$ref": "#/$defs/_ConfigReportText" },
830
884
  "html": { "$ref": "#/$defs/_ConfigReportHtml" },
831
885
  "markdown": { "$ref": "#/$defs/_ConfigReportMarkdown" },
832
- "stdout": { "$ref": "#/$defs/_ConfigReportStdout" },
833
- "browser": { "$ref": "#/$defs/_ConfigReportBrowser" },
834
- "discord": { "$ref": "#/$defs/_ConfigReportDiscord" },
835
- "email": { "$ref": "#/$defs/_ConfigReportEmail" },
836
- "github_issue": { "$ref": "#/$defs/_ConfigReportGithubIssue" },
837
- "gotify": { "$ref": "#/$defs/_ConfigReportGotify" },
838
- "ifttt": { "$ref": "#/$defs/_ConfigReportIfttt" },
839
- "mailgun": { "$ref": "#/$defs/_ConfigReportMailgun" },
840
- "matrix": { "$ref": "#/$defs/_ConfigReportMatrix" },
841
- "ntfy": { "$ref": "#/$defs/_ConfigReportNtfy" },
842
- "prowl": { "$ref": "#/$defs/_ConfigReportProwl" },
843
- "pushbullet": { "$ref": "#/$defs/_ConfigReportPushbullet" },
844
- "pushover": { "$ref": "#/$defs/_ConfigReportPushover" },
845
- "run_command": { "$ref": "#/$defs/_ConfigReportRunCommand" },
846
- "telegram": { "$ref": "#/$defs/_ConfigReportTelegram" },
847
- "webhook": { "$ref": "#/$defs/_ConfigReportWebhook" },
848
- "xmpp": { "$ref": "#/$defs/_ConfigReportXmpp" }
886
+ "stdout": {
887
+ "anyOf": [
888
+ { "$ref": "#/$defs/_ConfigReportStdout" },
889
+ { "type": "array", "items": { "$ref": "#/$defs/_ConfigReportStdout" }, "minItems": 1 }
890
+ ]
891
+ },
892
+ "browser": {
893
+ "anyOf": [
894
+ { "$ref": "#/$defs/_ConfigReportBrowser" },
895
+ { "type": "array", "items": { "$ref": "#/$defs/_ConfigReportBrowser" }, "minItems": 1 }
896
+ ]
897
+ },
898
+ "discord": {
899
+ "anyOf": [
900
+ { "$ref": "#/$defs/_ConfigReportDiscord" },
901
+ { "type": "array", "items": { "$ref": "#/$defs/_ConfigReportDiscord" }, "minItems": 1 }
902
+ ]
903
+ },
904
+ "email": {
905
+ "anyOf": [
906
+ { "$ref": "#/$defs/_ConfigReportEmail" },
907
+ { "type": "array", "items": { "$ref": "#/$defs/_ConfigReportEmail" }, "minItems": 1 }
908
+ ]
909
+ },
910
+ "github_issue": {
911
+ "anyOf": [
912
+ { "$ref": "#/$defs/_ConfigReportGithubIssue" },
913
+ { "type": "array", "items": { "$ref": "#/$defs/_ConfigReportGithubIssue" }, "minItems": 1 }
914
+ ]
915
+ },
916
+ "gotify": {
917
+ "anyOf": [
918
+ { "$ref": "#/$defs/_ConfigReportGotify" },
919
+ { "type": "array", "items": { "$ref": "#/$defs/_ConfigReportGotify" }, "minItems": 1 }
920
+ ]
921
+ },
922
+ "ifttt": {
923
+ "anyOf": [
924
+ { "$ref": "#/$defs/_ConfigReportIfttt" },
925
+ { "type": "array", "items": { "$ref": "#/$defs/_ConfigReportIfttt" }, "minItems": 1 }
926
+ ]
927
+ },
928
+ "mailgun": {
929
+ "anyOf": [
930
+ { "$ref": "#/$defs/_ConfigReportMailgun" },
931
+ { "type": "array", "items": { "$ref": "#/$defs/_ConfigReportMailgun" }, "minItems": 1 }
932
+ ]
933
+ },
934
+ "matrix": {
935
+ "anyOf": [
936
+ { "$ref": "#/$defs/_ConfigReportMatrix" },
937
+ { "type": "array", "items": { "$ref": "#/$defs/_ConfigReportMatrix" }, "minItems": 1 }
938
+ ]
939
+ },
940
+ "ntfy": {
941
+ "anyOf": [
942
+ { "$ref": "#/$defs/_ConfigReportNtfy" },
943
+ { "type": "array", "items": { "$ref": "#/$defs/_ConfigReportNtfy" }, "minItems": 1 }
944
+ ]
945
+ },
946
+ "prowl": {
947
+ "anyOf": [
948
+ { "$ref": "#/$defs/_ConfigReportProwl" },
949
+ { "type": "array", "items": { "$ref": "#/$defs/_ConfigReportProwl" }, "minItems": 1 }
950
+ ]
951
+ },
952
+ "pushbullet": {
953
+ "anyOf": [
954
+ { "$ref": "#/$defs/_ConfigReportPushbullet" },
955
+ { "type": "array", "items": { "$ref": "#/$defs/_ConfigReportPushbullet" }, "minItems": 1 }
956
+ ]
957
+ },
958
+ "pushover": {
959
+ "anyOf": [
960
+ { "$ref": "#/$defs/_ConfigReportPushover" },
961
+ { "type": "array", "items": { "$ref": "#/$defs/_ConfigReportPushover" }, "minItems": 1 }
962
+ ]
963
+ },
964
+ "run_command": {
965
+ "anyOf": [
966
+ { "$ref": "#/$defs/_ConfigReportRunCommand" },
967
+ { "type": "array", "items": { "$ref": "#/$defs/_ConfigReportRunCommand" }, "minItems": 1 }
968
+ ]
969
+ },
970
+ "telegram": {
971
+ "anyOf": [
972
+ { "$ref": "#/$defs/_ConfigReportTelegram" },
973
+ { "type": "array", "items": { "$ref": "#/$defs/_ConfigReportTelegram" }, "minItems": 1 }
974
+ ]
975
+ },
976
+ "webhook": {
977
+ "anyOf": [
978
+ { "$ref": "#/$defs/_ConfigReportWebhook" },
979
+ { "type": "array", "items": { "$ref": "#/$defs/_ConfigReportWebhook" }, "minItems": 1 }
980
+ ]
981
+ },
982
+ "xmpp": {
983
+ "anyOf": [
984
+ { "$ref": "#/$defs/_ConfigReportXmpp" },
985
+ { "type": "array", "items": { "$ref": "#/$defs/_ConfigReportXmpp" }, "minItems": 1 }
986
+ ]
987
+ }
849
988
  }
850
989
  },
851
990
  "_ConfigJobDefaults": {
852
991
  "title": "Job defaults",
853
- "description": "Default directives applied to jobs by kind. All keys are optional; any directive set under 'url', 'browser', or 'command' overrides the same directive set under 'all' (the 'headers' directive merges header-by-header).",
992
+ "description": "Default directives applied to jobs by kind. All keys are optional; any directive set under 'url_jobs', 'browser_jobs', or 'command_jobs' overrides the same directive set under 'all_jobs' (the 'headers' directive merges header-by-header).",
854
993
  "type": "object",
855
994
  "properties": {
856
995
  "_note": {
857
996
  "type": "string",
858
997
  "description": "Free-form note (ignored by webchanges; keys starting with '_' are not interpreted)."
859
998
  },
860
- "all": {
999
+ "all_jobs": {
861
1000
  "type": "object",
862
1001
  "description": "Directives applied to every job, including those defined in hooks.py."
863
1002
  },
864
- "url": {
1003
+ "url_jobs": {
865
1004
  "type": "object",
866
1005
  "description": "Directives applied to 'url' jobs without 'use_browser'."
867
1006
  },
868
- "browser": {
1007
+ "browser_jobs": {
869
1008
  "type": "object",
870
1009
  "description": "Directives applied to 'url' jobs with 'use_browser: true'."
871
1010
  },
872
- "command": {
1011
+ "command_jobs": {
873
1012
  "type": "object",
874
1013
  "description": "Directives applied to 'command' jobs."
1014
+ },
1015
+ "all": {
1016
+ "type": "object",
1017
+ "description": "Deprecated; renamed 'all_jobs'.",
1018
+ "deprecated": true
1019
+ },
1020
+ "url": {
1021
+ "type": "object",
1022
+ "description": "Deprecated; renamed 'url_jobs'.",
1023
+ "deprecated": true
1024
+ },
1025
+ "browser": {
1026
+ "type": "object",
1027
+ "description": "Deprecated; renamed 'browser_jobs'.",
1028
+ "deprecated": true
1029
+ },
1030
+ "command": {
1031
+ "type": "object",
1032
+ "description": "Deprecated; renamed 'command_jobs'.",
1033
+ "deprecated": true
1034
+ },
1035
+ "shell": {
1036
+ "type": "object",
1037
+ "description": "Deprecated; renamed 'command_jobs'.",
1038
+ "deprecated": true
875
1039
  }
876
1040
  }
877
1041
  },