cloudinary 1.1.1 → 1.1.2

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.
@@ -3,117 +3,135 @@ require 'rest_client'
3
3
  require 'json'
4
4
 
5
5
  class Cloudinary::Uploader
6
-
6
+
7
+ # @deprecated use {Cloudinary::Utils.build_eager} instead
7
8
  def self.build_eager(eager)
8
- return nil if eager.nil?
9
- Cloudinary::Utils.build_array(eager).map do
10
- |transformation, format|
11
- transformation = transformation.clone
12
- format = transformation.delete(:format) || format
13
- [Cloudinary::Utils.generate_transformation_string(transformation), format].compact.join("/")
14
- end.join("|")
9
+ Cloudinary::Utils.build_eager(eager)
15
10
  end
16
-
11
+
12
+ # @private
17
13
  def self.build_upload_params(options)
18
14
  #symbolize keys
19
15
  options = options.clone
20
- options.keys.each{|key| options[key.to_sym] = options.delete(key) if key.is_a?(String)}
21
-
22
- params = {:timestamp=>(options[:timestamp] || Time.now.to_i),
23
- :transformation => Cloudinary::Utils.generate_transformation_string(options.clone),
24
- :public_id=>options[:public_id],
25
- :callback=>options[:callback],
26
- :format=>options[:format],
27
- :type=>options[:type],
28
- :backup=>Cloudinary::Utils.as_safe_bool(options[:backup]),
29
- :faces=>Cloudinary::Utils.as_safe_bool(options[:faces]),
30
- :exif=>Cloudinary::Utils.as_safe_bool(options[:exif]),
31
- :colors=>Cloudinary::Utils.as_safe_bool(options[:colors]),
32
- :image_metadata=>Cloudinary::Utils.as_safe_bool(options[:image_metadata]),
33
- :invalidate=>Cloudinary::Utils.as_safe_bool(options[:invalidate]),
34
- :eager=>build_eager(options[:eager]),
35
- :headers=>build_custom_headers(options[:headers]),
36
- :use_filename=>Cloudinary::Utils.as_safe_bool(options[:use_filename]),
37
- :unique_filename=>Cloudinary::Utils.as_safe_bool(options[:unique_filename]),
38
- :overwrite=>Cloudinary::Utils.as_safe_bool(options[:overwrite]),
39
- :discard_original_filename=>Cloudinary::Utils.as_safe_bool(options[:discard_original_filename]),
40
- :notification_url=>options[:notification_url],
41
- :eager_notification_url=>options[:eager_notification_url],
42
- :eager_async=>Cloudinary::Utils.as_safe_bool(options[:eager_async]),
43
- :proxy=>options[:proxy],
44
- :folder=>options[:folder],
45
- :allowed_formats => Cloudinary::Utils.build_array(options[:allowed_formats]).join(","),
46
- :tags=>options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(","),
47
- :context => Cloudinary::Utils.encode_hash(options[:context]),
48
- :face_coordinates => Cloudinary::Utils.encode_double_array(options[:face_coordinates]),
49
- :custom_coordinates => Cloudinary::Utils.encode_double_array(options[:custom_coordinates]),
50
- :moderation => options[:moderation],
51
- :raw_convert => options[:raw_convert],
52
- :ocr => options[:ocr],
53
- :categorization => options[:categorization],
54
- :detection => options[:detection],
55
- :similarity_search => options[:similarity_search],
56
- :background_removal => options[:background_removal],
57
- :auto_tagging => options[:auto_tagging] && options[:auto_tagging].to_f,
58
- :upload_preset => options[:upload_preset],
59
- :phash => Cloudinary::Utils.as_safe_bool(options[:phash]),
60
- :return_delete_token => Cloudinary::Utils.as_safe_bool(options[:return_delete_token]),
61
- }
62
- params
16
+ options.keys.each { |key| options[key.to_sym] = options.delete(key) if key.is_a?(String) }
17
+
18
+ params = {
19
+ :allowed_formats => Cloudinary::Utils.build_array(options[:allowed_formats]).join(","),
20
+ :auto_tagging => options[:auto_tagging] && options[:auto_tagging].to_f,
21
+ :background_removal => options[:background_removal],
22
+ :backup => Cloudinary::Utils.as_safe_bool(options[:backup]),
23
+ :callback => options[:callback],
24
+ :categorization => options[:categorization],
25
+ :colors => Cloudinary::Utils.as_safe_bool(options[:colors]),
26
+ :context => Cloudinary::Utils.encode_hash(options[:context]),
27
+ :custom_coordinates => Cloudinary::Utils.encode_double_array(options[:custom_coordinates]),
28
+ :detection => options[:detection],
29
+ :discard_original_filename => Cloudinary::Utils.as_safe_bool(options[:discard_original_filename]),
30
+ :eager => Cloudinary::Utils.build_eager(options[:eager]),
31
+ :eager_async => Cloudinary::Utils.as_safe_bool(options[:eager_async]),
32
+ :eager_notification_url => options[:eager_notification_url],
33
+ :exif => Cloudinary::Utils.as_safe_bool(options[:exif]),
34
+ :face_coordinates => Cloudinary::Utils.encode_double_array(options[:face_coordinates]),
35
+ :faces => Cloudinary::Utils.as_safe_bool(options[:faces]),
36
+ :folder => options[:folder],
37
+ :format => options[:format],
38
+ :headers => build_custom_headers(options[:headers]),
39
+ :image_metadata => Cloudinary::Utils.as_safe_bool(options[:image_metadata]),
40
+ :invalidate => Cloudinary::Utils.as_safe_bool(options[:invalidate]),
41
+ :moderation => options[:moderation],
42
+ :notification_url => options[:notification_url],
43
+ :ocr => options[:ocr],
44
+ :overwrite => Cloudinary::Utils.as_safe_bool(options[:overwrite]),
45
+ :phash => Cloudinary::Utils.as_safe_bool(options[:phash]),
46
+ :proxy => options[:proxy],
47
+ :public_id => options[:public_id],
48
+ :raw_convert => options[:raw_convert],
49
+ :responsive_breakpoints => Cloudinary::Utils.generate_responsive_breakpoints_string(options[:responsive_breakpoints]),
50
+ :return_delete_token => Cloudinary::Utils.as_safe_bool(options[:return_delete_token]),
51
+ :similarity_search => options[:similarity_search],
52
+ :tags => options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(","),
53
+ :timestamp => (options[:timestamp] || Time.now.to_i),
54
+ :transformation => Cloudinary::Utils.generate_transformation_string(options.clone),
55
+ :type => options[:type],
56
+ :unique_filename => Cloudinary::Utils.as_safe_bool(options[:unique_filename]),
57
+ :upload_preset => options[:upload_preset],
58
+ :use_filename => Cloudinary::Utils.as_safe_bool(options[:use_filename]),
59
+ }
60
+ params
63
61
  end
