blue_conductor 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -21,7 +21,7 @@ Or install it yourself as:
21
21
  Usage is easy. Call .song_for on the BlueConductor object and pass in a band name and song title.
22
22
 
23
23
  ```ruby
24
- BlueConductor.song_for('The Dear Hunter', 'The Church and the Dime')
24
+ BlueConductor.song_for('Van Halen', 'Panama')
25
25
  ```
26
26
 
27
27
 
@@ -30,9 +30,25 @@ Which will return a BlueConductor::Song object containing the following fields
30
30
  * `title`
31
31
  * `band`
32
32
  * `lyrics`
33
+ * `album`
34
+
35
+ Calling title or band will return the information that you originally passed in to the BlueConductor. Calling .lyrics will return the lyrics of that song as provided by songlyrics.com. If the lyrics to a song you entered in either do not exist, are not on the songlyrics website or if there was a spelling error, then calling .lyrics will return a string saying 'Sorry we do not have the requested lyrics'. Calling .album will return the album that the song is on.
36
+
37
+ BlueConductor has a second method called .record_for. Simply pass in the band name and the name of your favorite album and it will return an array of song objects containing the information of each song.
38
+
39
+ ```ruby
40
+ BlueConductor.record_for('Van Halen', '1984')
41
+ ```
42
+
43
+ Now, this method returns a BlueConductor::Producer objects that has the following fields on it
44
+
45
+ * `title`
46
+ * `band`
47
+ * `songs`
48
+ * `image`
33
49
  * `error`
34
50
 
35
- Calling title or band will return the information that you originally passed in to the BlueConductor. Calling .lyrics will return the lyrics of that song as provided by azlyrics.com. If the lyrics to a song you entered in either do not exist, are not on the azlyrics website or if there was a spelling error, then calling .lyrics will return a nil object and an error message will be placed in the .error field.
51
+ Title and band are obviously set to the values that you pass in. The .songs field though returns an array of BlueConductor::Song objects each with specific information about each song on the album provided. .image contains the image source of the album art and the error field only contains a string if the album/band you provided is not on songlyrics.com.
36
52
 
37
53
  ##CLI
38
54
 
@@ -6,10 +6,10 @@ require "blue_conductor/version"
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "blue_conductor"
8
8
  gem.version = BlueConductor::VERSION
9
- gem.authors = ["Alex Williams", "Craig Williams"]
9
+ gem.authors = ["Alex Williams"]
10
10
  gem.email = ["alexwilliams4@me.com"]
11
- gem.description = %q{Scrapes azLyrics.com for song lyrics}
12
- gem.summary = %q{azlyrics.com scraper}
11
+ gem.description = %q{Scrapes songlyrics.com for song lyrics}
12
+ gem.summary = %q{songlyrics.com scraper}
13
13
  gem.homepage = ""
14
14
 
15
15
  gem.files = `git ls-files`.split($/)
@@ -1,25 +1,39 @@
1
1
  require 'open-uri'
2
2
  require 'nokogiri'
3
+ require 'net/http'
3
4
 
4
5
  require_relative 'blue_conductor/version'
5
6
  require_relative 'blue_conductor/band_manager'
6
- require_relative 'blue_conductor/sanitizer'
7
- require_relative 'blue_conductor/http/request'
8
- require_relative 'blue_conductor/http/response'
9
- require_relative 'blue_conductor/http/url_generator'
7
+ require_relative 'blue_conductor/producer'
10
8
  require_relative 'blue_conductor/song'
11
9
 
10
+ require_relative 'blue_conductor/http/request'
11
+
12
+ require_relative 'blue_conductor/http/song/sanitizer'
13
+ require_relative 'blue_conductor/http/song/response'
14
+ require_relative 'blue_conductor/http/song/url_generator'
15
+
16
+ require_relative 'blue_conductor/http/record/sanitizer'
17
+ require_relative 'blue_conductor/http/record/response'
18
+ require_relative 'blue_conductor/http/record/url_generator'
19
+
20
+
12
21
  module BlueConductor
