slidize_cloud 24.9.0 → 24.10.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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +9 -0
  3. data/README.md +118 -0
  4. data/Rakefile +10 -0
  5. data/TestData/macros.pptm +0 -0
  6. data/TestData/master.pptx +0 -0
  7. data/TestData/protected.pptx +0 -0
  8. data/TestData/test.pptx +0 -0
  9. data/TestData/watermark.png +0 -0
  10. data/git_push.sh +57 -0
  11. data/lib/slidize_cloud/api/slidize_api.rb +829 -0
  12. data/lib/slidize_cloud/api_client.rb +451 -0
  13. data/lib/slidize_cloud/api_error.rb +75 -0
  14. data/lib/slidize_cloud/configuration.rb +389 -0
  15. data/lib/slidize_cloud/models/convert_request.rb +238 -0
  16. data/lib/slidize_cloud/models/convert_to_video_request.rb +245 -0
  17. data/lib/slidize_cloud/models/export_format.rb +83 -0
  18. data/lib/slidize_cloud/models/image_watermark_options.rb +247 -0
  19. data/lib/slidize_cloud/models/image_watermark_request.rb +256 -0
  20. data/lib/slidize_cloud/models/merge_options.rb +246 -0
  21. data/lib/slidize_cloud/models/merge_request.rb +247 -0
  22. data/lib/slidize_cloud/models/protect_request.rb +245 -0
  23. data/lib/slidize_cloud/models/protection_options.rb +256 -0
  24. data/lib/slidize_cloud/models/replace_text_options.rb +256 -0
  25. data/lib/slidize_cloud/models/replace_text_request.rb +247 -0
  26. data/lib/slidize_cloud/models/split_options.rb +237 -0
  27. data/lib/slidize_cloud/models/split_request.rb +245 -0
  28. data/lib/slidize_cloud/models/text_watermark_options.rb +277 -0
  29. data/lib/slidize_cloud/models/text_watermark_request.rb +247 -0
  30. data/lib/slidize_cloud/models/unprotect_request.rb +236 -0
  31. data/lib/slidize_cloud/models/video_options.rb +287 -0
  32. data/lib/slidize_cloud/models/video_resolution_type.rb +59 -0
  33. data/lib/slidize_cloud/models/video_transition_type.rb +63 -0
  34. data/lib/slidize_cloud/version.rb +32 -0
  35. data/lib/slidize_cloud.rb +76 -0
  36. data/slidize_cloud.gemspec +56 -0
  37. data/spec/api_client_spec.rb +240 -0
  38. data/spec/configuration_spec.rb +99 -0
  39. data/spec/spec_helper.rb +128 -0
  40. metadata +44 -3