64
-
62
+
63
+ # @private
64
+ def self.build_explicit_api_params(public_id, options = {})
65
+ options = Cloudinary::Utils.symbolize_keys options
66
+ params = {
67
+ :callback => options[:callback],
68
+ :eager => Cloudinary::Utils.build_eager(options[:eager]),
69
+ :eager_async => Cloudinary::Utils.as_safe_bool(options[:eager_async]),
70
+ :eager_notification_url => options[:eager_notification_url],
71
+ :face_coordinates => options[:face_coordinates] && Cloudinary::Utils.encode_double_array(options[:face_coordinates]),
72
+ :headers => build_custom_headers(options[:headers]),
73
+ :invalidate => Cloudinary::Utils.as_safe_bool(options[:invalidate]),
74
+ :public_id => public_id,
75
+ :responsive_breakpoints => Cloudinary::Utils.generate_responsive_breakpoints_string(options[:responsive_breakpoints]),
76
+ :tags => options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(","),
77
+ :timestamp => (options[:timestamp] || Time.now.to_i),
78
+ :type => options[:type]
79
+ }
80
+ params
81
+ end
82
+
65
83
  def self.unsigned_upload(file, upload_preset, options={})
66
84
  upload(file, options.merge(:unsigned => true, :upload_preset => upload_preset))
