File size: 5,045 Bytes
046723b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# Responsible for building the storage dict into a set of rules ("JSON Schema") acceptable via the API
# Probably other ways to solve this when the backend switches to some ORM
from changedetectionio.notification import valid_notification_formats


def build_time_between_check_json_schema():
    # Setup time between check schema
    schema_properties_time_between_check = {
        "type": "object",
        "additionalProperties": False,
        "properties": {}
    }
    for p in ['weeks', 'days', 'hours', 'minutes', 'seconds']:
        schema_properties_time_between_check['properties'][p] = {
            "anyOf": [
                {
                    "type": "integer"
                },
                {
                    "type": "null"
                }
            ]
        }

    return schema_properties_time_between_check

def build_watch_json_schema(d):
    # Base JSON schema
    schema = {
        'type': 'object',
        'properties': {},
    }

    for k, v in d.items():
        # @todo 'integer' is not covered here because its almost always for internal usage

        if isinstance(v, type(None)):
            schema['properties'][k] = {
                "anyOf": [
                    {"type": "null"},
                ]
            }
        elif isinstance(v, list):
            schema['properties'][k] = {
                "anyOf": [
                    {"type": "array",
                     # Always is an array of strings, like text or regex or something
                     "items": {
                         "type": "string",
                         "maxLength": 5000
                     }
                     },
                ]
            }
        elif isinstance(v, bool):
            schema['properties'][k] = {
                "anyOf": [
                    {"type": "boolean"},
                ]
            }
        elif isinstance(v, str):
            schema['properties'][k] = {
                "anyOf": [
                    {"type": "string",
                     "maxLength": 5000},
                ]
            }

    # Can also be a string (or None by default above)
    for v in ['body',
              'notification_body',
              'notification_format',
              'notification_title',
              'proxy',
              'tag',
              'title',
              'webdriver_js_execute_code'
              ]:
        schema['properties'][v]['anyOf'].append({'type': 'string', "maxLength": 5000})

    # None or Boolean
    schema['properties']['track_ldjson_price_data']['anyOf'].append({'type': 'boolean'})

    schema['properties']['method'] = {"type": "string",
                                      "enum": ["GET", "POST", "DELETE", "PUT"]
                                      }

    schema['properties']['fetch_backend']['anyOf'].append({"type": "string",
                                                           "enum": ["html_requests", "html_webdriver"]
                                                           })



    # All headers must be key/value type dict
    schema['properties']['headers'] = {
        "type": "object",
        "patternProperties": {
            # Should always be a string:string type value
            ".*": {"type": "string"},
        }
    }

    schema['properties']['notification_format'] = {'type': 'string',
                                                   'enum': list(valid_notification_formats.keys())
                                                   }

    # Stuff that shouldn't be available but is just state-storage
    for v in ['previous_md5', 'last_error', 'has_ldjson_price_data', 'previous_md5_before_filters', 'uuid']:
        del schema['properties'][v]

    schema['properties']['webdriver_delay']['anyOf'].append({'type': 'integer'})

    schema['properties']['time_between_check'] = build_time_between_check_json_schema()

    schema['properties']['browser_steps'] = {
        "anyOf": [
            {
                "type": "array",
                "items": {
                    "type": "object",
                    "properties": {
                        "operation": {
                            "type": ["string", "null"],
                            "maxLength": 5000  # Allows null and any string up to 5000 chars (including "")
                        },
                        "selector": {
                            "type": ["string", "null"],
                            "maxLength": 5000
                        },
                        "optional_value": {
                            "type": ["string", "null"],
                            "maxLength": 5000
                        }
                    },
                    "required": ["operation", "selector", "optional_value"],
                    "additionalProperties": False  # No extra keys allowed
                }
            },
            {"type": "null"},  # Allows null for `browser_steps`
            {"type": "array", "maxItems": 0}  # Allows empty array []
        ]
    }

    # headers ?
    return schema