isrc 1.0.2 → 1.0.3
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.
- checksums.yaml +5 -13
- data/lib/isrc.rb +124 -71
- data/lib/isrc/version.rb +1 -1
- data/spec/isrc_spec.rb +26 -8
- metadata +17 -17
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
ZmRiYTg5YWQzYTg4OWIzNzU5NDI3YTU5YmQ3OTA5MWVmZWZlMDRkNg==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bd97834b5c09da196ffc4e68c34b6be56cc63ed7
|
4
|
+
data.tar.gz: 0159b3fe894a23048a316f50818e3dc83b6fdc97
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
OGRlMWU3ZTE5MjM3OWNhNWY0ODJlNDYwNWMyOTU4MTNmNmViMjRkZTRhYTQ2
|
11
|
-
OTIwMTc2YWRiMDJhZjE1NzI0MDU2MTk1OWJmYzhiODNmODMzNTc=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
YTZiMmFmMDkxNTQ5OWVlNGE0NGJlNmE5ZjUzMzlkNzJlMzRiNTJlYTk4MjM1
|
14
|
-
MWNhYzIxYTc5NTFjZGZlNmJhYzg3NWJkNjE5Y2E2NTkwMDUxMmFlNGYzYmYx
|
15
|
-
NDc3OGI1N2NjYmUxYTI0MTdjZDA0NDhlOTBlZTAzYmUwMzBjMzU=
|
6
|
+
metadata.gz: da759b2fdeb7f8e97e593002ca9ab2c3aa2f9cfff4f12b68614e1c6a4384c499dc7df87458a8862856dbef0ba8791ef55a0a6b92825fd2a095700e5cbd1184cd
|
7
|
+
data.tar.gz: a1c1f55955dbcacca8d21f4c0adadfe179395a478370f3522dfa1e284dba66712b0104d62f0fa31a006e723be055d841a93a53dad5111760d3bc2c1cd583f49a
|
data/lib/isrc.rb
CHANGED
@@ -9,86 +9,57 @@ module ISRC
|
|
9
9
|
PPLUK_SESSION_GRAB_URL = 'http://repsearch.ppluk.com/ARSWeb/appmanager/ARS/main'
|
10
10
|
PPLUK_AJAX_SEARCH_URL = 'http://repsearch.ppluk.com/ARSWeb/block/send-receive-updates'
|
11
11
|
|
12
|
+
def self.configure(&block)
|
13
|
+
ISRC::Configuration.instance_eval(&block)
|
14
|
+
end
|
15
|
+
|
12
16
|
class PPLUK
|
13
17
|
def retrieve(opts)
|
14
|
-
#
|
15
|
-
|
18
|
+
# NOTE the online search is a bit funky: adding more to the search make the results worse
|
19
|
+
# trying out a three word limit
|
16
20
|
|
17
|
-
|
18
|
-
agent.log = Logger.new "mech.log"
|
19
|
-
agent.user_agent_alias = 'Mac Safari'
|
21
|
+
pieces = self.extract_song_peices(opts[:title])
|
20
22
|
|
21
|
-
|
22
|
-
view_state = self.extract_view_state(isrc_session_init.body)
|
23
|
-
ice_session, ice_session_count = self.extract_ice_session(isrc_session_init.body)
|
23
|
+
# try the first two pieces at first
|
24
24
|
|
25
|
-
#
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
# if the song is only one word, submit request with on processing
|
26
|
+
if pieces[:all].size == 1
|
27
|
+
@matches = self.request(opts)
|
28
|
+
elsif pieces[:all].size > 1
|
29
|
+
# let's try increasing the number of pieces, starting from 2
|
30
|
+
pieces_count = 1
|
30
31
|
|
31
|
-
|
32
|
-
|
32
|
+
begin
|
33
|
+
pieces_count += 1
|
33
34
|
|
34
|
-
|
35
|
-
shortened_title = title_pieces.slice(0, [opts[:title_size], title_pieces.size].min).join(' ')
|
36
|
-
|
37
|
-
# puts "Title: #{shortened_title}\nArtist: #{opts[:artist]}"
|
38
|
-
|
39
|
-
begin
|
40
|
-
isrc_search = agent.post PPLUK_AJAX_SEARCH_URL, {
|
41
|
-
'ice.submit.partial' => 'false',
|
42
|
-
# 'ice.event.target' => 'T400335881332330323192:ars_form:search_button',
|
43
|
-
# 'ice.event.captured' => 'T400335881332330323192:ars_form:search_button',
|
44
|
-
# 'ice.event.type' => 'onclick',
|
45
|
-
# 'ice.event.alt' => 'false',
|
46
|
-
# 'ice.event.ctrl' => 'false',
|
47
|
-
# 'ice.event.shift' => 'false',
|
48
|
-
# 'ice.event.meta' => 'false',
|
49
|
-
# 'ice.event.x' => '47',
|
50
|
-
# 'ice.event.y' => '65',
|
51
|
-
# 'ice.event.left' => 'false',
|
52
|
-
# 'ice.event.right' => 'false',
|
53
|
-
'T5000782701386267377497:ars_form:search_button' => 'Search',
|
54
|
-
'T5000782701386267377497:ars_form:isrc_code' => '',
|
55
|
-
'T5000782701386267377497:ars_form:rec_title_idx' => '',
|
56
|
-
'T5000782701386267377497:ars_form:rec_title' => shortened_title,
|
57
|
-
'T5000782701386267377497:ars_form:rec_band_artist_idx' => '',
|
58
|
-
'T5000782701386267377497:ars_form:rec_band_artist' => opts[:artist],
|
59
|
-
'javax.faces.RenderKitId' => 'ICEfacesRenderKit',
|
60
|
-
'javax.faces.ViewState' => view_state,
|
61
|
-
'icefacesCssUpdates' => '',
|
62
|
-
'T5000782701386267377497:ars_form' => '',
|
63
|
-
'ice.session' => ice_session,
|
64
|
-
'ice.view' => view_state,
|
65
|
-
'ice.focus' => '',
|
66
|
-
|
67
|
-
# the rand is 19 characters long in the browser's HTTP requests
|
68
|
-
'rand' => sprintf('%1.17f', rand)
|
69
|
-
}
|
70
|
-
rescue Mechanize::ResponseCodeError => e
|
71
|
-
agent.log.error "Error submitting AJAX request: #{e.page.body}"
|
72
|
-
end
|
35
|
+
shortened_title = pieces[:all].slice(0, pieces_count).join(' ')
|
73
36
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
37
|
+
@matches = self.request({
|
38
|
+
title: shortened_title,
|
39
|
+
artist: opts[:artist]
|
40
|
+
})
|
41
|
+
end while @matches.empty? && pieces[:all].size > pieces_count + 1
|
79
42
|
|
80
|
-
#
|
81
|
-
|
43
|
+
# given 'Surrender [Original Mix]' the above algorithm will submit the entire title
|
44
|
+
# if that didn't work, strip out all meta elements and try greatest to least number of song pieces
|
82
45
|
|
83
|
-
#
|
84
|
-
|
46
|
+
# TODO we shouldn't allow one letter or two letter title requests
|
47
|
+
# TODO remove stop words
|
48
|
+
# TODO detect when meta == title pieces
|
85
49
|
|
86
|
-
|
87
|
-
|
50
|
+
pieces_count = pieces[:title].size
|
51
|
+
|
52
|
+
while @matches.empty? && pieces_count > 0
|
53
|
+
shortened_title = pieces[:title].slice(0, pieces_count).join(' ')
|
54
|
+
|
55
|
+
@matches = self.request({
|
56
|
+
title: shortened_title,
|
57
|
+
artist: opts[:artist]
|
58
|
+
})
|
59
|
+
|
60
|
+
pieces_count -= 1
|
61
|
+
end
|
88
62
|
|
89
|
-
# if the shortened title did not work, try making it longer
|
90
|
-
if @matches.empty? && opts[:title_size] < title_pieces.size
|
91
|
-
self.retrieve(opts.merge({:title_size => opts[:title_size] + 1}))
|
92
63
|
end
|
93
64
|
end
|
94
65
|
|
@@ -132,9 +103,20 @@ module ISRC
|
|
132
103
|
|
133
104
|
protected
|
134
105
|
def extract_song_peices(title)
|
135
|
-
|
136
|
-
|
137
|
-
|
106
|
+
# this splits a song title into peices:
|
107
|
+
# * 'bracket' peice (meta)
|
108
|
+
# * 'parenthesis' peice (meta)
|
109
|
+
# * song words (title)
|
110
|
+
|
111
|
+
all_pieces = title.split(/(\([^)]+\)|\[[^\]]+\])/).reject { |s| s.strip.empty? }
|
112
|
+
title_pieces = all_pieces.shift.split(' ')
|
113
|
+
meta_pieces = all_pieces
|
114
|
+
|
115
|
+
{
|
116
|
+
all: [title_pieces, meta_pieces].flatten,
|
117
|
+
meta: meta_pieces,
|
118
|
+
title: title_pieces
|
119
|
+
}
|
138
120
|
end
|
139
121
|
|
140
122
|
def extract_view_state(body)
|
@@ -151,5 +133,76 @@ module ISRC
|
|
151
133
|
minutes.to_i * 60 + seconds.to_i
|
152
134
|
end
|
153
135
|
|
136
|
+
def request(opts = {})
|
137
|
+
puts "Title: #{opts[:title]}\nArtist: #{opts[:artist]}"
|
138
|
+
|
139
|
+
agent = Mechanize.new
|
140
|
+
# TODO log path needs to be configurable
|
141
|
+
agent.log = Logger.new "mech.log"
|
142
|
+
agent.user_agent_alias = 'Mac Safari'
|
143
|
+
|
144
|
+
# grab the main page HTML to pull session vars to make the AJAX request
|
145
|
+
isrc_session_init = agent.get(PPLUK_SESSION_GRAB_URL)
|
146
|
+
view_state = self.extract_view_state(isrc_session_init.body)
|
147
|
+
ice_session, ice_session_count = self.extract_ice_session(isrc_session_init.body)
|
148
|
+
|
149
|
+
# add the ice_sessions cookie for the AJAX search request
|
150
|
+
ice_cookie = Mechanize::Cookie.new('ice.sessions', "#{ice_session}##{ice_session_count}")
|
151
|
+
ice_cookie.path = "/"
|
152
|
+
ice_cookie.domain = "repsearch.ppluk.com"
|
153
|
+
agent.cookie_jar.add!(ice_cookie)
|
154
|
+
|
155
|
+
begin
|
156
|
+
isrc_search = agent.post PPLUK_AJAX_SEARCH_URL, {
|
157
|
+
'ice.submit.partial' => 'false',
|
158
|
+
# 'ice.event.target' => 'T400335881332330323192:ars_form:search_button',
|
159
|
+
# 'ice.event.captured' => 'T400335881332330323192:ars_form:search_button',
|
160
|
+
# 'ice.event.type' => 'onclick',
|
161
|
+
# 'ice.event.alt' => 'false',
|
162
|
+
# 'ice.event.ctrl' => 'false',
|
163
|
+
# 'ice.event.shift' => 'false',
|
164
|
+
# 'ice.event.meta' => 'false',
|
165
|
+
# 'ice.event.x' => '47',
|
166
|
+
# 'ice.event.y' => '65',
|
167
|
+
# 'ice.event.left' => 'false',
|
168
|
+
# 'ice.event.right' => 'false',
|
169
|
+
'T5000782701386267377497:ars_form:search_button' => 'Search',
|
170
|
+
'T5000782701386267377497:ars_form:isrc_code' => '',
|
171
|
+
'T5000782701386267377497:ars_form:rec_title_idx' => '',
|
172
|
+
'T5000782701386267377497:ars_form:rec_title' => opts[:title],
|
173
|
+
'T5000782701386267377497:ars_form:rec_band_artist_idx' => '',
|
174
|
+
'T5000782701386267377497:ars_form:rec_band_artist' => opts[:artist],
|
175
|
+
'javax.faces.RenderKitId' => 'ICEfacesRenderKit',
|
176
|
+
'javax.faces.ViewState' => view_state,
|
177
|
+
'icefacesCssUpdates' => '',
|
178
|
+
'T5000782701386267377497:ars_form' => '',
|
179
|
+
'ice.session' => ice_session,
|
180
|
+
'ice.view' => view_state,
|
181
|
+
'ice.focus' => '',
|
182
|
+
|
183
|
+
# the rand is 19 characters long in the browser's HTTP requests
|
184
|
+
'rand' => sprintf('%1.17f', rand)
|
185
|
+
}
|
186
|
+
rescue Mechanize::ResponseCodeError => e
|
187
|
+
agent.log.error "Error submitting AJAX request: #{e.page.body}"
|
188
|
+
end
|
189
|
+
|
190
|
+
# creates an array representation of the table:
|
191
|
+
# artist, title, isrc, rights holder, released, time
|
192
|
+
|
193
|
+
isrc_table = Nokogiri::HTML(isrc_search.body).css("table[id='T5000782701386267377497:ars_form:searchResultsTable'] tbody tr")
|
194
|
+
isrc_table.map do |m|
|
195
|
+
columns = m.css('td')
|
196
|
+
|
197
|
+
# if there is no ISRC don't bother looking
|
198
|
+
next if columns[2] == 'Not Supplied'
|
199
|
+
|
200
|
+
# zero length music wont be used
|
201
|
+
next if columns[-1] == '0:00sec'
|
202
|
+
|
203
|
+
columns.map &:text
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
154
207
|
end
|
155
208
|
end
|
data/lib/isrc/version.rb
CHANGED
data/spec/isrc_spec.rb
CHANGED
@@ -29,6 +29,16 @@ describe ISRC do
|
|
29
29
|
# however, the length delta is huge
|
30
30
|
end
|
31
31
|
|
32
|
+
it "handles results with brackets" do
|
33
|
+
isrc.retrieve artist: 'Curiosity Killed The Cat', title: 'Down to Earth'
|
34
|
+
isrc.match(time:'03:54')[:isrc].should == 'GBF088600037'
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'handles a mixed version of a song when there is not a mixed version listed' do
|
38
|
+
isrc.retrieve artist:'Kings of Leon', title: 'Use Somebody (Chew Fu Festival Fix)'
|
39
|
+
isrc.match(time:'5:37')[:isrc].should == 'USRC10800301'
|
40
|
+
end
|
41
|
+
|
32
42
|
it "handles edge cases that don't make sense" do
|
33
43
|
isrc.retrieve artist:'Toni Braxton', title:'Youre Making me High'
|
34
44
|
isrc.match(time:'4:12')[:isrc].should == 'USLF29600183'
|
@@ -49,17 +59,22 @@ describe ISRC do
|
|
49
59
|
end
|
50
60
|
|
51
61
|
context "song title processing" do
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
62
|
+
context 'of brackets' do
|
63
|
+
it "should parse them correctly with a one word song" do
|
64
|
+
pieces = isrc.send(:extract_song_peices, "Surrender [Original Mix]")
|
65
|
+
pieces[:all].size.should == 2
|
66
|
+
pieces[:all].last.should == "[Original Mix]"
|
67
|
+
pieces[:meta].size.should == 1
|
68
|
+
end
|
56
69
|
end
|
57
70
|
|
58
71
|
context 'of parenthesis' do
|
59
72
|
it "should count parenthesis as a single song peice" do
|
60
73
|
pieces = isrc.send(:extract_song_peices, "Want Me (Like Water) (New Vocal Mix No 1)")
|
61
|
-
pieces.size.should == 4
|
62
|
-
pieces.last.should == '(New Vocal Mix No 1)'
|
74
|
+
pieces[:all].size.should == 4
|
75
|
+
pieces[:all].last.should == '(New Vocal Mix No 1)'
|
76
|
+
pieces[:meta].size.should == 2
|
77
|
+
pieces[:title].size.should == 2
|
63
78
|
end
|
64
79
|
|
65
80
|
it "should handle a single word song with parenthesis" do
|
@@ -70,13 +85,16 @@ describe ISRC do
|
|
70
85
|
isrc.retrieve artist:'Frank Sinatra', title: 'Chicago (Digitally Remastered)'
|
71
86
|
isrc.match(time:'2:14')[:isrc].should == 'USCA20300966'
|
72
87
|
# or USCA29800388; they are basically the same
|
88
|
+
|
89
|
+
# Bagatelle in A minor, WoO 59 -`Für Elise` by Bella Davidovich...
|
73
90
|
end
|
74
91
|
end
|
75
92
|
|
76
93
|
it "should handle a standard multi-word title" do
|
77
94
|
pieces = isrc.send(:extract_song_peices, "Take Your Time")
|
78
|
-
pieces.size.should == 3
|
79
|
-
pieces.
|
95
|
+
pieces[:all].size.should == 3
|
96
|
+
pieces[:title].size.should == 3
|
97
|
+
pieces[:title].last.should == "Time"
|
80
98
|
end
|
81
99
|
|
82
100
|
end
|
metadata
CHANGED
@@ -1,83 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: isrc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Bianco
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: nokogiri
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: mechanize
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: guard
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
description: Pull ISRC codes from PPLK UK's database
|
@@ -87,8 +87,8 @@ executables: []
|
|
87
87
|
extensions: []
|
88
88
|
extra_rdoc_files: []
|
89
89
|
files:
|
90
|
-
- .gitignore
|
91
|
-
- .rspec
|
90
|
+
- ".gitignore"
|
91
|
+
- ".rspec"
|
92
92
|
- Gemfile
|
93
93
|
- Guardfile
|
94
94
|
- LICENSE
|
@@ -110,17 +110,17 @@ require_paths:
|
|
110
110
|
- lib
|
111
111
|
required_ruby_version: !ruby/object:Gem::Requirement
|
112
112
|
requirements:
|
113
|
-
- -
|
113
|
+
- - ">="
|
114
114
|
- !ruby/object:Gem::Version
|
115
115
|
version: '0'
|
116
116
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
117
|
requirements:
|
118
|
-
- -
|
118
|
+
- - ">="
|
119
119
|
- !ruby/object:Gem::Version
|
120
120
|
version: '0'
|
121
121
|
requirements: []
|
122
122
|
rubyforge_project:
|
123
|
-
rubygems_version: 2.
|
123
|
+
rubygems_version: 2.2.0
|
124
124
|
signing_key:
|
125
125
|
specification_version: 4
|
126
126
|
summary: Pull ISRC codes from PPLK UK's database
|