vzaar_api 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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