67
85
  end
68
-
86
+
69
87
  def self.upload(file, options={})
70
- call_api("upload", options) do
88
+ call_api("upload", options) do
71
89
  params = build_upload_params(options)
72
90
  if file.is_a?(Pathname)
73
91
  params[:file] = File.open(file, "rb")
74
92
  elsif file.respond_to?(:read) || file =~ /^ftp:|^https?:|^s3:|^data:[^;]*;base64,([a-zA-Z0-9\/+\n=]+)$/
75
93
  params[:file] = file
76
- else
94
+ else
77
95
  params[:file] = File.open(file, "rb")
78
96
  end
79
97
  [params, [:file]]
80
- end
98
+ end
81
99
  end
82
100
 
83
101
  # Upload large files. Note that public_id should include an extension for best results.
84
102
  def self.upload_large(file, public_id_or_options={}, old_options={})
85
103
  if public_id_or_options.is_a?(Hash)
86
- options = public_id_or_options
104
+ options = public_id_or_options
87
105
  public_id = options[:public_id]
88
106
  else
89
107
  public_id = public_id_or_options
90
- options = old_options
91
- end
108
+ options = old_options
109
+ end
92
110
  if file.is_a?(Pathname) || !file.respond_to?(:read)
93
111
  filename = file
94
- file = File.open(file, "rb")
112
+ file = File.open(file, "rb")
95
113
  else
96
114
  filename = "cloudinaryfile"
97
115
  end
98
- upload = upload_id = nil
99
- index = 0
116
+ upload = nil
117
+ index = 0
100
118
  chunk_size = options[:chunk_size] || 20_000_000
101
- while !file.eof?
102
- buffer = file.read(chunk_size)
119
+ until file.eof?
120
+ buffer = file.read(chunk_size)
103
121
  current_loc = index*chunk_size
104
- range = "bytes #{current_loc}-#{current_loc+buffer.size - 1}/#{file.size}"
105
- upload = upload_large_part(Cloudinary::Blob.new(buffer, :original_filename=>filename), options.merge(:public_id=>public_id, :content_range=>range))
106
- public_id = upload["public_id"]
107
- index += 1
122
+ range = "bytes #{current_loc}-#{current_loc+buffer.size - 1}/#{file.size}"
123
+ upload = upload_large_part(Cloudinary::Blob.new(buffer, :original_filename => filename), options.merge(:public_id => public_id, :content_range => range))
124
+ public_id = upload["public_id"]
125
+ index += 1
108
126
  end
109
127
  upload
110
128
  end
111
-
129
+
112
130
 
113
131
  # Upload large files. Note that public_id should include an extension for best results.
114
132
  def self.upload_large_part(file, options={})
115
133
  options[:resource_type] ||= :raw
116
- call_api("upload", options) do
134
+ call_api("upload", options) do
117
135
  params = build_upload_params(options)
118
136
  if file.is_a?(Pathname) || !file.respond_to?(:read)
119
137
  params[:file] = File.open(file, "rb")
@@ -121,168 +139,173 @@ class Cloudinary::Uploader
121
139
  params[:file] = file
122
140
  end
123
141
  [params, [:file]]
124
- end
142
+ end
125
143
  end
126
144
 
127
145
  def self.destroy(public_id, options={})
128
- call_api("destroy", options) do
146
+ call_api("destroy", options) do
129
147
  {
130
- :timestamp=>(options[:timestamp] || Time.now.to_i),
131
- :type=>options[:type],
132
- :public_id=> public_id,
133
- :invalidate=>options[:invalidate],
148
+ :timestamp => (options[:timestamp] || Time.now.to_i),
149
+ :type => options[:type],
150
+ :public_id => public_id,
151
+ :invalidate => options[:invalidate],
134
152
  }
