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,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,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,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,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
|