mp3lyrics 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6977220f3ee03ab44d150bb7e8ae2e56b8847186f5d2b764a48726516a629119
4
- data.tar.gz: 9509ff32bc484dd7787b7455c2307dc3f011ee077bc92060cd5d52be7ac3f8f3
3
+ metadata.gz: 331cb5ff0fa84f9be3d6c0a675b50864d50eb56174f267b783a1054117a2a9f2
4
+ data.tar.gz: f745bbffb2ce1bc05bfa9876296e16b65d6e16e9194c2e12a7f17e6f558e1dd7
5
5
  SHA512:
6
- metadata.gz: 403c3c6eb70255696bb2f042c692b34ef5a7e86a1aaf63b95bd34d567d382ae656929c6020f6b15c23c30694af1c09c5d97a9ce2f0ab1ffb4926d7aebf7c6222
7
- data.tar.gz: 06b5ff82066b8d73e0c88ab46dec6d5fe6d88e7fd22875463712c42735bd78c959915646ca921304b28a191d6a0e7e754990bac5d93ee09788cec01e91d9c472
6
+ metadata.gz: 0edbea1fe6ef0c41653729948908d664dd54deaa5b6dfda866b2227a9e8ca54af86a622d5c849d93190c914428c6f1bdede7f7fcbc52ad568034652f5dad4533
7
+ data.tar.gz: 50e9ca90379f70263016d6b8a6ef9525170db56e17e881fe6b9e8357d72f646af415eb02d3162afd79050f374782760b6ad46a90e79de02e12680040c2e14934
data/CHANGELOG.md CHANGED
@@ -1,9 +1,9 @@
1
- # Changelog
2
-
3
- All notable changes to this project will be documented in this file.
4
-
5
- # 0.1.2 (2021-01-09)
6
-
7
- ## Bug Fixes
8
-
9
- - Improves parsing certain titles that contain characters such as `'` or have a `(feat. XYZ)` in their title
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ # 0.1.2 (2021-01-09)
6
+
7
+ ## Bug Fixes
8
+
9
+ - Improves parsing certain titles that contain characters such as `'` or have a `(feat. XYZ)` in their title
data/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2021 Tim Brust
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Tim Brust
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -1,96 +1,96 @@
1
- # MP3Lyrics
2
-
3
- [![Ruby](https://github.com/timbru31/mp3lyrics/workflows/Ruby/badge.svg)](https://github.com/timbru31/mp3lyrics/actions?query=workflow%3ARuby)
4
-
5
- [![Code Climate coverage](https://img.shields.io/codeclimate/coverage/timbru31/mp3lyrics)](https://codeclimate.com/github/timbru31/mp3lyrics)
6
- [![Code Climate](https://img.shields.io/codeclimate/maintainability/timbru31/mp3lyrics)](https://codeclimate.com/github/timbru31/mp3lyrics)
7
- [![Known Vulnerabilities](https://snyk.io/test/github/timbru31/mp3lyrics/badge.svg)](https://snyk.io/test/github/timbru31/mp3lyrics)
8
- [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=timbru31/mp3lyrics)](https://dependabot.com)
9
-
10
- [![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE.md)
11
-
12
- ### Still in Alpha, ugly and WIP :)
13
-
14
- ## Info
15
-
16
- MP3Lyrics is a tool written in Ruby (currently only CLI) to download song lyrics from [MetroLyrics](https://www.metrolyrics.com), [AZLyrics](https://www.azlyrics.com) and [Genius](https://genius.com).
17
- The lyrics are added to the mp3 file via the [USLT (Unsynchronised lyric/text transcription)](https://id3.org/id3v2.4.0-frames) tag (with the power of [ruby-mp3info](https://github.com/moumar/ruby-mp3info)).
18
-
19
- ## Motivation
20
-
21
- #### Why Ruby?
22
-
23
- Because I wanted to try another language than Java.
24
-
25
- #### Why are you not using the LyricWiki API?
26
-
27
- ~~Although they have got a pretty neat [REST API](http://api.wikia.com/wiki/LyricWiki_API/REST) the lyrics can't be fully retrieved, most likely due to licensing issues.~~
28
- They no longer offer an API since January 2016. The site has since been shut down as of October 2020.
29
-
30
- #### Why are you not using musiXmatch API?
31
-
32
- Simply because they charge me (the developer) for retrieving the lyrics.
33
-
34
- #### Why are you not using MetroLyrics API?
35
-
36
- I don't have an API key (yet).
37
-
38
- #### Why are you not using Genius API?
39
-
40
- They do not offer fetching lyrics via the API (yet).
41
-
42
- #### Why not iTunes Lyrics Adder, Lyrics for iTunes, iSongText, Get Lyrical, ...?
43
-
44
- Either they were tied to iTunes and ugly DLL libraries, outdated/inactive, closed source or not cross platform. I'm mainly developing on my MacBook and my iTunes library is on my Windows system. I need something that works anywhere.
45
-
46
- By dropping the need (and support) of iTunes running somewhere in the background, the tool is more lightweight.
47
-
48
- ## Dependencies
49
-
50
- 1. Bundler
51
- 2. Nokogiri for HTML parsing
52
- 3. mp3info as a MP3 library
53
- 4. require_all for easier requiring of the wiki_api folder
54
- 5. For testing purposes you should install rubocop, rake, minitest and optionally coverage reporters for CodeClimate
55
-
56
- ## Installation
57
-
58
- ```shell
59
- gem install mp3lyrics
60
- ```
61
-
62
- ## Usage
63
-
64
- ```shell
65
- mp3lyrics <dir> [-override true/false] [-use genius/metrolyrics/azlyrics]
66
- ```
67
-
68
- **dir** is the folder with your music, it's iterated recursively.
69
- **override** is a boolean toggle to override existing lyrics (defaults to _false_).
70
- **use** is a specific wiki to be used to download lyrics (all wikis are used by default).
71
-
72
- ### Development usage
73
-
74
- The same options as above apply, but the binary has to be invoked from
75
-
76
- ```shell
77
- ./lib/mp3lyrics.rb
78
- ```
79
-
80
- ## Tests
81
-
82
- To execute the tests run
83
-
84
- ```shell
85
- bundle exec rake
86
- ```
87
-
88
- ## Future plans // ToDo
89
-
90
- - ~~Add support to other lyrics sites when 404 is returned from LyricWiki~~
91
- - GUI for easier usage (maybe)
92
- - Add test cases, see [#1](https://github.com/timbru31/mp3lyrics/issues/1)
93
-
94
- ---
95
-
96
- Built by (c) Tim Brust and contributors. Released under the MIT license.
1
+ # MP3Lyrics
2
+
3
+ [![Ruby](https://github.com/timbru31/mp3lyrics/workflows/Ruby/badge.svg)](https://github.com/timbru31/mp3lyrics/actions?query=workflow%3ARuby)
4
+
5
+ [![Code Climate coverage](https://img.shields.io/codeclimate/coverage/timbru31/mp3lyrics)](https://codeclimate.com/github/timbru31/mp3lyrics)
6
+ [![Code Climate](https://img.shields.io/codeclimate/maintainability/timbru31/mp3lyrics)](https://codeclimate.com/github/timbru31/mp3lyrics)
7
+ [![Known Vulnerabilities](https://snyk.io/test/github/timbru31/mp3lyrics/badge.svg)](https://snyk.io/test/github/timbru31/mp3lyrics)
8
+ [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=timbru31/mp3lyrics)](https://dependabot.com)
9
+
10
+ [![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE.md)
11
+
12
+ ### Still in Alpha, ugly and WIP :)
13
+
14
+ ## Info
15
+
16
+ MP3Lyrics is a tool written in Ruby (currently only CLI) to download song lyrics from [AZLyrics](https://www.azlyrics.com) or [Genius](https://genius.com).
17
+ The lyrics are added to the mp3 file via the [USLT (Unsynchronised lyric/text transcription)](https://id3.org/id3v2.4.0-frames) tag (with the power of [ruby-mp3info](https://github.com/moumar/ruby-mp3info)).
18
+
19
+ ## Motivation
20
+
21
+ #### Why Ruby?
22
+
23
+ Because I wanted to try another language than Java.
24
+
25
+ #### Why are you not using the LyricWiki API?
26
+
27
+ ~~Although they have got a pretty neat [REST API](http://api.wikia.com/wiki/LyricWiki_API/REST) the lyrics can't be fully retrieved, most likely due to licensing issues.~~
28
+ They no longer offer an API since January 2016. The site has since been shut down as of October 2020.
29
+
30
+ #### Why are you not using musiXmatch API?
31
+
32
+ Simply because they charge me (the developer) for retrieving the lyrics.
33
+
34
+ #### Why are you not using MetroLyrics API?
35
+
36
+ The site has been shut down as of July 2021.
37
+
38
+ #### Why are you not using Genius API?
39
+
40
+ They do not offer fetching lyrics via the API (yet).
41
+
42
+ #### Why not iTunes Lyrics Adder, Lyrics for iTunes, iSongText, Get Lyrical, ...?
43
+
44
+ Either they were tied to iTunes and ugly DLL libraries, outdated/inactive, closed source or not cross platform. I'm mainly developing on my MacBook and my iTunes library is on my Windows system. I need something that works anywhere.
45
+
46
+ By dropping the need (and support) of iTunes running somewhere in the background, the tool is more lightweight.
47
+
48
+ ## Dependencies
49
+
50
+ 1. Bundler
51
+ 2. Nokogiri for HTML parsing
52
+ 3. mp3info as a MP3 library
53
+ 4. require_all for easier requiring of the wiki_api folder
54
+ 5. For testing purposes you should install rubocop, rake, minitest and optionally coverage reporters for CodeClimate
55
+
56
+ ## Installation
57
+
58
+ ```shell
59
+ gem install mp3lyrics
60
+ ```
61
+
62
+ ## Usage
63
+
64
+ ```shell
65
+ mp3lyrics <dir> [-override true/false] [-use genius/azlyrics]
66
+ ```
67
+
68
+ **dir** is the folder with your music, it's iterated recursively.
69
+ **override** is a boolean toggle to override existing lyrics (defaults to _false_).
70
+ **use** is a specific wiki to be used to download lyrics (all wikis are used by default).
71
+
72
+ ### Development usage
73
+
74
+ The same options as above apply, but the binary has to be invoked from
75
+
76
+ ```shell
77
+ ./lib/mp3lyrics.rb
78
+ ```
79
+
80
+ ## Tests
81
+
82
+ To execute the tests run
83
+
84
+ ```shell
85
+ bundle exec rake
86
+ ```
87
+
88
+ ## Future plans // ToDo
89
+
90
+ - ~~Add support to other lyrics sites when 404 is returned from LyricWiki~~
91
+ - GUI for easier usage (maybe)
92
+ - Add test cases, see [#1](https://github.com/timbru31/mp3lyrics/issues/1)
93
+
94
+ ---
95
+
96
+ Built by (c) Tim Brust and contributors. Released under the MIT license.
data/bin/mp3lyrics CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require 'mp3lyrics'
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'mp3lyrics'
data/lib/mp3lyrics.rb CHANGED
@@ -1,106 +1,105 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require 'mp3info'
5
- require 'require_all'
6
-
7
- require_all './lib/wiki/'
8
-
9
- def to_b(string)
10
- !(string =~ /^(true|t|yes|y|1)$/i).nil?
11
- end
12
-
13
- def usage_message(override_options, use_options)
14
- "Usage: ./mp3lyrics.rb <dir> [-override #{override_options.join('/')}] [-use #{use_options.join('/')}]"
15
- end
16
-
17
- override_options = [true, false]
18
- use_options = %w[genius metrolyrics azlyrics]
19
-
20
- if ARGV.length.even? ||
21
- ARGV.count('-override') > 1 ||
22
- ARGV.count('-use') > 1
23
- # If there is an even number of arguments (includes no arguments)
24
- # or a flag has been used more than once
25
- puts usage_message(override_options, use_options)
26
- exit
27
- end
28
-
29
- dir = ARGV[0]
30
- override = false
31
- wiki_to_use = nil
32
-
33
- i = 1
34
- while i < ARGV.length
35
- case ARGV[i]
36
- when '-override'
37
- if override_options.include?(to_b(ARGV[i + 1]))
38
- override = to_b(ARGV[i + 1])
39
- else
40
- # If the argument after the override flag is invalid
41
- puts usage_message(override_options, use_options)
42
- exit
43
- end
44
- when '-use'
45
- if use_options.include?(ARGV[i + 1])
46
- wiki_to_use = ARGV[i + 1]
47
- else
48
- # If the argument after the use flag is invalid
49
- puts usage_message(override_options, use_options)
50
- exit
51
- end
52
- else
53
- # If the argument is not a valid flag
54
- puts usage_message(override_options, use_options)
55
- exit
56
- end
57
- i += 2
58
- end
59
-
60
- puts "
61
- Welcome to
62
- __ __ _____ ____ _ _
63
- | \\\/ | __ \\___ \\| | (_)
64
- | \\ \/ | |__) |__) | | _ _ _ __ _ ___ ___
65
- | |\\/| | ___\/|__ <| | | | | | \'__| |\/ __\/ __|
66
- | | | | | ___) | |___| |_| | | | | (__\\__ \\
67
- |_| |_|_| |____\/|______\\__, |_| |_|\\___|___\/
68
- __\/ |
69
- |___\/
70
-
71
- The current working directory is #{dir}
72
- Overriding existing lyrics is #{override}"
73
- puts "Specific wiki to use is #{wiki_to_use}" unless wiki_to_use.nil?
74
- puts "\n\r"
75
-
76
- wiki = Wiki.new
77
- files = Dir.glob("#{dir}/**/*")
78
- files.each do |file|
79
- filename = File.extname(file)
80
- next unless filename == '.mp3'
81
-
82
- Mp3Info.open(file) do |mp3|
83
- artist = mp3.tag.artist || mp3.tag1.artist || mp3.tag2.artist
84
- title = mp3.tag.title || mp3.tag1.title || mp3.tag2.title
85
- if artist.nil? || title.nil?
86
- puts "Skipping song because title or artist is not set...\n\r"
87
- next
88
- end
89
- puts "Fetching lyrics for #{artist} - #{title}"
90
- # Either no tag is set, the mp3 file has no USLT tag or we override anyway
91
- if !mp3.hastag2? || (mp3.hastag2? && !mp3.tag2.key?('USLT')) || override
92
- lyrics = nil
93
- lyrics = Genius.new.get_lyrics(artist, title) if wiki_to_use.nil? || wiki_to_use == 'genius'
94
- lyrics = MetroLyrics.new.get_lyrics(artist, title) if (wiki_to_use.nil? || wiki_to_use == 'metrolyrics') && lyrics.nil?
95
- lyrics = AZLyrics.new.get_lyrics(artist, title) if (wiki_to_use.nil? || wiki_to_use == 'azlyrics') && lyrics.nil?
96
- if lyrics.nil?
97
- puts "Did not find any lyrics\n\r"
98
- else
99
- puts "Lyrics found\n\r"
100
- wiki.set_lyrics(mp3, lyrics)
101
- end
102
- else
103
- puts "Skipping #{artist} - #{title} because lyrics are already set"
104
- end
105
- end
106
- end
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'mp3info'
5
+ require 'require_all'
6
+
7
+ require_all './lib/wiki/'
8
+
9
+ def to_b(string)
10
+ !(string =~ /^(true|t|yes|y|1)$/i).nil?
11
+ end
12
+
13
+ def usage_message(override_options, use_options)
14
+ "Usage: ./mp3lyrics.rb <dir> [-override #{override_options.join('/')}] [-use #{use_options.join('/')}]"
15
+ end
16
+
17
+ override_options = [true, false]
18
+ use_options = %w[genius azlyrics]
19
+
20
+ if ARGV.length.even? ||
21
+ ARGV.count('-override') > 1 ||
22
+ ARGV.count('-use') > 1
23
+ # If there is an even number of arguments (includes no arguments)
24
+ # or a flag has been used more than once
25
+ puts usage_message(override_options, use_options)
26
+ exit
27
+ end
28
+
29
+ dir = ARGV[0]
30
+ override = false
31
+ wiki_to_use = nil
32
+
33
+ i = 1
34
+ while i < ARGV.length
35
+ case ARGV[i]
36
+ when '-override'
37
+ if override_options.include?(to_b(ARGV[i + 1]))
38
+ override = to_b(ARGV[i + 1])
39
+ else
40
+ # If the argument after the override flag is invalid
41
+ puts usage_message(override_options, use_options)
42
+ exit
43
+ end
44
+ when '-use'
45
+ if use_options.include?(ARGV[i + 1])
46
+ wiki_to_use = ARGV[i + 1]
47
+ else
48
+ # If the argument after the use flag is invalid
49
+ puts usage_message(override_options, use_options)
50
+ exit
51
+ end
52
+ else
53
+ # If the argument is not a valid flag
54
+ puts usage_message(override_options, use_options)
55
+ exit
56
+ end
57
+ i += 2
58
+ end
59
+
60
+ puts "
61
+ Welcome to
62
+ __ __ _____ ____ _ _
63
+ | \\\/ | __ \\___ \\| | (_)
64
+ | \\ \/ | |__) |__) | | _ _ _ __ _ ___ ___
65
+ | |\\/| | ___\/|__ <| | | | | | \'__| |\/ __\/ __|
66
+ | | | | | ___) | |___| |_| | | | | (__\\__ \\
67
+ |_| |_|_| |____\/|______\\__, |_| |_|\\___|___\/
68
+ __\/ |
69
+ |___\/
70
+
71
+ The current working directory is #{dir}
72
+ Overriding existing lyrics is #{override}"
73
+ puts "Specific wiki to use is #{wiki_to_use}" unless wiki_to_use.nil?
74
+ puts "\n\r"
75
+
76
+ wiki = Wiki.new
77
+ files = Dir.glob("#{dir}/**/*")
78
+ files.each do |file|
79
+ filename = File.extname(file)
80
+ next unless filename == '.mp3'
81
+
82
+ Mp3Info.open(file) do |mp3|
83
+ artist = mp3.tag.artist || mp3.tag1.artist || mp3.tag2.artist
84
+ title = mp3.tag.title || mp3.tag1.title || mp3.tag2.title
85
+ if artist.nil? || title.nil?
86
+ puts "Skipping song because title or artist is not set...\n\r"
87
+ next
88
+ end
89
+ puts "Fetching lyrics for #{artist} - #{title}"
90
+ # Either no tag is set, the mp3 file has no USLT tag or we override anyway
91
+ if !mp3.hastag2? || (mp3.hastag2? && !mp3.tag2.key?('USLT')) || override
92
+ lyrics = nil
93
+ lyrics = Genius.new.get_lyrics(artist, title) if wiki_to_use.nil? || wiki_to_use == 'genius'
94
+ lyrics = AZLyrics.new.get_lyrics(artist, title) if (wiki_to_use.nil? || wiki_to_use == 'azlyrics') && lyrics.nil?
95
+ if lyrics.nil?
96
+ puts "Did not find any lyrics\n\r"
97
+ else
98
+ puts "Lyrics found\n\r"
99
+ wiki.set_lyrics(mp3, lyrics)
100
+ end
101
+ else
102
+ puts "Skipping #{artist} - #{title} because lyrics are already set"
103
+ end
104
+ end
105
+ end
data/lib/wiki/azlyrics.rb CHANGED
@@ -1,25 +1,25 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './wiki'
4
-
5
- # Fetches the lyrics from AZLyrics.com
6
- # Lyrics are stored accessed via the URL schema https://www.azlyrics.com/lyrics/ARTIST/SONG.html
7
- # They are inside /html/body/div[2]/div/div[2]/div[5], sadly no class to access.
8
- # There are hidden comments, which need to be removed.
9
- class AZLyrics < Wiki
10
- def get_lyrics(artist, song, limit = 10)
11
- artist = artist.delete(' ').gsub(/('|`|´|’|\?|\(|\))/, '').parameterize
12
- song = song.delete(' ').gsub(/('|`|´|’|\?|\(|\))/, '').gsub(/(?:\(?feat.*\)?)/, '').parameterize
13
-
14
- res = fetch("https://www.azlyrics.com/lyrics/#{artist.downcase}/#{song.downcase}.html", limit)
15
- return nil unless res.is_a? Net::HTTPSuccess
16
-
17
- lyrics = Nokogiri::HTML(res.body).xpath('/html/body/div[2]/div/div[2]/div[5]')
18
- prettify_lyrics(lyrics)
19
- end
20
-
21
- def prettify_lyrics(lyrics)
22
- lyrics.search('.//comment()').remove
23
- lyrics.inner_html.gsub('<br>', "\r").delete("\n").sub("\r\r", '')
24
- end
25
- end
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './wiki'
4
+
5
+ # Fetches the lyrics from AZLyrics.com
6
+ # Lyrics are stored accessed via the URL schema https://www.azlyrics.com/lyrics/ARTIST/SONG.html
7
+ # They are inside /html/body/div[2]/div/div[2]/div[5], sadly no class to access.
8
+ # There are hidden comments, which need to be removed.
9
+ class AZLyrics < Wiki
10
+ def get_lyrics(artist, song, limit = 10)
11
+ artist = artist.delete(' ').gsub(/('|`|´|’|\?|\(|\))/, '').parameterize
12
+ song = song.delete(' ').gsub(/('|`|´|’|\?|\(|\))/, '').gsub(/(?:\(?feat.*\)?)/, '').parameterize
13
+
14
+ res = fetch("https://www.azlyrics.com/lyrics/#{artist.downcase}/#{song.downcase}.html", limit)
15
+ return nil unless res.is_a? Net::HTTPSuccess
16
+
17
+ lyrics = Nokogiri::HTML(res.body).xpath('/html/body/div[2]/div/div[2]/div[5]')
18
+ prettify_lyrics(lyrics)
19
+ end
20
+
21
+ def prettify_lyrics(lyrics)
22
+ lyrics.search('.//comment()').remove
23
+ lyrics.inner_html.gsub('<br>', "\r").delete("\n").sub("\r\r", '')
24
+ end
25
+ end
data/lib/wiki/genius.rb CHANGED
@@ -1,19 +1,19 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './wiki'
4
-
5
- # Fetches the lyrics from Genius (formerly known as Rap Genius)
6
- # Lyrics are stored accessed via the URL schema https://genius.com/ARTIST-SONG-lyrics
7
- # They are inside //div[starts-with(@class, "Lyrics__Container")]
8
- class Genius < Wiki
9
- def get_lyrics(artist, song, limit = 10)
10
- artist = artist.tr(' ', '-').gsub(/('|`|´|’)/, '').gsub(/(?:\(?feat.*\)?)/, '').parameterize
11
- song = song.tr(' ', '-').gsub(/('|`|´|’)/, '').gsub(/(?:\(?feat.*\)?)/, '').parameterize
12
-
13
- res = fetch("https://genius.com/#{artist.downcase}-#{song.downcase}-lyrics", limit)
14
- return nil unless res.is_a? Net::HTTPSuccess
15
-
16
- lyrics = Nokogiri::HTML(res.body).xpath("//div[starts-with(@class, 'lyrics') or starts-with(@class, 'Lyrics__Container')]")
17
- lyrics.inner_html.gsub('<br>', "\r").gsub(%r{</?[^>]+>}, '').delete("\n").strip
18
- end
19
- end
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './wiki'
4
+
5
+ # Fetches the lyrics from Genius (formerly known as Rap Genius)
6
+ # Lyrics are stored accessed via the URL schema https://genius.com/ARTIST-SONG-lyrics
7
+ # They are inside //div[starts-with(@class, "Lyrics__Container")]
8
+ class Genius < Wiki
9
+ def get_lyrics(artist, song, limit = 10)
10
+ artist = artist.tr(' ', '-').gsub(/('|`|´|’)/, '').gsub(/(?:\(?feat.*\)?)/, '').parameterize
11
+ song = song.tr(' ', '-').gsub(/('|`|´|’)/, '').gsub(/(?:\(?feat.*\)?)/, '').parameterize
12
+
13
+ res = fetch("https://genius.com/#{artist.downcase}-#{song.downcase}-lyrics", limit)
14
+ return nil unless res.is_a? Net::HTTPSuccess
15
+
16
+ lyrics = Nokogiri::HTML(res.body).xpath("//div[starts-with(@class, 'lyrics') or starts-with(@class, 'Lyrics__Container')]")
17
+ lyrics.inner_html.gsub('<br>', "\r").gsub(%r{</?[^>]+>}, '').delete("\n").strip
18
+ end
19
+ end
data/lib/wiki/wiki.rb CHANGED
@@ -1,37 +1,37 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_support/inflector'
4
- require 'net/http'
5
- require 'nokogiri'
6
-
7
- # Base class to fetch different lyrics sites
8
- class Wiki
9
- def fetch(uri_str, limit = 10)
10
- raise ArgumentError, 'The wiki site is redirecting too much, aborting...' if limit.zero?
11
-
12
- uri = prepare_url(uri_str)
13
- response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
14
- req = Net::HTTP::Get.new(uri.path)
15
- begin
16
- http.request(req)
17
- rescue EOFError
18
- fetch(uri_str, limit - 1)
19
- end
20
- end
21
- case response
22
- when Net::HTTPRedirection
23
- fetch(response['location'], limit - 1)
24
- else
25
- response
26
- end
27
- end
28
-
29
- def set_lyrics(mp3, lyrics)
30
- mp3.tag2.USLT = lyrics
31
- end
32
-
33
- def prepare_url(uri_str)
34
- bom_fixed_uri = uri_str.gsub('%EF%BB%BF', '') # fix BOM
35
- URI.parse(bom_fixed_uri)
36
- end
37
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/inflector'
4
+ require 'net/http'
5
+ require 'nokogiri'
6
+
7
+ # Base class to fetch different lyrics sites
8
+ class Wiki
9
+ def fetch(uri_str, limit = 10)
10
+ raise ArgumentError, 'The wiki site is redirecting too much, aborting...' if limit.zero?
11
+
12
+ uri = prepare_url(uri_str)
13
+ response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
14
+ req = Net::HTTP::Get.new(uri.path)
15
+ begin
16
+ http.request(req)
17
+ rescue EOFError
18
+ fetch(uri_str, limit - 1)
19
+ end
20
+ end
21
+ case response
22
+ when Net::HTTPRedirection
23
+ fetch(response['location'], limit - 1)
24
+ else
25
+ response
26
+ end
27
+ end
28
+
29
+ def set_lyrics(mp3, lyrics)
30
+ mp3.tag2.USLT = lyrics
31
+ end
32
+
33
+ def prepare_url(uri_str)
34
+ bom_fixed_uri = uri_str.gsub('%EF%BB%BF', '') # fix BOM
35
+ URI.parse(bom_fixed_uri)
36
+ end
37
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mp3lyrics
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Brust
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-09 00:00:00.000000000 Z
11
+ date: 2021-08-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: CLI for mp3 lyrics fetching. Uses ruby-mp3info and fetches different
14
14
  lyric wikis
@@ -25,7 +25,6 @@ files:
25
25
  - lib/mp3lyrics.rb
26
26
  - lib/wiki/azlyrics.rb
27
27
  - lib/wiki/genius.rb
28
- - lib/wiki/metrolyrics.rb
29
28
  - lib/wiki/wiki.rb
30
29
  homepage: https://github.com/timbru31/
31
30
  licenses:
@@ -34,7 +33,7 @@ metadata:
34
33
  bug_tracker_uri: https://github.com/timbru31/mp3lyrics/issues?q=is%3Aopen+is%3Aissue
35
34
  changelog_uri: https://github.com/timbru31/mp3lyrics/blob/master/CHANGELOG.md
36
35
  source_code_uri: https://github.com/timbru31/mp3lyrics/
37
- post_install_message:
36
+ post_install_message:
38
37
  rdoc_options: []
39
38
  require_paths:
40
39
  - lib
@@ -42,15 +41,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
42
41
  requirements:
43
42
  - - ">="
44
43
  - !ruby/object:Gem::Version
45
- version: 2.5.0
44
+ version: 2.6.0
46
45
  required_rubygems_version: !ruby/object:Gem::Requirement
47
46
  requirements:
48
47
  - - ">="
49
48
  - !ruby/object:Gem::Version
50
49
  version: '0'
51
50
  requirements: []
52
- rubygems_version: 3.1.2
53
- signing_key:
51
+ rubygems_version: 3.0.1
52
+ signing_key:
54
53
  specification_version: 4
55
54
  summary: CLI for mp3 lyrics fetching
56
55
  test_files: []
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './wiki'
4
-
5
- # Fetches the lyrics from MetroLyrics
6
- # Lyrics are stored accessed via the URL schema https://www.metrolyrics.com/SONG-lyrics-ARTIST
7
- # They are inside //*[@id="lyrics-body-text"]
8
- # There are hidden comments and script tags, that needs to be removed.
9
- class MetroLyrics < Wiki
10
- def get_lyrics(artist, song, limit = 10)
11
- artist = artist.tr(' ', '-').parameterize
12
- song = song.tr(' ', '-').gsub(/(?:\(?feat.*\)?)/, '').parameterize
13
-
14
- res = fetch("https://www.metrolyrics.com/#{song.downcase}-lyrics-#{artist.downcase}.html", limit)
15
- return nil unless res.is_a? Net::HTTPSuccess
16
-
17
- lyrics = Nokogiri::HTML(res.body).xpath('//*[@id="lyrics-body-text"]')
18
- lyrics.search('.driver-photos').remove
19
- lyrics.search('.driver-related').remove
20
- prettify_lyrics(lyrics.inner_html)
21
- end
22
-
23
- def prettify_lyrics(lyrics)
24
- lyrics = lyrics.gsub('<br>', "\r")
25
- lyrics = lyrics.gsub("</p>\n<p class=\"verse\">", "\r")
26
- lyrics = lyrics.gsub(%r{</?[^>]+>}, '')
27
- lyrics = lyrics.delete("\t")
28
- lyrics.delete("\n")
29
- end
30
- end