@@ -0,0 +1,451 @@
1
+ =begin
2
+ /**
3
+ * --------------------------------------------------------------------------------------------------------------------
4
+ * <copyright company="Smallize">
5
+ * Copyright (c) 2024 Slidize for Cloud
6
+ * </copyright>
7
+ * <summary>
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in all
16
+ * copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ * SOFTWARE.
25
+ * </summary>
26
+ * --------------------------------------------------------------------------------------------------------------------
27
+ */
28
+ =end
29
+
30
+ require 'date'
31
+ require 'json'
32
+ require 'logger'
33
+ require 'tempfile'
34
+ require 'time'
35
+ require 'faraday'
36
+ require 'faraday/multipart' if Gem::Version.new(Faraday::VERSION) >= Gem::Version.new('2.0')
37
+
38
+ module SlidizeCloud
39
+ class ApiClient
40
+ # The Configuration object holding settings to be used in the API client.
41
+ attr_accessor :config
42
+
43
+ # Defines the headers to be used in HTTP requests of all API calls by default.
44
+ #
45
+ # @return [Hash]
46
+ attr_accessor :default_headers
47
+
48
+ # Initializes the ApiClient
49
+ # @option config [Configuration] Configuration for initializing the object, default to Configuration.default
50
+ def initialize(config = Configuration.default)
51
+ @config = config
52
+ @user_agent = "OpenAPI-Generator/#{VERSION}/ruby"
53
+ @default_headers = {
54
+ 'Content-Type' => 'application/json',
55
+ 'User-Agent' => @user_agent
56
+ }
57
+ end
58
+
59
+ def self.default
60
+ @@default ||= ApiClient.new
61
+ end
62
+
63
+ # Call an API with given options.
64
+ #
65
+ # @return [Array<(Object, Integer, Hash)>] an array of 3 elements:
66
+ # the data deserialized from response body (could be nil), response status code and response headers.
67
+ def call_api(http_method, path, opts = {})
68
+ begin
69
+ response = connection(opts).public_send(http_method.to_sym.downcase) do |req|
70
+ build_request(http_method, path, req, opts)
71
+ end
72
+
73
+ if config.debugging
74
+ config.logger.debug "HTTP response body ~BEGIN~\n#{response.body}\n~END~\n"
75
+ end
76
+
77
+ unless response.success?
78
+ if response.status == 0 && response.respond_to?(:return_message)
79
+ # Errors from libcurl will be made visible here
80
+ fail ApiError.new(code: 0,
81
+ message: response.return_message)
82
+ else
83
+ fail ApiError.new(code: response.status,
84
+ response_headers: response.headers,
85
+ response_body: response.body),
86
+ response.reason_phrase
87
+ end
88
+ end
89
+ rescue Faraday::TimeoutError
90
+ fail ApiError.new('Connection timed out')
91
+ rescue Faraday::ConnectionFailed
92
+ fail ApiError.new('Connection failed')
93
+ end
94
+
95
+ if opts[:return_type]
96
+ data = deserialize(response, opts[:return_type])
97
+ else
98
+ data = nil
99
+ end
100
+ return data, response.status, response.headers
101
+ end
102
+
103
+ # Builds the HTTP request
104
+ #
105
+ # @param [String] http_method HTTP method/verb (e.g. POST)
106
+ # @param [String] path URL path (e.g. /account/new)
107
+ # @option opts [Hash] :header_params Header parameters
108
+ # @option opts [Hash] :query_params Query parameters
109
+ # @option opts [Hash] :form_params Query parameters
110
+ # @option opts [Object] :body HTTP body (JSON/XML)
111
+ # @return [Faraday::Request] A Faraday Request
112
+ def build_request(http_method, path, request, opts = {})
113
+ url = build_request_url(path, opts)
114
+ http_method = http_method.to_sym.downcase
115
+
116
+ header_params = @default_headers.merge(opts[:header_params] || {})
117
+ query_params = opts[:query_params] || {}
118
+ form_params = opts[:form_params] || {}
119
+
120
+ update_params_for_auth! header_params, query_params, opts[:auth_names]
121
+
122
+ if [:post, :patch, :put, :delete].include?(http_method)
123
+ req_body = build_request_body(header_params, form_params, opts[:body])
124
+ if config.debugging
125
+ config.logger.debug "HTTP request body param ~BEGIN~\n#{req_body}\n~END~\n"
126
+ end
127
+ end
128
+ request.headers = header_params
129
+ request.body = req_body
130
+
131
+ # Overload default options only if provided
132
+ request.options.params_encoder = config.params_encoder if config.params_encoder
133
+ request.options.timeout = config.timeout if config.timeout
134
+
135
+ request.url url
136
+ request.params = query_params
137
+ download_file(request) if opts[:return_type] == 'File' || opts[:return_type] == 'Binary'
138
+ request
139
+ end
140
+
141
+ # Builds the HTTP request body
142
+ #
143
+ # @param [Hash] header_params Header parameters
144
+ # @param [Hash] form_params Query parameters
145
+ # @param [Object] body HTTP body (JSON/XML)
146
+ # @return [String] HTTP body data in the form of string
147
+ def build_request_body(header_params, form_params, body)
148
+ # http form
149
+ if header_params['Content-Type'] == 'application/x-www-form-urlencoded'
150
+ data = URI.encode_www_form(form_params)
151
+ elsif header_params['Content-Type'] == 'multipart/form-data'
152
+ data = {}
153
+ form_params.each do |key, value|
154
+ case value
155
+ when ::File, ::Tempfile
156
+ # TODO hardcode to application/octet-stream, need better way to detect content type
157
+ data[key] = Faraday::FilePart.new(value.path, 'application/octet-stream', value.path)
158
+ when ::Array, nil
159
+ if (value.count > 0 && value[0].is_a?(File))
160
+ data[key] = []
161
+ value.each { |f| data[key] << Faraday::FilePart.new(f.path, 'application/octet-stream', f.path)}
162
+ else
163
+ # let Faraday handle Array and nil parameters
164
+ data[key] = value
165
+ end
166
+ else
167
+ data[key] = object_to_http_body(value)
168
+ #data[key] = value.to_s
169
+ end
170
+ end
171
+ elsif body
172
+ data = body.is_a?(String) ? body : body.to_json
173
+ else
174
+ data = nil
175
+ end
176
+ data
177
+ end
178
+
179
+ def download_file(request)
180
+ @stream = []
181
+
182
+ # handle streaming Responses
183
+ request.options.on_data = Proc.new do |chunk, overall_received_bytes|
184
+ @stream << chunk
185
+ end
186
+ end
187
+
188
+ def connection(opts)
189
+ opts[:header_params]['Content-Type'] == 'multipart/form-data' ? connection_multipart : connection_regular
190
+ end
191
+
192
+ def connection_multipart
193
+ @connection_multipart ||= build_connection do |conn|
194
+ conn.request :multipart, flat_encode: true
195
+ conn.request :url_encoded
196
+ end
197
+ end
198
+
199
+ def connection_regular
200
+ @connection_regular ||= build_connection
201
+ end
202
+
203
+ def build_connection
204
+ Faraday.new(url: config.base_url, ssl: ssl_options, proxy: config.proxy) do |conn|
205
+ basic_auth(conn)
206
+ config.configure_middleware(conn)
207
+ yield(conn) if block_given?
208
+ conn.adapter(Faraday.default_adapter)
209
+ config.configure_connection(conn)
210
+ end
211
+ end
212
+
213
+ def ssl_options
214
+ {
215
+ ca_file: config.ssl_ca_file,
216
+ verify: config.ssl_verify,
217
+ verify_mode: config.ssl_verify_mode,
218
+ client_cert: config.ssl_client_cert,
219
+ client_key: config.ssl_client_key
220
+ }
221
+ end
222
+
223
+ def basic_auth(conn)
224
+ if config.username && config.password
225
+ if Gem::Version.new(Faraday::VERSION) >= Gem::Version.new('2.0')
226
+ conn.request(:authorization, :basic, config.username, config.password)
227
+ else
228
+ conn.request(:basic_auth, config.username, config.password)
229
+ end
230
+ end
231
+ end
232
+
233
+ # Check if the given MIME is a JSON MIME.
234
+ # JSON MIME examples:
235
+ # application/json
236
+ # application/json; charset=UTF8
237
+ # APPLICATION/JSON
238
+ # */*
239
+ # @param [String] mime MIME
240
+ # @return [Boolean] True if the MIME is application/json
241
+ def json_mime?(mime)
242
+ (mime == '*/*') || !(mime =~ /Application\/.*json(?!p)(;.*)?/i).nil?
243
+ end
244
+
245
+ # Deserialize the response to the given return type.
246
+ #
247
+ # @param [Response] response HTTP response
248
+ # @param [String] return_type some examples: "User", "Array<User>", "Hash<String, Integer>"
249
+ def deserialize(response, return_type)
250
+ body = response.body
251
+
252
+ # handle file downloading - return the File instance processed in request callbacks
253
+ # note that response body is empty when the file is written in chunks in request on_body callback
254
+ if return_type == 'File'
255
+ if @config.return_binary_data == true
256
+ # return byte stream
257
+ encoding = body.encoding
258
+ return @stream.join.force_encoding(encoding)
259
+ else
260
+ # return file instead of binary data
261
+ content_disposition = response.headers['Content-Disposition']
262
+ if content_disposition && content_disposition =~ /filename=/i
263
+ filename = content_disposition[/filename=['"]?([^'"\s]+)['"]?/, 1]
264
+ prefix = sanitize_filename(filename)
265
+ else
266
+ prefix = 'download-'
267
+ end
268
+ prefix = prefix + '-' unless prefix.end_with?('-')
269
+ encoding = body.encoding
270
+ @tempfile = Tempfile.open(prefix, @config.temp_folder_path, encoding: encoding)
271
+ @tempfile.write(@stream.join.force_encoding(encoding))
272
+ @tempfile.close
273
+ @config.logger.info "Temp file written to #{@tempfile.path}, please copy the file to a proper folder "\
274
+ "with e.g. `FileUtils.cp(tempfile.path, '/new/file/path')` otherwise the temp file "\
275
+ "will be deleted automatically with GC. It's also recommended to delete the temp file "\
276
+ "explicitly with `tempfile.delete`"
277
+ return @tempfile
278
+ end
279
+ end
280
+
281
+ return nil if body.nil? || body.empty?
282
+
283
+ # return response body directly for String return type
284
+ return body if return_type == 'String'
285
+
286
+ # ensuring a default content type
287
+ content_type = response.headers['Content-Type'] || 'application/json'
288
+
289
+ fail "Content-Type is not supported: #{content_type}" unless json_mime?(content_type)
290
+
291
+ begin
292
+ data = JSON.parse("[#{body}]", :symbolize_names => true)[0]
293
+ rescue JSON::ParserError => e
294
+ if %w(String Date Time).include?(return_type)
295
+ data = body
296
+ else
297
+ raise e
298
+ end
299
+ end
300
+
301
+ convert_to_type data, return_type
302
+ end
303
+
304
+ # Convert data to the given return type.
305
+ # @param [Object] data Data to be converted
306
+ # @param [String] return_type Return type
307
+ # @return [Mixed] Data in a particular type
308
+ def convert_to_type(data, return_type)
309
+ return nil if data.nil?
310
+ case return_type
311
+ when 'String'
312
+ data.to_s
313
+ when 'Integer'
314
+ data.to_i
315
+ when 'Float'
316
+ data.to_f
317
+ when 'Boolean'
318
+ data == true
319
+ when 'Time'
320
+ # parse date time (expecting ISO 8601 format)
321
+ Time.parse data
322
+ when 'Date'
323
+ # parse date time (expecting ISO 8601 format)
324
+ Date.parse data
325
+ when 'Object'
326
+ # generic object (usually a Hash), return directly
327
+ data
328
+ when /\AArray<(.+)>\z/
329
+ # e.g. Array<Pet>
330
+ sub_type = $1
331
+ data.map { |item| convert_to_type(item, sub_type) }
332
+ when /\AHash\<String, (.+)\>\z/
333
+ # e.g. Hash<String, Integer>
334
+ sub_type = $1
335
+ {}.tap do |hash|
336
+ data.each { |k, v| hash[k] = convert_to_type(v, sub_type) }
337
+ end
338
+ else
339
+ # models (e.g. Pet) or oneOf
340
+ klass = SlidizeCloud.const_get(return_type)
341
+ klass.respond_to?(:openapi_one_of) ? klass.build(data) : klass.build_from_hash(data)
342
+ end
343
+ end
344
+
345
+ # Sanitize filename by removing path.
346
+ # e.g. ../../sun.gif becomes sun.gif
347
+ #
348
+ # @param [String] filename the filename to be sanitized
349
+ # @return [String] the sanitized filename
350
+ def sanitize_filename(filename)
351
+ filename.gsub(/.*[\/\\]/, '')
352
+ end
353
+
354
+ def build_request_url(path, opts = {})
355
+ # Add leading and trailing slashes to path
356
+ path = "/#{path}".gsub(/\/+/, '/')
357
+ @config.base_url(opts[:operation]) + path
358
+ end
359
+
360
+ # Update header and query params based on authentication settings.
361
+ #
362
+ # @param [Hash] header_params Header parameters
363
+ # @param [Hash] query_params Query parameters
364
+ # @param [String] auth_names Authentication scheme name
365
+ def update_params_for_auth!(header_params, query_params, auth_names)
366
+ Array(auth_names).each do |auth_name|
367
+ auth_setting = @config.auth_settings[auth_name]
368
+ next unless auth_setting
369
+ case auth_setting[:in]
370
+ when 'header' then header_params[auth_setting[:key]] = auth_setting[:value]
371
+ when 'query' then query_params[auth_setting[:key]] = auth_setting[:value]
372
+ else fail ArgumentError, 'Authentication token must be in `query` or `header`'
373
+ end
374
+ end
375
+ end
376
+
377
+ # Sets user agent in HTTP header
378
+ #
379
+ # @param [String] user_agent User agent (e.g. openapi-generator/ruby/1.0.0)
380
+ def user_agent=(user_agent)
381
+ @user_agent = user_agent
382
+ @default_headers['User-Agent'] = @user_agent
383
+ end
384
+
385
+ # Return Accept header based on an array of accepts provided.
386
+ # @param [Array] accepts array for Accept
387
+ # @return [String] the Accept header (e.g. application/json)
388
+ def select_header_accept(accepts)
389
+ return nil if accepts.nil? || accepts.empty?
390
+ # use JSON when present, otherwise use all of the provided
391
+ json_accept = accepts.find { |s| json_mime?(s) }
392
+ json_accept || accepts.join(',')
393
+ end
394
+
395
+ # Return Content-Type header based on an array of content types provided.
396
+ # @param [Array] content_types array for Content-Type
397
+ # @return [String] the Content-Type header (e.g. application/json)
398
+ def select_header_content_type(content_types)
399
+ # return nil by default
400
+ return if content_types.nil? || content_types.empty?
401
+ # use JSON when present, otherwise use the first one
402
+ json_content_type = content_types.find { |s| json_mime?(s) }
403
+ json_content_type || content_types.first
404
+ end
405
+
406
+ # Convert object (array, hash, object, etc) to JSON string.
407
+ # @param [Object] model object to be converted into JSON string
408
+ # @return [String] JSON string representation of the object
409
+ def object_to_http_body(model)
410
+ return model if model.nil? || model.is_a?(String)
411
+ local_body = nil
412
+ if model.is_a?(Array)
413
+ local_body = model.map { |m| object_to_hash(m) }
414
+ else
415
+ local_body = object_to_hash(model)
416
+ end
417
+ local_body.to_json
418
+ end
419
+
420
+ # Convert object(non-array) to hash.
421
+ # @param [Object] obj object to be converted into JSON string
422
+ # @return [String] JSON string representation of the object
423
+ def object_to_hash(obj)
424
+ if obj.respond_to?(:to_hash)
425
+ obj.to_hash
426
+ else
427
+ obj
428
+ end
429
+ end
430
+
431
+ # Build parameter value according to the given collection format.
432
+ # @param [String] collection_format one of :csv, :ssv, :tsv, :pipes and :multi
433
+ def build_collection_param(param, collection_format)
434
+ case collection_format
435
+ when :csv
436
+ param.join(',')
437
+ when :ssv
438
+ param.join(' ')
439
+ when :tsv
440
+ param.join("\t")
441
+ when :pipes
442
+ param.join('|')
443
+ when :multi
444
+ # return the array directly as typhoeus will handle it as expected
445
+ param
446
+ else
447
+ fail "unknown collection format: #{collection_format.inspect}"
448
+ end
449
+ end
450
+ end
451
+ end
@@ -0,0 +1,75 @@
1
+ =begin
2
+ /**
3
+ * --------------------------------------------------------------------------------------------------------------------
4
+ * <copyright company="Smallize">
5
+ * Copyright (c) 2024 Slidize for Cloud
6
+ * </copyright>
7
+ * <summary>
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in all
16
+ * copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ * SOFTWARE.
25
+ * </summary>
26
+ * --------------------------------------------------------------------------------------------------------------------
27
+ */
28
+ =end
29
+
30
+ module SlidizeCloud
31
+ class ApiError < StandardError
32
+ attr_reader :code, :response_headers, :response_body
33
+
34
+ # Usage examples:
35
+ # ApiError.new
36
+ # ApiError.new("message")
37
+ # ApiError.new(:code => 500, :response_headers => {}, :response_body => "")
38
+ # ApiError.new(:code => 404, :message => "Not Found")
39
+ def initialize(arg = nil)
40
+ if arg.is_a? Hash
41
+ if arg.key?(:message) || arg.key?('message')
42
+ super(arg[:message] || arg['message'])
43
+ else
44
+ super arg
45
+ end
46
+
47
+ arg.each do |k, v|
48
+ instance_variable_set "@#{k}", v
49
+ end
50
+ else
51
+ super arg
52
+ @message = arg
53
+ end
54
+ end
55
+
56
+ # Override to_s to display a friendly error message
57
+ def to_s
58
+ message
59
+ end
60
+
61
+ def message
62
+ if @message.nil?
63
+ msg = "Error message: the server returns an error"
64
+ else
65
+ msg = @message
66
+ end
67
+
68
+ msg += "\nHTTP status code: #{code}" if code
69
+ msg += "\nResponse headers: #{response_headers}" if response_headers
70
+ msg += "\nResponse body: #{response_body}" if response_body
71
+
72
+ msg
73
+ end
74
+ end
75
+ end