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,35 @@
1
+ require_relative './../spec_helper'
2
+
3
+ module VzaarApi
4
+ describe 'Ingest recipe: Lookup' do
5
+
6
+ let(:described_class) { IngestRecipe }
7
+ let(:id) { api_envs['ingest_recipe']['default'] }
8
+
9
+ context 'when user is authenticated' do
10
+ before { setup_for :account_owner }
11
+
12
+ context 'and resource can be found' do
13
+ subject { described_class.find(id) }
14
+ specify { expect(subject.id).to eq id }
15
+ end
16
+
17
+ context 'and resource cannot be found' do
18
+ it 'raises an error' do
19
+ expect{ described_class.find(-1) }.to raise_error(
20
+ Error, 'Not found: Resource cannot be found')
21
+ end
22
+ end
23
+ end
24
+
25
+ context 'when user is not authenticated' do
26
+ before { setup_for :intruder }
27
+
28
+ it 'raises an error' do
29
+ expect{ described_class.find(id) }.to raise_error(
30
+ Error, 'Authentication failed: Invalid credentials')
31
+ end
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,97 @@
1
+ require_relative './../spec_helper'
2
+
3
+ module VzaarApi
4
+ describe 'Playlist: Create / Update / Delete' do
5
+
6
+ let(:described_class) { Playlist }
7
+
8
+ context 'when user is authenticated' do
9
+ before { setup_for :account_owner }
10
+
11
+ let(:attrs) { { title: 'new SDK playlist', category_id: api_envs['category_id'] } }
12
+
13
+ context "missing required parameters" do
14
+ it "errors out" do
15
+ expect{described_class.create}.to raise_error(
16
+ Error, "Invalid parameters: title is missing, category_id is missing"
17
+ )
18
+ end
19
+ end
20
+
21
+ it 'creates, updates and deletes a playlist' do
22
+ # create new playlist
23
+ playlist = described_class.create attrs
24
+ expect(playlist.title).to eq attrs[:title]
25
+ expect(playlist.category_id).to eq attrs[:category_id]
26
+ expect(playlist.max_vids).to eq 10
27
+ expect(playlist.sort_by).to eq 'created_at'
28
+ expect(playlist.sort_order).to eq 'desc'
29
+ expect(playlist.private).to be_truthy
30
+ expect(playlist.dimensions).to eq 'auto'
31
+ expect(playlist.position).to eq 'left'
32
+ expect(playlist.autoplay).to be_falsey
33
+ expect(playlist.continuous_play).to be_falsey
34
+ expect(playlist.embed_code).to match(
35
+ "<iframe id=\"vzpl-#{playlist.id}\" name=\"vzpl-#{playlist.id}\" " \
36
+ "title=\"vzaar video player\" class=\"vzaar video player\" " \
37
+ "type=\"text/html\" width=\"927\" height=\"432\" frameborder=\"0\" " \
38
+ "allowFullScreen allowTransparency=\"true\" mozallowfullscreen " \
39
+ "webkitAllowFullScreen src=\"//#{api_envs["vd_hostname"]}/playlists/#{playlist.id}\">" \
40
+ "</iframe>"
41
+ )
42
+
43
+ # reload the playlist
44
+ playlist = described_class.find(playlist.id)
45
+
46
+ # update the playlist
47
+ expect(playlist).not_to be_changed
48
+ new_title = playlist.title = "(updated): #{Time.now.utc}"
49
+ playlist.max_vids = 11
50
+ playlist.sort_by = 'title'
51
+ playlist.sort_order = 'asc'
52
+ playlist.private = false
53
+ playlist.dimensions = '400x200'
54
+ playlist.position = 'top'
55
+ playlist.autoplay = true
56
+ playlist.continuous_play = true
57
+
58
+ expect(playlist).to be_changed
59
+ playlist.save
60
+ expect(playlist).not_to be_changed
61
+
62
+ expect(playlist.title).to eq new_title
63
+ expect(playlist.max_vids).to eq 11
64
+ expect(playlist.sort_by).to eq 'title'
65
+ expect(playlist.sort_order).to eq 'asc'
66
+ expect(playlist.private).to be_falsey
67
+ expect(playlist.dimensions).to eq '400x200'
68
+ expect(playlist.position).to eq 'top'
69
+ expect(playlist.autoplay).to be_truthy
70
+ expect(playlist.continuous_play).to be_truthy
71
+ expect(playlist.embed_code).to match(
72
+ "<iframe id=\"vzpl-#{playlist.id}\" name=\"vzpl-#{playlist.id}\" " \
73
+ "title=\"vzaar video player\" class=\"vzaar video player\" " \
74
+ "type=\"text/html\" width=\"400\" height=\"330\" frameborder=\"0\" " \
75
+ "allowFullScreen allowTransparency=\"true\" mozallowfullscreen " \
76
+ "webkitAllowFullScreen src=\"//#{api_envs["vd_hostname"]}/playlists/#{playlist.id}\">" \
77
+ "</iframe>"
78
+ )
79
+
80
+ # delete the playlist
81
+ playlist.delete
82
+ expect{ described_class.find(playlist.id) }.to raise_error(
83
+ Error, 'Not found: Resource cannot be found')
84
+ end
85
+ end
86
+
87
+ context 'when user is not authenticated' do
88
+ before { setup_for :intruder }
89
+ let(:attrs) { { title: 'no', category_id: 2253 } }
90
+
91
+ it 'raises an error' do
92
+ expect{ described_class.create(attrs) }.to raise_error(
93
+ Error, 'Authentication failed: Invalid credentials')
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,37 @@
1
+ require_relative './../spec_helper'
2
+
3
+ module VzaarApi
4
+ describe 'Playlist: List' do
5
+
6
+ let(:described_class) { Playlist }
7
+
8
+ context 'when user is authenticated' do
9
+ before { setup_for :account_owner }
10
+
11
+ describe '#each_item' do
12
+ it 'retrieves the resource list' do
13
+ ids = described_class.each_item.map(&:id)
14
+ expect(ids).not_to be_empty
15
+ end
16
+ end
17
+
18
+ describe '#paginate' do
19
+ let(:pager) { described_class.paginate(page: 2, per_page: 1) }
20
+ specify { expect(pager.first.count).to eq 1 }
21
+ specify { expect(pager.next.count).to eq 1 }
22
+ specify { expect(pager.previous.count).to eq 1 }
23
+ specify { expect(pager.last.count).to eq 1 }
24
+ end
25
+ end
26
+
27
+ context 'when user is not authenticated' do
28
+ before { setup_for :intruder }
29
+
30
+ it 'raises an error' do
31
+ pager = described_class.paginate
32
+ expect{ pager.first }.to raise_error(
33
+ Error, 'Authentication failed: Invalid credentials')
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,34 @@
1
+ require_relative './../spec_helper'
2
+
3
+ module VzaarApi
4
+ describe 'Playlist: Lookup' do
5
+
6
+ let(:described_class) { Playlist }
7
+ let(:id) { api_envs['playlist_id'] }
8
+
9
+ context 'when user is authenticated' do
10
+ before { setup_for :account_owner }
11
+
12
+ context 'and resource can be found' do
13
+ subject { described_class.find(id) }
14
+ specify { expect(subject.id).to eq id }
15
+ end
16
+
17
+ context 'and resource cannot be found' do
18
+ it 'raises an error' do
19
+ expect{ described_class.find(-1) }.to raise_error(
20
+ Error, 'Not found: Resource cannot be found')
21
+ end
22
+ end
23
+ end
24
+
25
+ context 'when user is not authenticated' do
26
+ before { setup_for :intruder }
27
+
28
+ it 'raises an error' do
29
+ expect{ described_class.find(id) }.to raise_error(
30
+ Error, 'Authentication failed: Invalid credentials')
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,18 @@
1
+ require_relative './spec_helper'
2
+
3
+ module VzaarApi
4
+ describe 'Rate limit' do
5
+
6
+ let(:described_class) { EncodingPreset }
7
+ let(:id) { api_envs['encoding_preset_id'] }
8
+
9
+ before { setup_for :account_owner }
10
+
11
+ it 'is available after each request' do
12
+ EncodingPreset.find(id)
13
+ expect(VzaarApi.rate_limit).to eq 200
14
+ expect(VzaarApi.rate_limit_remaining).to be < 200
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+
4
+ require 'vzaar_api'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["./examples/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |c|
11
+ c.include Helpers
12
+ c.order = 'defined'
13
+ end
14
+
15
+ VCR.configure do |c|
16
+ c.allow_http_connections_when_no_cassette = true
17
+ end
@@ -0,0 +1,16 @@
1
+ module Helpers
2
+
3
+ def api_envs
4
+ @api_envs = begin
5
+ env = ENV["API_ENV"] || "development"
6
+ YAML.load_file("api_envs.yml")[env]
7
+ end
8
+ end
9
+
10
+ def setup_for(user)
11
+ VzaarApi.hostname = api_envs['hostname'] if api_envs['hostname']
12
+ VzaarApi.auth_token = api_envs[user.to_s]['auth_token']
13
+ VzaarApi.client_id = api_envs[user.to_s]['client_id']
14
+ end
15
+
16
+ end
Binary file
Binary file
@@ -0,0 +1,73 @@
1
+ require_relative './../spec_helper'
2
+
3
+ module VzaarApi
4
+ describe 'Video: Create' do
5
+
6
+ let(:described_class) { Video }
7
+
8
+ context 'when user is authenticated' do
9
+ before { setup_for :account_owner }
10
+
11
+ context 'when doing a single-part upload' do
12
+ it 'creates, updates and deletes the video' do
13
+ attrs = { title: "single: #{Time.now.utc}", path: 'examples/support/videos/small.mp4' }
14
+ video = described_class.create(attrs)
15
+ expect(video.title).to eq attrs[:title]
16
+
17
+ # reload the video
18
+ video = described_class.find(video.id)
19
+
20
+ # update the video
21
+ expect(video).not_to be_changed
22
+ video.title = "single (updated): #{Time.now.utc}"
23
+ video.description = 'this is the new description'
24
+ expect(video).to be_changed
25
+ video.save
26
+ expect(video).not_to be_changed
27
+
28
+ # delete the video
29
+ video.delete
30
+ expect{ described_class.find(video.id) }.to raise_error(
31
+ Error, 'Not found: Resource cannot be found')
32
+ end
33
+ end
34
+
35
+ context 'when doing a multi-part upload' do
36
+ it 'creates the video' do
37
+ attrs = { title: "multi-part: #{Time.now.utc}", path: 'examples/support/videos/medium.mp4' }
38
+ video = described_class.create(attrs)
39
+ expect(video.title).to eq attrs[:title]
40
+ end
41
+ end
42
+
43
+ context 'when doing a multi-part upload with a non-default ingest recipe' do
44
+ it 'creates the video' do
45
+ attrs = { title: "custom-recipe: #{Time.now.utc}",
46
+ ingest_recipe_id: api_envs['ingest_recipe']['other'],
47
+ path: 'examples/support/videos/medium.mp4' }
48
+ video = described_class.create(attrs)
49
+ expect(video.title).to eq attrs[:title]
50
+ end
51
+ end
52
+
53
+ context 'when doing a link upload' do
54
+ it 'creates the video' do
55
+ attrs = { title: "link: #{Time.now.utc}", url: 'https://www.dropbox.com/s/zu1n51dm9sabogq/dropbox-video.mp4?dl=0' }
56
+ video = described_class.create(attrs)
57
+ expect(video.title).to eq attrs[:title]
58
+ end
59
+ end
60
+ end
61
+
62
+ context 'when user is not authenticated' do
63
+ before { setup_for :intruder }
64
+
65
+ it 'raises an error' do
66
+ attrs = { path: 'examples/support/videos/small.mp4' }
67
+ expect{ described_class.create(attrs) }.to raise_error(
68
+ Error, 'Authentication failed: Invalid credentials')
69
+ end
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,9 @@
1
+ module VzaarApi
2
+ class Abstract
3
+
4
+ def initialize(attrs = {}); end
5
+
6
+ def update_from_attributes(attrs); end
7
+
8
+ end
9
+ end
@@ -0,0 +1,39 @@
1
+ module VzaarApi
2
+ class Category < Abstract
3
+
4
+ ENDPOINT = 'categories'
5
+
6
+ ATTR_READERS = [:id, :account_id, :user_id, :name,
7
+ :description, :parent_id, :depth,
8
+ :node_children_count, :tree_children_count,
9
+ :node_video_count, :tree_video_count,
10
+ :created_at, :updated_at].freeze
11
+
12
+ ATTR_ACCESSORS = [:name, :parent_id, :move_to_root].freeze
13
+
14
+ prepend Lib::HasAttributes
15
+ include Lib::HasCollectionBuilder
16
+ include Lib::HasResourceUrl
17
+ include Lib::ActiveObject::Find
18
+ include Lib::ActiveObject::Save
19
+ include Lib::ActiveObject::Delete
20
+ include Lib::WillPaginate
21
+
22
+ def initialize(attrs = {})
23
+ update_from_attributes attrs
24
+ end
25
+
26
+ def self.create(attrs = {})
27
+ url = Lib::Api.resource_url(ENDPOINT)
28
+ new Lib::Api.new.post(url, attrs).data
29
+ end
30
+
31
+ def subtree(query = {})
32
+ args = query.merge(
33
+ resource_url: resource_url("#{id}/subtree"),
34
+ resource_class: self.class
35
+ )
36
+ Lib::PagedResource.new(args)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,19 @@
1
+ module VzaarApi
2
+ class EncodingPreset < Abstract
3
+
4
+ ENDPOINT = 'encoding_presets'
5
+
6
+ ATTR_READERS = [:id, :name, :description, :output_format,
7
+ :bitrate_kbps, :long_dimension, :video_codec,
8
+ :profile, :frame_rate_upper_threshold, :keyframe_upper_threshold,
9
+ :audio_bitrate_kbps, :audio_channels, :audio_sample_rate,
10
+ :max_bitrate_kbps, :created_at, :updated_at].freeze
11
+
12
+ prepend Lib::HasAttributes
13
+ include Lib::HasCollectionBuilder
14
+ include Lib::HasResourceUrl
15
+ include Lib::ActiveObject::Find
16
+ include Lib::WillPaginate
17
+
18
+ end
19
+ end
@@ -0,0 +1,35 @@
1
+ module VzaarApi
2
+ class IngestRecipe < Abstract
3
+
4
+ ENDPOINT = 'ingest_recipes'
5
+
6
+ ATTR_READERS = [:id, :recipe_type, :account_id, :user_id,
7
+ :created_at, :updated_at].freeze
8
+
9
+ ATTR_ACCESSORS = [:name, :description, :default, :multipass,
10
+ :frame_grab_time, :encoding_preset_ids,
11
+ :generate_animated_thumb, :generate_sprite,
12
+ :use_watermark, :send_to_youtube,
13
+ :encoding_presets].freeze
14
+
15
+ prepend Lib::HasAttributes
16
+ include Lib::HasResourceUrl
17
+ include Lib::ActiveObject::Find
18
+ include Lib::ActiveObject::Create
19
+ include Lib::ActiveObject::Save
20
+ include Lib::ActiveObject::Delete
21
+ include Lib::WillPaginate
22
+
23
+ def initialize(attrs = {})
24
+ update_from_attributes(attrs)
25
+ end
26
+
27
+ private
28
+
29
+ def update_from_attributes(attrs = {})
30
+ @encoding_presets = EncodingPreset.build(attrs[:encoding_presets])
31
+ @encoding_preset_ids = @encoding_presets.map(&:id)
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,11 @@
1
+ module VzaarApi
2
+ class LegacyRendition < Abstract
3
+
4
+ ATTR_READERS = [:id, :type, :width, :height, :bitrate,
5
+ :status, :created_at, :updated_at].freeze
6
+
7
+ prepend Lib::HasAttributes
8
+ include Lib::HasCollectionBuilder
9
+
10
+ end
11
+ end
@@ -0,0 +1,92 @@
1
+ module VzaarApi
2
+ module Lib
3
+ module ActiveObject
4
+
5
+ module Find
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+ def find(id)
12
+ response = Lib::Api.new.get(resource_url(id))
13
+ new response.data
14
+ end
15
+ end
16
+ end
17
+
18
+ module Create
19
+ def self.included(base)
20
+ base.extend(ClassMethods)
21
+ end
22
+
23
+ module ClassMethods
24
+ def create(attrs)
25
+ response = Lib::Api.new.post(resource_url, attrs)
26
+ new response.data
27
+ end
28
+ end
29
+ end
30
+
31
+ module Save
32
+ def self.included(base)
33
+ base.include(InstanceMethods)
34
+ end
35
+
36
+ module InstanceMethods
37
+ def save
38
+ if changed?
39
+ response = Lib::Api.new.patch(resource_url(id), changed_attributes)
40
+ update_from_attributes response.data
41
+ saved!
42
+ end
43
+ true
44
+ end
45
+
46
+ def changed?
47
+ !changes.empty?
48
+ end
49
+
50
+ def changed
51
+ changes.keys
52
+ end
53
+
54
+ def changed_attributes
55
+ {}.tap do |result|
56
+ changes.each do |attr, vals|
57
+ result[attr] = vals[1]
58
+ end
59
+ end
60
+ end
61
+
62
+ def changes
63
+ @changes ||= {}
64
+ end
65
+
66
+ def has_changed?(attr)
67
+ changed.include? attr.to_sym
68
+ end
69
+
70
+ def saved!
71
+ @changes = nil
72
+ end
73
+ private :saved!
74
+ end
75
+ end
76
+
77
+ module Delete
78
+ def self.included(base)
79
+ base.include(InstanceMethods)
80
+ end
81
+
82
+ module InstanceMethods
83
+ def delete
84
+ Lib::Api.new.delete(resource_url(id))
85
+ true
86
+ end
87
+ end
88
+ end
89
+
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,54 @@
1
+ module VzaarApi
2
+ module Lib
3
+ class Api
4
+
5
+ def self.api_root_url
6
+ "#{VzaarApi.protocol}://#{VzaarApi.hostname}/api/v2"
7
+ end
8
+
9
+ def self.resource_url(resource, path = nil)
10
+ [api_root_url, resource, path].compact.join('/')
11
+ end
12
+
13
+ def delete(url)
14
+ handle_response http_client.delete(url, {}, headers)
15
+ end
16
+
17
+ def get(url, query = {})
18
+ handle_response http_client.get(url, query, headers)
19
+ end
20
+
21
+ def patch(url, body = {})
22
+ handle_response http_client.patch(url, body.to_json, headers)
23
+ end
24
+
25
+ def post(url, body = {})
26
+ handle_response http_client.post(url, body.to_json, headers)
27
+ end
28
+
29
+ def handle_response(response)
30
+ api_response = ApiResponse.new(response)
31
+ VzaarApi.rate_limit = api_response.rate_limit
32
+ VzaarApi.rate_limit_remaining = api_response.rate_limit_remaining
33
+ VzaarApi.rate_limit_reset = api_response.rate_limit_reset
34
+ return api_response if api_response.ok?
35
+ raise Error.new(api_response.error)
36
+ end
37
+
38
+ def http_client
39
+ HTTPClient.new.tap do |c|
40
+ c.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
41
+ end
42
+ end
43
+
44
+ def headers
45
+ {
46
+ 'X-Auth-Token' => VzaarApi.auth_token,
47
+ 'X-Client-Id' => VzaarApi.client_id,
48
+ 'Content-Type' => 'application/json'
49
+ }
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,61 @@
1
+ module VzaarApi
2
+ module Lib
3
+ class ApiResponse
4
+
5
+ attr_reader :response
6
+
7
+ def initialize(response)
8
+ @response = response
9
+ end
10
+
11
+ def data
12
+ json[:data]
13
+ end
14
+
15
+ def meta
16
+ json[:meta]
17
+ end
18
+
19
+ def error
20
+ simple_errors.join('; ')
21
+ end
22
+
23
+ def ok?
24
+ response.ok?
25
+ end
26
+
27
+ def rate_limit
28
+ rate_limit_value 'X-RateLimit-Limit'
29
+ end
30
+
31
+ def rate_limit_remaining
32
+ rate_limit_value 'X-RateLimit-Remaining'
33
+ end
34
+
35
+ def rate_limit_reset
36
+ rate_limit_value 'X-RateLimit-Reset'
37
+ end
38
+
39
+ private
40
+
41
+ def rate_limit_value(header)
42
+ if limit = response.headers[header]
43
+ limit.to_i
44
+ else
45
+ nil
46
+ end
47
+ end
48
+
49
+ def simple_errors
50
+ json[:errors].map { |e| [e[:message], e[:detail]].join(': ') }
51
+ end
52
+
53
+ def json
54
+ @json ||= JSON.parse(response.body, symbolize_names: true)
55
+ rescue JSON::ParserError
56
+ raise Error.new('Invalid JSON response from API')
57
+ end
58
+
59
+ end
60
+ end
61
+ end