myshows 0.1.1 → 0.2.0
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.tar.gz.sig +0 -0
- data/Manifest +2 -1
- data/README.rdoc +8 -0
- data/Rakefile +1 -1
- data/lib/myshows/profile.rb +20 -0
- data/lib/myshows/show.rb +34 -3
- data/lib/myshows/title_matcher.rb +67 -0
- data/myshows.gemspec +4 -4
- data/spec/myshows_spec.rb +50 -4
- data/spec/title_matcher_spec.rb +83 -0
- metadata +8 -5
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/Manifest
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
Manifest
|
2
2
|
README.rdoc
|
3
3
|
Rakefile
|
4
|
-
all-api.rb
|
5
4
|
lib/myshows.rb
|
6
5
|
lib/myshows/api.rb
|
7
6
|
lib/myshows/episode.rb
|
@@ -9,5 +8,7 @@ lib/myshows/item.rb
|
|
9
8
|
lib/myshows/profile.rb
|
10
9
|
lib/myshows/search.rb
|
11
10
|
lib/myshows/show.rb
|
11
|
+
lib/myshows/title_matcher.rb
|
12
12
|
myshows.gemspec
|
13
13
|
spec/myshows_spec.rb
|
14
|
+
spec/title_matcher_spec.rb
|
data/README.rdoc
CHANGED
@@ -11,6 +11,10 @@ And use
|
|
11
11
|
profile = MyShows::Profile.new 'demo', 'fe01ce2a7fbac8fafaed7c982a04e229'
|
12
12
|
profile.shows # => all user shows
|
13
13
|
|
14
|
+
# you can find show by title among user shows (smart search)
|
15
|
+
profile.show 'big bang theory' # => show "The Big Bang Theory"
|
16
|
+
profile.show 'TBBT' # => show "The Big Bang Theory"
|
17
|
+
|
14
18
|
search = MyShows::Search.new
|
15
19
|
tbbt = search.show("The Big Bang Theory").first
|
16
20
|
tbbt.title # => "The Big Bang Theory"
|
@@ -18,6 +22,10 @@ And use
|
|
18
22
|
# and many other fields provided by API
|
19
23
|
|
20
24
|
tbbt.episodes # => [...] - all episodes
|
25
|
+
|
26
|
+
# you can find episode by title (smart search)
|
27
|
+
pilot = tbbt.episode "the pilot episode"
|
28
|
+
# or by season and episode number
|
21
29
|
pilot = tbbt.episode 1, 1
|
22
30
|
pilot.title # => "Pilot"
|
23
31
|
pilot.show # => tbbt
|
data/Rakefile
CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
|
|
2
2
|
require 'rake'
|
3
3
|
require 'echoe'
|
4
4
|
|
5
|
-
Echoe.new('myshows', '0.
|
5
|
+
Echoe.new('myshows', '0.2.0') do |p|
|
6
6
|
p.summary = "MyShows API"
|
7
7
|
p.description = "Object-oriented wrapper over API of http://myshows.ru"
|
8
8
|
p.url = "http://github.com/cypok/myshows"
|
data/lib/myshows/profile.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'myshows/api'
|
2
|
+
require 'myshows/title_matcher'
|
2
3
|
|
3
4
|
module MyShows
|
4
5
|
# Profile initialization is needed to gain access
|
@@ -18,5 +19,24 @@ module MyShows
|
|
18
19
|
def shows
|
19
20
|
@api.user_shows
|
20
21
|
end
|
22
|
+
|
23
|
+
# Smart search of one of user shows by title
|
24
|
+
def show(title)
|
25
|
+
found = shows.values_at *matcher.match(title)
|
26
|
+
case found.count
|
27
|
+
when 0
|
28
|
+
raise MyShows::Error.new "show with title \"#{title}\" was not found"
|
29
|
+
when 1
|
30
|
+
found.first
|
31
|
+
else
|
32
|
+
raise MyShows::Error.new "ambiguous title \"#{title}\" corresponds to shows #{found.map {|s| %Q["#{s}"]} * ', '}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def matcher
|
39
|
+
@matcher ||= MyShows::TitleMatcher.new shows.map(&:title)
|
40
|
+
end
|
21
41
|
end
|
22
42
|
end
|
data/lib/myshows/show.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'myshows/item'
|
2
|
+
require 'myshows/title_matcher'
|
2
3
|
|
3
4
|
module MyShows
|
4
5
|
# Provides such methods:
|
@@ -36,9 +37,39 @@ module MyShows
|
|
36
37
|
@api.show_episodes self
|
37
38
|
end
|
38
39
|
|
39
|
-
# Returns episode by season and episode number
|
40
|
-
def episode(
|
41
|
-
|
40
|
+
# Returns episode by title (smart search) or by season and episode number
|
41
|
+
def episode(*args)
|
42
|
+
if args.first.is_a? String
|
43
|
+
episode_by_title *args
|
44
|
+
else
|
45
|
+
episode_by_numbers *args
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
protected
|
50
|
+
|
51
|
+
def episode_by_title(title)
|
52
|
+
found = episodes.values_at *matcher.match(title)
|
53
|
+
case found.count
|
54
|
+
when 0
|
55
|
+
raise MyShows::Error.new "episode with title \"#{title}\" was not found in show #{self}"
|
56
|
+
when 1
|
57
|
+
found.first
|
58
|
+
else
|
59
|
+
raise MyShows::Error.new "ambiguous title \"#{title}\" corresponds to episodes #{found.map {|s| %Q["#{s}"]} * ', '}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def matcher
|
64
|
+
@matcher ||= MyShows::TitleMatcher.new episodes.map(&:title)
|
65
|
+
end
|
66
|
+
|
67
|
+
def episode_by_numbers(season_number, episode_number)
|
68
|
+
episodes.detect {|e| e.season_number == season_number && e.episode_number == episode_number }.tap do |e|
|
69
|
+
if e.nil?
|
70
|
+
raise MyShows::Error.new "episode with number #{season_number}x#{episode_number} was not found in show #{self}"
|
71
|
+
end
|
72
|
+
end
|
42
73
|
end
|
43
74
|
end
|
44
75
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module MyShows
|
2
|
+
class TitleMatcher
|
3
|
+
# You could extend this list
|
4
|
+
MATCHING_PROCS = [
|
5
|
+
# simple
|
6
|
+
proc {|src, title| src == title },
|
7
|
+
|
8
|
+
# flash forward => FlashForward
|
9
|
+
# lietome => Lie to Me
|
10
|
+
proc {|src, title| src.gsub(' ', '') == title.gsub(' ', '') },
|
11
|
+
|
12
|
+
# tbbt => The Big Bang Theory
|
13
|
+
proc {|src, title| src == title.split.map{|w| w[0,1]} * '' },
|
14
|
+
|
15
|
+
# avatar => Avatar: The Last Airbender
|
16
|
+
proc {|src, title| title.split.include? src },
|
17
|
+
|
18
|
+
# house m d => House
|
19
|
+
proc {|src, title| src.split.include? title },
|
20
|
+
]
|
21
|
+
|
22
|
+
def initialize(titles)
|
23
|
+
@titles = titles.map {|s| strip(s)}
|
24
|
+
@titles_wo_articles = @titles.map {|t| wo_articles(t) }
|
25
|
+
end
|
26
|
+
|
27
|
+
# Tries to find title closest to src,
|
28
|
+
# returns list of indexes of titles
|
29
|
+
def match(src)
|
30
|
+
matched = []
|
31
|
+
|
32
|
+
src = strip(src)
|
33
|
+
|
34
|
+
|
35
|
+
MATCHING_PROCS.each do |matcher|
|
36
|
+
@titles.each_with_index do |title, i|
|
37
|
+
matched << i if matcher.call(src, title)
|
38
|
+
end
|
39
|
+
return matched unless matched.empty?
|
40
|
+
end
|
41
|
+
|
42
|
+
src_wo_articles = wo_articles(src)
|
43
|
+
MATCHING_PROCS.each do |matcher|
|
44
|
+
@titles_wo_articles.each_with_index do |title_wo_articles, i|
|
45
|
+
matched << i if matcher.call(src_wo_articles, title_wo_articles)
|
46
|
+
end
|
47
|
+
return matched unless matched.empty?
|
48
|
+
end
|
49
|
+
|
50
|
+
[]
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def strip(s)
|
56
|
+
s.clone.downcase.
|
57
|
+
gsub(/\(\d{4}\)/, ''). # to clean "V (2009)"
|
58
|
+
gsub(/\([A-Za-z]{2}\)/, ''). # to clean "Bless This House (US)"
|
59
|
+
gsub(/[^A-Za-z0-9]/, ' '). # to clean "Star Wars: the Clone Wars"
|
60
|
+
gsub(/ +/, ' ').strip # remove extra spaces
|
61
|
+
end
|
62
|
+
|
63
|
+
def wo_articles(str)
|
64
|
+
str.split.reject {|w| w =~ /^the|an?$/ } * ' '
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/myshows.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{myshows}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.2.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Vladimir Parfinenko"]
|
9
9
|
s.cert_chain = ["/Users/cypok/.gem/gem-public_cert.pem"]
|
10
|
-
s.date = %q{2011-01-
|
10
|
+
s.date = %q{2011-01-29}
|
11
11
|
s.description = %q{Object-oriented wrapper over API of http://myshows.ru}
|
12
12
|
s.email = %q{vladimir.parfinenko@gmail.com}
|
13
|
-
s.extra_rdoc_files = ["README.rdoc", "lib/myshows.rb", "lib/myshows/api.rb", "lib/myshows/episode.rb", "lib/myshows/item.rb", "lib/myshows/profile.rb", "lib/myshows/search.rb", "lib/myshows/show.rb"]
|
14
|
-
s.files = ["Manifest", "README.rdoc", "Rakefile", "lib/myshows.rb", "lib/myshows/api.rb", "lib/myshows/episode.rb", "lib/myshows/item.rb", "lib/myshows/profile.rb", "lib/myshows/search.rb", "lib/myshows/show.rb", "myshows.gemspec", "spec/myshows_spec.rb"]
|
13
|
+
s.extra_rdoc_files = ["README.rdoc", "lib/myshows.rb", "lib/myshows/api.rb", "lib/myshows/episode.rb", "lib/myshows/item.rb", "lib/myshows/profile.rb", "lib/myshows/search.rb", "lib/myshows/show.rb", "lib/myshows/title_matcher.rb"]
|
14
|
+
s.files = ["Manifest", "README.rdoc", "Rakefile", "lib/myshows.rb", "lib/myshows/api.rb", "lib/myshows/episode.rb", "lib/myshows/item.rb", "lib/myshows/profile.rb", "lib/myshows/search.rb", "lib/myshows/show.rb", "lib/myshows/title_matcher.rb", "myshows.gemspec", "spec/myshows_spec.rb", "spec/title_matcher_spec.rb"]
|
15
15
|
s.homepage = %q{http://github.com/cypok/myshows}
|
16
16
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Myshows", "--main", "README.rdoc"]
|
17
17
|
s.require_paths = ["lib"]
|
data/spec/myshows_spec.rb
CHANGED
@@ -11,6 +11,24 @@ describe MyShows do
|
|
11
11
|
it "should return user shows" do
|
12
12
|
@profile.shows.map(&:title).should include TBBT
|
13
13
|
end
|
14
|
+
|
15
|
+
describe "#show" do
|
16
|
+
it "should find user show by title" do
|
17
|
+
@profile.show('TBBT').title.should == TBBT
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should raise exception if show was not found" do
|
21
|
+
lambda do
|
22
|
+
@profile.show('WTF?')
|
23
|
+
end.should raise_error MyShows::Error
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should raise exception if title is ambiguous" do
|
27
|
+
lambda do
|
28
|
+
@profile.show('The')
|
29
|
+
end.should raise_error MyShows::Error
|
30
|
+
end
|
31
|
+
end
|
14
32
|
end
|
15
33
|
|
16
34
|
describe MyShows::Search do
|
@@ -42,10 +60,38 @@ describe MyShows do
|
|
42
60
|
@show.episodes.should have_at_least(10).items
|
43
61
|
end
|
44
62
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
63
|
+
describe "#episode" do
|
64
|
+
|
65
|
+
it "should find episode by season and episode number" do
|
66
|
+
e = @show.episode(1, 2)
|
67
|
+
e.season_number.should == 1
|
68
|
+
e.episode_number.should == 2
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should find episode by title" do
|
72
|
+
e = @show.episode("pilot")
|
73
|
+
e.title.should == "Pilot"
|
74
|
+
e.season_number.should == 1
|
75
|
+
e.episode_number.should == 1
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should raise exception if nothing was found" do
|
79
|
+
lambda do
|
80
|
+
@show.episode(99, 99)
|
81
|
+
end.should raise_error MyShows::Error
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should raise exception if nothing was found" do
|
85
|
+
lambda do
|
86
|
+
@show.episode "Non existent episode"
|
87
|
+
end.should raise_error MyShows::Error
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should raise exception if title is ambiguous" do
|
91
|
+
lambda do
|
92
|
+
@show.episode "The"
|
93
|
+
end.should raise_error MyShows::Error
|
94
|
+
end
|
49
95
|
end
|
50
96
|
end
|
51
97
|
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'myshows'
|
2
|
+
|
3
|
+
describe MyShows::TitleMatcher do
|
4
|
+
before :all do
|
5
|
+
@titles = <<-END
|
6
|
+
V (2009)
|
7
|
+
Star Wars: The Clone Wars (2008)
|
8
|
+
Over There (US)
|
9
|
+
South Park
|
10
|
+
Lost
|
11
|
+
How I Met Your Mother
|
12
|
+
The IT Crowd
|
13
|
+
Due South (1994)
|
14
|
+
The Big Bang Theory
|
15
|
+
Life on Mars (UK)
|
16
|
+
Lie to Me
|
17
|
+
Avatar: The Last Airbender
|
18
|
+
FlashForward
|
19
|
+
Desperate Housewifes
|
20
|
+
END
|
21
|
+
@titles = @titles.split "\n"
|
22
|
+
|
23
|
+
@matcher = MyShows::TitleMatcher.new @titles
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should find nothing" do
|
27
|
+
match("Unknown series").should be_empty
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should simply find" do
|
31
|
+
match("Lost").should == ["Lost"]
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should ingore year of series start" do
|
35
|
+
match("V").should == ["V (2009)"]
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should ingore country of series creation" do
|
39
|
+
match("Over There").should == ["Over There (US)"]
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should ignore all but letters" do
|
43
|
+
match("Star Wars The Clone Wars").should == ["Star Wars: The Clone Wars (2008)"]
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should find ambiguous titles" do
|
47
|
+
match("South").should == ["South Park", "Due South (1994)"]
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should find separeted title" do
|
51
|
+
match("Flash Forward").should == ["FlashForward"]
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should find joined title" do
|
55
|
+
match("lietome").should == ["Lie to Me"]
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should find some part of title in src" do
|
59
|
+
match("Avatar").should == ["Avatar: The Last Airbender"]
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should find abbreviated title" do
|
63
|
+
match("TBBT").should == ["The Big Bang Theory"]
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should find title with extra article" do
|
67
|
+
match("Life on a Mars").should == ["Life on Mars (UK)"]
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should find title without article" do
|
71
|
+
match("IT Crowd").should == ["The IT Crowd"]
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should find title with wrong article" do
|
75
|
+
match("An IT Crowd").should == ["The IT Crowd"]
|
76
|
+
end
|
77
|
+
|
78
|
+
protected
|
79
|
+
|
80
|
+
def match(src)
|
81
|
+
@titles.values_at *@matcher.match(src)
|
82
|
+
end
|
83
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: myshows
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Vladimir Parfinenko
|
@@ -36,7 +36,7 @@ cert_chain:
|
|
36
36
|
78F0qvtLjR0DAnN6uYs98PR+jHE+0ckLX3D9sw==
|
37
37
|
-----END CERTIFICATE-----
|
38
38
|
|
39
|
-
date: 2011-01-
|
39
|
+
date: 2011-01-29 00:00:00 +06:00
|
40
40
|
default_executable:
|
41
41
|
dependencies:
|
42
42
|
- !ruby/object:Gem::Dependency
|
@@ -110,6 +110,7 @@ extra_rdoc_files:
|
|
110
110
|
- lib/myshows/profile.rb
|
111
111
|
- lib/myshows/search.rb
|
112
112
|
- lib/myshows/show.rb
|
113
|
+
- lib/myshows/title_matcher.rb
|
113
114
|
files:
|
114
115
|
- Manifest
|
115
116
|
- README.rdoc
|
@@ -121,8 +122,10 @@ files:
|
|
121
122
|
- lib/myshows/profile.rb
|
122
123
|
- lib/myshows/search.rb
|
123
124
|
- lib/myshows/show.rb
|
125
|
+
- lib/myshows/title_matcher.rb
|
124
126
|
- myshows.gemspec
|
125
127
|
- spec/myshows_spec.rb
|
128
|
+
- spec/title_matcher_spec.rb
|
126
129
|
has_rdoc: true
|
127
130
|
homepage: http://github.com/cypok/myshows
|
128
131
|
licenses: []
|
metadata.gz.sig
CHANGED
Binary file
|