vzaar_api 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 (138) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.rspec +4 -0
  4. data/.tool-versions +1 -0
  5. data/.travis.yml +3 -0
  6. data/Changelog +50 -0
  7. data/Gemfile +3 -0
  8. data/Guardfile +25 -0
  9. data/README.md +55 -0
  10. data/Rakefile +26 -0
  11. data/examples/README.md +33 -0
  12. data/examples/api_envs.yml.example +31 -0
  13. data/examples/category/create_update_delete_spec.rb +100 -0
  14. data/examples/category/list_spec.rb +38 -0
  15. data/examples/category/list_subtree_spec.rb +40 -0
  16. data/examples/category/lookup_spec.rb +35 -0
  17. data/examples/encoding_preset/list_spec.rb +38 -0
  18. data/examples/encoding_preset/lookup_spec.rb +35 -0
  19. data/examples/ingest_recipe/create_update_delete_spec.rb +70 -0
  20. data/examples/ingest_recipe/list_spec.rb +38 -0
  21. data/examples/ingest_recipe/lookup_spec.rb +35 -0
  22. data/examples/playlist/create_update_delete_spec.rb +97 -0
  23. data/examples/playlist/list_spec.rb +37 -0
  24. data/examples/playlist/lookup_spec.rb +34 -0
  25. data/examples/rate_limit_spec.rb +18 -0
  26. data/examples/spec_helper.rb +17 -0
  27. data/examples/support/helpers.rb +16 -0
  28. data/examples/support/videos/medium.mp4 +0 -0
  29. data/examples/support/videos/small.mp4 +0 -0
  30. data/examples/video/create_update_delete_spec.rb +73 -0
  31. data/lib/vzaar_api/abstract.rb +9 -0
  32. data/lib/vzaar_api/category.rb +39 -0
  33. data/lib/vzaar_api/encoding_preset.rb +19 -0
  34. data/lib/vzaar_api/ingest_recipe.rb +35 -0
  35. data/lib/vzaar_api/legacy_rendition.rb +11 -0
  36. data/lib/vzaar_api/lib/active_object.rb +92 -0
  37. data/lib/vzaar_api/lib/api.rb +54 -0
  38. data/lib/vzaar_api/lib/api_response.rb +61 -0
  39. data/lib/vzaar_api/lib/has_attributes.rb +49 -0
  40. data/lib/vzaar_api/lib/has_collection_builder.rb +17 -0
  41. data/lib/vzaar_api/lib/has_resource_url.rb +24 -0
  42. data/lib/vzaar_api/lib/paged_resource.rb +80 -0
  43. data/lib/vzaar_api/lib/will_paginate.rb +22 -0
  44. data/lib/vzaar_api/link_upload.rb +14 -0
  45. data/lib/vzaar_api/playlist.rb +29 -0
  46. data/lib/vzaar_api/rendition.rb +16 -0
  47. data/lib/vzaar_api/signature/abstract.rb +40 -0
  48. data/lib/vzaar_api/signature/factory.rb +39 -0
  49. data/lib/vzaar_api/signature/multipart.rb +23 -0
  50. data/lib/vzaar_api/signature/single.rb +17 -0
  51. data/lib/vzaar_api/strategy/video/create.rb +46 -0
  52. data/lib/vzaar_api/upload/s3.rb +90 -0
  53. data/lib/vzaar_api/upload/virtual_file.rb +14 -0
  54. data/lib/vzaar_api/version.rb +4 -0
  55. data/lib/vzaar_api/video.rb +38 -0
  56. data/lib/vzaar_api.rb +60 -0
  57. data/spec/fixtures/vcr_cassettes/categories/each_item.yml +363 -0
  58. data/spec/fixtures/vcr_cassettes/categories/find.yml +61 -0
  59. data/spec/fixtures/vcr_cassettes/categories/find_404.yml +49 -0
  60. data/spec/fixtures/vcr_cassettes/categories/paginate_first.yml +61 -0
  61. data/spec/fixtures/vcr_cassettes/categories/paginate_last.yml +119 -0
  62. data/spec/fixtures/vcr_cassettes/categories/paginate_next.yml +120 -0
  63. data/spec/fixtures/vcr_cassettes/categories/paginate_previous.yml +120 -0
  64. data/spec/fixtures/vcr_cassettes/categories/subtree.yml +127 -0
  65. data/spec/fixtures/vcr_cassettes/categories/subtree_paginate_first.yml +123 -0
  66. data/spec/fixtures/vcr_cassettes/categories/subtree_paginate_last.yml +185 -0
  67. data/spec/fixtures/vcr_cassettes/categories/subtree_paginate_next.yml +184 -0
  68. data/spec/fixtures/vcr_cassettes/categories/subtree_paginate_previous.yml +184 -0
  69. data/spec/fixtures/vcr_cassettes/encoding_presets/each_item.yml +299 -0
  70. data/spec/fixtures/vcr_cassettes/encoding_presets/find.yml +62 -0
  71. data/spec/fixtures/vcr_cassettes/encoding_presets/find_404.yml +51 -0
  72. data/spec/fixtures/vcr_cassettes/encoding_presets/paginate_first.yml +62 -0
  73. data/spec/fixtures/vcr_cassettes/encoding_presets/paginate_last.yml +121 -0
  74. data/spec/fixtures/vcr_cassettes/encoding_presets/paginate_next.yml +121 -0
  75. data/spec/fixtures/vcr_cassettes/encoding_presets/paginate_previous.yml +121 -0
  76. data/spec/fixtures/vcr_cassettes/ingest_recipes/create_200.yml +63 -0
  77. data/spec/fixtures/vcr_cassettes/ingest_recipes/create_422.yml +52 -0
  78. data/spec/fixtures/vcr_cassettes/ingest_recipes/delete_204.yml +166 -0
  79. data/spec/fixtures/vcr_cassettes/ingest_recipes/delete_422.yml +112 -0
  80. data/spec/fixtures/vcr_cassettes/ingest_recipes/each_item.yml +182 -0
  81. data/spec/fixtures/vcr_cassettes/ingest_recipes/find.yml +62 -0
  82. data/spec/fixtures/vcr_cassettes/ingest_recipes/find_404.yml +51 -0
  83. data/spec/fixtures/vcr_cassettes/ingest_recipes/paginate_first.yml +62 -0
  84. data/spec/fixtures/vcr_cassettes/ingest_recipes/paginate_last.yml +122 -0
  85. data/spec/fixtures/vcr_cassettes/ingest_recipes/paginate_next.yml +121 -0
  86. data/spec/fixtures/vcr_cassettes/ingest_recipes/paginate_previous.yml +122 -0
  87. data/spec/fixtures/vcr_cassettes/ingest_recipes/update_200.yml +242 -0
  88. data/spec/fixtures/vcr_cassettes/ingest_recipes/update_422.yml +113 -0
  89. data/spec/fixtures/vcr_cassettes/playlists/each_item.yml +607 -0
  90. data/spec/fixtures/vcr_cassettes/playlists/find.yml +66 -0
  91. data/spec/fixtures/vcr_cassettes/playlists/find_404.yml +51 -0
  92. data/spec/fixtures/vcr_cassettes/playlists/paginate_first.yml +74 -0
  93. data/spec/fixtures/vcr_cassettes/playlists/paginate_last.yml +146 -0
  94. data/spec/fixtures/vcr_cassettes/playlists/paginate_next.yml +145 -0
  95. data/spec/fixtures/vcr_cassettes/playlists/paginate_previous.yml +145 -0
  96. data/spec/fixtures/vcr_cassettes/signature/multipart_201.yml +62 -0
  97. data/spec/fixtures/vcr_cassettes/signature/multipart_422.yml +52 -0
  98. data/spec/fixtures/vcr_cassettes/signature/single_201.yml +62 -0
  99. data/spec/fixtures/vcr_cassettes/signature/single_422.yml +51 -0
  100. data/spec/fixtures/vcr_cassettes/upload/multipart_201.yml +279868 -0
  101. data/spec/fixtures/vcr_cassettes/upload/multipart_403.yml +116578 -0
  102. data/spec/fixtures/vcr_cassettes/upload/single_201.yml +23388 -0
  103. data/spec/fixtures/vcr_cassettes/upload/single_403.yml +23374 -0
  104. data/spec/fixtures/vcr_cassettes/videos/create/error.yml +51 -0
  105. data/spec/fixtures/vcr_cassettes/videos/create/guid_201.yml +65 -0
  106. data/spec/fixtures/vcr_cassettes/videos/create/guid_error.yml +52 -0
  107. data/spec/fixtures/vcr_cassettes/videos/create/link_201.yml +65 -0
  108. data/spec/fixtures/vcr_cassettes/videos/create/link_error.yml +51 -0
  109. data/spec/fixtures/vcr_cassettes/videos/create/path_201.yml +23509 -0
  110. data/spec/fixtures/vcr_cassettes/videos/delete_204.yml +168 -0
  111. data/spec/fixtures/vcr_cassettes/videos/find.yml +66 -0
  112. data/spec/fixtures/vcr_cassettes/videos/find_404.yml +51 -0
  113. data/spec/fixtures/vcr_cassettes/videos/paginate_first.yml +71 -0
  114. data/spec/fixtures/vcr_cassettes/videos/paginate_last.yml +137 -0
  115. data/spec/fixtures/vcr_cassettes/videos/paginate_next.yml +139 -0
  116. data/spec/fixtures/vcr_cassettes/videos/paginate_previous.yml +139 -0
  117. data/spec/spec_helper.rb +103 -0
  118. data/spec/support/files/video-1.0MB.mp4 +0 -0
  119. data/spec/support/files/video-12.0MB.mp4 +0 -0
  120. data/spec/support/files/video-4.9MB.mp4 +0 -0
  121. data/spec/support/files/video-5.0MB.mp4 +0 -0
  122. data/spec/support/helpers.rb +16 -0
  123. data/spec/vzaar_api/category_spec.rb +141 -0
  124. data/spec/vzaar_api/encoding_preset_spec.rb +92 -0
  125. data/spec/vzaar_api/ingest_recipe_spec.rb +197 -0
  126. data/spec/vzaar_api/lib/api_spec.rb +28 -0
  127. data/spec/vzaar_api/playlist_spec.rb +97 -0
  128. data/spec/vzaar_api/rendition_spec.rb +55 -0
  129. data/spec/vzaar_api/signature/factory_spec.rb +68 -0
  130. data/spec/vzaar_api/signature/multipart_spec.rb +81 -0
  131. data/spec/vzaar_api/signature/single_spec.rb +72 -0
  132. data/spec/vzaar_api/upload/s3_spec.rb +112 -0
  133. data/spec/vzaar_api/video_spec.rb +248 -0
  134. data/spec/vzaar_api/vzaar_api_spec.rb +18 -0
  135. data/spec/vzaar_api_helper.rb +19 -0
  136. data/vzaar.png +0 -0
  137. data/vzaar_api.gemspec +35 -0
  138. metadata +413 -0