135
- end
153
+ end
136
154
  end
137
155
 
138
156
  def self.rename(from_public_id, to_public_id, options={})
139
- call_api("rename", options) do
157
+ call_api("rename", options) do
140
158
  {
141
- :timestamp=>(options[:timestamp] || Time.now.to_i),
142
- :type=>options[:type],
143
- :overwrite=>options[:overwrite],
144
- :from_public_id=>from_public_id,
145
- :to_public_id=>to_public_id,
159
+ :timestamp => (options[:timestamp] || Time.now.to_i),
160
+ :type => options[:type],
161
+ :overwrite => Cloudinary::Utils.as_safe_bool(options[:overwrite]),
162
+ :from_public_id => from_public_id,
163
+ :to_public_id => to_public_id,
164
+ :invalidate => Cloudinary::Utils.as_safe_bool(options[:invalidate])
146
165
  }
147
- end
166
+ end
148
167
  end
149
168
 
150
169
  def self.exists?(public_id, options={})
151
170
  cloudinary_url = Cloudinary::Utils.cloudinary_url(public_id, options)
152
171
  begin
153
- RestClient::Request.execute(:method => :head, :url => cloudinary_url, :timeout=>5).code.to_s =~ /2\d{2}/
154
- rescue RestClient::ResourceNotFound => e
172
+ RestClient::Request.execute(:method => :head, :url => cloudinary_url, :timeout => 5).code.to_s =~ /2\d{2}/
173
+ rescue RestClient::ResourceNotFound
155
174
  return false
156
175
  end
157
-
176
+
158
177
  end
159
178
 
160
179
  def self.explicit(public_id, options={})
161
- call_api("explicit", options) do
162
- {
163
- :timestamp=>(options[:timestamp] || Time.now.to_i),
164
- :type=>options[:type],
165
- :public_id=> public_id,
166
- :callback=> options[:callback],
167
- :eager=>build_eager(options[:eager]),
168
- :eager_notification_url=>options[:eager_notification_url],
169
- :eager_async=>Cloudinary::Utils.as_safe_bool(options[:eager_async]),
170
- :headers=>build_custom_headers(options[:headers]),
171
- :tags=>options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(","),
172
- :face_coordinates => options[:face_coordinates] && Cloudinary::Utils.encode_double_array(options[:face_coordinates])
173
- }
174
- end
180
+ call_api("explicit", options) do
181
+ self.build_explicit_api_params(public_id, options)
182
+ end
175
183
  end
176
-
177
- TEXT_PARAMS = [:public_id, :font_family, :font_size, :font_color, :text_align, :font_weight, :font_style, :background, :opacity, :text_decoration, :line_spacing]
184
+
185
+ # Creates a new archive in the server and returns information in JSON format
186
+ def self.create_archive(options={}, target_format = nil)
187
+ call_api("generate_archive", options) do
188
+ opt = Cloudinary::Utils.archive_params(options)
189
+ opt[:target_format] = target_format if target_format
190
+ opt
191
+ end
192
+ end
193
+
194
+ # Creates a new zip archive in the server and returns information in JSON format
195
+ def self.create_zip(options={})
196
+ create_archive(options, "zip")
197
+ end
198
+
199
+ TEXT_PARAMS = [:public_id, :font_family, :font_size, :font_color, :text_align, :font_weight, :font_style, :background, :opacity, :text_decoration, :line_spacing]
200
+
178
201
  def self.text(text, options={})
179
202
  call_api("text", options) do
180
- params = {:timestamp => Time.now.to_i, :text=>text}
181
- TEXT_PARAMS.each{|k| params[k] = options[k] if !options[k].nil?}
203
+ params = { :timestamp => Time.now.to_i, :text => text }
204
+ TEXT_PARAMS.each { |k| params[k] = options[k] unless options[k].nil? }
182
205
  params
183
206
  end
184
- end
185
-
207
+ end
208
+
186
209
  def self.generate_sprite(tag, options={})
