helix 0.0.2.7.pre → 0.0.2.8.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +11 -74
- data/lib/helix.rb +2 -0
- data/lib/helix/album.rb +1 -1
- data/lib/helix/base.rb +23 -3
- data/lib/helix/config.rb +38 -4
- data/lib/helix/durationed_media.rb +5 -5
- data/lib/helix/library.rb +3 -1
- data/lib/helix/media.rb +3 -62
- data/lib/helix/restful.rb +89 -0
- data/lib/helix/track.rb +2 -0
- data/lib/helix/uploadable.rb +52 -0
- data/lib/helix/video.rb +42 -16
- data/spec/album_spec.rb +2 -1
- data/spec/base_spec.rb +50 -73
- data/spec/config_spec.rb +82 -1
- data/spec/durationed_media_spec.rb +2 -1
- data/spec/image_spec.rb +2 -1
- data/spec/library_spec.rb +14 -9
- data/spec/media_spec.rb +80 -43
- data/spec/tag_spec.rb +1 -1
- data/spec/track_spec.rb +117 -5
- data/spec/video_spec.rb +188 -8
- metadata +24 -23
data/lib/helix/track.rb
CHANGED
@@ -0,0 +1,52 @@
|
|
1
|
+
module Helix
|
2
|
+
|
3
|
+
# Mixed-in to ORM classes that are capable of being uploaded.
|
4
|
+
|
5
|
+
module Uploadable
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
|
9
|
+
def upload(file_name)
|
10
|
+
RestClient.post(upload_server_name,
|
11
|
+
{ file: File.new(file_name.to_s, "rb") },
|
12
|
+
{ multipart: true } )
|
13
|
+
http_close
|
14
|
+
end
|
15
|
+
|
16
|
+
def upload_server_name
|
17
|
+
upload_get(:http_open)
|
18
|
+
end
|
19
|
+
|
20
|
+
def http_open
|
21
|
+
upload_server_name
|
22
|
+
end
|
23
|
+
|
24
|
+
def upload_open
|
25
|
+
upload_server_name
|
26
|
+
end
|
27
|
+
|
28
|
+
def http_close
|
29
|
+
upload_get(:http_close)
|
30
|
+
end
|
31
|
+
|
32
|
+
def upload_close
|
33
|
+
http_close
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def upload_get(action)
|
39
|
+
url = config.build_url( resource_label: "upload_sessions",
|
40
|
+
guid: config.signature(:ingest),
|
41
|
+
action: action,
|
42
|
+
content_type: "" )
|
43
|
+
RestClient.get(url)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.included(klass); klass.extend(ClassMethods); end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
data/lib/helix/video.rb
CHANGED
@@ -17,25 +17,38 @@ module Helix
|
|
17
17
|
# @return [Symbol] Name of the class.
|
18
18
|
def self.resource_label_sym; super; end
|
19
19
|
|
20
|
+
# Used to create a slice video from an existing video.
|
21
|
+
# API doc reference: /doc/api/video/slice
|
22
|
+
#
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# Reference Twistage API documentation
|
26
|
+
# to see valid xml to pass.
|
27
|
+
# xml_string = "<xml></xml>"
|
28
|
+
# Helix::Video.slice({ guid: "239c59483d346",
|
29
|
+
# use_raw_xml: xml_string })
|
30
|
+
#
|
31
|
+
# @param [Hash] The hash used in this.
|
32
|
+
# @return [String] Returns a blank string.
|
20
33
|
def self.slice(attrs={})
|
21
34
|
rest_post(:slice, attrs)
|
22
35
|
end
|
23
36
|
|
24
|
-
|
25
37
|
# Used to retrieve a stillframe for a video by using
|
26
38
|
# the video guid.
|
39
|
+
# API doc reference: /doc/api/video/still_frames
|
27
40
|
#
|
28
41
|
# @example
|
29
|
-
# sf_data = Helix::Video.
|
42
|
+
# sf_data = Helix::Video.stillframe_for("239c59483d346") #=> xDC\xF1?\xE9*?\xFF\xD9
|
30
43
|
# File.open("original.jpg", "w") { |f| f.puts sf_data }
|
31
44
|
#
|
32
|
-
# @param
|
33
|
-
# @param
|
45
|
+
# @param [String] Guid is the string containing the guid for the video.
|
46
|
+
# @param [Hash] Opts a hash of options for building URL.
|
34
47
|
# @return [String] Stillframe jpg data, save it to a file with extension .jpg.
|
35
|
-
def self.
|
36
|
-
opts
|
37
|
-
RestClient.log
|
38
|
-
url
|
48
|
+
def self.stillframe_for(guid, original_opts={})
|
49
|
+
opts = original_opts.clone
|
50
|
+
RestClient.log = 'helix.log' if opts.delete(:log)
|
51
|
+
url = stillframe_url(guid, opts)
|
39
52
|
RestClient.get(url)
|
40
53
|
end
|
41
54
|
|
@@ -46,7 +59,7 @@ module Helix
|
|
46
59
|
# video_data = video.download #=> xDC\xF1?\xE9*?\xFF\xD9
|
47
60
|
# File.open("my_video.mp4", "w") { |f| f.puts video_data }
|
48
61
|
#
|
49
|
-
# @param
|
62
|
+
# @param [Hash] opts a hash of options for building URL
|
50
63
|
# @return [String] Raw video data, save it to a file
|
51
64
|
def download(opts={})
|
52
65
|
generic_download(opts.merge(action: :file))
|
@@ -58,35 +71,48 @@ module Helix
|
|
58
71
|
# video = Helix::Video.find("239c59483d346")
|
59
72
|
# video_data = video.play #=> xDC\xF1?\xE9*?\xFF\xD9
|
60
73
|
#
|
61
|
-
# @param
|
74
|
+
# @param [Hash] opts a hash of options for building URL
|
62
75
|
# @return [String] Raw video data
|
63
76
|
def play(opts={})
|
64
77
|
generic_download(opts.merge(action: :play))
|
65
78
|
end
|
66
79
|
|
80
|
+
# Used to retrieve a stillframe data for a video by using
|
81
|
+
# the video guid.
|
82
|
+
#
|
83
|
+
# @example
|
84
|
+
# video = Helix::Video.find("239c59483d346")
|
85
|
+
# sf_data = video.stillframe #=> xDC\xF1?\xE9*?\xFF\xD9
|
86
|
+
# File.open("original.jpg", "w") { |f| f.puts sf_data }
|
87
|
+
#
|
88
|
+
# @param [Hash] opts a hash of options for building URL
|
89
|
+
# @return [String] Stillframe jpg data, save it to a file with extension .jpg.
|
67
90
|
def stillframe(opts={})
|
68
|
-
self.class.
|
91
|
+
self.class.stillframe_for(self.guid, opts)
|
69
92
|
end
|
70
93
|
|
71
94
|
private
|
72
95
|
|
73
|
-
def self.
|
96
|
+
def self.stillframe_dimensions(opts)
|
74
97
|
width = opts[:width].to_s + "w" unless opts[:width].nil?
|
75
98
|
height = opts[:height].to_s + "h" unless opts[:height].nil?
|
76
99
|
width = "original" if opts[:width].nil? && opts[:height].nil?
|
77
100
|
[width, height]
|
78
101
|
end
|
79
102
|
|
80
|
-
def self.
|
103
|
+
def self.stillframe_url(guid, opts)
|
81
104
|
server = opts[:server] || config.credentials[:server] || "service-staging"
|
82
|
-
width, height =
|
105
|
+
width, height = stillframe_dimensions(opts)
|
83
106
|
url = "#{server}.twistage.com/videos/#{guid}/screenshots/"
|
84
107
|
url << "#{width.to_s}#{height.to_s}.jpg"
|
85
108
|
end
|
86
109
|
|
87
110
|
def generic_download(opts)
|
88
|
-
content_type
|
89
|
-
url
|
111
|
+
content_type = opts[:content_type] || ''
|
112
|
+
url = config.build_url( action: opts[:action],
|
113
|
+
content_type: content_type,
|
114
|
+
guid: guid,
|
115
|
+
resource_label: plural_resource_label )
|
90
116
|
RestClient.get(url, params: {signature: config.signature(:view)})
|
91
117
|
end
|
92
118
|
|
data/spec/album_spec.rb
CHANGED
@@ -5,7 +5,8 @@ describe Helix::Album do
|
|
5
5
|
let(:klass) { Helix::Album }
|
6
6
|
|
7
7
|
subject { klass }
|
8
|
-
|
8
|
+
mods = [ Helix::Base, Helix::Media ]
|
9
|
+
mods.each { |mod| its(:ancestors) { should include(mod) } }
|
9
10
|
its(:guid_name) { should eq('album_id') }
|
10
11
|
its(:resource_label_sym) { should be(:album) }
|
11
12
|
its(:plural_resource_label) { should eq('albums') }
|
data/spec/base_spec.rb
CHANGED
@@ -3,14 +3,6 @@ require 'helix'
|
|
3
3
|
|
4
4
|
describe Helix::Base do
|
5
5
|
|
6
|
-
def set_stubs(obj, even_sig=false)
|
7
|
-
obj.instance_variable_set(:@attributes, {})
|
8
|
-
obj.stub(:resource_label_sym) { :video }
|
9
|
-
obj.stub(:plural_resource_label) { 'videos' }
|
10
|
-
obj.stub(:guid) { 'some_guid' }
|
11
|
-
obj.stub(:signature) { 'some_sig' } if even_sig
|
12
|
-
end
|
13
|
-
|
14
6
|
let(:klass) { Helix::Base }
|
15
7
|
|
16
8
|
subject { klass }
|
@@ -35,82 +27,67 @@ describe Helix::Base do
|
|
35
27
|
end
|
36
28
|
|
37
29
|
shared_examples_for "a search all with opts" do
|
38
|
-
let(:mock_config) { mock(Helix::Config, build_url: :built_url, get_response: {}) }
|
39
30
|
subject { klass.method(meth) }
|
40
31
|
its(:arity) { should eq(-1) }
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
before(:each) do klass.stub(:plural_resource_label) { plural_resource_label } end
|
46
|
-
it "should clone the opts arg" do
|
47
|
-
opts.should_receive(:clone) { opts }
|
48
|
-
klass.send(meth, opts)
|
49
|
-
end
|
50
|
-
it "should build a XML URL -> the_url" do
|
51
|
-
mock_config.should_receive(:build_url).with(content_type: :xml,
|
52
|
-
resource_label: plural_resource_label)
|
53
|
-
klass.send(meth, opts)
|
54
|
-
end
|
55
|
-
it "should get_response(the_url, {sig_type: :view}.merge(opts) -> raw_response" do
|
56
|
-
mock_config.should_receive(:get_response).with(:built_url, {sig_type: :view}.merge(opts))
|
57
|
-
klass.send(meth, opts)
|
32
|
+
context "when there is NOT a config instance" do
|
33
|
+
before(:each) do Helix::Config.stub(:instance) { nil } end
|
34
|
+
it "should raise a NoConfigurationLoaded exception" do
|
35
|
+
lambda { klass.send(meth) }.should raise_error(Helix::NoConfigurationLoaded)
|
58
36
|
end
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
end
|
65
|
-
context "when data_sets is nil" do
|
66
|
-
it "should return []" do expect(klass.send(meth, opts)).to eq([]) end
|
37
|
+
end
|
38
|
+
context "when there is a config instance" do
|
39
|
+
let(:mock_config) do
|
40
|
+
dss = (0..2).map { |x| :"attrs_#{x}" }
|
41
|
+
mock(Helix::Config, build_url: :built_url, get_aggregated_data_sets: dss)
|
67
42
|
end
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
43
|
+
before(:each) do Helix::Config.stub(:instance) { mock_config } end
|
44
|
+
context "and NOT given an opts Hash" do
|
45
|
+
let(:plural_resource_label) { :videos }
|
46
|
+
before(:each) do klass.stub(:plural_resource_label) { plural_resource_label } end
|
47
|
+
it "should get_aggregated_data_sets(the_url, plural_resource_label, {sig_type: :view}" do
|
48
|
+
opts = {sig_type: :view}
|
49
|
+
mock_config.should_receive(:get_aggregated_data_sets).with(:built_url, plural_resource_label, opts) { [:expected] }
|
50
|
+
klass.send(meth, opts)
|
51
|
+
end
|
52
|
+
[ Helix::Video ].each do |child|
|
53
|
+
it "should should instantiate #{child.to_s} from each data_set" do
|
54
|
+
opts = {sig_type: :view}
|
55
|
+
children = child.send(meth, opts)
|
56
|
+
children.each_with_index do |c,idx|
|
57
|
+
expect(c).to be_a(child)
|
58
|
+
expect(c.attributes).to be(:"attrs_#{idx}")
|
59
|
+
end
|
60
|
+
end
|
76
61
|
end
|
77
62
|
end
|
78
63
|
end
|
79
64
|
end
|
80
65
|
|
81
66
|
shared_examples_for "a search all without opts" do
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
before(:each) do klass.stub(:plural_resource_label) { plural_resource_label } end
|
88
|
-
it "should build a XML URL -> the_url" do
|
89
|
-
mock_config.should_receive(:build_url).with(content_type: :xml,
|
90
|
-
resource_label: plural_resource_label)
|
91
|
-
klass.send(meth)
|
92
|
-
end
|
93
|
-
it "should get_response(the_url, {sig_type: :view} -> raw_response" do
|
94
|
-
mock_config.should_receive(:get_response).with(:built_url, {sig_type: :view})
|
95
|
-
klass.send(meth)
|
96
|
-
end
|
97
|
-
it "should read raw_response[plural_resource_label] -> data_sets" do
|
98
|
-
mock_raw_response = mock(Object)
|
99
|
-
mock_config.stub(:get_response) { mock_raw_response }
|
100
|
-
mock_raw_response.should_receive(:[]).with(plural_resource_label)
|
101
|
-
klass.send(meth)
|
67
|
+
subject { klass.method(meth) }
|
68
|
+
context "when there is a config instance" do
|
69
|
+
let(:mock_config) do
|
70
|
+
dss = (0..2).map { |x| :"attrs_#{x}" }
|
71
|
+
mock(Helix::Config, build_url: :built_url, get_aggregated_data_sets: dss)
|
102
72
|
end
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
klass.
|
111
|
-
|
112
|
-
|
113
|
-
|
73
|
+
before(:each) do Helix::Config.stub(:instance) { mock_config } end
|
74
|
+
context "and NOT given an opts Hash" do
|
75
|
+
let(:plural_resource_label) { :videos }
|
76
|
+
before(:each) do klass.stub(:plural_resource_label) { plural_resource_label } end
|
77
|
+
it "should get_aggregated_data_sets(the_url, plural_resource_label, {sig_type: :view}" do
|
78
|
+
opts = {sig_type: :view}
|
79
|
+
mock_config.should_receive(:get_aggregated_data_sets).with(:built_url, plural_resource_label, opts) { [:expected] }
|
80
|
+
klass.send(meth)
|
81
|
+
end
|
82
|
+
[ Helix::Video ].each do |child|
|
83
|
+
it "should should instantiate #{child.to_s} from each data_set" do
|
84
|
+
opts = {sig_type: :view}
|
85
|
+
children = child.send(meth)
|
86
|
+
children.each_with_index do |c,idx|
|
87
|
+
expect(c).to be_a(child)
|
88
|
+
expect(c.attributes).to be(:"attrs_#{idx}")
|
89
|
+
end
|
90
|
+
end
|
114
91
|
end
|
115
92
|
end
|
116
93
|
end
|
data/spec/config_spec.rb
CHANGED
@@ -23,10 +23,26 @@ describe Helix::Config do
|
|
23
23
|
subject { klass::DEFAULT_FILENAME }
|
24
24
|
it { should eq('./helix.yml') }
|
25
25
|
end
|
26
|
+
describe "ITEMS_PER_PAGE" do
|
27
|
+
subject { klass::ITEMS_PER_PAGE }
|
28
|
+
it { should eq(100) }
|
29
|
+
end
|
26
30
|
describe "SCOPES" do
|
27
31
|
subject { klass::SCOPES }
|
28
32
|
it { should eq([:reseller, :company, :library]) }
|
29
33
|
end
|
34
|
+
describe "SIG_DURATION" do
|
35
|
+
subject { klass::SIG_DURATION }
|
36
|
+
it { should eq(1200) } # in minutes
|
37
|
+
end
|
38
|
+
describe "STARTING_PAGE" do
|
39
|
+
subject { klass::STARTING_PAGE }
|
40
|
+
it { should eq(1) }
|
41
|
+
end
|
42
|
+
describe "TIME_OFFSET" do
|
43
|
+
subject { klass::TIME_OFFSET }
|
44
|
+
it { should eq(1000 * 60) } # 1000 minutes
|
45
|
+
end
|
30
46
|
describe "VALID_SIG_TYPES" do
|
31
47
|
subject { klass::VALID_SIG_TYPES }
|
32
48
|
it { should eq([:ingest, :update, :view]) }
|
@@ -302,6 +318,34 @@ describe Helix::Config do
|
|
302
318
|
end
|
303
319
|
end
|
304
320
|
|
321
|
+
describe "#get_aggregated_data_sets" do
|
322
|
+
let(:meth) { :get_aggregated_data_sets }
|
323
|
+
subject { obj.method(meth) }
|
324
|
+
its(:arity) { should eq(-3) }
|
325
|
+
context "when called" do
|
326
|
+
let(:opts) { {opts_key1: :opts_val1} }
|
327
|
+
let(:label) { :videos }
|
328
|
+
before(:each) do
|
329
|
+
obj.stub(:signature) { :the_sig }
|
330
|
+
end
|
331
|
+
subject { obj.send(meth, :a_url, label, opts) }
|
332
|
+
it "should successively call RestClient.get with the opts arg merged with pagination info and return the parsed results" do
|
333
|
+
base_opts = {opts_key1: :opts_val1, per_page: 100, signature: :the_sig}
|
334
|
+
opts1 = {params: base_opts.merge(page: 1)}
|
335
|
+
opts2 = {params: base_opts.merge(page: 2)}
|
336
|
+
opts3 = {params: base_opts.merge(page: 3)}
|
337
|
+
non_final_response = mock(String, headers: {is_last_page: 'false'})
|
338
|
+
final_response = mock(String, headers: {is_last_page: 'true'})
|
339
|
+
RestClient.should_receive(:get).with(:a_url, opts1) { non_final_response }
|
340
|
+
RestClient.should_receive(:get).with(:a_url, opts2) { non_final_response }
|
341
|
+
RestClient.should_receive(:get).with(:a_url, opts3) { final_response }
|
342
|
+
obj.stub(:parse_response_by_url_format).with(non_final_response, :a_url) { {label => [:non_final]} }
|
343
|
+
obj.stub(:parse_response_by_url_format).with(final_response, :a_url) { {label => [:final]} }
|
344
|
+
expect(obj.send(meth, :a_url, label, opts)).to eq([:non_final, :non_final, :final])
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
305
349
|
describe "#get_response" do
|
306
350
|
let(:meth) { :get_response }
|
307
351
|
subject { obj.method(meth) }
|
@@ -363,6 +407,43 @@ describe Helix::Config do
|
|
363
407
|
end
|
364
408
|
end
|
365
409
|
|
410
|
+
describe "#last_page?" do
|
411
|
+
let(:meth) { :last_page? }
|
412
|
+
subject { obj.method(meth) }
|
413
|
+
its(:arity) { should eq(0) }
|
414
|
+
context "when called" do
|
415
|
+
subject { obj.send(meth) }
|
416
|
+
context "when there is no @response" do
|
417
|
+
before(:each) { obj.instance_variable_set(:@response, nil) }
|
418
|
+
it { should be false }
|
419
|
+
end
|
420
|
+
context "when there is a @response" do
|
421
|
+
let(:mock_response) { mock(String) }
|
422
|
+
before(:each) { obj.instance_variable_set(:@response, mock_response) }
|
423
|
+
context "and there is no @response.headers" do
|
424
|
+
before(:each) { mock_response.stub(:headers) { nil } }
|
425
|
+
it { should be false }
|
426
|
+
end
|
427
|
+
context "and there is a @response.headers" do
|
428
|
+
context "and @response.headers does NOT have the key :is_last_page" do
|
429
|
+
before(:each) do mock_response.stub(:headers) { {} } end
|
430
|
+
it { should be false }
|
431
|
+
end
|
432
|
+
context "and @response.headers has the key :is_last_page" do
|
433
|
+
context "and @response.headers[:is_last_page] == 'truthy'" do
|
434
|
+
before(:each) do mock_response.stub(:headers) { {is_last_page: 'truthy'} } end
|
435
|
+
it { should be false }
|
436
|
+
end
|
437
|
+
context "and @response.headers[:is_last_page] == 'true'" do
|
438
|
+
before(:each) do mock_response.stub(:headers) { {is_last_page: 'true'} } end
|
439
|
+
it { should be true }
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
443
|
+
end
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
366
447
|
describe "#license_key" do
|
367
448
|
let(:meth) { :license_key }
|
368
449
|
subject { obj.method(meth) }
|
@@ -399,7 +480,7 @@ describe Helix::Config do
|
|
399
480
|
end
|
400
481
|
it "should return the proxy specified in the config" do
|
401
482
|
obj.credentials[:proxy_uri] = 'http://test.proxy'
|
402
|
-
expect(obj.send(meth)).to eq 'http://test.proxy'
|
483
|
+
expect(obj.send(meth)).to eq 'http://test.proxy'
|
403
484
|
end
|
404
485
|
it "should return just proxy uri if only pass exists" do
|
405
486
|
obj.credentials[:proxy_password] = 'fake_pass'
|
@@ -10,7 +10,8 @@ describe Helix::DurationedMedia do
|
|
10
10
|
klasses = [ Helix::Video, Helix::Track ]
|
11
11
|
klasses.each do |klass|
|
12
12
|
subject { klass }
|
13
|
-
|
13
|
+
mods = [ Helix::Base, Helix::DurationedMedia, Helix::Media ]
|
14
|
+
mods.each { |mod| its(:ancestors) { should include(mod) } }
|
14
15
|
|
15
16
|
describe "Constants"
|
16
17
|
|