@@ -0,0 +1,49 @@
1
+ module VzaarApi
2
+ module Lib
3
+ module HasAttributes
4
+
5
+ def self.prepended(klass)
6
+ klass::ATTR_READERS.each do |attr|
7
+ klass.send :attr_reader, attr
8
+ end
9
+
10
+ unless defined? klass::ATTR_ACCESSORS
11
+ klass.const_set 'ATTR_ACCESSORS', [].freeze
12
+ end
13
+
14
+ klass::ATTR_ACCESSORS.each do |attr|
15
+ klass.send :attr_accessor, attr
16
+
17
+ klass.send(:define_method, "#{attr}=") do |val|
18
+ if self.changes[attr]
19
+ self.changes[attr][1] = val
20
+ else
21
+ self.changes[attr] = [self.send(attr), val]
22
+ end
23
+ val
24
+ end
25
+ end
26
+ end
27
+
28
+ def initialize(attrs = {})
29
+ self.class::ATTR_READERS.each do |attr|
30
+ instance_variable_set("@#{attr}", attrs[attr])
31
+ end
32
+ self.class::ATTR_ACCESSORS.each do |attr|
33
+ instance_variable_set("@#{attr}", attrs[attr])
34
+ end
35
+ super
36
+ end
37
+
38
+ private
39
+
40
+ def update_from_attributes(attrs = {})
41
+ attrs.each do |attr, val|
42
+ instance_variable_set("@#{attr}", attrs[attr])
43
+ end
44
+ super
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,17 @@
1
+ module VzaarApi
2
+ module Lib
3
+ module HasCollectionBuilder
4
+
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ def build(data = [])
11
+ Array(data).map { |attrs| new attrs }
12
+ end
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,24 @@
1
+ module VzaarApi
2
+ module Lib
3
+ module HasResourceUrl
4
+
5
+ def self.included(base)
6
+ base.include(InstanceMethods)
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ module InstanceMethods
11
+ def resource_url(path = nil)
12
+ self.class.resource_url(path)
13
+ end
14
+ end
15
+
16
+ module ClassMethods
17
+ def resource_url(path = nil)
18
+ Api.resource_url self::ENDPOINT, path
19
+ end
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,80 @@
1
+ module VzaarApi
2
+ module Lib
3
+ class PagedResource
4
+
5
+ attr_reader :query, :meta, :collection, :resource_class, :resource_url
6
+
7
+ def initialize(query = {})
8
+ @query = query.dup
9
+ @resource_class = @query.delete(:resource_class)
10
+ @resource_url = @query.delete(:resource_url)
11
+ @loaded = false
12
+ end
13
+
14
+ def loaded?
15
+ @loaded
16
+ end
17
+
18
+ def each_item
19
+ return enum_for :each_item unless block_given?
20
+ begin
21
+ each { |record| yield record }
22
+ end while !self.next.empty?
23
+ end
24
+
25
+ def first
26
+ loaded? ? load_page_url(:first) : load!
27
+ end
28
+
29
+ def next
30
+ load_page_url :next
31
+ end
32
+
33
+ def previous
34
+ load_page_url :previous
35
+ end
36
+
37
+ def last
38
+ load_page_url :last
39
+ end
40
+
41
+ private
42
+
43
+ def load!
44
+ @loaded = true
45
+ load_from_url resource_url, query
46
+ end
47
+
48
+ def load_page_url(page)
49
+ load! unless loaded?
50
+ if url = meta_link(page)
51
+ load_from_url meta[:links][page]
52
+ else
53
+ []
54
+ end
55
+ end
56
+
57
+ def meta_link(page)
58
+ return unless meta
59
+ meta[:links][page]
60
+ end
61
+
62
+ def each
63
+ return enum_for :each unless block_given?
64
+ load! unless collection
65
+ collection.each { |record| yield record }
66
+ end
67
+
68
+ def load_from_url(url, query = {})
69
+ response = Api.new.get(url, query)
70
+ @meta = response.meta
71
+ @collection = build_collection response.data
72
+ end
73
+
74
+ def build_collection(items)
75
+ items.map { |attrs| resource_class.new attrs }
76
+ end
77
+
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,22 @@
1
+ module VzaarApi
2
+ module Lib
3
+ module WillPaginate
4
+
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ def each_item(query = {}, &block)
11
+ paginate(query).each_item(&block)
12
+ end
13
+
14
+ def paginate(query = {})
15
+ args = query.merge({ resource_url: resource_url, resource_class: self })
16
+ Lib::PagedResource.new(args)
17
+ end
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ module VzaarApi
2
+ module LinkUpload
3
+
4
+ include Lib::HasResourceUrl
5
+
6
+ ENDPOINT = 'link_uploads'
7
+
8
+ def self.create(attrs = {})
9
+ attrs[:uploader] = UPLOADER
10
+ Video.new Lib::Api.new.post(resource_url, attrs).data
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,29 @@
1
+ module VzaarApi
2
+ class Playlist < Abstract
3
+
4
+ ENDPOINT = 'feeds/playlists'
5
+
6
+ ATTR_READERS = %i(
7
+ id title sort_order sort_by autoplay continuous_play category_id
8
+ embed_code created_at updated_at
9
+ ).freeze
10
+
11
+ ATTR_ACCESSORS = %i(
12
+ category_id title sort_by sort_order private dimensions max_vids
13
+ position autoplay continuous_play max_vids
14
+ ).freeze
15
+
16
+ prepend Lib::HasAttributes
17
+ include Lib::HasCollectionBuilder
18
+ include Lib::HasResourceUrl
19
+ include Lib::ActiveObject::Find
20
+ include Lib::ActiveObject::Save
21
+ include Lib::ActiveObject::Delete
22
+ include Lib::WillPaginate
23
+
24
+ def self.create(attrs = {})
25
+ url = Lib::Api.resource_url(ENDPOINT)
26
+ new Lib::Api.new.post(url, attrs).data
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,16 @@
1
+ module VzaarApi
2
+ class Rendition < Abstract
3
+
4
+ ATTR_READERS = [:audio_bitrate_kbps, :audio_channels,
5
+ :audio_sample_rate, :bitrate_kbps,
6
+ :encoding_preset_id, :error_message,
7
+ :frame_rate, :height, :id, :keyframe,
8
+ :name, :output_format, :profile, :size_in_bytes,
9
+ :source_as_rendition, :state, :video_codec, :width,
10
+ :created_at, :updated_at].freeze
11
+
12
+ prepend Lib::HasAttributes
13
+ include Lib::HasCollectionBuilder
14
+
15
+ end
16
+ end
@@ -0,0 +1,40 @@
1
+ module VzaarApi
2
+ module Signature
3
+ class Abstract
4
+
5
+ include Lib::HasResourceUrl
6
+
7
+ attr_reader :access_key_id, :acl, :bucket, :content_type,
8
+ :guid, :key, :policy, :signature, :success_action_status,
9
+ :upload_hostname
10
+
11
+ def initialize(attrs = {})
12
+ @access_key_id = attrs[:access_key_id]
13
+ @acl = attrs[:acl]
14
+ @bucket = attrs[:bucket]
15
+ @content_type = attrs[:content_type]
16
+ @guid = attrs[:guid]
17
+ @key = attrs[:key]
18
+ @policy = attrs[:policy]
19
+ @signature = attrs[:signature]
20
+ @success_action_status = attrs[:success_action_status]
21
+ @upload_hostname = attrs[:upload_hostname]
22
+ after_initialize(attrs)
23
+ end
24
+
25
+ def after_initialize(attrs = {})
26
+ raise Error.new('Cannot call #after_initialize on Signature::Abstract')
27
+ end
28
+
29
+ def multipart?
30
+ raise Error.new('Cannot call #multipart? on Signature::Abstract')
31
+ end
32
+
33
+ def self.create(attrs = {})
34
+ attrs[:uploader] = UPLOADER
35
+ new Lib::Api.new.post(resource_url, attrs).data
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,39 @@
1
+ module VzaarApi
2
+ module Signature
3
+ class Factory
4
+
5
+ # 5MB is min size required for multipart upload
6
+ MIN_S3_MULTIPART_FILE_SIZE = 5 * (1024 ** 2)
7
+
8
+ attr_reader :attrs, :path
9
+
10
+ def initialize(attrs)
11
+ @attrs = attrs
12
+ @path = attrs.fetch(:path)
13
+ end
14
+
15
+ def self.create(attrs)
16
+ new(attrs).create
17
+ end
18
+
19
+ def create
20
+ klass = multipart? ? Multipart : Single
21
+ klass.create(multipart_attrs)
22
+ end
23
+
24
+ def multipart?
25
+ multipart_attrs[:filesize].to_i >= MIN_S3_MULTIPART_FILE_SIZE
26
+ end
27
+
28
+ def multipart_attrs
29
+ {
30
+ filesize: File::Stat.new(path).size,
31
+ filename: File.basename(path)
32
+ }
33
+ rescue Errno::ENOENT
34
+ raise Error.new 'Invalid parameters: path is invalid'
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,23 @@
1
+ module VzaarApi
2
+ module Signature
3
+ class Multipart < Abstract
4
+
5
+ include Lib::HasResourceUrl
6
+
7
+ ENDPOINT = 'signature/multipart'
8
+
9
+ attr_reader :upload_hostname, :part_size, :part_size_in_bytes, :parts
10
+
11
+ def after_initialize(attrs = {})
12
+ @part_size = attrs[:part_size]
13
+ @part_size_in_bytes = attrs[:part_size_in_bytes]
14
+ @parts = attrs[:parts]
15
+ end
16
+
17
+ def multipart?
18
+ true
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ module VzaarApi
2
+ module Signature
3
+ class Single < Abstract
4
+
5
+ ENDPOINT = 'signature/single'
6
+
7
+ def after_initialize(attrs = {})
8
+ # no-op in this class
9
+ end
10
+
11
+ def multipart?
12
+ false
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,46 @@
1
+ module VzaarApi
2
+ module Strategy
3
+ module Video
4
+ class Create
5
+
6
+ attr_reader :attrs, :video_class
7
+
8
+ def initialize(attrs, video_class)
9
+ @attrs = attrs
10
+ @video_class = video_class
11
+ end
12
+
13
+ def execute
14
+ case
15
+ when attrs.has_key?(:guid)
16
+ create_from_guid
17
+ when attrs.has_key?(:path)
18
+ create_from_path
19
+ when attrs.has_key?(:url)
20
+ create_from_url
21
+ else
22
+ raise Error.new('Invalid parameters: Expected one of :guid, :path, :url')
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def create_from_guid
29
+ url = Lib::Api.resource_url video_class::ENDPOINT
30
+ video_class.new Lib::Api.new.post(url, attrs).data
31
+ end
32
+
33
+ def create_from_path
34
+ signature = Signature::Factory.create(attrs)
35
+ upload_attrs = Upload::S3.new(attrs, signature).execute
36
+ video_class.create upload_attrs
37
+ end
38
+
39
+ def create_from_url
40
+ LinkUpload.create(attrs.merge({ uploader: UPLOADER }))
41
+ end
42
+
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,90 @@
1
+ module VzaarApi
2
+ module Upload
3
+ class S3
4
+ extend Forwardable
5
+
6
+ SEND_TIMEOUT = 1800
7
+
8
+ attr_reader :attrs, :path, :signature
9
+
10
+ def_delegators :@signature, :access_key_id, :acl, :bucket,
11
+ :guid, :key, :multipart?, :part_size_in_bytes, :policy,
12
+ :success_action_status, :upload_hostname
13
+
14
+ def initialize(attrs, signature)
15
+ @attrs = attrs.dup
16
+ @path = @attrs.delete(:path)
17
+ @signature = signature
18
+ end
19
+
20
+ def execute
21
+ if multipart?
22
+ multipart_upload
23
+ else
24
+ single_part_upload
25
+ end
26
+ attrs.merge({ guid: guid })
27
+ end
28
+
29
+ private
30
+
31
+ def multipart_upload
32
+ _headers = headers.dup
33
+ chunk = 0
34
+ File.open(path, "r") do |file|
35
+ until file.eof?
36
+ _headers['key'] = "#{key}.#{chunk}"
37
+ _headers['file'] = VirtualFile.new(file, part_size_in_bytes)
38
+ validate_response! upload_file(_headers)
39
+ chunk += 1
40
+ end
41
+ end
42
+ rescue => e
43
+ raise Error.new(e.message)
44
+ end
45
+
46
+ def single_part_upload
47
+ File.open(path, "r") do |file|
48
+ _headers = headers.dup
49
+ _headers['key'] = key
50
+ _headers['file'] = file
51
+ validate_response! upload_file(_headers)
52
+ end
53
+ rescue => e
54
+ raise Error.new(e.message)
55
+ end
56
+
57
+ def upload_file(headers)
58
+ http_client.post upload_hostname, headers
59
+ end
60
+
61
+ def headers
62
+ @headers ||= {
63
+ 'acl' => acl,
64
+ 'bucket' => bucket,
65
+ 'success_action_status' => success_action_status,
66
+ 'policy' => policy,
67
+ 'AWSAccessKeyId' => access_key_id,
68
+ 'signature' => signature.signature,
69
+ 'x-amz-meta-uploader' => UPLOADER
70
+ }
71
+ end
72
+
73
+ def http_client
74
+ @http_client ||= begin
75
+ HTTPClient.new.tap { |c| c.send_timeout = SEND_TIMEOUT }
76
+ end
77
+ end
78
+
79
+ def validate_response!(response)
80
+ return if response.ok?
81
+ raise error_message(response.body)
82
+ end
83
+
84
+ def error_message(body)
85
+ /Message\>(.+)\<\/Message/.match(body)[1]
86
+ end
87
+
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,14 @@
1
+ module VzaarApi
2
+ module Upload
3
+ class VirtualFile < StringIO
4
+
5
+ attr_reader :path
6
+
7
+ def initialize(file, chunk_size)
8
+ @path = File.basename file.path
9
+ super file.read(chunk_size)
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,4 @@
1
+ module VzaarApi
2
+ VERSION = '2.0.0'
3
+ UPLOADER = 'Ruby-2.0.0'
4
+ end
@@ -0,0 +1,38 @@
1
+ module VzaarApi
2
+ class Video < Abstract
3
+
4
+ ENDPOINT = 'videos'
5
+
6
+ ATTR_READERS = [:id, :user_id, :account_id, :categories,
7
+ :renditions, :legacy_renditions, :url,
8
+ :thumbnail_url, :state,
9
+ :created_at, :updated_at].freeze
10
+
11
+ ATTR_ACCESSORS = [:category_ids, :description, :private, :seo_url, :title].freeze
12
+
13
+ prepend Lib::HasAttributes
14
+ include Lib::HasResourceUrl
15
+ include Lib::ActiveObject::Find
16
+ include Lib::ActiveObject::Save
17
+ include Lib::ActiveObject::Delete
18
+ include Lib::WillPaginate
19
+
20
+ def initialize(attrs = {})
21
+ update_from_attributes attrs
22
+ end
23
+
24
+ def self.create(attrs = {})
25
+ Strategy::Video::Create.new(attrs, self).execute
26
+ end
27
+
28
+ private
29
+
30
+ def update_from_attributes(attrs)
31
+ @categories = Category.build(attrs[:categories])
32
+ @category_ids = @categories.map(&:id)
33
+ @renditions = Rendition.build(attrs[:renditions])
34
+ @legacy_renditions = LegacyRendition.build(attrs[:renditions])
35
+ end
36
+
37
+ end
38
+ end
data/lib/vzaar_api.rb ADDED
@@ -0,0 +1,60 @@
1
+ $: << File.dirname(__FILE__)
2
+
3
+ require 'forwardable'
4
+ require 'httpclient'
5
+ require 'json'
6
+
7
+ require 'vzaar_api/version'
8
+
9
+ require 'vzaar_api/lib/api'
10
+ require 'vzaar_api/lib/api_response'
11
+ require 'vzaar_api/lib/active_object'
12
+ require 'vzaar_api/lib/has_attributes'
13
+ require 'vzaar_api/lib/has_collection_builder'
14
+ require 'vzaar_api/lib/has_resource_url'
15
+ require 'vzaar_api/lib/paged_resource'
16
+ require 'vzaar_api/lib/will_paginate'
17
+
18
+ require 'vzaar_api/abstract'
19
+ require 'vzaar_api/category'
20
+ require 'vzaar_api/encoding_preset'
21
+ require 'vzaar_api/ingest_recipe'
22
+ require 'vzaar_api/legacy_rendition'
23
+ require 'vzaar_api/link_upload'
24
+ require 'vzaar_api/playlist'
25
+ require 'vzaar_api/rendition'
26
+ require 'vzaar_api/strategy/video/create'
27
+ require 'vzaar_api/video'
28
+
29
+ require 'vzaar_api/signature/abstract'
30
+ require 'vzaar_api/signature/factory'
31
+ require 'vzaar_api/signature/multipart'
32
+ require 'vzaar_api/signature/single'
33
+
34
+ require 'vzaar_api/upload/s3'
35
+ require 'vzaar_api/upload/virtual_file'
36
+
37
+ module VzaarApi
38
+ class Error < StandardError ; end
39
+
40
+ DEFAULT_HOSTNAME = 'api.vzaar.com'
41
+ DEFAULT_PROTOCOL = 'https'
42
+
43
+ class << self
44
+ attr_accessor :auth_token, :client_id, :hostname,
45
+ :rate_limit, :rate_limit_remaining, :rate_limit_reset
46
+
47
+ def hostname
48
+ @hostname || DEFAULT_HOSTNAME
49
+ end
50
+
51
+ def protocol
52
+ @protocol || DEFAULT_PROTOCOL
53
+ end
54
+
55
+ def protocol=(value)
56
+ @protocol = value.downcase == 'https' ? 'https' : 'http'
57
+ end
58
+ end
59
+
60
+ end