187
210
  version_store = options.delete(:version_store)
188
-
211
+
189
212
  result = call_api("sprite", options) do
190
213
  {
191
- :timestamp=>(options[:timestamp] || Time.now.to_i),
192
- :tag=>tag,
193
- :async=>options[:async],
194
- :notification_url=>options[:notification_url],
195
- :transformation => Cloudinary::Utils.generate_transformation_string(options.merge(:fetch_format=>options[:format]))
196
- }
214
+ :timestamp => (options[:timestamp] || Time.now.to_i),
215
+ :tag => tag,
216
+ :async => options[:async],
217
+ :notification_url => options[:notification_url],
218
+ :transformation => Cloudinary::Utils.generate_transformation_string(options.merge(:fetch_format => options[:format]))
219
+ }
197
220
  end
198
-
221
+
199
222
  if version_store == :file && result && result["version"]
200
223
  if defined?(Rails) && defined?(Rails.root)
201
224
  FileUtils.mkdir_p("#{Rails.root}/tmp/cloudinary")
202
- File.open("#{Rails.root}/tmp/cloudinary/cloudinary_sprite_#{tag}.version", "w"){|file| file.print result["version"].to_s}
203
- end
204
- end
225
+ File.open("#{Rails.root}/tmp/cloudinary/cloudinary_sprite_#{tag}.version", "w") { |file| file.print result["version"].to_s }
226
+ end
227
+ end
205
228
  return result
206
229
  end
207
230
 
208
231
  def self.multi(tag, options={})
209
232
  call_api("multi", options) do
210
233
  {
211
- :timestamp=>(options[:timestamp] || Time.now.to_i),
212
- :tag=>tag,
213
- :format=>options[:format],
214
- :async=>options[:async],
215
- :notification_url=>options[:notification_url],
216
- :transformation => Cloudinary::Utils.generate_transformation_string(options.clone)
217
- }
234
+ :timestamp => (options[:timestamp] || Time.now.to_i),
235
+ :tag => tag,
236
+ :format => options[:format],
237
+ :async => options[:async],
238
+ :notification_url => options[:notification_url],
239
+ :transformation => Cloudinary::Utils.generate_transformation_string(options.clone)
240
+ }
218
241
  end
219
242
  end
220
-
221
- def self.explode(public_id, options={})
243
+
244
+ def self.explode(public_id, options={})
222
245
  call_api("explode", options) do
223
246
  {
224
- :timestamp=>(options[:timestamp] || Time.now.to_i),
225
- :public_id=>public_id,
226
- :type=>options[:type],
227
- :format=>options[:format],
228
- :notification_url=>options[:notification_url],
229
- :transformation => Cloudinary::Utils.generate_transformation_string(options.clone)
230
- }
247
+ :timestamp => (options[:timestamp] || Time.now.to_i),
248
+ :public_id => public_id,
249
+ :type => options[:type],
250
+ :format => options[:format],
251
+ :notification_url => options[:notification_url],
252
+ :transformation => Cloudinary::Utils.generate_transformation_string(options.clone)
253
+ }
231
254
  end
232
255
  end
233
-
256
+
234
257
  # options may include 'exclusive' (boolean) which causes clearing this tag from all other resources
235
258
  def self.add_tag(tag, public_ids = [], options = {})
236
259
  exclusive = options.delete(:exclusive)
237
- command = exclusive ? "set_exclusive" : "add"
238
- return self.call_tags_api(tag, command, public_ids, options)
260
+ command = exclusive ? "set_exclusive" : "add"
261
+ return self.call_tags_api(tag, command, public_ids, options)
239
262
  end
240
263
 
241
264
  def self.remove_tag(tag, public_ids = [], options = {})
242
- return self.call_tags_api(tag, "remove", public_ids, options)
265
+ return self.call_tags_api(tag, "remove", public_ids, options)
243
266
  end
244
267
 
245
268
  def self.replace_tag(tag, public_ids = [], options = {})
