vzaar_api 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rspec +4 -0
- data/.tool-versions +1 -0
- data/.travis.yml +3 -0
- data/Changelog +50 -0
- data/Gemfile +3 -0
- data/Guardfile +25 -0
- data/README.md +55 -0
- data/Rakefile +26 -0
- data/examples/README.md +33 -0
- data/examples/api_envs.yml.example +31 -0
- data/examples/category/create_update_delete_spec.rb +100 -0
- data/examples/category/list_spec.rb +38 -0
- data/examples/category/list_subtree_spec.rb +40 -0
- data/examples/category/lookup_spec.rb +35 -0
- data/examples/encoding_preset/list_spec.rb +38 -0
- data/examples/encoding_preset/lookup_spec.rb +35 -0
- data/examples/ingest_recipe/create_update_delete_spec.rb +70 -0
- data/examples/ingest_recipe/list_spec.rb +38 -0
- data/examples/ingest_recipe/lookup_spec.rb +35 -0
- data/examples/playlist/create_update_delete_spec.rb +97 -0
- data/examples/playlist/list_spec.rb +37 -0
- data/examples/playlist/lookup_spec.rb +34 -0
- data/examples/rate_limit_spec.rb +18 -0
- data/examples/spec_helper.rb +17 -0
- data/examples/support/helpers.rb +16 -0
- data/examples/support/videos/medium.mp4 +0 -0
- data/examples/support/videos/small.mp4 +0 -0
- data/examples/video/create_update_delete_spec.rb +73 -0
- data/lib/vzaar_api/abstract.rb +9 -0
- data/lib/vzaar_api/category.rb +39 -0
- data/lib/vzaar_api/encoding_preset.rb +19 -0
- data/lib/vzaar_api/ingest_recipe.rb +35 -0
- data/lib/vzaar_api/legacy_rendition.rb +11 -0
- data/lib/vzaar_api/lib/active_object.rb +92 -0
- data/lib/vzaar_api/lib/api.rb +54 -0
- data/lib/vzaar_api/lib/api_response.rb +61 -0
- data/lib/vzaar_api/lib/has_attributes.rb +49 -0
- data/lib/vzaar_api/lib/has_collection_builder.rb +17 -0
- data/lib/vzaar_api/lib/has_resource_url.rb +24 -0
- data/lib/vzaar_api/lib/paged_resource.rb +80 -0
- data/lib/vzaar_api/lib/will_paginate.rb +22 -0
- data/lib/vzaar_api/link_upload.rb +14 -0
- data/lib/vzaar_api/playlist.rb +29 -0
- data/lib/vzaar_api/rendition.rb +16 -0
- data/lib/vzaar_api/signature/abstract.rb +40 -0
- data/lib/vzaar_api/signature/factory.rb +39 -0
- data/lib/vzaar_api/signature/multipart.rb +23 -0
- data/lib/vzaar_api/signature/single.rb +17 -0
- data/lib/vzaar_api/strategy/video/create.rb +46 -0
- data/lib/vzaar_api/upload/s3.rb +90 -0
- data/lib/vzaar_api/upload/virtual_file.rb +14 -0
- data/lib/vzaar_api/version.rb +4 -0
- data/lib/vzaar_api/video.rb +38 -0
- data/lib/vzaar_api.rb +60 -0
- data/spec/fixtures/vcr_cassettes/categories/each_item.yml +363 -0
- data/spec/fixtures/vcr_cassettes/categories/find.yml +61 -0
- data/spec/fixtures/vcr_cassettes/categories/find_404.yml +49 -0
- data/spec/fixtures/vcr_cassettes/categories/paginate_first.yml +61 -0
- data/spec/fixtures/vcr_cassettes/categories/paginate_last.yml +119 -0
- data/spec/fixtures/vcr_cassettes/categories/paginate_next.yml +120 -0
- data/spec/fixtures/vcr_cassettes/categories/paginate_previous.yml +120 -0
- data/spec/fixtures/vcr_cassettes/categories/subtree.yml +127 -0
- data/spec/fixtures/vcr_cassettes/categories/subtree_paginate_first.yml +123 -0
- data/spec/fixtures/vcr_cassettes/categories/subtree_paginate_last.yml +185 -0
- data/spec/fixtures/vcr_cassettes/categories/subtree_paginate_next.yml +184 -0
- data/spec/fixtures/vcr_cassettes/categories/subtree_paginate_previous.yml +184 -0
- data/spec/fixtures/vcr_cassettes/encoding_presets/each_item.yml +299 -0
- data/spec/fixtures/vcr_cassettes/encoding_presets/find.yml +62 -0
- data/spec/fixtures/vcr_cassettes/encoding_presets/find_404.yml +51 -0
- data/spec/fixtures/vcr_cassettes/encoding_presets/paginate_first.yml +62 -0
- data/spec/fixtures/vcr_cassettes/encoding_presets/paginate_last.yml +121 -0
- data/spec/fixtures/vcr_cassettes/encoding_presets/paginate_next.yml +121 -0
- data/spec/fixtures/vcr_cassettes/encoding_presets/paginate_previous.yml +121 -0
- data/spec/fixtures/vcr_cassettes/ingest_recipes/create_200.yml +63 -0
- data/spec/fixtures/vcr_cassettes/ingest_recipes/create_422.yml +52 -0
- data/spec/fixtures/vcr_cassettes/ingest_recipes/delete_204.yml +166 -0
- data/spec/fixtures/vcr_cassettes/ingest_recipes/delete_422.yml +112 -0
- data/spec/fixtures/vcr_cassettes/ingest_recipes/each_item.yml +182 -0
- data/spec/fixtures/vcr_cassettes/ingest_recipes/find.yml +62 -0
- data/spec/fixtures/vcr_cassettes/ingest_recipes/find_404.yml +51 -0
- data/spec/fixtures/vcr_cassettes/ingest_recipes/paginate_first.yml +62 -0
- data/spec/fixtures/vcr_cassettes/ingest_recipes/paginate_last.yml +122 -0
- data/spec/fixtures/vcr_cassettes/ingest_recipes/paginate_next.yml +121 -0
- data/spec/fixtures/vcr_cassettes/ingest_recipes/paginate_previous.yml +122 -0
- data/spec/fixtures/vcr_cassettes/ingest_recipes/update_200.yml +242 -0
- data/spec/fixtures/vcr_cassettes/ingest_recipes/update_422.yml +113 -0
- data/spec/fixtures/vcr_cassettes/playlists/each_item.yml +607 -0
- data/spec/fixtures/vcr_cassettes/playlists/find.yml +66 -0
- data/spec/fixtures/vcr_cassettes/playlists/find_404.yml +51 -0
- data/spec/fixtures/vcr_cassettes/playlists/paginate_first.yml +74 -0
- data/spec/fixtures/vcr_cassettes/playlists/paginate_last.yml +146 -0
- data/spec/fixtures/vcr_cassettes/playlists/paginate_next.yml +145 -0
- data/spec/fixtures/vcr_cassettes/playlists/paginate_previous.yml +145 -0
- data/spec/fixtures/vcr_cassettes/signature/multipart_201.yml +62 -0
- data/spec/fixtures/vcr_cassettes/signature/multipart_422.yml +52 -0
- data/spec/fixtures/vcr_cassettes/signature/single_201.yml +62 -0
- data/spec/fixtures/vcr_cassettes/signature/single_422.yml +51 -0
- data/spec/fixtures/vcr_cassettes/upload/multipart_201.yml +279868 -0
- data/spec/fixtures/vcr_cassettes/upload/multipart_403.yml +116578 -0
- data/spec/fixtures/vcr_cassettes/upload/single_201.yml +23388 -0
- data/spec/fixtures/vcr_cassettes/upload/single_403.yml +23374 -0
- data/spec/fixtures/vcr_cassettes/videos/create/error.yml +51 -0
- data/spec/fixtures/vcr_cassettes/videos/create/guid_201.yml +65 -0
- data/spec/fixtures/vcr_cassettes/videos/create/guid_error.yml +52 -0
- data/spec/fixtures/vcr_cassettes/videos/create/link_201.yml +65 -0
- data/spec/fixtures/vcr_cassettes/videos/create/link_error.yml +51 -0
- data/spec/fixtures/vcr_cassettes/videos/create/path_201.yml +23509 -0
- data/spec/fixtures/vcr_cassettes/videos/delete_204.yml +168 -0
- data/spec/fixtures/vcr_cassettes/videos/find.yml +66 -0
- data/spec/fixtures/vcr_cassettes/videos/find_404.yml +51 -0
- data/spec/fixtures/vcr_cassettes/videos/paginate_first.yml +71 -0
- data/spec/fixtures/vcr_cassettes/videos/paginate_last.yml +137 -0
- data/spec/fixtures/vcr_cassettes/videos/paginate_next.yml +139 -0
- data/spec/fixtures/vcr_cassettes/videos/paginate_previous.yml +139 -0
- data/spec/spec_helper.rb +103 -0
- data/spec/support/files/video-1.0MB.mp4 +0 -0
- data/spec/support/files/video-12.0MB.mp4 +0 -0
- data/spec/support/files/video-4.9MB.mp4 +0 -0
- data/spec/support/files/video-5.0MB.mp4 +0 -0
- data/spec/support/helpers.rb +16 -0
- data/spec/vzaar_api/category_spec.rb +141 -0
- data/spec/vzaar_api/encoding_preset_spec.rb +92 -0
- data/spec/vzaar_api/ingest_recipe_spec.rb +197 -0
- data/spec/vzaar_api/lib/api_spec.rb +28 -0
- data/spec/vzaar_api/playlist_spec.rb +97 -0
- data/spec/vzaar_api/rendition_spec.rb +55 -0
- data/spec/vzaar_api/signature/factory_spec.rb +68 -0
- data/spec/vzaar_api/signature/multipart_spec.rb +81 -0
- data/spec/vzaar_api/signature/single_spec.rb +72 -0
- data/spec/vzaar_api/upload/s3_spec.rb +112 -0
- data/spec/vzaar_api/video_spec.rb +248 -0
- data/spec/vzaar_api/vzaar_api_spec.rb +18 -0
- data/spec/vzaar_api_helper.rb +19 -0
- data/vzaar.png +0 -0
- data/vzaar_api.gemspec +35 -0
- 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,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,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
|