13
22
  def self.song_for(band, song)
14
23
  manager = BlueConductor::BandManager.new(band, song)
15
- manager.url_generator = BlueConductor::HTTP::UrlGenerator
24
+ manager.url_generator = BlueConductor::HTTP::Song::UrlGenerator
16
25
  manager.request = BlueConductor::HTTP::Request
17
- manager.parser = BlueConductor::HTTP::Response
26
+ manager.parser = BlueConductor::HTTP::Song::Response
18
27
 
19
28
  manager.song!
20
29
  end
21
30
 
22
31
  def self.record_for(band, record_title)
23
- # BlueConductor::BandManager.new(band, song).record!
32
+ producer = BlueConductor::Producer.new(band, record_title)
33
+ producer.url_generator = BlueConductor::HTTP::Record::UrlGenerator
34
+ producer.request = BlueConductor::HTTP::Request
35
+ producer.parser = BlueConductor::HTTP::Record::Response
36
+
37
+ producer.record!
24
38
  end
25
39
  end
@@ -1,12 +1,12 @@
1
1
  module BlueConductor
2
2
  class BandManager
3
- attr_reader :band, :song, :data, :error
3
+ attr_reader :band, :song, :data, :album
4
4
  attr_accessor :url_generator, :request, :parser
5
5
 
6
6
  def initialize(band, song)
7
7
  @band = band
8
8
  @song = song
9
- @error = ''
9
+ @album = ''
10
10
  @data = ''
11
11
  end
12
12
 
@@ -14,11 +14,8 @@ module BlueConductor
14
14
  url = url_generator.generate(self)
15
15
  html = request.fetch(url)
16
16
 
17
- if html
18
- @data = parser.parse(html)
19
- else
20
- @error = 'The band/song does not exist || there was a spelling error'
21
- end
17
+ @data = parser.data(html)
18
+ @album = parser.album(html)
22
19
 
23
20
  BlueConductor::Song.new(self)
24
21
  end
@@ -0,0 +1,19 @@
1
+ module BlueConductor
2
+ module HTTP
3
+ module Record
4
+ class Response
5
+
6
+ def self.parse(html)
7
+ doc = Nokogiri::HTML(html)
8
+ doc.css('.rightcol .tracklist td a').map(&:text)
9
+ end
10
+
11
+ def self.parse_image(html)
12
+ doc = Nokogiri::HTML(html)
13
+ doc.css('.leftcol img')[0]['src']
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+
@@ -0,0 +1,25 @@
1
+ module BlueConductor
2
+ module HTTP
3
+ module Record
4
+ class Sanitizer
5
+ UNWANTED_CHARS = %r([^a-zA-Z0-9])
6
+
7
+ attr_reader :band, :title
8
+
9
+ def initialize(producer)
10
+ @band = producer.band
11
+ @title = producer.title
12
+ end
13
+
14
+ def clean
15
+ @band = strip(@band)
16
+ @title = strip(@title)
17
+ end
18
+
19
+ def strip(str)
20
+ str.downcase.gsub(UNWANTED_CHARS, "-")
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,16 @@
1
+ module BlueConductor
2
+ module HTTP
3
+ module Record
4
+ class UrlGenerator
5
+ BASE_URI = "http://www.songlyrics.com/"
6
+
7
+ def self.generate(producer)
8
+ sanitizer = BlueConductor::HTTP::Record::Sanitizer.new(producer)
9
+ sanitizer.clean
10
+
11
+ "#{BASE_URI}#{sanitizer.band}/#{sanitizer.title}/"
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -3,12 +3,18 @@ module BlueConductor
3
3
  class Request
4
4
 
5
5
  def self.fetch(url)
6
- begin
7
- open(url)
8
- rescue OpenURI::HTTPError
9
- nil
6
+ response = Net::HTTP.get_response(URI.parse(url))
7
+
8
+ if response.code == '301'
9
+ parse(response['location'])
10
+ else
11
+ parse(url)
10
12
  end
