helix 0.0.2.7.pre → 0.0.2.8.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|