246
- return self.call_tags_api(tag, "replace", public_ids, options)
269
+ return self.call_tags_api(tag, "replace", public_ids, options)
247
270
  end
248
-
271
+
249
272
  private
250
-
273
+
251
274
  def self.call_tags_api(tag, command, public_ids = [], options = {})
252
275
  return call_api("tags", options) do
253
276
  {
254
- :timestamp=>(options[:timestamp] || Time.now.to_i),
255
- :tag=>tag,
277
+ :timestamp => (options[:timestamp] || Time.now.to_i),
278
+ :tag => tag,
256
279
  :public_ids => Cloudinary::Utils.build_array(public_ids),
257
- :command => command,
258
- :type => options[:type]
259
- }
260
- end
280
+ :command => command,
281
+ :type => options[:type]
282
+ }
283
+ end
261
284
  end
262
-
285
+
263
286
  def self.call_api(action, options)
264
- options = options.clone
287
+ options = options.clone
265
288
  return_error = options.delete(:return_error)
266
289
 
267
290
  params, non_signable = yield
268
- non_signable ||= []
269
-
291
+ non_signable ||= []
292
+
270
293
  unless options[:unsigned]
271
- api_key = options[:api_key] || Cloudinary.config.api_key || raise(CloudinaryException, "Must supply api_key")
272
- api_secret = options[:api_secret] || Cloudinary.config.api_secret || raise(CloudinaryException, "Must supply api_secret")
273
- params[:signature] = Cloudinary::Utils.api_sign_request(params.reject{|k,v| non_signable.include?(k)}, api_secret)
274
- params[:api_key] = api_key
294
+ api_key = options[:api_key] || Cloudinary.config.api_key || raise(CloudinaryException, "Must supply api_key")
295
+ api_secret = options[:api_secret] || Cloudinary.config.api_secret || raise(CloudinaryException, "Must supply api_secret")
296
+ params[:signature] = Cloudinary::Utils.api_sign_request(params.reject { |k, v| non_signable.include?(k) }, api_secret)
297
+ params[:api_key] = api_key
275
298
  end
276
299
  timeout = options[:timeout] || Cloudinary.config.timeout || 60
277
300
 
278
301
  result = nil
279
-
280
- api_url = Cloudinary::Utils.cloudinary_api_url(action, options)
281
- headers = {"User-Agent" => Cloudinary::USER_AGENT}
302
+
303
+ api_url = Cloudinary::Utils.cloudinary_api_url(action, options)
304
+ headers = { "User-Agent" => Cloudinary::USER_AGENT }
282
305
  headers['Content-Range'] = options[:content_range] if options[:content_range]
283
- RestClient::Request.execute(:method => :post, :url => api_url, :payload => params.reject{|k, v| v.nil? || v==""}, :timeout=> timeout, :headers => headers) do
284
- |response, request, tmpresult|
285
- raise CloudinaryException, "Server returned unexpected status code - #{response.code} - #{response.body}" if ![200,400,401,403,404,500].include?(response.code)
306
+ RestClient::Request.execute(:method => :post, :url => api_url, :payload => params.reject { |k, v| v.nil? || v=="" }, :timeout => timeout, :headers => headers) do
307
+ |response, request, tmpresult|
308
+ raise CloudinaryException, "Server returned unexpected status code - #{response.code} - #{response.body}" unless [200, 400, 401, 403, 404, 500].include?(response.code)
286
309
  begin
287
310
  result = Cloudinary::Utils.json_decode(response.body)
288
311
  rescue => e
@@ -295,13 +318,13 @@ class Cloudinary::Uploader
295
318
  else
296
319
  raise CloudinaryException, result["error"]["message"]
297
320
  end
298
- end
321
+ end
299
322
  end
300
-
301
- result
323
+
324
+ result
302
325
  end
303
-
326
+
304
327
  def self.build_custom_headers(headers)
305
- Array(headers).map{|*a| a.join(": ")}.join("\n")
328
+ Array(headers).map { |*a| a.join(": ") }.join("\n")
306
329
  end
307
330
  end