lyrics 0.0.2

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.
Files changed (50) hide show
  1. data/.document +5 -0
  2. data/.gitignore +21 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +17 -0
  5. data/Rakefile +45 -0
  6. data/VERSION +1 -0
  7. data/bin/lyrics +66 -0
  8. data/lib/lyrics.rb +4 -0
  9. data/lib/lyrics/cli/application.rb +99 -0
  10. data/lib/lyrics/cli/optionsparser.rb +228 -0
  11. data/lib/lyrics/cli/pluginadapter.rb +56 -0
  12. data/lib/lyrics/cli/plugins.rb +79 -0
  13. data/lib/lyrics/cli/wikipluginadapter.rb +139 -0
  14. data/lib/lyrics/i18n/README +1 -0
  15. data/lib/lyrics/i18n/en.rb +181 -0
  16. data/lib/lyrics/i18n/es.rb +181 -0
  17. data/lib/lyrics/i18n/i18n.rb +126 -0
  18. data/lib/lyrics/i18n/sk.rb +174 -0
  19. data/lib/lyrics/itrans/COPYRIGHT +31 -0
  20. data/lib/lyrics/itrans/itrans +0 -0
  21. data/lib/lyrics/itrans/itrans.txt +8 -0
  22. data/lib/lyrics/itrans/lyric.txt +23 -0
  23. data/lib/lyrics/itrans/udvng.ifm +206 -0
  24. data/lib/lyrics/lyrics.rb +567 -0
  25. data/lib/lyrics/lyrics_AZLyrics.rb +113 -0
  26. data/lib/lyrics/lyrics_DarkLyrics.rb +124 -0
  27. data/lib/lyrics/lyrics_Giitaayan.rb +124 -0
  28. data/lib/lyrics/lyrics_Jamendo.rb +166 -0
  29. data/lib/lyrics/lyrics_LeosLyrics.rb +142 -0
  30. data/lib/lyrics/lyrics_LoudSongs.rb +135 -0
  31. data/lib/lyrics/lyrics_LyricWiki.rb +328 -0
  32. data/lib/lyrics/lyrics_LyricsDownload.rb +118 -0
  33. data/lib/lyrics/lyrics_LyricsMania.rb +141 -0
  34. data/lib/lyrics/lyrics_Lyriki.rb +286 -0
  35. data/lib/lyrics/lyrics_SeekLyrics.rb +108 -0
  36. data/lib/lyrics/lyrics_Sing365.rb +103 -0
  37. data/lib/lyrics/lyrics_TerraLetras.rb +126 -0
  38. data/lib/lyrics/mediawikilyrics.rb +1417 -0
  39. data/lib/lyrics/utils/formdata.rb +56 -0
  40. data/lib/lyrics/utils/htmlentities.rb +291 -0
  41. data/lib/lyrics/utils/http.rb +198 -0
  42. data/lib/lyrics/utils/itrans.rb +160 -0
  43. data/lib/lyrics/utils/logger.rb +123 -0
  44. data/lib/lyrics/utils/strings.rb +378 -0
  45. data/lib/lyrics/utils/xmlhash.rb +111 -0
  46. data/lyrics.gemspec +98 -0
  47. data/spec/lyrics_spec.rb +7 -0
  48. data/spec/spec.opts +1 -0
  49. data/spec/spec_helper.rb +9 -0
  50. metadata +137 -0
