myshows 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|