tivohmo 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/tivohmo/adapters/plex/application.rb +6 -1
- data/lib/tivohmo/adapters/plex/category.rb +1 -1
- data/lib/tivohmo/adapters/plex/episode.rb +6 -1
- data/lib/tivohmo/adapters/plex/movie.rb +2 -1
- data/lib/tivohmo/adapters/plex/qualified_category.rb +7 -2
- data/lib/tivohmo/adapters/plex/section.rb +13 -9
- data/lib/tivohmo/beacon.rb +6 -2
- data/lib/tivohmo/server.rb +18 -1
- data/lib/tivohmo/version.rb +1 -1
- data/spec/adapters/plex/category_spec.rb +18 -14
- data/spec/adapters/plex/episode_spec.rb +1 -1
- data/spec/adapters/plex/movie_spec.rb +1 -1
- data/spec/adapters/plex/qualified_category_spec.rb +15 -10
- data/spec/adapters/plex/section_spec.rb +11 -8
- data/spec/beacon_spec.rb +1 -1
- data/spec/server_spec.rb +27 -0
- data/spec/spec_helper.rb +2 -0
- data/tivohmo.gemspec +1 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d174442bc2cdc54f0c321af10235ca9b7b0cd5e6
|
4
|
+
data.tar.gz: 9879d1b6792705f0838f2f9a12c7fd00f4b1bc1e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 82fb8a7e0deb9d7d62be6b8809264dabaf1c23d776d53fa7ea90a0094a99ad354e97ef676663c863b6620ec5a13820b88a8449af865e036f0d7a0e430e4fcd8f
|
7
|
+
data.tar.gz: fdcae9f54909c5122e99fe76528f3690f58f67cbc0853c535b51100faa3a4ff5eb6caf2c3688a84c968ee581e44cc14899d206252351a3764689ff5b88b7c0f7
|
@@ -25,7 +25,12 @@ module TivoHMO
|
|
25
25
|
def children
|
26
26
|
synchronize do
|
27
27
|
if super.blank?
|
28
|
-
Array(server.library.sections)
|
28
|
+
sections = Array(server.library.sections)
|
29
|
+
# Sort by title descending so that creation times are
|
30
|
+
# correct for tivo sort of newest first (Time.now for
|
31
|
+
# created_at in Section)
|
32
|
+
sections = sections.sort_by(&:title).reverse
|
33
|
+
sections.each do |section|
|
29
34
|
add_child(Section.new(section))
|
30
35
|
end
|
31
36
|
end
|
@@ -16,7 +16,8 @@ module TivoHMO
|
|
16
16
|
|
17
17
|
self.title = delegate.title
|
18
18
|
self.modified_at = Time.at(delegate.updated_at.to_i)
|
19
|
-
self.created_at = Time.
|
19
|
+
self.created_at = Time.parse(delegate.originally_available_at) rescue nil
|
20
|
+
self.created_at ||= Time.at(delegate.added_at.to_i)
|
20
21
|
end
|
21
22
|
|
22
23
|
def metadata
|
@@ -41,6 +42,10 @@ module TivoHMO
|
|
41
42
|
# group tv shows under same name if we can extract a seriesId
|
42
43
|
guid = delegate.guid
|
43
44
|
if guid =~ /thetvdb:\/\/(\d+)/
|
45
|
+
# TODO: figure out how to get zap2it series IDs into plex
|
46
|
+
# If we had zap2it ids in plex metadata and extracted them
|
47
|
+
# here, tivo would show a relevant thumbnail image for the
|
48
|
+
# series in the My Shows UI.
|
44
49
|
md.series_id = "SH#{$1}"
|
45
50
|
end
|
46
51
|
|
@@ -16,7 +16,8 @@ module TivoHMO
|
|
16
16
|
|
17
17
|
self.title = delegate.title
|
18
18
|
self.modified_at = Time.at(delegate.updated_at.to_i)
|
19
|
-
self.created_at = Time.
|
19
|
+
self.created_at = Time.parse(delegate.originally_available_at) rescue nil
|
20
|
+
self.created_at ||= Time.at(delegate.added_at.to_i)
|
20
21
|
end
|
21
22
|
|
22
23
|
def metadata
|
@@ -20,7 +20,7 @@ module TivoHMO
|
|
20
20
|
self.category_qualifier = category_qualifier
|
21
21
|
self.title = category_type.to_s.titleize
|
22
22
|
self.modified_at = Time.at(delegate.updated_at.to_i)
|
23
|
-
self.created_at = Time.
|
23
|
+
self.created_at = Time.now
|
24
24
|
end
|
25
25
|
|
26
26
|
def children
|
@@ -35,7 +35,12 @@ module TivoHMO
|
|
35
35
|
end
|
36
36
|
|
37
37
|
if super.blank?
|
38
|
-
Array(delegate.send(category_qualifier))
|
38
|
+
qualified = Array(delegate.send(category_qualifier))
|
39
|
+
# Sort by title descending so that creation times are
|
40
|
+
# correct for tivo sort of newest first (Time.now for
|
41
|
+
# created_at in Category)
|
42
|
+
qualified = qualified.sort_by{|c| c[:title] }.reverse
|
43
|
+
qualified.each do |category_value|
|
39
44
|
add_child(Category.new(delegate, category_type, category_value))
|
40
45
|
end
|
41
46
|
end
|
@@ -17,24 +17,28 @@ module TivoHMO
|
|
17
17
|
|
18
18
|
self.title = delegate.title
|
19
19
|
self.modified_at = Time.at(delegate.updated_at.to_i)
|
20
|
-
self.created_at = Time.
|
20
|
+
self.created_at = Time.now
|
21
21
|
end
|
22
22
|
|
23
23
|
def children
|
24
24
|
synchronize do
|
25
25
|
if super.blank?
|
26
|
-
|
26
|
+
# Tivo time sorting is reverse chronological (newest first), so
|
27
|
+
# order it here in reverse order so the creation time cause the
|
28
|
+
# right sorting ("all" is newest and comes first)
|
29
|
+
add_child(QualifiedCategory.new(delegate, :by_collection, :collections))
|
30
|
+
add_child(QualifiedCategory.new(delegate, :by_content_rating, :content_ratings))
|
31
|
+
add_child(QualifiedCategory.new(delegate, :by_folder, :folders))
|
32
|
+
add_child(QualifiedCategory.new(delegate, :by_genre, :genres))
|
33
|
+
add_child(QualifiedCategory.new(delegate, :by_year, :years))
|
34
|
+
add_child(QualifiedCategory.new(delegate, :by_first_character, :first_characters))
|
35
|
+
|
27
36
|
#add_child(Category.new(delegate, :unwatched))
|
28
|
-
add_child(Category.new(delegate, :newest))
|
29
37
|
add_child(Category.new(delegate, :on_deck))
|
38
|
+
add_child(Category.new(delegate, :newest))
|
30
39
|
add_child(Category.new(delegate, :recently_viewed))
|
40
|
+
add_child(Category.new(delegate, :recently_added))
|
31
41
|
add_child(Category.new(delegate, :all))
|
32
|
-
add_child(QualifiedCategory.new(delegate, :by_genre, :genres))
|
33
|
-
add_child(QualifiedCategory.new(delegate, :by_year, :years))
|
34
|
-
add_child(QualifiedCategory.new(delegate, :by_first_character, :first_characters))
|
35
|
-
add_child(QualifiedCategory.new(delegate, :by_collection, :collections))
|
36
|
-
add_child(QualifiedCategory.new(delegate, :by_folder, :folders))
|
37
|
-
add_child(QualifiedCategory.new(delegate, :by_content_rating, :content_ratings))
|
38
42
|
end
|
39
43
|
end
|
40
44
|
|
data/lib/tivohmo/beacon.rb
CHANGED
@@ -7,7 +7,7 @@ module TivoHMO
|
|
7
7
|
class Beacon
|
8
8
|
include GemLogger::LoggerSupport
|
9
9
|
|
10
|
-
def initialize(service_port, limit: -1, interval:
|
10
|
+
def initialize(service_port, limit: -1, interval: 10)
|
11
11
|
@interval = interval
|
12
12
|
@limit = limit
|
13
13
|
@uid = SecureRandom.uuid
|
@@ -23,7 +23,11 @@ module TivoHMO
|
|
23
23
|
@running = true
|
24
24
|
@broadcast_thread = Thread.new do
|
25
25
|
while @running
|
26
|
-
|
26
|
+
begin
|
27
|
+
broadcast
|
28
|
+
rescue => e
|
29
|
+
logger.log_exception(e, "Ignoring exception in beacon thread")
|
30
|
+
end
|
27
31
|
sleep(@interval)
|
28
32
|
@limit = @limit - 1
|
29
33
|
break if @limit == 0
|
data/lib/tivohmo/server.rb
CHANGED
@@ -61,6 +61,19 @@ module TivoHMO
|
|
61
61
|
headers['TiVo_TCD_ID']
|
62
62
|
end
|
63
63
|
|
64
|
+
def select_all_items(children)
|
65
|
+
just_items = []
|
66
|
+
all = children.dup
|
67
|
+
all.each do |child|
|
68
|
+
if child.is_a?(TivoHMO::API::Container)
|
69
|
+
all.concat(child.children)
|
70
|
+
else
|
71
|
+
just_items << child
|
72
|
+
end
|
73
|
+
end
|
74
|
+
children = just_items.uniq {|node| node.identifier }
|
75
|
+
end
|
76
|
+
|
64
77
|
def sort(items, sort_order)
|
65
78
|
sort_order = sort_order.split(/\s*,\s*/)
|
66
79
|
|
@@ -181,7 +194,8 @@ module TivoHMO
|
|
181
194
|
item_count = (params['ItemCount'] || 8).to_i
|
182
195
|
|
183
196
|
# Yes or No, default no
|
184
|
-
|
197
|
+
# TODO: fix this when tivo side is fixed or config mechanism added to globally disable recurse
|
198
|
+
recurse = false #(params['Recurse'] == 'Yes')
|
185
199
|
|
186
200
|
# csv of Type, Title, CreationDate, LastChangeDate, Random
|
187
201
|
# reverse with preceding !
|
@@ -216,6 +230,9 @@ module TivoHMO
|
|
216
230
|
halt 404, "No container found for #{container_path}" unless container
|
217
231
|
|
218
232
|
children = container.children
|
233
|
+
|
234
|
+
children = select_all_items(children) if recurse
|
235
|
+
|
219
236
|
children = sort(children, sort_order) if sort_order
|
220
237
|
|
221
238
|
if anchor_item
|
data/lib/tivohmo/version.rb
CHANGED
@@ -8,15 +8,19 @@ describe TivoHMO::Adapters::Plex::Category do
|
|
8
8
|
describe "#initialize" do
|
9
9
|
|
10
10
|
it "should instantiate" do
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
11
|
+
now = Time.now
|
12
|
+
Timecop.freeze(now) do
|
13
|
+
category = described_class.new(plex_delegate, :newest)
|
14
|
+
expect(category).to be_a described_class
|
15
|
+
expect(category).to be_a TivoHMO::API::Container
|
16
|
+
expect(category.category_type).to eq(:newest)
|
17
|
+
expect(category.category_value).to be_nil
|
18
|
+
expect(category.title).to eq('Newest')
|
19
|
+
expect(category.identifier).to eq(plex_delegate.key)
|
20
|
+
expect(category.modified_at).to eq(Time.at(plex_delegate.updated_at))
|
21
|
+
expect(category.created_at).to eq(now)
|
22
|
+
end
|
23
|
+
|
20
24
|
end
|
21
25
|
|
22
26
|
it "should use_category_value for title if present" do
|
@@ -32,7 +36,7 @@ describe TivoHMO::Adapters::Plex::Category do
|
|
32
36
|
describe "#children" do
|
33
37
|
|
34
38
|
it "should memoize" do
|
35
|
-
listing = [plex_stub(::Plex::Movie)]
|
39
|
+
listing = [plex_stub(::Plex::Movie, originally_available_at: "2013-01-02")]
|
36
40
|
allow(plex_delegate).to receive(:newest).and_return(listing)
|
37
41
|
section = described_class.new(plex_delegate, :newest)
|
38
42
|
expect(section.children.object_id).to eq(section.children.object_id)
|
@@ -40,8 +44,8 @@ describe TivoHMO::Adapters::Plex::Category do
|
|
40
44
|
|
41
45
|
it "should have children" do
|
42
46
|
listing = [
|
43
|
-
plex_stub(::Plex::Movie),
|
44
|
-
plex_stub(::Plex::Episode),
|
47
|
+
plex_stub(::Plex::Movie, originally_available_at: "2013-01-02"),
|
48
|
+
plex_stub(::Plex::Episode, originally_available_at: "2013-01-02"),
|
45
49
|
plex_stub(::Plex::Show)
|
46
50
|
]
|
47
51
|
allow(plex_delegate).to receive(:newest).and_return(listing)
|
@@ -51,8 +55,8 @@ describe TivoHMO::Adapters::Plex::Category do
|
|
51
55
|
|
52
56
|
it "should use category_value for children" do
|
53
57
|
listing = [
|
54
|
-
plex_stub(::Plex::Movie),
|
55
|
-
plex_stub(::Plex::Episode),
|
58
|
+
plex_stub(::Plex::Movie, originally_available_at: "2013-01-02"),
|
59
|
+
plex_stub(::Plex::Episode, originally_available_at: "2013-01-02"),
|
56
60
|
plex_stub(::Plex::Show)
|
57
61
|
]
|
58
62
|
cval = {title: 'Title', key: 'key'}
|
@@ -20,7 +20,7 @@ describe TivoHMO::Adapters::Plex::Episode do
|
|
20
20
|
expect(episode.title).to eq(plex_delegate.title)
|
21
21
|
expect(episode.identifier).to eq(plex_delegate.key)
|
22
22
|
expect(episode.modified_at).to eq(Time.at(plex_delegate.updated_at))
|
23
|
-
expect(episode.created_at).to eq(Time.
|
23
|
+
expect(episode.created_at).to eq(Time.parse(plex_delegate.originally_available_at))
|
24
24
|
end
|
25
25
|
|
26
26
|
end
|
@@ -16,7 +16,7 @@ describe TivoHMO::Adapters::Plex::Movie do
|
|
16
16
|
expect(movie.title).to eq(plex_delegate.title)
|
17
17
|
expect(movie.identifier).to eq(plex_delegate.key)
|
18
18
|
expect(movie.modified_at).to eq(Time.at(plex_delegate.updated_at))
|
19
|
-
expect(movie.created_at).to eq(Time.
|
19
|
+
expect(movie.created_at).to eq(Time.parse(plex_delegate.originally_available_at))
|
20
20
|
end
|
21
21
|
|
22
22
|
end
|
@@ -9,15 +9,18 @@ describe TivoHMO::Adapters::Plex::QualifiedCategory do
|
|
9
9
|
describe "#initialize" do
|
10
10
|
|
11
11
|
it "should instantiate" do
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
12
|
+
now = Time.now
|
13
|
+
Timecop.freeze(now) do
|
14
|
+
qcat = described_class.new(plex_delegate, :by_year, '2000')
|
15
|
+
expect(qcat).to be_a described_class
|
16
|
+
expect(qcat).to be_a TivoHMO::API::Container
|
17
|
+
expect(qcat.title).to eq("By Year")
|
18
|
+
expect(qcat.category_qualifier).to eq('2000')
|
19
|
+
expect(qcat.title).to eq("By Year")
|
20
|
+
expect(qcat.identifier).to eq(plex_delegate.key)
|
21
|
+
expect(qcat.modified_at).to eq(Time.at(plex_delegate.updated_at))
|
22
|
+
expect(qcat.created_at).to eq(now)
|
23
|
+
end
|
21
24
|
end
|
22
25
|
|
23
26
|
end
|
@@ -43,7 +46,9 @@ describe TivoHMO::Adapters::Plex::QualifiedCategory do
|
|
43
46
|
expect(section.children.size).to eq(2)
|
44
47
|
expect(section.children[0]).to be_instance_of(TivoHMO::Adapters::Plex::Category)
|
45
48
|
expect(section.children[0].category_type).to be(:by_year)
|
46
|
-
|
49
|
+
# reverse order due to sorting by title reversed to work with tivo newest first sorting
|
50
|
+
expect(section.children[0].category_value).to eq(listing[1])
|
51
|
+
expect(section.children[1].category_value).to eq(listing[0])
|
47
52
|
end
|
48
53
|
|
49
54
|
end
|
@@ -8,13 +8,16 @@ describe TivoHMO::Adapters::Plex::Section do
|
|
8
8
|
describe "#initialize" do
|
9
9
|
|
10
10
|
it "should instantiate" do
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
now = Time.now
|
12
|
+
Timecop.freeze(now) do
|
13
|
+
section = described_class.new(plex_delegate)
|
14
|
+
expect(section).to be_a described_class
|
15
|
+
expect(section).to be_a TivoHMO::API::Container
|
16
|
+
expect(section.title).to eq(plex_delegate.title)
|
17
|
+
expect(section.identifier).to eq(plex_delegate.key)
|
18
|
+
expect(section.modified_at).to eq(Time.at(plex_delegate.updated_at))
|
19
|
+
expect(section.created_at).to eq(now)
|
20
|
+
end
|
18
21
|
end
|
19
22
|
|
20
23
|
end
|
@@ -30,7 +33,7 @@ describe TivoHMO::Adapters::Plex::Section do
|
|
30
33
|
section = described_class.new(plex_delegate)
|
31
34
|
expect(section.children.size).to eq(11)
|
32
35
|
classes = [TivoHMO::Adapters::Plex::Category, TivoHMO::Adapters::Plex::QualifiedCategory]
|
33
|
-
expect(section.children.collect(&:class).uniq).to eq(classes)
|
36
|
+
expect(section.children.collect(&:class).uniq.sort_by(&:name)).to eq(classes.sort_by(&:name))
|
34
37
|
end
|
35
38
|
|
36
39
|
end
|
data/spec/beacon_spec.rb
CHANGED
@@ -9,7 +9,7 @@ describe TivoHMO::Beacon do
|
|
9
9
|
beacon = described_class.new(1234)
|
10
10
|
expect(beacon).to be_a described_class
|
11
11
|
expect(beacon.instance_variable_get(:@limit)).to eq(-1)
|
12
|
-
expect(beacon.instance_variable_get(:@interval)).to eq(
|
12
|
+
expect(beacon.instance_variable_get(:@interval)).to eq(10)
|
13
13
|
expect(beacon.instance_variable_get(:@services)).to eq(['TiVoMediaServer:1234/http'])
|
14
14
|
end
|
15
15
|
|
data/spec/server_spec.rb
CHANGED
@@ -288,6 +288,33 @@ describe TivoHMO::Server do
|
|
288
288
|
|
289
289
|
end
|
290
290
|
|
291
|
+
describe "recursing" do
|
292
|
+
|
293
|
+
before(:each) do
|
294
|
+
other_container = container.add_child(TestAPI::Container.new("c2"))
|
295
|
+
other_container.add_child(TestAPI::Item.new("i2")) # dupe child
|
296
|
+
other_container.add_child(TestAPI::Item.new("i98")) # unique child
|
297
|
+
|
298
|
+
third_container = other_container.add_child(TestAPI::Container.new("c3"))
|
299
|
+
other_container.add_child(TestAPI::Item.new("i99")) # unique child
|
300
|
+
other_container.add_child(TestAPI::Item.new("i3")) # dupe child
|
301
|
+
|
302
|
+
3.times do |i|
|
303
|
+
container.add_child(TestAPI::Item.new("i#{i + 2}"))
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
it "recurses all items uniquely" do
|
308
|
+
skip "recurse disabled because tivo forces it on initially (no memory)"
|
309
|
+
get "/TiVoConnect?Command=QueryContainer&Container=/a1/c1&Recurse=Yes"
|
310
|
+
expect(last_response.status).to eq(200)
|
311
|
+
doc = Nokogiri::XML(last_response.body)
|
312
|
+
child_titles = doc.xpath("/TiVoContainer/Item/Details/Title").collect(&:content)
|
313
|
+
expect(child_titles).to eq(["i1", "i2", "i3", "i4", "i98", "i99"])
|
314
|
+
end
|
315
|
+
|
316
|
+
end
|
317
|
+
|
291
318
|
describe "sorting" do
|
292
319
|
|
293
320
|
before(:each) do
|
data/spec/spec_helper.rb
CHANGED
data/tivohmo.gemspec
CHANGED
@@ -26,6 +26,7 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_development_dependency "rspec"
|
27
27
|
spec.add_development_dependency "rack-test"
|
28
28
|
spec.add_development_dependency "nokogiri"
|
29
|
+
spec.add_development_dependency "timecop"
|
29
30
|
|
30
31
|
# core dependencies
|
31
32
|
spec.add_dependency "activesupport"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tivohmo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Conway
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -122,6 +122,20 @@ dependencies:
|
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: timecop
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
140
|
name: activesupport
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|