@@ -0,0 +1,118 @@
1
+ # Copyright (C) 2007 by Sergio Pistone
2
+ # sergio_pistone@yahoo.com.ar
3
+ #
4
+ # This program is free software; you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation; either version 2 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the
16
+ # Free Software Foundation, Inc.,
17
+ # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
+
19
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__))
20
+
21
+ require "utils/strings"
22
+ require "utils/htmlentities"
23
+ require "lyrics"
24
+
25
+ class LyricsDownload < Lyrics
26
+
27
+ @@white_chars = "'\"¿?¡!()[].,;:-/& "
28
+
29
+ def LyricsDownload.site_host()
30
+ return "www.lyricsdownload.com"
31
+ end
32
+
33
+ def LyricsDownload.site_name()
34
+ return "Lyrics Download"
35
+ end
36
+
37
+ def LyricsDownload.lyrics_test_data()
38
+ return [
39
+ Request.new( "Nirvana", "Smells Like Teen Spirit", "Nevermind" ),
40
+ Request.new( "Radiohead", "Optimistic", "Kid A" ),
41
+ Request.new( "Massive Attack", "Protection", "Protection" ),
42
+ Request.new( "Portishead", "Wandering Star", "Dummy" ),
43
+ ]
44
+ end
45
+
46
+ def cleanup_artist( artist )
47
+ artist = artist.gsub( /^the /i, "" )
48
+ Strings.remove_vocal_accents!( artist )
49
+ artist.gsub!( "&", "and" )
50
+ artist.tr!( @@white_chars, " " )
51
+ artist.strip!()
52
+ artist.tr!( " ", "-" )
53
+ return artist
54
+ end
55
+
56
+ def cleanup_title( title )
57
+ title = Strings.remove_vocal_accents( title )
58
+ title.gsub!( "&", "and" )
59
+ title.tr!( @@white_chars, " " )
60
+ title.strip!()
61
+ title.tr!( " ", "-" )
62
+ return title
63
+ end
64
+
65
+ def build_lyrics_fetch_data( request )
66
+ artist = cleanup_title( request.artist )
67
+ title = cleanup_title( request.title )
68
+ return FetchPageData.new( "http://#{site_host()}/#{artist}-#{title}-lyrics.html" )
69
+ end
70
+
71
+ def parse_lyrics( response, page_body )
72
+
73
+ page_body = Strings.latin12utf8( page_body )
74
+ page_body.tr_s!( " \n\r\t", " " )
75
+ page_body.tr_s!( "’", "'" )
76
+ # page_body.tr_s!( "‘", "'" )
77
+
78
+ if (md = /<title>([^<]+) - ([^<]+) LYRICS ?<\/title>/i.match( page_body ))
79
+ response.artist, response.title = md[1].strip(), md[2].strip()
80
+ end
81
+
82
+ return if ! page_body.gsub!( /^.*<div class="KonaBody" ><div id="div_customCSS">/, "" )
83
+ return if ! page_body.gsub!( /<\/div> ?<\/div>.*$/, "" )
84
+
85
+ page_body.gsub!( /\ ?<br ?\/?> ?/i, "\n" )
86
+ page_body.strip!()
87
+
88
+ response.lyrics = page_body
89
+
90
+ end
91
+
92
+ def build_suggestions_fetch_data( request )
93
+ artist = cleanup_artist( request.artist )
94
+ return FetchPageData.new( "http://#{site_host()}/#{artist}-lyrics.html" )
95
+ end
96
+
97
+ def parse_suggestions( request, page_body, page_url )
98
+
99
+ page_body = Strings.latin12utf8( page_body )
100
+ page_body.tr_s!( " \n\r\t", " " )
101
+ page_body.tr_s!( "’", "'" )
102
+
103
+ suggestions = []
104
+
105
+ return suggestions if ! page_body.sub!( /^.*Lyrics list aplhabetically:<\/font><\/td>/, "" )
106
+ return suggestions if ! page_body.sub!( /<\/ul> ?<\/td> ?<\/tr> ?<\/table> ?<center><div>.*$/, "" )
107
+
108
+ page_body.split( "</li>" ).each() do |entry|
109
+ if (md = /<a class="txt_1" href="([^"]+)"><font size=2>([^<]+) Lyrics<\/font><\/a>/.match( entry ))
110
+ suggestions << Suggestion.new( request.artist, md[2], "http://#{site_host()}/#{md[1]}" )
111
+ end
112
+ end
113
+
114
+ return suggestions
115
+
116
+ end
117
+
118
+ end
@@ -0,0 +1,141 @@
1
+ # Copyright (C) 2007-2008 by
2
+ # Davide Lo Re <boyska@gmail.com>
3
+ # Sergio Pistone <sergio_pistone@yahoo.com.ar>
4
+ #
5
+ # This program is free software; you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation; either version 2 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program; if not, write to the
17
+ # Free Software Foundation, Inc.,
18
+ # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
+
20
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__))
21
+
22
+ require "utils/strings"
23
+ require "lyrics"
24
+
25
+ require "cgi"
26
+
27
+ class LyricsMania < Lyrics
28
+
29
+ def LyricsMania.site_host()
30
+ return "www.lyricsmania.com"
31
+ end
32
+
33
+ def LyricsMania.site_name()
34
+ return "LyricsMania"
35
+ end
36
+
37
+ def LyricsMania.lyrics_test_data()
38
+ return [
39
+ Request.new( "Nirvana", "Lounge Act", "Nevermind" ),
40
+ Request.new( "Radiohead", "Idioteque", "Kid A" ),
41
+ Request.new( "Pearl Jam", "Porch", "Ten" ),
42
+ Request.new( "The Smashing Pumpkins", "Mayonaise", "Siamese Dream" ),
43
+ ]
44
+ end
45
+
46
+ def LyricsMania.build_song_add_url( request )
47
+ return "http://#{site_host()}/add.html"
48
+ end
49
+
50
+ def LyricsMania.build_google_feeling_lucky_url( artist, title=nil )
51
+ query = Strings.google_search_quote( artist )
52
+ query << " " << Strings.google_search_quote( title + " lyrics" ) if title
53
+ return Strings.build_google_feeling_lucky_url( query, site_host() )
54
+ end
55
+
56
+ def build_lyrics_fetch_data( request )
57
+ return FetchPageData.new( build_google_feeling_lucky_url( request.artist, request.title ) )
58
+ end
59
+
60
+ def lyrics_page_valid?( request, page_body, page_url )
61
+ md = /<title>([^<]+) Lyrics<\/title>/i.match( page_body )
62
+ return false if ! md
63
+ page_title = Strings.normalize( md[1] )
64
+ return page_title.index( Strings.normalize( request.artist ) ) &&
65
+ page_title.index( Strings.normalize( request.title ) )
66
+ end
67
+
68
+ def parse_lyrics( response, page_body )
69
+
70
+ page_body = Strings.latin12utf8( page_body )
71
+ page_body.tr_s!( " \n\r\t", " " )
72
+
73
+ return if ! page_body.sub!( /^.* lyrics<\/h3>/, "" ) # metadata
74
+
75
+ metadata = {}
76
+ ["artist", "album"].each() do |key|
77
+ if (md =/#{key}: <b><a href=[^>]+>([^<]+)<\/a><\/b>/i.match( page_body ))
78
+ metadata[key.downcase()] = md[1].strip().sub( /\ *lyrics$/, "" )
79
+ end
80
+ end
81
+ ["year", "title"].each() do |key|
82
+ if (md =/#{key}: ([^<]+)<(br|\/td)>/i.match( page_body ))
83
+ metadata[key.downcase()] = md[1].strip()
84
+ end
85
+ end
86
+
87
+ response.artist = metadata["artist"] if metadata.include?( "artist" )
88
+ response.title = metadata["title"] if metadata.include?( "title" )
89
+ response.album = metadata["album"] if metadata.include?( "album" )
90
+ response.year = metadata["year"] if metadata.include?( "year" )
91
+
92
+ md = /<\/span> ?<\/center>(.*)<center> ?<span style/.match( page_body )
93
+ return if ! md
94
+
95
+ page_body = md[1]
96
+ page_body.sub!( /&#91;.+ Lyrics on http:\/\/#{site_host()}\/ &#93;/, "" )
97
+ page_body.sub!( /^.*<\/a>/, "" ) # additional (optional) crap at the beginning
98
+ page_body.gsub!( /<u>&lt;a[^<]+&lt;\/a&gt;<\/u>/, "" ) # yet more crap
99
+ page_body.gsub!( /\ ?<br ?\/?> ?/i, "\n" )
100
+ page_body.sub!( /^\ ?<strong>Lyrics to [^<]+<\/strong> :<\/?br> */i, "" )
101
+
102
+ page_body.strip!()
103
+
104
+ response.lyrics = page_body
105
+
106
+ end
107
+
108
+ def build_suggestions_fetch_data( request )
109
+ return FetchPageData.new( build_google_feeling_lucky_url( request.artist ) )
110
+ end
111
+
112
+ def suggestions_page_valid?( request, page_body, page_url )
113
+ md = /<title>([^<]+) Lyrics<\/title>/i.match( page_body )
114
+ return md ? Strings.normalize( md[1] ).index( Strings.normalize( request.artist ) ) : nil
115
+ end
116
+
117
+ # returns an array of maps with following keys: url, artist, title
118
+ def parse_suggestions( request, page_body, page_url )
119
+
120
+ page_body = Strings.latin12utf8( page_body )
121
+ page_body.tr_s!( " \n\r\t", " " )
122
+
123
+ suggestions = []
124
+
125
+ # remove table with other artists at the bottom
126
+ return suggestions if ! page_body.sub!( /(.*)<table.*/, "\\1" )
127
+
128
+ md = /<table width=100%>(.*)<\/table>/.match( page_body )
129
+ return suggestions if ! md
130
+
131
+ md[1].split( /<a href=/ ).each() do |entry|
132
+ if (md = /"(\/lyrics\/[^"]+)" title="[^"]+"> ?([^>]+) lyrics<\/a><br>/.match( entry ))
133
+ suggestions << Suggestion.new( request.artist, md[2], "http://#{site_host()}#{md[1]}" )
134
+ end
135
+ end
136
+
137
+ return suggestions
138
+
139
+ end
140
+
141
+ end
@@ -0,0 +1,286 @@
1
+ # Copyright (C) 2006-2008 by Sergio Pistone
2
+ # sergio_pistone@yahoo.com.ar
3
+ #
4
+ # This program is free software; you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation; either version 2 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the
16
+ # Free Software Foundation, Inc.,
17
+ # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
+
19
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__))
20
+
21
+ require "utils/strings"
22
+ require "utils/http"
23
+ require "mediawikilyrics"
24
+
25
+ require "uri"
26
+ require "cgi"
27
+
28
+ class Lyriki < MediaWikiLyrics
29
+
30
+ def Lyriki.site_host()
31
+ return "www.lyriki.com"
32
+ end
33
+
34
+ def Lyriki.site_name()
35
+ return "Lyriki"
36
+ end
37
+
38
+ def Lyriki.control_page()
39
+ return "Lyriki:Wiki-Lyrics"
40
+ end
41
+
42
+ def parse_lyrics( response, page_body )
43
+
44
+ custom_data = {}
45
+
46
+ if (md = /\{\{\s*[Ss]ong\s*\|.*$/m.match( page_body ))
47
+
48
+ template_data = parse_template( md[0] )
49
+ template_data["params"].each() do |key, value|
50
+ custom_data[key.to_s()] = value
51
+ if value.is_a?( String )
52
+ value.gsub!( /<br ?\/?>/i, "; " ) if key != "song"
53
+ value.gsub!( /<\/?[^>]+\/?>/, " " )
54
+ value.tr_s!( " \n\r\t", " " )
55
+ value.strip!()
56
+ end
57
+ end
58
+
59
+ response.title = custom_data["song"] if custom_data.include?( "song" )
60
+
61
+ if custom_data["artist"].is_a?( String )
62
+ response.artist = custom_data["artist"]
63
+ elsif custom_data["artists"].is_a?( Array )
64
+ artist = ""
65
+ custom_data["artists"].each() do |token|
66
+ if token.is_a?( String )
67
+ artist << token.gsub( /\[\[|\]\]/, "" )
68
+ elsif token.is_a?( Hash ) && token["name"].downcase() == "song artist" && token["params"][1]
69
+ artist << token["params"][1]
70
+ end
71
+ end
72
+ artist.gsub!( /\s*<br *\/?>\s*/i, " " )
73
+ response.artist = artist
74
+ elsif custom_data["artists"].is_a?( String ) # this case is DEPRECATED by Lyriki guides
75
+ response.artist = custom_data["artists"].gsub( /\[\[|\]\]/, "" )
76
+ end
77
+
78
+ if custom_data["album"].is_a?( String )
79
+ response.album, response.year = custom_data["album"], custom_data["year"]
80
+ elsif custom_data["albums"].is_a?( Array )
81
+ custom_data["albums"].each() do |token|
82
+ if token.is_a?( String )
83
+ if (md = /([^:]+):(.+) \(([0-9]{4,4})\)/.match( token ))
84
+ response.album, response.year = md[2], md[3]
85
+ break
86
+ end
87
+ elsif token.is_a?( Hash )
88
+ if token["name"].downcase() == "song album" && token["params"][2] && token["params"][3]
89
+ response.album, response.year = token["params"][2], token["params"][3]
90
+ break
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ end
97
+
98
+ custom_data["reviewed"] = (/\{\{[Aa]utoGenerated\}\}/.match( page_body ) == nil)
99
+
100
+ if (md = /<lyrics>(.*)<\/lyrics>/im.match( page_body ))
101
+ page_body = md[1]
102
+ page_body.gsub!( /[ \t]*[\r\n][ \t]*/m, "\n" )
103
+ else
104
+ page_body.gsub!( /\{\{.*\}\}\n?/, "" )
105
+ page_body.gsub!( /\[\[Category:.*\]\]\n?/, "" )
106
+ page_body.gsub!( /\ *== *(External *Links|Links) *==.*$/im, "" )
107
+ page_body = page_body.split( "\n" ).collect() do |line|
108
+ if line.index( /\s/ ) == 0
109
+ "\n" + line
110
+ else
111
+ line
112
+ end
113
+ end.join( "" )
114
+ page_body.gsub!( /\s*<br ?\/?>\s*/i, "\n" )
115
+ end
116
+
117
+ response.lyrics = page_body if ! Strings.empty?( page_body )
118
+ response.custom_data = custom_data
119
+
120
+ end
121
+
122
+ def Lyriki.build_tracks( album_data )
123
+ ret = ""
124
+ album_data.tracks.each() do |track|
125
+ track_length = track.length > 0 ?
126
+ "|#{track.length / 60}:#{track.length % 60 < 10 ? "0#{track.length % 60}" : track.length % 60}" :
127
+ ""
128
+ track_artist = cleanup_title_token( track.artist )
129
+ track_title = cleanup_title_token( track.title )
130
+ if album_data.various_artists?
131
+ ret += "# {{song link va|#{track_artist}|#{track_title}#{track_length}}}\n"
132
+ else
133
+ ret += "# {{song link|#{track_artist}|#{track_title}#{track_length}}}\n"
134
+ end
135
+ end
136
+ return ret
137
+ end
138
+
139
+ def Lyriki.build_album_page( reviewed, artist, album, year, month, day, tracks, album_art )
140
+
141
+ raise ArgumentError if Strings.empty?( artist ) || Strings.empty?( album ) || Strings.empty?( tracks )
142
+
143
+ s_name = get_sort_name( album )
144
+ s_letter = get_sort_letter( album )
145
+
146
+ album_art = nil if ! year || album_art == build_album_art_name( artist, album, year, "jpg", false )
147
+
148
+ contents = \
149
+ "#{reviewed ? "" : "{{autoGenerated}}\n"}" \
150
+ "{{Album\n" \
151
+ "| album = #{album}\n" \
152
+ "| artist = #{artist}\n" \
153
+ "| released = #{build_date( year, month, day )}\n" \
154
+ "#{album_art ? "| image = #{album_art}\n" : ""}" \
155
+ "| tracks =\n"
156
+
157
+ return \
158
+ "#{contents}" \
159
+ "#{tracks.strip()}\n" \
160
+ "}}\n" \
161
+ "\n" \
162
+ "{{C:Album|#{s_letter}|#{s_name}}}"
163
+ end
164
+
165
+ def Lyriki.build_song_page( reviewed, artist, title, album, year, credits, lyricist, lyrics )
166
+
167
+ raise ArgumentError if artist == nil || title == nil
168
+
169
+ s_name = get_sort_name( title )
170
+ s_letter = get_sort_letter( title )
171
+ year = year.to_i() <= 1900 ? "" : year.to_s()
172
+
173
+ song_page = reviewed ? "": "{{autoGenerated}}\n"
174
+
175
+ if (md = /^([^\s].*)\s+feat\.\s+([^\s].*)$/i.match( artist.strip() ))
176
+ artist, fartist = md[1].strip(), md[2]
177
+ song_page <<
178
+ "{{Song\n" \
179
+ "| song = #{title}\n" \
180
+ "| artists = {{song artist|#{artist}}}<br />feat. {{song artist|#{fartist}}}\n" \
181
+ "| albums = {{song album|#{artist}|#{album}|#{year}}}\n" \
182
+ "| credits = #{credits.to_s().split( "; " ).join( "<br />" )}\n" \
183
+ "| lyricist = #{lyricist.to_s().split( "; " ).join( "<br />" )}\n" \
184
+ "}}\n" \
185
+ else
186
+ song_page <<
187
+ "{{Song\n" \
188
+ "| song = #{title}\n" \
189
+ "| artist = #{artist}\n" \
190
+ "| album = #{album}\n" \
191
+ "| year = #{year}\n" \
192
+ "| credits = #{credits.to_s().split( "; " ).join( "<br />" )}\n" \
193
+ "| lyricist = #{lyricist.to_s().split( "; " ).join( "<br />" )}\n" \
194
+ "}}\n" \
195
+ end
196
+
197
+ return song_page <<
198
+ "\n" \
199
+ "<lyrics>#{Strings.empty?( lyrics ) ? "<tt>(Instrumental)</tt>" : lyrics}</lyrics>\n" \
200
+ "\n" \
201
+ "{{C:Song|#{s_letter}|#{s_name}}}"
202
+ end
203
+
204
+ def Lyriki.build_album_art_name( artist, album, year, extension="jpg", cleanup=true )
205
+ if cleanup
206
+ artist = cleanup_title_token( artist )
207
+ album = cleanup_title_token( album )
208
+ end
209
+ album_art_name = "AlbumArt-#{artist}-#{album}_(#{year})#{Strings.empty?( extension ) ? "" : ".#{extension.strip()}"}".gsub( " ", "_" )
210
+ return Strings.remove_invalid_filename_chars( album_art_name )
211
+ end
212
+
213
+ def Lyriki.build_album_art_description( artist, album, year, cleanup=true )
214
+ if cleanup
215
+ artist = cleanup_title_token( artist )
216
+ album = cleanup_title_token( album )
217
+ end
218
+ return "#{artist}:#{album} (#{year})"
219
+ end
220
+
221
+ def Lyriki.find_album_art_name( artist, album, year )
222
+
223
+ normalized_artist = cleanup_title_token( artist )
224
+ Strings.remove_invalid_filename_chars!( normalized_artist )
225
+ Strings.normalize!( normalized_artist )
226
+ normalized_artist.gsub!( " ", "" )
227
+
228
+ normalized_album = cleanup_title_token( album )
229
+ Strings.remove_invalid_filename_chars!( normalized_album )
230
+ Strings.normalize!( normalized_album )
231
+ normalized_album.gsub!( " ", "" )
232
+
233
+ year = year.to_s().strip()
234
+
235
+ artist = cleanup_title_token( artist )
236
+ Strings.remove_invalid_filename_chars!( artist )
237
+ search_url = "http://#{site_host()}/index.php?ns6=1&search=#{CGI.escape( artist )}&searchx=Search&limit=500"
238
+ response, search_url = HTTP.fetch_page_get( search_url )
239
+
240
+ return nil if response == nil || response.body() == nil
241
+
242
+ candidates = []
243
+ parse_search_results( response.body(), true ).each() do |result|
244
+
245
+ next if result[@@SEARCH_RESULT_TITLE].index( "Image:" ) != 0
246
+
247
+ normalized_title = Strings.normalize( result[@@SEARCH_RESULT_TITLE] )
248
+ normalized_title.gsub!( " ", "" )
249
+
250
+ matches = 0
251
+ idx1 = normalized_title.index( "albumart" )
252
+ matches += 1 if idx1
253
+ idx1 = idx1 ? idx1 + "albumart".size : 0
254
+ idx2 = normalized_title.index( normalized_artist, idx1 )
255
+ matches += 4 if idx2
256
+ idx2 = idx2 ? idx2 + normalized_artist.size : idx1
257
+ idx3 = normalized_title.index( normalized_album, idx2 )
258
+ next if idx3 == nil
259
+ idx3 = idx3 ? idx3 + normalized_album.size : idx2
260
+ idx3 = normalized_title.index( year, idx3 )
261
+ matches += 2 if idx3
262
+
263
+ candidates.insert( -1, [ matches, result[@@SEARCH_RESULT_TITLE] ] )
264
+ end
265
+
266
+ if candidates.size > 0
267
+ candidates.sort!() { |x,y| y[0] <=> x[0] }
268
+ return URI.decode( candidates[0][1].slice( "Image:".size..-1 ).gsub( " ", "_" ) )
269
+ else
270
+ return nil
271
+ end
272
+ end
273
+
274
+ def Lyriki.cleanup_title_token!( title, downcase=false )
275
+ title.gsub!( /\[[^\]\[]*\]/, "" )
276
+ title.gsub!( /[\[|\]].*$/, "" )
277
+ title.gsub!( /`|´|’/, "'" )
278
+ title.gsub!( /''|«|»/, "\"" )
279
+ title.squeeze!( " " )
280
+ title.strip!()
281
+ title.gsub!( "+", "and" )
282
+ Strings.titlecase!( title, true, downcase )
283
+ return title
284
+ end
285
+
286
+ end