mirror of
https://github.com/dgtlmoon/changedetection.io.git
synced 2025-12-21 15:35:46 +00:00
Compare commits
3 Commits
OpenAPI-va
...
API-OpenAP
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0ab1ab6be | ||
|
|
f4f716fffa | ||
|
|
6e6136aaa7 |
4
.github/workflows/test-only.yml
vendored
4
.github/workflows/test-only.yml
vendored
@@ -15,10 +15,6 @@ jobs:
|
||||
ruff check . --select E9,F63,F7,F82
|
||||
# Complete check with errors treated as warnings
|
||||
ruff check . --exit-zero
|
||||
- name: Validate OpenAPI spec
|
||||
run: |
|
||||
pip install openapi-spec-validator
|
||||
python3 -c "from openapi_spec_validator import validate_spec; import yaml; validate_spec(yaml.safe_load(open('docs/api-spec.yaml')))"
|
||||
|
||||
test-application-3-10:
|
||||
needs: lint-code
|
||||
|
||||
@@ -3,7 +3,7 @@ from changedetectionio.strtobool import strtobool
|
||||
from flask_restful import abort, Resource
|
||||
from flask import request
|
||||
import validators
|
||||
from . import auth, validate_openapi_request
|
||||
from . import auth
|
||||
|
||||
|
||||
class Import(Resource):
|
||||
@@ -12,7 +12,6 @@ class Import(Resource):
|
||||
self.datastore = kwargs['datastore']
|
||||
|
||||
@auth.check_token
|
||||
@validate_openapi_request('importWatches')
|
||||
def post(self):
|
||||
"""Import a list of watched URLs."""
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
from flask_expects_json import expects_json
|
||||
from flask_restful import Resource, abort
|
||||
from flask_restful import Resource
|
||||
from . import auth
|
||||
from flask_restful import abort, Resource
|
||||
from flask import request
|
||||
from . import auth, validate_openapi_request
|
||||
from . import auth
|
||||
from . import schema_create_notification_urls, schema_delete_notification_urls
|
||||
|
||||
class Notifications(Resource):
|
||||
@@ -10,7 +12,6 @@ class Notifications(Resource):
|
||||
self.datastore = kwargs['datastore']
|
||||
|
||||
@auth.check_token
|
||||
@validate_openapi_request('getNotifications')
|
||||
def get(self):
|
||||
"""Return Notification URL List."""
|
||||
|
||||
@@ -21,7 +22,6 @@ class Notifications(Resource):
|
||||
}, 200
|
||||
|
||||
@auth.check_token
|
||||
@validate_openapi_request('addNotifications')
|
||||
@expects_json(schema_create_notification_urls)
|
||||
def post(self):
|
||||
"""Create Notification URLs."""
|
||||
@@ -49,7 +49,6 @@ class Notifications(Resource):
|
||||
return {'notification_urls': added_urls}, 201
|
||||
|
||||
@auth.check_token
|
||||
@validate_openapi_request('replaceNotifications')
|
||||
@expects_json(schema_create_notification_urls)
|
||||
def put(self):
|
||||
"""Replace Notification URLs."""
|
||||
@@ -72,7 +71,6 @@ class Notifications(Resource):
|
||||
return {'notification_urls': clean_urls}, 200
|
||||
|
||||
@auth.check_token
|
||||
@validate_openapi_request('deleteNotifications')
|
||||
@expects_json(schema_delete_notification_urls)
|
||||
def delete(self):
|
||||
"""Delete Notification URLs."""
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from flask_restful import Resource, abort
|
||||
from flask import request
|
||||
from . import auth, validate_openapi_request
|
||||
from . import auth
|
||||
|
||||
class Search(Resource):
|
||||
def __init__(self, **kwargs):
|
||||
@@ -8,7 +8,6 @@ class Search(Resource):
|
||||
self.datastore = kwargs['datastore']
|
||||
|
||||
@auth.check_token
|
||||
@validate_openapi_request('searchWatches')
|
||||
def get(self):
|
||||
"""Search for watches by URL or title text."""
|
||||
query = request.args.get('q', '').strip()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from flask_restful import Resource
|
||||
from . import auth, validate_openapi_request
|
||||
from . import auth
|
||||
|
||||
|
||||
class SystemInfo(Resource):
|
||||
@@ -9,7 +9,6 @@ class SystemInfo(Resource):
|
||||
self.update_q = kwargs['update_q']
|
||||
|
||||
@auth.check_token
|
||||
@validate_openapi_request('getSystemInfo')
|
||||
def get(self):
|
||||
"""Return system info."""
|
||||
import time
|
||||
|
||||
@@ -7,7 +7,7 @@ from flask import request
|
||||
from . import auth
|
||||
|
||||
# Import schemas from __init__.py
|
||||
from . import schema_tag, schema_create_tag, schema_update_tag, validate_openapi_request
|
||||
from . import schema_tag, schema_create_tag, schema_update_tag
|
||||
|
||||
|
||||
class Tag(Resource):
|
||||
@@ -19,7 +19,6 @@ class Tag(Resource):
|
||||
# Get information about a single tag
|
||||
# curl http://localhost:5000/api/v1/tag/<string:uuid>
|
||||
@auth.check_token
|
||||
@validate_openapi_request('getTag')
|
||||
def get(self, uuid):
|
||||
"""Get data for a single tag/group, toggle notification muting, or recheck all."""
|
||||
from copy import deepcopy
|
||||
@@ -51,7 +50,6 @@ class Tag(Resource):
|
||||
return tag
|
||||
|
||||
@auth.check_token
|
||||
@validate_openapi_request('deleteTag')
|
||||
def delete(self, uuid):
|
||||
"""Delete a tag/group and remove it from all watches."""
|
||||
if not self.datastore.data['settings']['application']['tags'].get(uuid):
|
||||
@@ -68,7 +66,6 @@ class Tag(Resource):
|
||||
return 'OK', 204
|
||||
|
||||
@auth.check_token
|
||||
@validate_openapi_request('updateTag')
|
||||
@expects_json(schema_update_tag)
|
||||
def put(self, uuid):
|
||||
"""Update tag information."""
|
||||
@@ -83,7 +80,6 @@ class Tag(Resource):
|
||||
|
||||
|
||||
@auth.check_token
|
||||
@validate_openapi_request('createTag')
|
||||
# Only cares for {'title': 'xxxx'}
|
||||
def post(self):
|
||||
"""Create a single tag/group."""
|
||||
@@ -104,7 +100,6 @@ class Tags(Resource):
|
||||
self.datastore = kwargs['datastore']
|
||||
|
||||
@auth.check_token
|
||||
@validate_openapi_request('listTags')
|
||||
def get(self):
|
||||
"""List tags/groups."""
|
||||
result = {}
|
||||
|
||||
@@ -11,7 +11,7 @@ from . import auth
|
||||
import copy
|
||||
|
||||
# Import schemas from __init__.py
|
||||
from . import schema, schema_create_watch, schema_update_watch, validate_openapi_request
|
||||
from . import schema, schema_create_watch, schema_update_watch
|
||||
|
||||
|
||||
class Watch(Resource):
|
||||
@@ -25,7 +25,6 @@ class Watch(Resource):
|
||||
# @todo - version2 - ?muted and ?paused should be able to be called together, return the watch struct not "OK"
|
||||
# ?recheck=true
|
||||
@auth.check_token
|
||||
@validate_openapi_request('getWatch')
|
||||
def get(self, uuid):
|
||||
"""Get information about a single watch, recheck, pause, or mute."""
|
||||
from copy import deepcopy
|
||||
@@ -58,7 +57,6 @@ class Watch(Resource):
|
||||
return watch
|
||||
|
||||
@auth.check_token
|
||||
@validate_openapi_request('deleteWatch')
|
||||
def delete(self, uuid):
|
||||
"""Delete a watch and related history."""
|
||||
if not self.datastore.data['watching'].get(uuid):
|
||||
@@ -68,7 +66,6 @@ class Watch(Resource):
|
||||
return 'OK', 204
|
||||
|
||||
@auth.check_token
|
||||
@validate_openapi_request('updateWatch')
|
||||
@expects_json(schema_update_watch)
|
||||
def put(self, uuid):
|
||||
"""Update watch information."""
|
||||
@@ -94,7 +91,6 @@ class WatchHistory(Resource):
|
||||
# Get a list of available history for a watch by UUID
|
||||
# curl http://localhost:5000/api/v1/watch/<string:uuid>/history
|
||||
@auth.check_token
|
||||
@validate_openapi_request('getWatchHistory')
|
||||
def get(self, uuid):
|
||||
"""Get a list of all historical snapshots available for a watch."""
|
||||
watch = self.datastore.data['watching'].get(uuid)
|
||||
@@ -109,7 +105,6 @@ class WatchSingleHistory(Resource):
|
||||
self.datastore = kwargs['datastore']
|
||||
|
||||
@auth.check_token
|
||||
@validate_openapi_request('getWatchSnapshot')
|
||||
def get(self, uuid, timestamp):
|
||||
"""Get single snapshot from watch."""
|
||||
watch = self.datastore.data['watching'].get(uuid)
|
||||
@@ -143,7 +138,6 @@ class WatchFavicon(Resource):
|
||||
self.datastore = kwargs['datastore']
|
||||
|
||||
@auth.check_token
|
||||
@validate_openapi_request('getWatchFavicon')
|
||||
def get(self, uuid):
|
||||
"""Get favicon for a watch."""
|
||||
watch = self.datastore.data['watching'].get(uuid)
|
||||
@@ -178,7 +172,6 @@ class CreateWatch(Resource):
|
||||
self.update_q = kwargs['update_q']
|
||||
|
||||
@auth.check_token
|
||||
@validate_openapi_request('createWatch')
|
||||
@expects_json(schema_create_watch)
|
||||
def post(self):
|
||||
"""Create a single watch."""
|
||||
@@ -214,7 +207,6 @@ class CreateWatch(Resource):
|
||||
return "Invalid or unsupported URL", 400
|
||||
|
||||
@auth.check_token
|
||||
@validate_openapi_request('listWatches')
|
||||
def get(self):
|
||||
"""List watches."""
|
||||
list = {}
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
import copy
|
||||
import yaml
|
||||
import functools
|
||||
from flask import request, abort
|
||||
from openapi_core import OpenAPI
|
||||
from openapi_core.contrib.flask import FlaskOpenAPIRequest
|
||||
from . import api_schema
|
||||
from ..model import watch_base
|
||||
|
||||
@@ -30,38 +25,6 @@ schema_create_notification_urls['required'] = ['notification_urls']
|
||||
schema_delete_notification_urls = copy.deepcopy(schema_notification_urls)
|
||||
schema_delete_notification_urls['required'] = ['notification_urls']
|
||||
|
||||
# Load OpenAPI spec for validation
|
||||
_openapi_spec = None
|
||||
|
||||
def get_openapi_spec():
|
||||
global _openapi_spec
|
||||
if _openapi_spec is None:
|
||||
import os
|
||||
spec_path = os.path.join(os.path.dirname(__file__), '../../docs/api-spec.yaml')
|
||||
with open(spec_path, 'r') as f:
|
||||
spec_dict = yaml.safe_load(f)
|
||||
_openapi_spec = OpenAPI.from_dict(spec_dict)
|
||||
return _openapi_spec
|
||||
|
||||
def validate_openapi_request(operation_id):
|
||||
"""Decorator to validate incoming requests against OpenAPI spec."""
|
||||
def decorator(f):
|
||||
@functools.wraps(f)
|
||||
def wrapper(*args, **kwargs):
|
||||
try:
|
||||
spec = get_openapi_spec()
|
||||
openapi_request = FlaskOpenAPIRequest(request)
|
||||
result = spec.unmarshal_request(openapi_request, operation_id)
|
||||
if result.errors:
|
||||
abort(400, message=f"OpenAPI validation failed: {result.errors}")
|
||||
return f(*args, **kwargs)
|
||||
except Exception as e:
|
||||
# If OpenAPI validation fails, log but don't break existing functionality
|
||||
print(f"OpenAPI validation warning for {operation_id}: {e}")
|
||||
return f(*args, **kwargs)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
# Import all API resources
|
||||
from .Watch import Watch, WatchHistory, WatchSingleHistory, CreateWatch, WatchFavicon
|
||||
from .Tags import Tags, Tag
|
||||
|
||||
@@ -203,7 +203,7 @@ nav
|
||||
|
||||
<div class="tab-pane-inner" id="api">
|
||||
<h4>API Access</h4>
|
||||
<p>Drive your changedetection.io via API, More about <a href="https://changedetection.io/docs/api_v1/index.html">API access and examples here</a>.</p>
|
||||
<p>Drive your changedetection.io via API, More about <a href="https://github.com/dgtlmoon/changedetection.io/wiki/API-Reference">API access here</a></p>
|
||||
|
||||
<div class="pure-control-group">
|
||||
{{ render_checkbox_field(form.application.form.api_access_token_enabled) }}
|
||||
|
||||
@@ -28,7 +28,7 @@ info:
|
||||
|
||||
For example: `x-api-key: YOUR_API_KEY`
|
||||
|
||||
version: 0.1.0
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: ChangeDetection.io
|
||||
url: https://github.com/dgtlmoon/changedetection.io
|
||||
@@ -89,8 +89,6 @@ tags:
|
||||
Configure global notification endpoints that can be used across all your watches. Supports various
|
||||
notification services including email, Discord, Slack, webhooks, and many other popular platforms.
|
||||
These settings serve as defaults that can be overridden at the individual watch or tag level.
|
||||
|
||||
The notification syntax uses [https://github.com/caronc/apprise](https://github.com/caronc/apprise).
|
||||
|
||||
- name: Search
|
||||
description: |
|
||||
@@ -125,7 +123,7 @@ components:
|
||||
uuid:
|
||||
type: string
|
||||
format: uuid
|
||||
description: Unique identifier for the web page change monitor (watch)
|
||||
description: Unique identifier for the watch
|
||||
readOnly: true
|
||||
url:
|
||||
type: string
|
||||
@@ -134,11 +132,11 @@ components:
|
||||
maxLength: 5000
|
||||
title:
|
||||
type: string
|
||||
description: Custom title for the web page change monitor (watch)
|
||||
description: Custom title for the watch
|
||||
maxLength: 5000
|
||||
tag:
|
||||
type: string
|
||||
description: Tag UUID to associate with this web page change monitor (watch)
|
||||
description: Tag UUID to associate with this watch
|
||||
maxLength: 5000
|
||||
tags:
|
||||
type: array
|
||||
@@ -147,7 +145,7 @@ components:
|
||||
description: Array of tag UUIDs
|
||||
paused:
|
||||
type: boolean
|
||||
description: Whether the web page change monitor (watch) is paused
|
||||
description: Whether the watch is paused
|
||||
muted:
|
||||
type: boolean
|
||||
description: Whether notifications are muted
|
||||
@@ -197,7 +195,7 @@ components:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Notification URLs for this web page change monitor (watch)
|
||||
description: Notification URLs for this watch
|
||||
notification_title:
|
||||
type: string
|
||||
description: Custom notification title
|
||||
@@ -267,7 +265,7 @@ components:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Default notification URLs for web page change monitors (watches) with this tag
|
||||
description: Default notification URLs for watches with this tag
|
||||
notification_muted:
|
||||
type: boolean
|
||||
description: Whether notifications are muted for this tag
|
||||
@@ -291,7 +289,7 @@ components:
|
||||
properties:
|
||||
watch_count:
|
||||
type: integer
|
||||
description: Total number of web page change monitors (watches)
|
||||
description: Total number of watches
|
||||
tag_count:
|
||||
type: integer
|
||||
description: Total number of tags
|
||||
@@ -309,7 +307,7 @@ components:
|
||||
type: object
|
||||
additionalProperties:
|
||||
$ref: '#/components/schemas/Watch'
|
||||
description: Dictionary of matching web page change monitors (watches) keyed by UUID
|
||||
description: Dictionary of matching watches keyed by UUID
|
||||
|
||||
WatchHistory:
|
||||
type: object
|
||||
@@ -328,10 +326,9 @@ components:
|
||||
paths:
|
||||
/watch:
|
||||
get:
|
||||
operationId: listWatches
|
||||
tags: [Watch Management]
|
||||
summary: List all watches
|
||||
description: Return concise list of available web page change monitors (watches) and basic info
|
||||
description: Return concise list of available watches and basic info
|
||||
x-code-samples:
|
||||
- lang: 'curl'
|
||||
source: |
|
||||
@@ -391,10 +388,9 @@ paths:
|
||||
last_checked: 1640998800
|
||||
last_changed: 1640995200
|
||||
post:
|
||||
operationId: createWatch
|
||||
tags: [Watch Management]
|
||||
summary: Create a new watch
|
||||
description: Create a single web page change monitor (watch). Requires at least 'url' to be set.
|
||||
description: Create a single watch. Requires at least 'url' to be set.
|
||||
x-code-samples:
|
||||
- lang: 'curl'
|
||||
source: |
|
||||
@@ -440,7 +436,7 @@ paths:
|
||||
hours: 1
|
||||
responses:
|
||||
'200':
|
||||
description: Web page change monitor (watch) created successfully
|
||||
description: Watch created successfully
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
@@ -455,10 +451,10 @@ paths:
|
||||
|
||||
/watch/{uuid}:
|
||||
get:
|
||||
operationId: getWatch
|
||||
operationId: getSingleWatch
|
||||
tags: [Watch Management]
|
||||
summary: Get single watch
|
||||
description: Retrieve web page change monitor (watch) information and set muted/paused status. Returns the FULL Watch JSON.
|
||||
description: Retrieve watch information and set muted/paused status. Returns the FULL Watch JSON.
|
||||
x-code-samples:
|
||||
- lang: 'curl'
|
||||
source: |
|
||||
@@ -476,13 +472,13 @@ paths:
|
||||
- name: uuid
|
||||
in: path
|
||||
required: true
|
||||
description: Web page change monitor (watch) unique ID
|
||||
description: Watch unique ID
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- name: recheck
|
||||
in: query
|
||||
description: Recheck this web page change monitor (watch)
|
||||
description: Recheck this watch
|
||||
schema:
|
||||
type: string
|
||||
enum: ["1", "true"]
|
||||
@@ -510,7 +506,7 @@ paths:
|
||||
type: string
|
||||
example: "OK"
|
||||
'404':
|
||||
description: Web page change monitor (watch) not found
|
||||
description: Watch not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
@@ -520,7 +516,7 @@ paths:
|
||||
operationId: updateWatch
|
||||
tags: [Watch Management]
|
||||
summary: Update watch
|
||||
description: Update an existing web page change monitor (watch) using JSON. Accepts the same structure as returned in [get single watch information](#operation/getWatch).
|
||||
description: Update an existing watch using JSON. Accepts the same structure as returned in [get single watch information](#operation/getSingleWatch).
|
||||
x-code-samples:
|
||||
- lang: 'curl'
|
||||
source: |
|
||||
@@ -553,7 +549,7 @@ paths:
|
||||
- name: uuid
|
||||
in: path
|
||||
required: true
|
||||
description: Web page change monitor (watch) unique ID
|
||||
description: Watch unique ID
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
@@ -565,7 +561,7 @@ paths:
|
||||
$ref: '#/components/schemas/Watch'
|
||||
responses:
|
||||
'200':
|
||||
description: Web page change monitor (watch) updated successfully
|
||||
description: Watch updated successfully
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
@@ -575,10 +571,9 @@ paths:
|
||||
description: Server error
|
||||
|
||||
delete:
|
||||
operationId: deleteWatch
|
||||
tags: [Watch Management]
|
||||
summary: Delete watch
|
||||
description: Delete a web page change monitor (watch) and all related history
|
||||
description: Delete a watch and all related history
|
||||
x-code-samples:
|
||||
- lang: 'curl'
|
||||
source: |
|
||||
@@ -596,13 +591,13 @@ paths:
|
||||
- name: uuid
|
||||
in: path
|
||||
required: true
|
||||
description: Web page change monitor (watch) unique ID
|
||||
description: Watch unique ID
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
'200':
|
||||
description: Web page change monitor (watch) deleted successfully
|
||||
description: Watch deleted successfully
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
@@ -611,10 +606,9 @@ paths:
|
||||
|
||||
/watch/{uuid}/history:
|
||||
get:
|
||||
operationId: getWatchHistory
|
||||
tags: [Watch History]
|
||||
summary: Get watch history
|
||||
description: Get a list of all historical snapshots available for a web page change monitor (watch)
|
||||
description: Get a list of all historical snapshots available for a watch
|
||||
x-code-samples:
|
||||
- lang: 'curl'
|
||||
source: |
|
||||
@@ -632,7 +626,7 @@ paths:
|
||||
- name: uuid
|
||||
in: path
|
||||
required: true
|
||||
description: Web page change monitor (watch) unique ID
|
||||
description: Watch unique ID
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
@@ -647,14 +641,13 @@ paths:
|
||||
"1640995200": "/path/to/snapshot1.txt"
|
||||
"1640998800": "/path/to/snapshot2.txt"
|
||||
'404':
|
||||
description: Web page change monitor (watch) not found
|
||||
description: Watch not found
|
||||
|
||||
/watch/{uuid}/history/{timestamp}:
|
||||
get:
|
||||
operationId: getWatchSnapshot
|
||||
tags: [Snapshots]
|
||||
summary: Get single snapshot
|
||||
description: Get single snapshot from web page change monitor (watch). Use 'latest' for the most recent snapshot.
|
||||
description: Get single snapshot from watch. Use 'latest' for the most recent snapshot.
|
||||
x-code-samples:
|
||||
- lang: 'curl'
|
||||
source: |
|
||||
@@ -673,7 +666,7 @@ paths:
|
||||
- name: uuid
|
||||
in: path
|
||||
required: true
|
||||
description: Web page change monitor (watch) unique ID
|
||||
description: Watch unique ID
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
@@ -704,10 +697,9 @@ paths:
|
||||
|
||||
/watch/{uuid}/favicon:
|
||||
get:
|
||||
operationId: getWatchFavicon
|
||||
tags: [Favicon]
|
||||
summary: Get watch favicon
|
||||
description: Get the favicon for a web page change monitor (watch) as displayed in the watch overview list.
|
||||
description: Get the favicon for a watch as displayed in the watch overview list.
|
||||
x-code-samples:
|
||||
- lang: 'curl'
|
||||
source: |
|
||||
@@ -727,7 +719,7 @@ paths:
|
||||
- name: uuid
|
||||
in: path
|
||||
required: true
|
||||
description: Web page change monitor (watch) unique ID
|
||||
description: Watch unique ID
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
@@ -744,7 +736,6 @@ paths:
|
||||
|
||||
/tags:
|
||||
get:
|
||||
operationId: listTags
|
||||
tags: [Group / Tag Management]
|
||||
summary: List all tags
|
||||
description: Return list of available tags/groups
|
||||
@@ -781,62 +772,11 @@ paths:
|
||||
notification_urls: ["discord://webhook_id/webhook_token"]
|
||||
notification_muted: false
|
||||
|
||||
/tag:
|
||||
post:
|
||||
operationId: createTag
|
||||
tags: [Group / Tag Management]
|
||||
summary: Create tag
|
||||
description: Create a single tag/group
|
||||
x-code-samples:
|
||||
- lang: 'curl'
|
||||
source: |
|
||||
curl -X POST "http://localhost:5000/api/v1/tag" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"title": "Important Sites"
|
||||
}'
|
||||
- lang: 'Python'
|
||||
source: |
|
||||
import requests
|
||||
|
||||
headers = {
|
||||
'x-api-key': 'YOUR_API_KEY',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
data = {'title': 'Important Sites'}
|
||||
response = requests.post('http://localhost:5000/api/v1/tag',
|
||||
headers=headers, json=data)
|
||||
print(response.json())
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Tag'
|
||||
example:
|
||||
title: "Important Sites"
|
||||
responses:
|
||||
'201':
|
||||
description: Tag created successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
uuid:
|
||||
type: string
|
||||
format: uuid
|
||||
description: UUID of the created tag
|
||||
'400':
|
||||
description: Invalid or unsupported tag
|
||||
|
||||
/tag/{uuid}:
|
||||
get:
|
||||
operationId: getTag
|
||||
tags: [Group / Tag Management]
|
||||
summary: Get single tag
|
||||
description: Retrieve tag information, set notification_muted status, recheck all web page change monitors (watches) in tag.
|
||||
description: Retrieve tag information, set notification_muted status, recheck all in tag.
|
||||
x-code-samples:
|
||||
- lang: 'curl'
|
||||
source: |
|
||||
@@ -866,7 +806,7 @@ paths:
|
||||
enum: [muted, unmuted]
|
||||
- name: recheck
|
||||
in: query
|
||||
description: Queue all web page change monitors (watches) with this tag for recheck
|
||||
description: Queue all watches with this tag for recheck
|
||||
schema:
|
||||
type: string
|
||||
enum: ["true"]
|
||||
@@ -885,7 +825,6 @@ paths:
|
||||
description: Tag not found
|
||||
|
||||
put:
|
||||
operationId: updateTag
|
||||
tags: [Group / Tag Management]
|
||||
summary: Update tag
|
||||
description: Update an existing tag using JSON
|
||||
@@ -936,10 +875,9 @@ paths:
|
||||
description: Server error
|
||||
|
||||
delete:
|
||||
operationId: deleteTag
|
||||
tags: [Group / Tag Management]
|
||||
summary: Delete tag
|
||||
description: Delete a tag/group and remove it from all web page change monitors (watches)
|
||||
description: Delete a tag/group and remove it from all watches
|
||||
x-code-samples:
|
||||
- lang: 'curl'
|
||||
source: |
|
||||
@@ -965,10 +903,48 @@ paths:
|
||||
'200':
|
||||
description: Tag deleted successfully
|
||||
|
||||
post:
|
||||
tags: [Group / Tag Management]
|
||||
summary: Create tag
|
||||
description: Create a single tag/group
|
||||
x-code-samples:
|
||||
- lang: 'curl'
|
||||
source: |
|
||||
curl -X POST "http://localhost:5000/api/v1/tag/550e8400-e29b-41d4-a716-446655440000" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"title": "Important Sites"
|
||||
}'
|
||||
- lang: 'Python'
|
||||
source: |
|
||||
import requests
|
||||
|
||||
headers = {
|
||||
'x-api-key': 'YOUR_API_KEY',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
tag_uuid = '550e8400-e29b-41d4-a716-446655440000'
|
||||
data = {'title': 'Important Sites'}
|
||||
response = requests.post(f'http://localhost:5000/api/v1/tag/{tag_uuid}',
|
||||
headers=headers, json=data)
|
||||
print(response.text)
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Tag'
|
||||
example:
|
||||
title: "Important Sites"
|
||||
responses:
|
||||
'200':
|
||||
description: Tag created successfully
|
||||
'500':
|
||||
description: Server error
|
||||
|
||||
/notifications:
|
||||
get:
|
||||
operationId: getNotifications
|
||||
tags: [Notifications]
|
||||
summary: Get notification URLs
|
||||
description: Return the notification URL list from the configuration
|
||||
@@ -993,7 +969,6 @@ paths:
|
||||
$ref: '#/components/schemas/NotificationUrls'
|
||||
|
||||
post:
|
||||
operationId: addNotifications
|
||||
tags: [Notifications]
|
||||
summary: Add notification URLs
|
||||
description: Add one or more notification URLs to the configuration
|
||||
@@ -1047,7 +1022,6 @@ paths:
|
||||
description: Invalid input
|
||||
|
||||
put:
|
||||
operationId: replaceNotifications
|
||||
tags: [Notifications]
|
||||
summary: Replace notification URLs
|
||||
description: Replace all notification URLs with the provided list (can be empty)
|
||||
@@ -1095,7 +1069,6 @@ paths:
|
||||
description: Invalid input
|
||||
|
||||
delete:
|
||||
operationId: deleteNotifications
|
||||
tags: [Notifications]
|
||||
summary: Delete notification URLs
|
||||
description: Delete one or more notification URLs from the configuration
|
||||
@@ -1140,10 +1113,9 @@ paths:
|
||||
|
||||
/search:
|
||||
get:
|
||||
operationId: searchWatches
|
||||
tags: [Search]
|
||||
summary: Search watches
|
||||
description: Search web page change monitors (watches) by URL or title text
|
||||
description: Search watches by URL or title text
|
||||
x-code-samples:
|
||||
- lang: 'curl'
|
||||
source: |
|
||||
@@ -1195,7 +1167,6 @@ paths:
|
||||
|
||||
/import:
|
||||
post:
|
||||
operationId: importWatches
|
||||
tags: [Import]
|
||||
summary: Import watch URLs
|
||||
description: Import a list of URLs to monitor. Accepts line-separated URLs in request body.
|
||||
@@ -1221,17 +1192,17 @@ paths:
|
||||
parameters:
|
||||
- name: tag_uuids
|
||||
in: query
|
||||
description: Tag UUID to apply to imported web page change monitors (watches)
|
||||
description: Tag UUID to apply to imported watches
|
||||
schema:
|
||||
type: string
|
||||
- name: tag
|
||||
in: query
|
||||
description: Tag name to apply to imported web page change monitors (watches)
|
||||
description: Tag name to apply to imported watches
|
||||
schema:
|
||||
type: string
|
||||
- name: proxy
|
||||
in: query
|
||||
description: Proxy key to use for imported web page change monitors (watches)
|
||||
description: Proxy key to use for imported watches
|
||||
schema:
|
||||
type: string
|
||||
- name: dedupe
|
||||
@@ -1266,7 +1237,6 @@ paths:
|
||||
|
||||
/systeminfo:
|
||||
get:
|
||||
operationId: getSystemInfo
|
||||
tags: [System Information]
|
||||
summary: Get system information
|
||||
description: Return information about the current system state
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -89,9 +89,6 @@ pytest-flask ~=1.2
|
||||
# Anything 4.0 and up but not 5.0
|
||||
jsonschema ~= 4.0
|
||||
|
||||
# OpenAPI validation support
|
||||
openapi-core[flask] >= 0.19.0
|
||||
|
||||
|
||||
loguru
|
||||
|
||||
|
||||
Reference in New Issue
Block a user