telestream_cloud_flip 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.
Files changed (118) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +7 -0
  3. data/README.md +130 -0
  4. data/Rakefile +8 -0
  5. data/docs/CanceledResponse.md +8 -0
  6. data/docs/CloudNotificationSettings.md +11 -0
  7. data/docs/CloudNotificationSettingsEvents.md +11 -0
  8. data/docs/CopyProfileBody.md +9 -0
  9. data/docs/CountResponse.md +8 -0
  10. data/docs/CreateEncodingBody.md +10 -0
  11. data/docs/CreateVideoBody.md +12 -0
  12. data/docs/DeletedResponse.md +8 -0
  13. data/docs/Encoding.md +38 -0
  14. data/docs/EncodingSignedUrl.md +8 -0
  15. data/docs/EncodingSignedUrls.md +8 -0
  16. data/docs/Error.md +9 -0
  17. data/docs/ExtraFile.md +10 -0
  18. data/docs/Factory.md +25 -0
  19. data/docs/FactoryBody.md +23 -0
  20. data/docs/FactoryBodyStorageCredentialAttributes.md +11 -0
  21. data/docs/FactorySync.md +8 -0
  22. data/docs/FactorySyncBody.md +8 -0
  23. data/docs/FlipApi.md +2179 -0
  24. data/docs/PaginatedEncodingsCollection.md +11 -0
  25. data/docs/PaginatedFactoryCollection.md +11 -0
  26. data/docs/PaginatedProfilesCollection.md +11 -0
  27. data/docs/PaginatedVideoCollection.md +11 -0
  28. data/docs/PaginatedWorkflowsCollection.md +11 -0
  29. data/docs/Profile.md +135 -0
  30. data/docs/ProfileBody.md +137 -0
  31. data/docs/ResubmitVideoBody.md +8 -0
  32. data/docs/RetriedResponse.md +8 -0
  33. data/docs/SignedVideoUrl.md +8 -0
  34. data/docs/UpdateEncodingBody.md +9 -0
  35. data/docs/UploadSession.md +13 -0
  36. data/docs/Video.md +31 -0
  37. data/docs/VideoMetadata.md +7 -0
  38. data/docs/VideoUploadBody.md +24 -0
  39. data/git_push.sh +55 -0
  40. data/lib/telestream_cloud_flip/api/flip_api.rb +2385 -0
  41. data/lib/telestream_cloud_flip/api_client.rb +389 -0
  42. data/lib/telestream_cloud_flip/api_error.rb +38 -0
  43. data/lib/telestream_cloud_flip/configuration.rb +209 -0
  44. data/lib/telestream_cloud_flip/models/canceled_response.rb +189 -0
  45. data/lib/telestream_cloud_flip/models/cloud_notification_settings.rb +237 -0
  46. data/lib/telestream_cloud_flip/models/cloud_notification_settings_events.rb +239 -0
  47. data/lib/telestream_cloud_flip/models/copy_profile_body.rb +209 -0
  48. data/lib/telestream_cloud_flip/models/count_response.rb +189 -0
  49. data/lib/telestream_cloud_flip/models/create_encoding_body.rb +214 -0
  50. data/lib/telestream_cloud_flip/models/create_video_body.rb +231 -0
  51. data/lib/telestream_cloud_flip/models/deleted_response.rb +189 -0
  52. data/lib/telestream_cloud_flip/models/encoding.rb +486 -0
  53. data/lib/telestream_cloud_flip/models/encoding_signed_url.rb +189 -0
  54. data/lib/telestream_cloud_flip/models/encoding_signed_urls.rb +191 -0
  55. data/lib/telestream_cloud_flip/models/error.rb +199 -0
  56. data/lib/telestream_cloud_flip/models/extra_file.rb +221 -0
  57. data/lib/telestream_cloud_flip/models/factory.rb +388 -0
  58. data/lib/telestream_cloud_flip/models/factory_body.rb +374 -0
  59. data/lib/telestream_cloud_flip/models/factory_body_storage_credential_attributes.rb +215 -0
  60. data/lib/telestream_cloud_flip/models/factory_sync.rb +222 -0
  61. data/lib/telestream_cloud_flip/models/factory_sync_body.rb +227 -0
  62. data/lib/telestream_cloud_flip/models/paginated_encodings_collection.rb +240 -0
  63. data/lib/telestream_cloud_flip/models/paginated_factory_collection.rb +220 -0
  64. data/lib/telestream_cloud_flip/models/paginated_profiles_collection.rb +220 -0
  65. data/lib/telestream_cloud_flip/models/paginated_video_collection.rb +220 -0
  66. data/lib/telestream_cloud_flip/models/paginated_workflows_collection.rb +220 -0
  67. data/lib/telestream_cloud_flip/models/profile.rb +1777 -0
  68. data/lib/telestream_cloud_flip/models/profile_body.rb +1762 -0
  69. data/lib/telestream_cloud_flip/models/resubmit_video_body.rb +189 -0
  70. data/lib/telestream_cloud_flip/models/retried_response.rb +189 -0
  71. data/lib/telestream_cloud_flip/models/signed_video_url.rb +189 -0
  72. data/lib/telestream_cloud_flip/models/update_encoding_body.rb +199 -0
  73. data/lib/telestream_cloud_flip/models/upload_session.rb +249 -0
  74. data/lib/telestream_cloud_flip/models/video.rb +418 -0
  75. data/lib/telestream_cloud_flip/models/video_metadata.rb +179 -0
  76. data/lib/telestream_cloud_flip/models/video_upload_body.rb +362 -0
  77. data/lib/telestream_cloud_flip/uploader.rb +244 -0
  78. data/lib/telestream_cloud_flip/version.rb +18 -0
  79. data/lib/telestream_cloud_flip.rb +79 -0
  80. data/spec/api/flip_api_spec.rb +550 -0
  81. data/spec/api_client_spec.rb +226 -0
  82. data/spec/configuration_spec.rb +42 -0
  83. data/spec/models/canceled_response_spec.rb +42 -0
  84. data/spec/models/cloud_notification_settings_events_spec.rb +60 -0
  85. data/spec/models/cloud_notification_settings_spec.rb +60 -0
  86. data/spec/models/copy_profile_body_spec.rb +48 -0
  87. data/spec/models/count_response_spec.rb +42 -0
  88. data/spec/models/create_encoding_body_spec.rb +54 -0
  89. data/spec/models/create_video_body_spec.rb +66 -0
  90. data/spec/models/deleted_response_spec.rb +42 -0
  91. data/spec/models/encoding_signed_url_spec.rb +42 -0
  92. data/spec/models/encoding_signed_urls_spec.rb +42 -0
  93. data/spec/models/encoding_spec.rb +222 -0
  94. data/spec/models/error_spec.rb +48 -0
  95. data/spec/models/extra_file_spec.rb +54 -0
  96. data/spec/models/factory_body_spec.rb +136 -0
  97. data/spec/models/factory_body_storage_credential_attributes_spec.rb +60 -0
  98. data/spec/models/factory_spec.rb +148 -0
  99. data/spec/models/factory_sync_body_spec.rb +46 -0
  100. data/spec/models/factory_sync_spec.rb +46 -0
  101. data/spec/models/paginated_encodings_collection_spec.rb +60 -0
  102. data/spec/models/paginated_factory_collection_spec.rb +60 -0
  103. data/spec/models/paginated_profiles_collection_spec.rb +60 -0
  104. data/spec/models/paginated_video_collection_spec.rb +60 -0
  105. data/spec/models/paginated_workflows_collection_spec.rb +60 -0
  106. data/spec/models/profile_body_spec.rb +916 -0
  107. data/spec/models/profile_spec.rb +916 -0
  108. data/spec/models/resubmit_video_body_spec.rb +42 -0
  109. data/spec/models/retried_response_spec.rb +42 -0
  110. data/spec/models/signed_video_url_spec.rb +42 -0
  111. data/spec/models/update_encoding_body_spec.rb +48 -0
  112. data/spec/models/upload_session_spec.rb +72 -0
  113. data/spec/models/video_metadata_spec.rb +36 -0
  114. data/spec/models/video_spec.rb +180 -0
  115. data/spec/models/video_upload_body_spec.rb +138 -0
  116. data/spec/spec_helper.rb +111 -0
  117. data/telestream_cloud_flip.gemspec +47 -0
  118. metadata +396 -0