11
13
  end
14
+
15
+ def self.parse(location)
16
+ Net::HTTP.get(URI.parse(location))
17
+ end
12
18
  end
13
19
  end
14
20
  end
@@ -0,0 +1,22 @@
1
+ module BlueConductor
2
+ module HTTP
3
+ module Song
4
+ class Response
5
+
6
+ def self.data(html)
7
+ doc = Nokogiri::HTML(html)
8
+ doc.css('p#songLyricsDiv').text
9
+ end
10
+
11
+ def self.album(html)
12
+ doc = Nokogiri::HTML(html)
13
+ begin
14
+ doc.css('div.pagetitle a')[1].text
15
+ rescue
16
+ 'Album Missing'
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ module BlueConductor
2
+ module HTTP
3
+ module Song
4
+ class Sanitizer
5
+ UNWANTED_CHARS = %r([^a-zA-Z0-9])
6
+
7
+ attr_reader :band, :song
8
+
9
+ def initialize(manager)
10
+ @band = manager.band
11
+ @song = manager.song
12
+ end
13
+
14
+ def clean
15
+ @band = strip(@band)
16
+ @song = strip(@song)
17
+ end
18
+
19
+ def strip(str)
20
+ str.downcase.gsub(UNWANTED_CHARS, "-")
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,16 @@
1
+ module BlueConductor
2
+ module HTTP
3
+ module Song
4
+ class UrlGenerator
5
+ BASE_URI = "http://www.songlyrics.com/"
6
+
7
+ def self.generate(manager)
8
+ sanitizer = BlueConductor::HTTP::Song::Sanitizer.new(manager)
9
+ sanitizer.clean
10
+
11
+ "#{BASE_URI}#{sanitizer.band}/#{sanitizer.song}-lyrics/"
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,32 @@
1
+ module BlueConductor
2
+ class Producer
3
+ attr_reader :band, :title, :songs, :image, :error
4
+ attr_accessor :url_generator, :request, :parser
5
+
6
+ def initialize(band, record_title)
7
+ @band = band
8
+ @title = record_title
9
+ @songs = nil
10
+ @image = ''
11
+ @error = ''
12
+ end
13
+
14
+ def record!
15
+ url = url_generator.generate(self)
16
+ html = request.fetch(url)
17
+ tracklist = parser.parse(html)
18
+
19
+ if tracklist.nil? || tracklist.empty?
20
+ @error = 'The album requested is not available || there was a spelling error'
21
+ else
22
+ @image = parser.parse_image(html)
23
+
24
+ @songs = tracklist.map do |song|
25
+ BlueConductor.song_for(@band, song)
26
+ end
27
+ end
28
+
29
+ self
30
+ end
31
+ end
32
+ end
@@ -1,12 +1,12 @@
1
1
  module BlueConductor
2
2
  class Song
3
- attr_accessor :title, :band, :lyrics, :error
3
+ attr_accessor :title, :band, :album, :lyrics
4
4
 
5
5
  def initialize(manager)
6
6
  @title = manager.song
7
7
  @band = manager.band
8
+ @album = manager.album
8
9
  @lyrics = manager.data
9
- @error = manager.error
10
10
  end
11
11
  end
12
12
  end
@@ -1,3 +1,3 @@
1
1
  module BlueConductor
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
data/lyric CHANGED
@@ -15,6 +15,7 @@ track = BlueConductor.song_for(band, song)
15
15
  puts '*'*100
16
16
  puts "Band: #{track.band}"
17
17
  puts "Title: #{track.title}"
18
+ puts "Album: #{track.album}"
18
19
  puts "Lyrics:"
19
20
  puts '-'*100
20
21
  puts track.lyrics
@@ -3,21 +3,20 @@ require 'spec_helper'
3
3
  describe BlueConductor::BandManager do
4
4
  subject { BlueConductor::BandManager.new(band, song) }
5
5
 
