calmlens 0.20.0 → 0.22.0
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.
- checksums.yaml +4 -4
- data/README.md +4 -1
- data/lib/calmlens/assets.rb +149 -110
- data/lib/calmlens/cdn.rb +197 -41
- data/lib/calmlens/error_codes.rb +100 -84
- data/lib/calmlens/errors.rb +11 -2
- data/lib/calmlens/events.rb +50 -1
- data/lib/calmlens/folders.rb +14 -9
- data/lib/calmlens/hash_lists.rb +29 -9
- data/lib/calmlens/internal.rb +9 -19
- data/lib/calmlens/lenses.rb +79 -6
- data/lib/calmlens/option_keys.rb +56 -26
- data/lib/calmlens/policies.rb +50 -18
- data/lib/calmlens/project_configuration.rb +113 -0
- data/lib/calmlens/resource.rb +24 -6
- data/lib/calmlens/server_client.rb +17 -6
- data/lib/calmlens/session.rb +29 -12
- data/lib/calmlens/testing/asset_filters.rb +39 -0
- data/lib/calmlens/testing/classification.rb +8 -2
- data/lib/calmlens/testing/fake_api.rb +950 -397
- data/lib/calmlens/testing/mock_decision.rb +6 -4
- data/lib/calmlens/testing/rsql.rb +245 -0
- data/lib/calmlens/testing/test_input_detections.rb +61 -0
- data/lib/calmlens/testing/test_input_scenario.rb +6 -2
- data/lib/calmlens/testing/test_inputs.rb +30 -10
- data/lib/calmlens/testing.rb +56 -15
- data/lib/calmlens/transform_rules.rb +1 -1
- data/lib/calmlens/upload_body.rb +85 -2
- data/lib/calmlens/upload_mime_types.rb +9 -1
- data/lib/calmlens/upload_tokens.rb +3 -3
- data/lib/calmlens/version.rb +1 -1
- data/lib/calmlens/webhooks.rb +58 -13
- data/lib/calmlens.rb +1 -0
- data/sig/calmlens.rbs +112 -13
- data/sig/error_codes.rbs +28 -20
- data/sig/qualifiers.rbs +2 -0
- data/sig/types.rbs +488 -190
- metadata +6 -2
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module CalmLens
|
|
4
|
+
# The project's upload presets: the rules for uploads made from browsers and apps. {#ensure}
|
|
5
|
+
# creates or replaces presets by `key`, for applications that declare theirs in code or
|
|
6
|
+
# configuration. Reach it through {ServerClient#upload_presets}.
|
|
7
|
+
class UploadPresets < Resource
|
|
8
|
+
# The prefix of this resource's operations in Internal::OPTION_KEYS.
|
|
9
|
+
OPERATIONS = 'uploadPresets'
|
|
10
|
+
|
|
11
|
+
# Lists one page of the project's upload presets, oldest first unless `sort` says otherwise.
|
|
12
|
+
# @option options [String] :cursor the previous page's `nextCursor`
|
|
13
|
+
# @option options [Integer] :page_size 1 to 100, default 50
|
|
14
|
+
# @option options [String] :sort `createdAt` and `id`, comma-separated, descending when prefixed
|
|
15
|
+
# with `-`; `createdAt` by default
|
|
16
|
+
# @return [Hash] a cursor page: items, nextCursor and hasMore.
|
|
17
|
+
def list(options = {})
|
|
18
|
+
call(options, __method__) do |api, request|
|
|
19
|
+
cursor_page(request('GET', project('upload-presets'), query: api, request_options: request), 'upload preset')
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Iterates every upload preset of the project, fetching pages as needed.
|
|
24
|
+
# @param options [Hash] the options of {#list}; `cursor` sets the starting position.
|
|
25
|
+
# @yieldparam upload_preset [Hash]
|
|
26
|
+
# @return [Enumerator, nil] an Enumerator when no block is given.
|
|
27
|
+
def each(options = {}, &block)
|
|
28
|
+
return enum_for(:each, options) unless block
|
|
29
|
+
|
|
30
|
+
each_item(options, __method__, method(:list), &block)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Creates each preset, or replaces it with the definition sent, by `key`. Fields left out take
|
|
34
|
+
# their defaults; an unchanged preset keeps its revision. Every preset is checked before any is
|
|
35
|
+
# saved. Send each preset's `revision` (0 for one that must not exist yet) to refuse a change
|
|
36
|
+
# made since with `upload-preset/revision-conflict`.
|
|
37
|
+
# @option options [Array<Hash>] :upload_presets `[{key:, name:, revision:, access:, enabled:, ...}]`,
|
|
38
|
+
# at most 50
|
|
39
|
+
# @return [Hash] `uploadPresets`: the stored presets, in the order sent.
|
|
40
|
+
def ensure(options)
|
|
41
|
+
call(options, __method__) do |api, request|
|
|
42
|
+
request('PUT', project('upload-presets'), body: api, request_options: request)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Deletes an upload preset. Browsers can no longer upload through it; assets already uploaded stay.
|
|
47
|
+
# @option options [String] :upload_preset_id
|
|
48
|
+
# @return [nil]
|
|
49
|
+
def delete(options)
|
|
50
|
+
call(options, __method__) do |api, request|
|
|
51
|
+
request('DELETE', "/upload-presets/#{Internal.segment(api['uploadPresetId'])}", request_options: request)
|
|
52
|
+
nil
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# The project's settings, with defaults filled in. {#update} replaces them: settings left out
|
|
58
|
+
# return to their defaults. Send the `revision` you read to refuse a change made since with
|
|
59
|
+
# `project-settings/revision-conflict`. Reach it through {ServerClient#project_settings}.
|
|
60
|
+
class ProjectSettings < Resource
|
|
61
|
+
# The prefix of this resource's operations in Internal::OPTION_KEYS.
|
|
62
|
+
OPERATIONS = 'projectSettings'
|
|
63
|
+
|
|
64
|
+
# @return [Hash] `projectId`, `revision` and `settings`.
|
|
65
|
+
def get(options = {})
|
|
66
|
+
call(options, __method__) { |_api, request| request('GET', project('settings'), request_options: request) }
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Replaces the project's settings; unchanged settings keep their revision. The project's policy
|
|
70
|
+
# and metadata fields have their own methods.
|
|
71
|
+
# @option options [Integer] :revision the revision you read
|
|
72
|
+
# @option options [Hash] :settings the complete settings
|
|
73
|
+
# @option options [Numeric] :search_indexing_budget_units needed when turning on
|
|
74
|
+
# `aiMediaSearchEnabled`: the most indexing units you accept for existing media
|
|
75
|
+
# @return [Hash] `projectId`, `revision` and `settings`.
|
|
76
|
+
def update(options)
|
|
77
|
+
call(options, __method__) { |api, request| request('PUT', project('settings'), body: api, request_options: request) }
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# The project's metadata fields, in display order. They share the project settings' `revision`;
|
|
82
|
+
# {#ensure} creates or replaces fields by ID and keeps the others. Reach it through
|
|
83
|
+
# {ServerClient#metadata_fields}.
|
|
84
|
+
class MetadataFields < Resource
|
|
85
|
+
# The prefix of this resource's operations in Internal::OPTION_KEYS.
|
|
86
|
+
OPERATIONS = 'metadataFields'
|
|
87
|
+
|
|
88
|
+
# @return [Hash] `projectId`, `revision` and `fields`.
|
|
89
|
+
def list(options = {})
|
|
90
|
+
call(options, __method__) { |_api, request| request('GET', project('metadata-fields'), request_options: request) }
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Creates each field, or replaces it by ID. Other fields are kept; new ones are added at the end.
|
|
94
|
+
# @option options [Integer] :revision the revision you read
|
|
95
|
+
# @option options [Array<Hash>] :fields `[{id:, title:, type:, icon:, color:, description:}]`
|
|
96
|
+
# @return [Hash] `projectId`, `revision` and `fields`.
|
|
97
|
+
def ensure(options)
|
|
98
|
+
call(options, __method__) { |api, request| request('PUT', project('metadata-fields'), body: api, request_options: request) }
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Deletes a field definition; assets keep the metadata values they hold.
|
|
102
|
+
# @option options [String] :field_id
|
|
103
|
+
# @option options [Integer] :revision the revision you read
|
|
104
|
+
# @return [nil]
|
|
105
|
+
def delete(options)
|
|
106
|
+
call(options, __method__) do |api, request|
|
|
107
|
+
request('DELETE', project("metadata-fields/#{Internal.segment(api['fieldId'])}"),
|
|
108
|
+
query: without(api, 'fieldId'), request_options: request)
|
|
109
|
+
nil
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
data/lib/calmlens/resource.rb
CHANGED
|
@@ -19,9 +19,9 @@ module CalmLens
|
|
|
19
19
|
# beside a request's; Internal::OPTION_KEYS, generated from the API, has the rest.
|
|
20
20
|
LOCAL_OPTION_KEYS = {
|
|
21
21
|
'assets.waitForDecision' => %w[assetId timeout].freeze,
|
|
22
|
-
'cdn.getAssetUrl' => %w[
|
|
23
|
-
'cdn.serve' => %w[
|
|
24
|
-
'uploadTokens.sign' => %w[
|
|
22
|
+
'cdn.getAssetUrl' => %w[assetId externalId lens projectId resource transform viewerClaims].freeze,
|
|
23
|
+
'cdn.serve' => %w[assetId externalId init lens projectId resource transform viewerClaims].freeze,
|
|
24
|
+
'uploadTokens.sign' => %w[expiresIn externalId uploadPresetId].freeze
|
|
25
25
|
}.freeze
|
|
26
26
|
private_constant :LOCAL_OPTION_KEYS
|
|
27
27
|
|
|
@@ -30,9 +30,10 @@ module CalmLens
|
|
|
30
30
|
# `sdk/invalid-argument` instead of being silently dropped.
|
|
31
31
|
# An option given as nil is left out, as if omitted, unless the API takes null for it
|
|
32
32
|
# (Internal::NULLABLE_OPTION_KEYS), such as `description: nil` to clear a description;
|
|
33
|
-
# `keep_nil: true` sends every option as given, as for a lens definition.
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
# `keep_nil: true` sends every option as given, as for a lens definition. `prefix` names the
|
|
34
|
+
# operation's resource, the resource's own unless the method belongs to the client itself.
|
|
35
|
+
def call(options, method, keep_nil: false, prefix: self.class::OPERATIONS)
|
|
36
|
+
operation = [prefix, Internal.camelize(method)].compact.join('.')
|
|
36
37
|
check_option_keys(options, operation)
|
|
37
38
|
api, request = Internal.options(options)
|
|
38
39
|
nullable = Internal::NULLABLE_OPTION_KEYS.fetch(operation, [])
|
|
@@ -84,6 +85,23 @@ module CalmLens
|
|
|
84
85
|
end
|
|
85
86
|
end
|
|
86
87
|
|
|
88
|
+
# A list's response, once it is a cursor page: a Hash with an `items` Array. `what` names the
|
|
89
|
+
# items in the `sdk/invalid-response` error otherwise.
|
|
90
|
+
def cursor_page(response, what)
|
|
91
|
+
return response if response.is_a?(Hash) && response['items'].is_a?(Array)
|
|
92
|
+
|
|
93
|
+
raise InvalidResponseError.new(SdkErrorCodes::INVALID_RESPONSE, "Invalid #{what} page")
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Iterates the items of every page `list` returns for `options`, from its `cursor`, yielding each
|
|
97
|
+
# to `block`. `method` names the public iterator, whose options are checked like the list's.
|
|
98
|
+
def each_item(options, method, list, &block)
|
|
99
|
+
api, request = call(options, method) { |*split| split }
|
|
100
|
+
listing = pages(api['cursor']) { |cursor| list.call(api.merge('cursor' => cursor, 'request_options' => request)) }
|
|
101
|
+
listing.each { |page| page['items'].each(&block) }
|
|
102
|
+
nil
|
|
103
|
+
end
|
|
104
|
+
|
|
87
105
|
# Records a cursor an iteration sends, raising `sdk/invalid-response` (with `details['cursor']`)
|
|
88
106
|
# when a page with more to follow hands back one it already sent, which would repeat pages forever.
|
|
89
107
|
def new_cursor!(sent, cursor)
|
|
@@ -49,6 +49,14 @@ module CalmLens
|
|
|
49
49
|
attr_reader :events
|
|
50
50
|
# @return [CDN]
|
|
51
51
|
attr_reader :cdn
|
|
52
|
+
# @return [Lenses]
|
|
53
|
+
attr_reader :lenses
|
|
54
|
+
# @return [UploadPresets]
|
|
55
|
+
attr_reader :upload_presets
|
|
56
|
+
# @return [ProjectSettings]
|
|
57
|
+
attr_reader :project_settings
|
|
58
|
+
# @return [MetadataFields]
|
|
59
|
+
attr_reader :metadata_fields
|
|
52
60
|
|
|
53
61
|
# @param api_key [String] a project API key. Keep it on your server.
|
|
54
62
|
# @param project_id [String]
|
|
@@ -64,7 +72,7 @@ module CalmLens
|
|
|
64
72
|
# @param max_response_bytes [Integer] the largest response body read; a larger one fails with
|
|
65
73
|
# `sdk/response-too-large`, before it is read when its `Content-Length` says so.
|
|
66
74
|
# @param max_retries [Integer] retries of requests that are safe to repeat: GET/HEAD, and uploads,
|
|
67
|
-
# which carry an `Idempotency-Key`. Connection failures, timeouts, 429, 502, 503, 504 and
|
|
75
|
+
# which carry an `Idempotency-Key`. Connection failures, timeouts, 429, 500, 502, 503, 504 and
|
|
68
76
|
# `idempotency/request-in-progress` are retried with jittered exponential backoff, honouring
|
|
69
77
|
# `Retry-After`. Other writes are never retried. 0 disables retries.
|
|
70
78
|
# @param retry_base_delay [Numeric] seconds before the first retry when the API gives no
|
|
@@ -98,6 +106,9 @@ module CalmLens
|
|
|
98
106
|
@events = Events.new(@session)
|
|
99
107
|
@cdn = CDN.new(@session)
|
|
100
108
|
@lenses = Lenses.new(@session)
|
|
109
|
+
@upload_presets = UploadPresets.new(@session)
|
|
110
|
+
@project_settings = ProjectSettings.new(@session)
|
|
111
|
+
@metadata_fields = MetadataFields.new(@session)
|
|
101
112
|
end
|
|
102
113
|
|
|
103
114
|
# @return [String]
|
|
@@ -119,11 +130,11 @@ module CalmLens
|
|
|
119
130
|
nil
|
|
120
131
|
end
|
|
121
132
|
|
|
122
|
-
# Creates
|
|
123
|
-
# this client already saved are not sent again
|
|
124
|
-
#
|
|
125
|
-
# consecutive requests, in order.
|
|
126
|
-
# @option options [Array<Hash>] :lenses `[{identifier:, name:, type:,
|
|
133
|
+
# Creates named lenses (saved transforms), or changes them to these definitions, and returns
|
|
134
|
+
# them. Definitions this client already saved are not sent again, and sending the same
|
|
135
|
+
# definition again returns the lens unchanged. More than 100 new definitions are sent in
|
|
136
|
+
# consecutive requests, in order. {#lenses} manages lenses one by one.
|
|
137
|
+
# @option options [Array<Hash>] :lenses `[{identifier:, name:, type:, active:, transform:, ...}]`
|
|
127
138
|
# @return [Array<Hash>] the saved lenses, in the given order.
|
|
128
139
|
def ensure_lenses(options) = @lenses.ensure_lenses(options)
|
|
129
140
|
|
data/lib/calmlens/session.rb
CHANGED
|
@@ -10,7 +10,7 @@ module CalmLens
|
|
|
10
10
|
# The resources share one session per client. It never prints the API key.
|
|
11
11
|
# @api private
|
|
12
12
|
class Session
|
|
13
|
-
RETRYABLE_STATUSES = [429, 502, 503, 504].freeze
|
|
13
|
+
RETRYABLE_STATUSES = [429, 500, 502, 503, 504].freeze
|
|
14
14
|
USER_AGENT = "calmlens-ruby/#{VERSION} (ruby/#{RUBY_VERSION})".freeze
|
|
15
15
|
|
|
16
16
|
# Raised through the transport so an exception from the caller's streaming block is
|
|
@@ -99,10 +99,11 @@ module CalmLens
|
|
|
99
99
|
|
|
100
100
|
# Sends a CDN request, retrying like an API read, and returns the last response rather than
|
|
101
101
|
# raising an error status. With a block, yields the streaming {Response} and returns the block's
|
|
102
|
-
# value; otherwise returns the response with its body read.
|
|
103
|
-
|
|
102
|
+
# value; otherwise returns the response with its body read. `authenticate: false` sends no API
|
|
103
|
+
# key, as a browser would.
|
|
104
|
+
def cdn(method, url, headers, request_options, authenticate: true, &block)
|
|
104
105
|
limit = request_options.fetch(:max_response_bytes, nil)
|
|
105
|
-
execute(method, url, headers, nil, request_options, allow_http_errors: true) do |response|
|
|
106
|
+
execute(method, url, headers, nil, request_options, allow_http_errors: true, authenticate: authenticate) do |response|
|
|
106
107
|
next response.tap { response.body(limit: limit) } unless block
|
|
107
108
|
|
|
108
109
|
streaming = Response.new(status: response.status, headers: response.headers) do |&sink|
|
|
@@ -122,6 +123,14 @@ module CalmLens
|
|
|
122
123
|
end
|
|
123
124
|
end
|
|
124
125
|
|
|
126
|
+
# Fetches JSON from the CDN without the API key, as a browser would, and returns it parsed. An
|
|
127
|
+
# error status raises the error the CDN's body names, such as `signed-url/expired`.
|
|
128
|
+
def cdn_json(url)
|
|
129
|
+
execute('GET', url, { 'Accept' => 'application/json' }, nil, {}, authenticate: false) do |response|
|
|
130
|
+
parse('GET', response, @max_response_bytes)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
125
134
|
# Resolves lens definitions, sending only definitions this client has not saved before, at most
|
|
126
135
|
# ServerClient::ENSURE_LENSES_MAX_PER_REQUEST per request, in order. Calls are serialized, so concurrent calls
|
|
127
136
|
# for the same definitions send them once.
|
|
@@ -142,7 +151,7 @@ module CalmLens
|
|
|
142
151
|
raise InvalidResponseError.new(SdkErrorCodes::INVALID_RESPONSE, 'Unexpected lens response')
|
|
143
152
|
end
|
|
144
153
|
|
|
145
|
-
# A
|
|
154
|
+
# A changed lens replaces the cached definition with the same identifier.
|
|
146
155
|
chunk.keys.zip(returned).each do |key, lens|
|
|
147
156
|
@lenses.delete_if { |_, saved| saved['identifier'] == lens['identifier'] }
|
|
148
157
|
@lenses[key] = lens
|
|
@@ -156,9 +165,16 @@ module CalmLens
|
|
|
156
165
|
end
|
|
157
166
|
end
|
|
158
167
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
168
|
+
# Drops the cached definitions of the lenses the block selects, which lenses.create, update
|
|
169
|
+
# and delete changed, so ensure_lenses sends their definitions again.
|
|
170
|
+
def forget_lenses(&selected)
|
|
171
|
+
@lens_lock.synchronize { @lenses.delete_if { |_, lens| selected.call(lens) } }
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def headers_for(extra, authenticate: true)
|
|
175
|
+
headers = extra.reject { |name, _| %w[x-api-key user-agent authorization].include?(name.downcase) }
|
|
176
|
+
.merge('User-Agent' => USER_AGENT)
|
|
177
|
+
authenticate ? headers.merge('X-Api-Key' => @api_key) : headers
|
|
162
178
|
end
|
|
163
179
|
|
|
164
180
|
private
|
|
@@ -168,7 +184,7 @@ module CalmLens
|
|
|
168
184
|
def lens_key(lens)
|
|
169
185
|
fields = { 'identifier' => lens['identifier'], 'name' => lens['name'], 'description' => lens['description'],
|
|
170
186
|
'type' => lens['type'], 'transform' => lens['transform'] }
|
|
171
|
-
|
|
187
|
+
fields['active'] = lens['active'] if lens.key?('active')
|
|
172
188
|
JSON.generate(canonical(fields))
|
|
173
189
|
end
|
|
174
190
|
|
|
@@ -186,14 +202,15 @@ module CalmLens
|
|
|
186
202
|
returned.zip(sent).all? { |saved, definition| saved.is_a?(Hash) && saved['identifier'] == definition['identifier'] }
|
|
187
203
|
end
|
|
188
204
|
|
|
189
|
-
# Sends a request, retrying transport failures, timeouts, 429, 502–504 and
|
|
205
|
+
# Sends a request, retrying transport failures, timeouts, 429, 500, 502–504 and
|
|
190
206
|
# `idempotency/request-in-progress` when it is safe to repeat: reads, and requests with an
|
|
191
207
|
# `Idempotency-Key` whose body can be sent again. Redirects are never followed.
|
|
192
|
-
def execute(method, url, headers, body, request_options, allow_http_errors: false, deadline: nil, &handler)
|
|
208
|
+
def execute(method, url, headers, body, request_options, allow_http_errors: false, deadline: nil, authenticate: true, &handler)
|
|
193
209
|
retries = request_options.fetch(:max_retries, @max_retries)
|
|
194
210
|
retryable = retries.positive? && (%w[GET HEAD].include?(method) || headers.key?('Idempotency-Key')) &&
|
|
195
211
|
(body.nil? || body.replayable?)
|
|
196
|
-
request = Transport::Request.new(method: method, url: url, headers: headers_for(headers
|
|
212
|
+
request = Transport::Request.new(method: method, url: url, headers: headers_for(headers, authenticate: authenticate),
|
|
213
|
+
body: body&.content,
|
|
197
214
|
open_timeout: request_options.fetch(:open_timeout, @open_timeout),
|
|
198
215
|
timeout: request_options.fetch(:timeout, @timeout))
|
|
199
216
|
limit = request_options.fetch(:max_response_bytes, @max_response_bytes)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Generated by packages/sdk-contract/mockAssetFilters.ts from ASSET_FILTER_FIELDS (packages/shared-backend/src/AssetFilters.ts) and listFilterOperators (PaginationUtils.ts); do not edit.
|
|
4
|
+
# A filter may name only these fields, each with only its operators; anything else is
|
|
5
|
+
# filter/invalid. A number field's value must be a finite number, and `null` is a
|
|
6
|
+
# missing value only on a nullable field.
|
|
7
|
+
module CalmLens
|
|
8
|
+
module MockAssetFilters
|
|
9
|
+
# Each field a filter may name, with its kind, whether it is nullable and its operators.
|
|
10
|
+
FIELDS = {
|
|
11
|
+
'id' => { kind: 'text', nullable: false, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
12
|
+
'parentId' => { kind: 'text', nullable: true, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
13
|
+
'folderId' => { kind: 'text', nullable: true, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
14
|
+
'uploadPresetId' => { kind: 'text', nullable: true, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
15
|
+
'createdAt' => { kind: 'number', nullable: false, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
16
|
+
'updatedAt' => { kind: 'number', nullable: false, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
17
|
+
'type' => { kind: 'text', nullable: false, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
18
|
+
'name' => { kind: 'text', nullable: false, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
19
|
+
'description' => { kind: 'text', nullable: true, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
20
|
+
'externalId' => { kind: 'text', nullable: true, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
21
|
+
'externalUrl' => { kind: 'text', nullable: true, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
22
|
+
'authorId' => { kind: 'text', nullable: true, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
23
|
+
'tags' => { kind: 'list', nullable: false, operators: ['=in=', '=out='].freeze }.freeze,
|
|
24
|
+
'visibility' => { kind: 'text', nullable: true, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
25
|
+
'upload.status' => { kind: 'text', nullable: false, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
26
|
+
'upload.updatedAt' => { kind: 'number', nullable: true, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
27
|
+
'classification.status' => { kind: 'text', nullable: false, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
28
|
+
'classification.updatedAt' => { kind: 'number', nullable: true, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
29
|
+
'classification.completedAt' => { kind: 'number', nullable: true, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
30
|
+
'classification.moderation.status' => { kind: 'text', nullable: false, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
31
|
+
'content.status' => { kind: 'text', nullable: false, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
32
|
+
'content.removalReason' => { kind: 'text', nullable: true, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
33
|
+
'content.updatedAt' => { kind: 'number', nullable: true, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
34
|
+
'content.format' => { kind: 'text', nullable: true, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
35
|
+
'content.extension' => { kind: 'text', nullable: true, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
36
|
+
'content.sizeInBytes' => { kind: 'number', nullable: true, operators: ['==', '!=', '>', '>=', '<', '<=', '=in=', '=out='].freeze }.freeze,
|
|
37
|
+
}.freeze
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# Generated by packages/sdk-contract/mockClassification.ts from packages/shared/src/ModerationCategories.ts and
|
|
3
|
+
# Generated by packages/sdk-contract/mockClassification.ts from packages/shared/src/ModerationCategories.ts, ModerationPolicyDimensions.ts and TestTriggers.ts; do not edit.
|
|
4
4
|
module CalmLens
|
|
5
5
|
module MockClassification
|
|
6
6
|
# The parent categories, in the API's order.
|
|
@@ -8,7 +8,7 @@ module CalmLens
|
|
|
8
8
|
|
|
9
9
|
# Each category's qualifiers.
|
|
10
10
|
QUALIFIERS = {
|
|
11
|
-
"sexual" => ["sexual-pornographic-media", "sexual-nudity", "sexual-activity", "sexual-explicit-language", "sexual-assault-media", "sexual-non-consensual", "sexual-intimate-image-abuse", "sexual-extreme", "sexual-minors", "sexual-solicitation", "sexual-paid", "sexual-adult-promotion", "sexual-revealing-clothing", "sexual-suggestive", "sexual-non-erotic-nudity", "sexual-text", "sexual-historical", "sexual-documentary", "sexual-educational", "sexual-discussion", "sexual-fictional", "sexual-support-prevention"].freeze,
|
|
11
|
+
"sexual" => ["sexual-pornographic-media", "sexual-nudity", "sexual-activity", "sexual-explicit-language", "sexual-assault-media", "sexual-non-consensual", "sexual-intimate-image-abuse", "sexual-extreme", "sexual-strangulation", "sexual-incest", "sexual-minors", "sexual-solicitation", "sexual-paid", "sexual-adult-promotion", "sexual-revealing-clothing", "sexual-suggestive", "sexual-non-erotic-nudity", "sexual-text", "sexual-historical", "sexual-documentary", "sexual-educational", "sexual-discussion", "sexual-fictional", "sexual-support-prevention"].freeze,
|
|
12
12
|
"violence" => ["violence-high-impact", "violence-attack", "violence-threat", "violence-preparation", "violence-encouragement", "violence-wish", "violence-coded-incitement", "violence-extremism", "violence-injury", "violence-violent-death", "violence-natural-death", "violence-graphic", "violence-decapitation-act", "violence-gore", "violence-weapon", "violence-sport", "violence-text", "violence-historical", "violence-documentary", "violence-educational", "violence-discussion", "violence-fictional", "violence-fantasy", "violence-support-prevention"].freeze,
|
|
13
13
|
"self-harm" => ["self-harm-age-restricted", "self-harm-thoughts", "self-harm-preparation", "self-harm-act", "self-harm-methods", "self-harm-encouragement", "self-harm-historical", "self-harm-documentary", "self-harm-educational", "self-harm-fictional", "self-harm-support-prevention"].freeze,
|
|
14
14
|
"harassment" => ["harassment-abuse", "harassment-mild", "harassment-bullying", "harassment-public-target", "harassment-threat", "harassment-sexual", "harassment-encouragement", "harassment-historical", "harassment-documentary", "harassment-educational", "harassment-fictional", "harassment-support-prevention"].freeze,
|
|
@@ -20,5 +20,11 @@ module CalmLens
|
|
|
20
20
|
|
|
21
21
|
# Qualifiers the input type sets, which a test input scenario cannot list.
|
|
22
22
|
INPUT_QUALIFIERS = ["sexual-text", "violence-text"].freeze
|
|
23
|
+
|
|
24
|
+
# Test scenario detections: entries per list, the basis points of a full side, the oldest age and the age presets.
|
|
25
|
+
TEST_DETECTIONS_MAX = 32
|
|
26
|
+
TEST_DETECTION_BOX_MAX = 10000
|
|
27
|
+
TEST_FACE_AGE_MAX = 120
|
|
28
|
+
TEST_FACE_AGE_PRESETS = ["adult", "minor"].freeze
|
|
23
29
|
end
|
|
24
30
|
end
|