cloudinary 1.28.0 → 2.0.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.
@@ -68,7 +68,7 @@ class Cloudinary::Api
68
68
  type = options[:type]
69
69
  uri = "resources/#{resource_type}"
70
70
  uri += "/#{type}" unless type.blank?
71
- call_api(:get, uri, only(options, :next_cursor, :max_results, :prefix, :tags, :context, :moderations, :direction, :start_at, :metadata), options)
71
+ call_api(:get, uri, list_resources_params(options).merge(only(options, :prefix, :start_at)), options)
72
72
  end
73
73
 
74
74
  # Lists assets with the specified tag.
@@ -87,7 +87,7 @@ class Cloudinary::Api
87
87
  def self.resources_by_tag(tag, options={})
88
88
  resource_type = options[:resource_type] || "image"
89
89
  uri = "resources/#{resource_type}/tags/#{tag}"
90
- call_api(:get, uri, only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction, :metadata), options)
90
+ call_api(:get, uri, list_resources_params(options), options)
91
91
  end
92
92
 
93
93
  # Lists assets currently in the specified moderation queue and status.
@@ -107,7 +107,7 @@ class Cloudinary::Api
107
107
  def self.resources_by_moderation(kind, status, options={})
108
108
  resource_type = options[:resource_type] || "image"
109
109
  uri = "resources/#{resource_type}/moderations/#{kind}/#{status}"
110
- call_api(:get, uri, only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction, :metadata), options)
110
+ call_api(:get, uri, list_resources_params(options), options)
111
111
  end
112
112
 
113
113
  # Lists assets with the specified contextual metadata.
@@ -129,30 +129,9 @@ class Cloudinary::Api
129
129
  def self.resources_by_context(key, value=nil, options={})
130
130
  resource_type = options[:resource_type] || "image"
131
131
  uri = "resources/#{resource_type}/context"
132
- params = only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction, :key, :value, :metadata)
133
- params[:key] = key
134
- params[:value] = value
135
- call_api(:get, uri, params, options)
132
+ call_api(:get, uri, list_resources_params(options, :key => key, :value => value), options)
136
133
  end
137
134
 
138
- # Returns the details of the specified asset and all its derived assets by asset id.
139
- #
140
- # Note that if you only need details about the original asset,
141
- # you can also use the Uploader::upload or Uploader::explicit methods, which return the same information and
142
- # are not rate limited.
143
- #
144
- # @param [String] asset_id The Asset ID of the asset.
145
- # @param [Hash] options The optional parameters. See the <a href=https://cloudinary.com/documentation/admin_api#get_the_details_of_a_single_resource target="_blank"> Admin API</a> documentation.
146
- #
147
- # @return [Cloudinary::Api::Response]
148
- #
149
- # @see https://cloudinary.com/documentation/admin_api#get_the_details_of_a_single_resource
150
- def self.resource_by_asset_id(asset_id, options={})
151
- uri = "resources/#{asset_id}"
152
- params = prepare_resource_details_params(options)
153
- call_api(:get, uri, params, options)
154
- end
155
-
156
135
  # Lists assets with the specified public IDs.
157
136
  #
158
137
  # @param [String|Array] public_ids The requested public_ids (up to 100).
@@ -168,7 +147,7 @@ class Cloudinary::Api
168
147
  resource_type = options[:resource_type] || "image"
169
148
  type = options[:type] || "upload"
170
149
  uri = "resources/#{resource_type}/#{type}"
171
- call_api(:get, uri, only(options, :tags, :context, :moderations).merge(:public_ids => public_ids), options)
150
+ call_api(:get, uri, resources_params(options, :public_ids => public_ids), options)
172
151
  end
173
152
 
174
153
  # Lists assets with the specified asset IDs.
@@ -184,9 +163,7 @@ class Cloudinary::Api
184
163
  # @see https://cloudinary.com/documentation/admin_api#get_resources
185
164
  def self.resources_by_asset_ids(asset_ids, options={})
186
165
  uri = "resources/by_asset_ids"
187
- params = only(options, :public_ids, :tags, :moderations, :context)
188
- params[:asset_ids] = asset_ids
189
- call_api(:get, uri, params, options)
166
+ call_api(:get, uri, resources_params(options, :asset_ids => asset_ids), options)
190
167
  end
191
168
 
192
169
  # Returns all assets stored directly in a specified asset folder, regardless of the public ID paths of those assets.
@@ -202,9 +179,7 @@ class Cloudinary::Api
202
179
  # @see https://cloudinary.com/documentation/dynamic_folders#new_admin_api_endpoints
203
180
  def self.resources_by_asset_folder(asset_folder, options={})
204
181
  uri = "resources/by_asset_folder"