6
- let(:band) { 'The Dear Hunter' }
7
- let(:song) { 'Red Hands' }
8
- let(:data) { "Even if you never strayed from me\nI'd question your fidelity" }
9
- let(:manager_mock) { mock(band: band, song: song, data: data) }
10
- let(:song_object) { BlueConductor::Song.new(manager_mock) }
6
+ let(:band) { 'Van Halen' }
7
+ let(:song) { 'Unchained' }
8
+ let(:data) { "Change, nothin' stays the same" }
9
+ let(:album) { 'Fair Warning' }
11
10
 
12
11
  before do
13
- subject.url_generator = BlueConductor::HTTP::UrlGenerator
12
+ subject.url_generator = BlueConductor::HTTP::Song::UrlGenerator
14
13
  subject.request = BlueConductor::HTTP::Request
15
- subject.parser = BlueConductor::HTTP::Response
14
+ subject.parser = BlueConductor::HTTP::Song::Response
16
15
  end
17
16
 
18
17
  describe '.new' do
19
18
  it 'creates an instance of itself' do
20
- subject.band.should == band
19
+ subject.band.should == band
21
20
  subject.song.should == song
22
21
  end
23
22
  end
@@ -31,6 +30,7 @@ describe BlueConductor::BandManager do
31
30
 
32
31
  @track.title.should == song
33
32
  @track.band.should == band
33
+ @track.album.should == album
34
34
  @track.lyrics.should =~ /#{data}/
35
35
  end
36
36
  end
@@ -44,7 +44,8 @@ describe BlueConductor::BandManager do
44
44
  @track = subject.song!
45
45
  end
46
46
 
47
- @track.error.should =~ /does not exist/
47
+ @track.lyrics.should =~ /Sorry, we have no/
48
+ @track.album.should =~ /Album Missing/
48
49
  @track.title.should == song
49
50
  @track.band.should == band
50
51
  end
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ describe BlueConductor::Producer do
4
+ subject { BlueConductor::Producer.new(band, record) }
5
+
6
+ let(:band) { 'Van Halen' }
7
+ let(:record) { 'Fair Warning' }
8
+ let(:track_list) { ['Dirty Movies', 'Hear About It Later', 'One Foot Out The Door',
9
+ 'Push Comes to Shove', "Sinner's Swing", 'So This Is Love?',
10
+ 'Sunday Afternoon In The Park', 'Unchained', 'Mean Street'
11
+ ]}
12
+
13
+ before do
14
+ subject.url_generator = BlueConductor::HTTP::Record::UrlGenerator
15
+ subject.request = BlueConductor::HTTP::Request
16
+ subject.parser = BlueConductor::HTTP::Record::Response
17
+ end
18
+
19
+ describe '.new' do
20
+ it 'creates an instance of itself' do
21
+ subject.band.should == band
22
+ subject.title.should == record
23
+ end
24
+ end
25
+
26
+ describe '#record' do
27
+ context 'when the band and record are valid' do
28
+ it 'returns an array of songs' do
29
+ VCR.use_cassette 'full_album' do
30
+ @record = subject.record!
31
+ end
32
+
33
+ @record.songs.map(&:title).should == track_list
34
+ @record.image.should == 'http://cdn1.songlyricscom.netdna-cdn.com/album_covers/202/van-halen-fair-warning/van-halen-6832-fair-warning.jpg'
35
+ end
36
+ end
37
+
38
+ context 'when the band and record are invalid' do
39
+
40
+ let(:band) { 'asdf' }
41
+ let(:record) { 'asdf'}
42
+
43
+ it 'raises an error' do
44
+ VCR.use_cassette 'invalid_album' do
45
+ @record = subject.record!
46
+ end
47
+
48
+ @record.error.should == 'The album requested is not available || there was a spelling error'
49
+ @record.band.should == band
50
+ @record.title.should == record
51
+ @record.songs.should == nil
52
+ @record.image.should == ''
53
+ end
54
+ end
55
+ end
56
+ end