@@ -0,0 +1,362 @@
1
+ =begin
2
+ #Flip API
3
+
4
+ #Description
5
+
6
+ OpenAPI spec version: 3.1.0
7
+ Contact: cloudsupport@telestream.net
8
+ Generated by: https://github.com/swagger-api/swagger-codegen.git
9
+ Swagger Codegen version: 2.3.0
10
+
11
+ =end
12
+
13
+ require 'date'
14
+
15
+ module TelestreamCloud::Flip
16
+
17
+ class VideoUploadBody
18
+ # Size of the file that will be uploaded in `bytes`.
19
+ attr_accessor :file_size
20
+
21
+ # Name of the file that will be uploaded.
22
+ attr_accessor :file_name
23
+
24
+ # A list of names of additional files that will be uploaded.
25
+ attr_accessor :extra_files
26
+
27
+ # A comma-separated list of profile names or IDs to be used during encoding. Alternatively, specify none so no encodings will created right away.
28
+ attr_accessor :profiles
29
+
30
+ attr_accessor :path_format
31
+
32
+ # Payload is an arbitrary text of length 256 or shorter that you can store along the Video. It is typically used to retain an association with one of your own DB record ID.
33
+ attr_accessor :payload
34
+
35
+ attr_accessor :extra_variables
36
+
37
+ # URL pointing to an image that will be used asa watermark.
38
+ attr_accessor :watermark_url
39
+
40
+ # Determines distance between the left edge of a video and the left edge of a watermark image. Can be specified in pixels or percents. This parameter can be set only if watermark_right is not.
41
+ attr_accessor :watermark_left
42
+
43
+ # Determines distance between the top edge of a video and the top edge of a watermark image. Can be specified in pixels or percents. This parameter can be set only if watermark_bottom is not.
44
+ attr_accessor :watermark_top
45
+
46
+ # Determines distance between the right edge of a video and the right edge of a watermark image. Can be specified in pixels or percents. This parameter can be set only if watermark_left is not.
47
+ attr_accessor :watermark_right
48
+
49
+ # Determines distance between the bottom edge of a video and the bottom edge of a watermark image. Can be specified in pixels or percents. This parameter can be set only if watermark_top is not.
50
+ attr_accessor :watermark_bottom
51
+
52
+ # Determines width of the watermark image. Should be specified in pixels.
53
+ attr_accessor :watermark_width
54
+
55
+ # Determines width of the watermark image. Should be specified in pixels.
56
+ attr_accessor :watermark_height
57
+
58
+ # Length of the uploaded video. Should be formatted as follows: HH:MM:SS
59
+ attr_accessor :clip_length
60
+
61
+ # Clip starts at a specific offset.
62
+ attr_accessor :clip_offset
63
+
64
+ attr_accessor :multi_chunk
65
+
66
+
67
+ # Attribute mapping from ruby-style variable name to JSON key.
68
+ def self.attribute_map
69
+ {
70
+ :'file_size' => :'file_size',
71
+ :'file_name' => :'file_name',
72
+ :'extra_files' => :'extra_files',
73
+ :'profiles' => :'profiles',
74
+ :'path_format' => :'path_format',
75
+ :'payload' => :'payload',
76
+ :'extra_variables' => :'extra_variables',
77
+ :'watermark_url' => :'watermark_url',
78
+ :'watermark_left' => :'watermark_left',
79
+ :'watermark_top' => :'watermark_top',
80
+ :'watermark_right' => :'watermark_right',
81
+ :'watermark_bottom' => :'watermark_bottom',
82
+ :'watermark_width' => :'watermark_width',
83
+ :'watermark_height' => :'watermark_height',
84
+ :'clip_length' => :'clip_length',
85
+ :'clip_offset' => :'clip_offset',
86
+ :'multi_chunk' => :'multi_chunk'
87
+ }
88
+ end
89
+
90
+ # Attribute type mapping.
91
+ def self.swagger_types
92
+ {
93
+ :'file_size' => :'Integer',
94
+ :'file_name' => :'String',
95
+ :'extra_files' => :'Array<ExtraFile>',
96
+ :'profiles' => :'String',
97
+ :'path_format' => :'String',
98
+ :'payload' => :'String',
99
+ :'extra_variables' => :'Hash<String, String>',
100
+ :'watermark_url' => :'String',
101
+ :'watermark_left' => :'String',
102
+ :'watermark_top' => :'String',
103
+ :'watermark_right' => :'String',
104
+ :'watermark_bottom' => :'String',
105
+ :'watermark_width' => :'String',
106
+ :'watermark_height' => :'String',
107
+ :'clip_length' => :'String',
108
+ :'clip_offset' => :'String',
109
+ :'multi_chunk' => :'BOOLEAN'
110
+ }
111
+ end
112
+
113
+ # Initializes the object
114
+ # @param [Hash] attributes Model attributes in the form of hash
115
+ def initialize(attributes = {})
116
+ return unless attributes.is_a?(Hash)
117
+
118
+ # convert string to symbol for hash key
119
+ attributes = attributes.each_with_object({}){|(k,v), h| h[k.to_sym] = v}
120
+
121
+ if attributes.has_key?(:'file_size')
122
+ self.file_size = attributes[:'file_size']
123
+ end
124
+
125
+ if attributes.has_key?(:'file_name')
126
+ self.file_name = attributes[:'file_name']
127
+ end
128
+
129
+ if attributes.has_key?(:'extra_files')
130
+ if (value = attributes[:'extra_files']).is_a?(Array)
131
+ self.extra_files = value
132
+ end
133
+ end
134
+
135
+ if attributes.has_key?(:'profiles')
136
+ self.profiles = attributes[:'profiles']
137
+ end
138
+
139
+ if attributes.has_key?(:'path_format')
140
+ self.path_format = attributes[:'path_format']
141
+ end
142
+
143
+ if attributes.has_key?(:'payload')
144
+ self.payload = attributes[:'payload']
145
+ end
146
+
147
+ if attributes.has_key?(:'extra_variables')
148
+ if (value = attributes[:'extra_variables']).is_a?(Hash)
149
+ self.extra_variables = value
150
+ end
151
+ end
152
+
153
+ if attributes.has_key?(:'watermark_url')
154
+ self.watermark_url = attributes[:'watermark_url']
155
+ end
156
+
157
+ if attributes.has_key?(:'watermark_left')
158
+ self.watermark_left = attributes[:'watermark_left']
159
+ end
160
+
161
+ if attributes.has_key?(:'watermark_top')
162
+ self.watermark_top = attributes[:'watermark_top']
163
+ end
164
+
165
+ if attributes.has_key?(:'watermark_right')
166
+ self.watermark_right = attributes[:'watermark_right']
167
+ end
168
+
169
+ if attributes.has_key?(:'watermark_bottom')
170
+ self.watermark_bottom = attributes[:'watermark_bottom']
171
+ end
172
+
173
+ if attributes.has_key?(:'watermark_width')
174
+ self.watermark_width = attributes[:'watermark_width']
175
+ end
176
+
177
+ if attributes.has_key?(:'watermark_height')
178
+ self.watermark_height = attributes[:'watermark_height']
179
+ end
180
+
181
+ if attributes.has_key?(:'clip_length')
182
+ self.clip_length = attributes[:'clip_length']
183
+ end
184
+
185
+ if attributes.has_key?(:'clip_offset')
186
+ self.clip_offset = attributes[:'clip_offset']
187
+ end
188
+
189
+ if attributes.has_key?(:'multi_chunk')
190
+ self.multi_chunk = attributes[:'multi_chunk']
191
+ else
192
+ self.multi_chunk = true
193
+ end
194
+
195
+ end
196
+
197
+ # Show invalid properties with the reasons. Usually used together with valid?
198
+ # @return Array for valid properties with the reasons
199
+ def list_invalid_properties
200
+ invalid_properties = Array.new
201
+ if @file_size.nil?
202
+ invalid_properties.push("invalid value for 'file_size', file_size cannot be nil.")
203
+ end
204
+
205
+ if @file_name.nil?
206
+ invalid_properties.push("invalid value for 'file_name', file_name cannot be nil.")
207
+ end
208
+
209
+ return invalid_properties
210
+ end
211
+
212
+ # Check to see if the all the properties in the model are valid
213
+ # @return true if the model is valid
214
+ def valid?
215
+ return false if @file_size.nil?
216
+ return false if @file_name.nil?
217
+ return true
218
+ end
219
+
220
+ # Checks equality by comparing each attribute.
221
+ # @param [Object] Object to be compared
222
+ def ==(o)
223
+ return true if self.equal?(o)
224
+ self.class == o.class &&
225
+ file_size == o.file_size &&
226
+ file_name == o.file_name &&
227
+ extra_files == o.extra_files &&
228
+ profiles == o.profiles &&
229
+ path_format == o.path_format &&
230
+ payload == o.payload &&
231
+ extra_variables == o.extra_variables &&
232
+ watermark_url == o.watermark_url &&
233
+ watermark_left == o.watermark_left &&
234
+ watermark_top == o.watermark_top &&
235
+ watermark_right == o.watermark_right &&
236
+ watermark_bottom == o.watermark_bottom &&
237
+ watermark_width == o.watermark_width &&
238
+ watermark_height == o.watermark_height &&
239
+ clip_length == o.clip_length &&
240
+ clip_offset == o.clip_offset &&
241
+ multi_chunk == o.multi_chunk
242
+ end
243
+
244
+ # @see the `==` method
245
+ # @param [Object] Object to be compared
246
+ def eql?(o)
247
+ self == o
248
+ end
249
+
250
+ # Calculates hash code according to all attributes.
251
+ # @return [Fixnum] Hash code
252
+ def hash
253
+ [file_size, file_name, extra_files, profiles, path_format, payload, extra_variables, watermark_url, watermark_left, watermark_top, watermark_right, watermark_bottom, watermark_width, watermark_height, clip_length, clip_offset, multi_chunk].hash
254
+ end
255
+
256
+ # Builds the object from hash
257
+ # @param [Hash] attributes Model attributes in the form of hash
258
+ # @return [Object] Returns the model itself
259
+ def build_from_hash(attributes)
260
+ return nil unless attributes.is_a?(Hash)
261
+ self.class.swagger_types.each_pair do |key, type|
262
+ if type =~ /\AArray<(.*)>/i
263
+ # check to ensure the input is an array given that the the attribute
264
+ # is documented as an array but the input is not
265
+ if attributes[self.class.attribute_map[key]].is_a?(Array)
266
+ self.send("#{key}=", attributes[self.class.attribute_map[key]].map{ |v| _deserialize($1, v) } )
267
+ end
268
+ elsif !attributes[self.class.attribute_map[key]].nil?
269
+ self.send("#{key}=", _deserialize(type, attributes[self.class.attribute_map[key]]))
270
+ end # or else data not found in attributes(hash), not an issue as the data can be optional
271
+ end
272
+
273
+ self
274
+ end
275
+
276
+ # Deserializes the data based on type
277
+ # @param string type Data type
278
+ # @param string value Value to be deserialized
279
+ # @return [Object] Deserialized data
280
+ def _deserialize(type, value)
281
+ case type.to_sym
282
+ when :DateTime
283
+ DateTime.parse(value)
284
+ when :Date
285
+ Date.parse(value)
286
+ when :String
287
+ value.to_s
288
+ when :Integer
289
+ value.to_i
290
+ when :Float
291
+ value.to_f
292
+ when :BOOLEAN
293
+ if value.to_s =~ /\A(true|t|yes|y|1)\z/i
294
+ true
295
+ else
296
+ false
297
+ end
298
+ when :Object
299
+ # generic object (usually a Hash), return directly
300
+ value
301
+ when /\AArray<(?<inner_type>.+)>\z/
302
+ inner_type = Regexp.last_match[:inner_type]
303
+ value.map { |v| _deserialize(inner_type, v) }
304
+ when /\AHash<(?<k_type>.+?), (?<v_type>.+)>\z/
305
+ k_type = Regexp.last_match[:k_type]
306
+ v_type = Regexp.last_match[:v_type]
307
+ {}.tap do |hash|
308
+ value.each do |k, v|
309
+ hash[_deserialize(k_type, k)] = _deserialize(v_type, v)
310
+ end
311
+ end
312
+ else # model
313
+ temp_model = TelestreamCloud::Flip.const_get(type).new
314
+ temp_model.build_from_hash(value)
315
+ end
316
+ end
317
+
318
+ # Returns the string representation of the object
319
+ # @return [String] String presentation of the object
320
+ def to_s
321
+ to_hash.to_s
322
+ end
323
+
324
+ # to_body is an alias to to_hash (backward compatibility)
325
+ # @return [Hash] Returns the object in the form of hash
326
+ def to_body
327
+ to_hash
328
+ end
329
+
330
+ # Returns the object in the form of hash
331
+ # @return [Hash] Returns the object in the form of hash
332
+ def to_hash
333
+ hash = {}
334
+ self.class.attribute_map.each_pair do |attr, param|
335
+ value = self.send(attr)
336
+ next if value.nil?
337
+ hash[param] = _to_hash(value)
338
+ end
339
+ hash
340
+ end
341
+
342
+ # Outputs non-array value in the form of hash
343
+ # For object, use to_hash. Otherwise, just return the value
344
+ # @param [Object] value Any valid value
345
+ # @return [Hash] Returns the value in the form of hash
346
+ def _to_hash(value)
347
+ if value.is_a?(Array)
348
+ value.compact.map{ |v| _to_hash(v) }
349
+ elsif value.is_a?(Hash)
350
+ {}.tap do |hash|
351
+ value.each { |k, v| hash[k] = _to_hash(v) }
352
+ end
353
+ elsif value.respond_to? :to_hash
354
+ value.to_hash
355
+ else
356
+ value
357
+ end
358
+ end
359
+
360
+ end
361
+
362
+ end
@@ -0,0 +1,244 @@
1
+ require 'pathname'
2
+ require 'json'
3
+ require 'concurrent'
4
+
5
+ module TelestreamCloud::Flip
6
+ class Uploader
7
+ class FileReader
8
+ attr_reader :file
9
+
10
+ def initialize(path)
11
+ @mutex = Mutex.new
12
+ @path = path
13
+ reopen
14
+ end
15
+
16
+ def [](range)
17
+ @mutex.synchronize do
18
+ file.seek(range.begin)
19
+ file.read(range.size)
20
+ end
21
+ end
22
+
23
+ def size
24
+ @size ||= file.size
25
+ end
26
+
27
+ def name
28
+ Pathname.new(file.path).basename
29
+ end
30
+
31
+ def close
32
+ @file.close
33
+ @file = nil
34
+ end
35
+
36
+ def reopen
37
+ @file ||= File.open(@path)
38
+ end
39
+ end
40
+
41
+ class FileUploadSession
42
+ attr_reader :uploader, :reader, :tag
43
+
44
+ def initialize(uploader, path, tag = nil)
45
+ @uploader = uploader
46
+ @reader = FileReader.new(path)
47
+ @tag = tag
48
+ @status = :ready
49
+ end
50
+
51
+ def success?
52
+ @status == :success
53
+ end
54
+
55
+ def params
56
+ upload_params = {
57
+ file_size: reader.size,
58
+ file_name: reader.name
59
+ }
60
+
61
+ upload_params[:tag] = @tag if @tag
62
+ upload_params
63
+ end
64
+
65
+ def upload!
66
+ reader.reopen
67
+
68
+ upload_chunks(missing_parts)
69
+
70
+ raise MissingPartError unless missing_parts.empty?
71
+
72
+ @status = :success
73
+ ensure
74
+ reader.close
75
+ end
76
+
77
+ private
78
+
79
+ def upload_chunks(indexes)
80
+ indexes.each do |index|
81
+ send_chunk(index)
82
+ end
83
+ end
84
+
85
+ def session
86
+ uploader.send(:session)
87
+ end
88
+
89
+ def send_chunk(index)
90
+ range = (index * part_size...[(index + 1) * part_size, reader.size].min)
91
+
92
+ # TODO: remove when 1.9 dropped
93
+ unless range.respond_to?(:size)
94
+ def range.size; self.end - self.begin + (exclude_end? ? 0 : 1); end
95
+ end
96
+
97
+ response = Typhoeus.put(
98
+ session.location,
99
+ body: reader[range],
100
+ headers: {
101
+ 'Content-Type' => 'application/octet-stream',
102
+ 'X-Part' => index.to_s,
103
+ 'Content-Length' => range.size.to_s,
104
+ 'X-Extra-File-Tag' => tag,
105
+ }.reject { |_, v| v.nil? }
106
+ )
107
+
108
+ puts response.body
109
+
110
+ uploader.send(:set_resource_id, response)
111
+ response
112
+ end
113
+
114
+ def missing_parts
115
+ upload_status['missing_parts']
116
+ end
117
+
118
+ def upload_status
119
+ response = Typhoeus.get(
120
+ session.location,
121
+ headers: {
122
+ 'X-Extra-File-Tag' => @tag
123
+ }.reject { |_, v| v.nil? }
124
+ )
125
+ JSON.parse(response.body)
126
+ end
127
+
128
+ def parts; session.parts; end
129
+ def part_size; session.part_size; end
130
+ def max_connections; session.max_connections; end
131
+ end
132
+
133
+ class ConcurrentFileUploadSession < FileUploadSession
134
+ def upload_chunks(indexes)
135
+
136
+ indexes.map do |index|
137
+ Concurrent::Future.execute(executor: uploader.thread_pool) do
138
+ send_chunk(index)
139
+ end
140
+ end.map(&:value)
141
+ end
142
+ end
143
+
144
+ class UploadError < StandardError; end
145
+ class MissingPartError < StandardError; end
146
+
147
+ attr_reader :reader, :status, :error, :thread_pool, :concurrency
148
+
149
+ def self.upload(options)
150
+ retries = options.delete(:retries)
151
+ new(options).tap { |x| x.upload(*[retries].compact) }.video
152
+ end
153
+
154
+ def initialize(client, options)
155
+ @client = client
156
+
157
+ @thread_pool = Concurrent::ThreadPoolExecutor.new(
158
+ min_threads: 5,
159
+ max_threads: 5,
160
+ max_queue: 100,
161
+ fallback_policy: :caller_runs
162
+ )
163
+
164
+ file = options.delete(:file) do |key|
165
+ raise KeyError, "key not found: #{key}"
166
+ end
167
+
168
+ @extra_files = parse_extra_files(options.delete(:extra_files))
169
+
170
+ @upload_session = upload_session(file)
171
+
172
+ defaults = {
173
+ multi_chunk: true
174
+ }.merge(@upload_session.params)
175
+
176
+ @params = defaults.merge(options)
177
+
178
+ @params[:extra_files] = @extra_files.map(&:params) if @extra_files
179
+
180
+ @status = :ready
181
+ end
182
+
183
+ def parse_extra_files(extra_files)
184
+ return [] unless extra_files
185
+
186
+ extra_files.flat_map do |tag, paths|
187
+ paths = [paths] unless paths.kind_of?(Array)
188
+
189
+ paths.each_with_index.map do |path, i|
190
+ upload_session(path, paths.size > 1 ? "#{tag}.index-#{i}" : tag)
191
+ end
192
+ end
193
+ end
194
+
195
+ def upload(retries = 5)
196
+ session
197
+
198
+ count = 0
199
+ begin
200
+ count += 1
201
+ upload!
202
+ raise MissingPartError unless success?
203
+ rescue StandardError => e
204
+ puts e
205
+ @error = e
206
+ retry if count < retries
207
+ end
208
+
209
+ @resource_id
210
+ end
211
+
212
+ def success?
213
+ @resource_id && @upload_session.success? && Array(@extra_files).all?(&:success?)
214
+ end
215
+
216
+ def upload_session(path, tag = nil)
217
+ ConcurrentFileUploadSession.new(self, path, tag)
218
+ end
219
+
220
+ private
221
+
222
+ def upload!
223
+ @upload_session.upload!
224
+ @extra_files.each(&:upload!)
225
+ end
226
+
227
+ def set_resource_id(response)
228
+ return if response.code != 200 || response.body.empty?
229
+ @resource_id = JSON.parse(response.body).fetch('id')
230
+ end
231
+
232
+ def session
233
+ return @session if defined?(@session)
234
+ @session = case @client.class.name
235
+ when "TelestreamCloud::Flip::FlipApi"
236
+ @factory_id ||= @params.delete(:factory_id) do |key|
237
+ raise KeyError, "key not found: #{key}"
238
+ end
239
+
240
+ @client.upload_video(@factory_id, @params)
241
+ end
242
+ end
243
+ end
244
+ end
@@ -0,0 +1,18 @@
1
+ module TelestreamCloud
2
+ end
3
+
4
+ =begin
5
+ #Flip API
6
+
7
+ #Description
8
+
9
+ OpenAPI spec version: 3.1.0
10
+ Contact: cloudsupport@telestream.net
11
+ Generated by: https://github.com/swagger-api/swagger-codegen.git
12
+ Swagger Codegen version: 2.3.0
13
+
14
+ =end
15
+
16
+ module TelestreamCloud::Flip
17
+ VERSION = "2.0.0"
18
+ end
@@ -0,0 +1,79 @@
1
+ module TelestreamCloud
2
+ end
3
+
4
+ =begin
5
+ #Flip API
6
+
7
+ #Description
8
+
9
+ OpenAPI spec version: 3.1.0
10
+ Contact: cloudsupport@telestream.net
11
+ Generated by: https://github.com/swagger-api/swagger-codegen.git
12
+ Swagger Codegen version: 2.3.0
13
+
14
+ =end
15
+
16
+ # Common files
17
+ require 'telestream_cloud_flip/api_client'
18
+ require 'telestream_cloud_flip/api_error'
19
+ require 'telestream_cloud_flip/version'
20
+ require 'telestream_cloud_flip/configuration'
21
+
22
+ # Models
23
+ require 'telestream_cloud_flip/models/canceled_response'
24
+ require 'telestream_cloud_flip/models/cloud_notification_settings'
25
+ require 'telestream_cloud_flip/models/cloud_notification_settings_events'
26
+ require 'telestream_cloud_flip/models/copy_profile_body'
27
+ require 'telestream_cloud_flip/models/count_response'
28
+ require 'telestream_cloud_flip/models/create_encoding_body'
29
+ require 'telestream_cloud_flip/models/create_video_body'
30
+ require 'telestream_cloud_flip/models/deleted_response'
31
+ require 'telestream_cloud_flip/models/encoding'
32
+ require 'telestream_cloud_flip/models/encoding_signed_url'
33
+ require 'telestream_cloud_flip/models/encoding_signed_urls'
34
+ require 'telestream_cloud_flip/models/error'
35
+ require 'telestream_cloud_flip/models/extra_file'
36
+ require 'telestream_cloud_flip/models/factory'
37
+ require 'telestream_cloud_flip/models/factory_body'
38
+ require 'telestream_cloud_flip/models/factory_body_storage_credential_attributes'
39
+ require 'telestream_cloud_flip/models/factory_sync'
40
+ require 'telestream_cloud_flip/models/factory_sync_body'
41
+ require 'telestream_cloud_flip/models/paginated_encodings_collection'
42
+ require 'telestream_cloud_flip/models/paginated_factory_collection'
43
+ require 'telestream_cloud_flip/models/paginated_profiles_collection'
44
+ require 'telestream_cloud_flip/models/paginated_video_collection'
45
+ require 'telestream_cloud_flip/models/paginated_workflows_collection'
46
+ require 'telestream_cloud_flip/models/profile'
47
+ require 'telestream_cloud_flip/models/profile_body'
48
+ require 'telestream_cloud_flip/models/resubmit_video_body'
49
+ require 'telestream_cloud_flip/models/retried_response'
50
+ require 'telestream_cloud_flip/models/signed_video_url'
51
+ require 'telestream_cloud_flip/models/update_encoding_body'
52
+ require 'telestream_cloud_flip/models/upload_session'
53
+ require 'telestream_cloud_flip/models/video'
54
+ require 'telestream_cloud_flip/models/video_metadata'
55
+ require 'telestream_cloud_flip/models/video_upload_body'
56
+
57
+ # APIs
58
+ require 'telestream_cloud_flip/api/flip_api'
59
+
60
+ # Uploader
61
+ require 'telestream_cloud_flip/uploader'
62
+
63
+ module TelestreamCloud::Flip
64
+ class << self
65
+ # Customize default settings for the SDK using block.
66
+ # TelestreamCloud::Flip.configure do |config|
67
+ # config.username = "xxx"
68
+ # config.password = "xxx"
69
+ # end
70
+ # If no block given, return the default Configuration object.
71
+ def configure
72
+ if block_given?
73
+ yield(Configuration.default)
74
+ else
75
+ Configuration.default
76
+ end
77
+ end
78
+ end
79
+ end