205
- params = only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction, :key, :value, :metadata)
206
- params[:asset_folder] = asset_folder
207
- call_api(:get, uri, params, options)
182
+ call_api(:get, uri, list_resources_params(options, :asset_folder => asset_folder), options)
208
183
  end
209
184
 
210
185
  # Find images based on their visual content.
@@ -243,6 +218,23 @@ class Cloudinary::Api
243
218
  call_api(:get, uri, prepare_resource_details_params(options), options)
244
219
  end
245
220
 
221
+ # Returns the details of the specified asset and all its derived assets by asset id.
222
+ #
223
+ # Note that if you only need details about the original asset,
224
+ # you can also use the Uploader::upload or Uploader::explicit methods, which return the same information and
225
+ # are not rate limited.
226
+ #
227
+ # @param [String] asset_id The Asset ID of the asset.
228
+ # @param [Hash] options The optional parameters. See the <a href=https://cloudinary.com/documentation/admin_api#get_the_details_of_a_single_resource target="_blank"> Admin API</a> documentation.
229
+ #
230
+ # @return [Cloudinary::Api::Response]
231
+ #
232
+ # @see https://cloudinary.com/documentation/admin_api#get_the_details_of_a_single_resource
233
+ def self.resource_by_asset_id(asset_id, options={})
234
+ uri = "resources/#{asset_id}"
235
+ call_api(:get, uri, prepare_resource_details_params(options), options)
236
+ end
237
+
246
238
  # Reverts to the latest backed up version of the specified deleted assets.
247
239
  #
248
240
  # @param [String|Array] public_ids The public IDs of the backed up assets to restore. They can be existing or
@@ -657,7 +649,7 @@ class Cloudinary::Api
657
649
  #
658
650
  # @see https://cloudinary.com/documentation/admin_api#update_an_upload_preset
659
651
  def self.update_upload_preset(name, options={})
660
- params = Cloudinary::Uploader.build_upload_params(options)
652
+ params = Cloudinary::Uploader.build_upload_params(options, true)
661
653
  call_api(:put, "upload_presets/#{name}", params.merge(only(options, :unsigned, :disallow_public_id, :live)), options)
662
654
  end
663
655
 
@@ -672,7 +664,7 @@ class Cloudinary::Api
672
664
  #
673
665
  # @see https://cloudinary.com/documentation/admin_api#create_an_upload_preset
674
666
  def self.create_upload_preset(options={})
675
- params = Cloudinary::Uploader.build_upload_params(options)
667
+ params = Cloudinary::Uploader.build_upload_params(options, true)
676
668
  call_api(:post, "upload_presets", params.merge(only(options, :name, :unsigned, :disallow_public_id, :live)), options)
677
669
  end
678
670
 
@@ -1230,6 +1222,25 @@ class Cloudinary::Api
1230
1222
  call_metadata_rules_api(:delete, uri, {}, options)
1231
1223
  end
1232
1224
 
1225
+ # Analyzes an asset with the requested analysis type.
1226
+ #
1227
+ # @param [Object] input_type The type of input for the asset to analyze ('uri').
1228
+ # @param [Object] analysis_type The type of analysis to run ('google_tagging', 'captioning', 'fashion').
1229
+ # @param [Hash] options The optional parameters.
1230
+ #
1231
+ # @return [Cloudinary::Api::Response]
1232
+ #
1233
+ # @raise [Cloudinary::Api::Error]
1234
+ def self.analyze(input_type, analysis_type, options = {})
1235
+ api_uri = ["analysis", "analyze", input_type]
1236
+ params = only(options, :uri, :parameters)
1237
+ params["analysis_type"] = analysis_type
1238
+
1239
+ options[:api_version] = 'v2'
1240
+
1241
+ call_api(:post, api_uri, params, options)
1242
+ end
1243
+
1233
1244
  protected
1234
1245
 
1235
1246
  # Execute a call api for input params.
@@ -1244,13 +1255,14 @@ class Cloudinary::Api
1244
1255
  api_key = options[:api_key] || Cloudinary.config.api_key
1245
1256
  api_secret = options[:api_secret] || Cloudinary.config.api_secret
1246
1257
  oauth_token = options[:oauth_token] || Cloudinary.config.oauth_token
1258
+ api_version = options[:api_version] || Cloudinary.config.api_version || 'v1_1'
1247
1259
 
1248
1260
  validate_authorization(api_key, api_secret, oauth_token)
1249
1261
 
1250
1262
  auth = { :key => api_key, :secret => api_secret, :oauth_token => oauth_token }
1251
1263
 
1252
1264
  call_cloudinary_api(method, uri, auth, params, options) do |cloudinary, inner_uri|
1253
- [cloudinary, 'v1_1', cloud_name, inner_uri]
1265
+ [cloudinary, api_version, cloud_name, inner_uri]
1254
1266
  end
1255
1267
  end
1256
1268
 
@@ -1262,7 +1274,7 @@ class Cloudinary::Api
1262
1274
  return Cloudinary::Utils.json_decode(response.body)
1263
1275
  rescue => e
1264
1276
  # Error is parsing json
1265
- raise GeneralError.new("Error parsing server response (#{response.code}) - #{response.body}. Got - #{e}")
1277
+ raise GeneralError.new("Error parsing server response (#{response.status}) - #{response.body}. Got - #{e}")
1266
1278
  end
1267
1279
 
1268
1280
  # Protected function that assists with performing an API call to the metadata_fields part of the Admin API.
@@ -1399,4 +1411,19 @@ class Cloudinary::Api
1399
1411
  params[by_key] = value
1400
1412
  call_api("post", "resources/#{resource_type}/#{type}/update_access_mode", params, options)
1401
1413
  end
1414
+
1415
+ private
1416
+
1417
+ RESOURCES_PARAMS = [:tags, :context, :metadata, :moderations, :fields].freeze
1418
+ LIST_RESOURCES_PARAMS = [:next_cursor, :max_results, :direction].freeze
1419
+
1420
+ def self.resources_params(options, params = {})
1421
+ params.merge!(only(options, *RESOURCES_PARAMS))
1422
+ params[:fields] = Cloudinary::Utils.build_array(options[:fields]).join(",") unless params[:fields].nil?
1423
+ params
1424
+ end
1425
+
1426
+ def self.list_resources_params(options, params = {})
1427
+ params.merge(resources_params(options)).merge!(only(options, *LIST_RESOURCES_PARAMS))
1428
+ end
1402
1429
  end
@@ -1,11 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'openssl'
4
- if RUBY_VERSION > "2"
5
- require "ostruct"
6
- else
7
- require "cloudinary/ostruct2"
8
- end
4
+ require "ostruct"
9
5
 
10
6
 
11
7
  module Cloudinary
@@ -1,7 +1,8 @@
1
- require "rest_client"
1
+ require "faraday"
2
2
  require "json"
3
3
 
4
4
  module Cloudinary::BaseApi
5
+ @adapter = nil
5
6
  class Error < CloudinaryException; end
6
7
  class NotFound < Error; end
7
8
  class NotAllowed < Error; end
@@ -15,17 +16,19 @@ module Cloudinary::BaseApi
15
16
  attr_reader :rate_limit_reset_at, :rate_limit_remaining, :rate_limit_allowed
16
17
 
17
18
  def initialize(response=nil)
18
- if response
19
- # This sets the instantiated self as the response Hash
20
- update Cloudinary::Api.parse_json_response response
19
+ unless response
20
+ return
21
+ end
21
22
 
22
- # According to RFC 2616, header names are case-insensitive.
23
- lc_headers = response.headers.transform_keys(&:downcase)
23
+ # This sets the instantiated self as the response Hash
24
+ update Cloudinary::Api.parse_json_response response
24
25
 
25
- @rate_limit_allowed = lc_headers[:x_featureratelimit_limit].to_i if lc_headers[:x_featureratelimit_limit]
26
- @rate_limit_reset_at = Time.parse(lc_headers[:x_featureratelimit_reset]) if lc_headers[:x_featureratelimit_reset]
27
- @rate_limit_remaining = lc_headers[:x_featureratelimit_remaining].to_i if lc_headers[:x_featureratelimit_remaining]
28
- end
26
+ # According to RFC 2616, header names are case-insensitive.
27
+ lc_headers = response.headers.transform_keys(&:downcase)
28
+
29
+ @rate_limit_allowed = lc_headers["x-featureratelimit-limit"].to_i if lc_headers["x-featureratelimit-limit"]
30
+ @rate_limit_reset_at = Time.parse(lc_headers["x-featureratelimit-reset"]) if lc_headers["x-featureratelimit-reset"]
31
+ @rate_limit_remaining = lc_headers["x-featureratelimit-remaining"].to_i if lc_headers["x-featureratelimit-remaining"]
29
32
  end
30
33
  end
31
34
 
@@ -36,28 +39,30 @@ module Cloudinary::BaseApi
36
39
  end
37
40
 
38
41
  def call_json_api(method, api_url, payload, timeout, headers, proxy = nil, user = nil, password = nil)
39
- RestClient::Request.execute(method: method,
40
- url: api_url,
41
- payload: payload,
42
- timeout: timeout,
43
- headers: headers,
44
- proxy: proxy,
45
- user: user,
46
- password: password) do |response|
47
- return Response.new(response) if response.code == 200
48
- exception_class = case response.code
49
- when 400 then BadRequest
50
- when 401 then AuthorizationRequired
51
- when 403 then NotAllowed
52
- when 404 then NotFound
53
- when 409 then AlreadyExists
54
- when 420 then RateLimited
55
- when 500 then GeneralError
56
- else raise GeneralError.new("Server returned unexpected status code - #{response.code} - #{response.body}")
57
- end
58
- json = Cloudinary::Api.parse_json_response(response)
59
- raise exception_class.new(json["error"]["message"])
42
+ conn = Faraday.new(url: api_url) do |faraday|
43
+ faraday.proxy = proxy if proxy
44
+ faraday.request :json
45
+ faraday.adapter @adapter || Faraday.default_adapter
60
46
  end
47
+
48
+ response = conn.run_request(method.downcase.to_sym, nil, payload, headers) do |req|
49
+ req.options.timeout = timeout if timeout
50
+ req.basic_auth(user, password) if user && password
51
+ end
52
+
53
+ return Response.new(response) if response.status == 200
54
+ exception_class = case response.status
55
+ when 400 then BadRequest
56
+ when 401 then AuthorizationRequired
57
+ when 403 then NotAllowed
58
+ when 404 then NotFound
59
+ when 409 then AlreadyExists
60
+ when 420 then RateLimited
61
+ when 500 then GeneralError
62
+ else raise GeneralError.new("Server returned unexpected status code - #{response.status} - #{response.body}")
63
+ end
64
+ json = Cloudinary::Api.parse_json_response(response)
65
+ raise exception_class.new(json["error"]["message"])
61
66
  end
62
67
 
63
68
  private
@@ -36,7 +36,8 @@ class Cloudinary::CarrierWave::Storage < ::CarrierWave::Storage::Abstract
36
36
  params[:type]=uploader.class.storage_type
37
37
 
38
38
  params[:resource_type] ||= :auto
39
- uploader.metadata = Cloudinary::Uploader.upload(data, params)
39
+ upload_method = uploader.upload_chunked? ? "upload_large" : "upload"
40
+ uploader.metadata = Cloudinary::Uploader.send(upload_method, data, params)
40
41
  if uploader.metadata["error"]
41
42
  raise Cloudinary::CarrierWave::UploadError.new(uploader.metadata["error"]["message"], uploader.metadata["error"]["http_code"])
42
43
  end
@@ -192,11 +192,6 @@ module Cloudinary::CarrierWave
192
192
 
193
193
  end
194
194
 
195
- # @deprecated
196
- def self.split_format(identifier)
197
- return Cloudinary::PreloadedFile.split_format(identifier)
198
- end
199
-
200
195
  def default_format
201
196
  "png"
202
197
  end
@@ -286,13 +286,6 @@ module CloudinaryHelper
286
286
  Cloudinary::Utils.private_download_url(public_id, format, options)
287
287
  end
288
288
 
289
- # Helper method that uses the deprecated ZIP download API.
290
- # Replaced by cl_download_zip_url that uses the more advanced and robust archive generation and download API
291
- # @deprecated
292
- def cl_zip_download_url(tag, options = {})
293
- Cloudinary::Utils.zip_download_url(tag, options)
294
- end
295
-
296
289
  # @see {Cloudinary::Utils.download_archive_url}
297
290
  def cl_download_archive_url(options = {})
298
291
  Cloudinary::Utils.download_archive_url(options)
@@ -304,13 +297,13 @@ module CloudinaryHelper
304
297
  end
305
298
 
306
299
  def cl_signed_download_url(public_id, options = {})
307
- Cloudinary::Utils.signed_download_url(public_id, options)
300
+ Cloudinary::Utils.cloudinary_url(public_id, options)
308
301
  end
309
302
 
310
303
  def self.included(base)
311
304
  ActionView::Helpers::FormBuilder.send(:include, Cloudinary::FormBuilder)
312
305
  base.class_eval do
313
- if !method_defined?(:image_tag)
306
+ unless method_defined?(:image_tag)
314
307
  include ActionView::Helpers::AssetTagHelper
315
308
  end
316
309
  alias_method :image_tag_without_cloudinary, :image_tag unless public_method_defined? :image_tag_without_cloudinary
@@ -325,7 +318,6 @@ module CloudinaryHelper
325
318
  private
326
319
 
327
320
  def cloudinary_url_internal(source, options = {})
328
- options[:ssl_detected] = request.ssl? if defined?(request) && request && request.respond_to?(:ssl?)
329
321
  if defined?(CarrierWave::Uploader::Base) && source.is_a?(CarrierWave::Uploader::Base)
330
322
  if source.version_name.present?
331
323
  options[:transformation] = Cloudinary::Utils.build_array(source.transformation) + Cloudinary::Utils.build_array(options[:transformation])