rapgenius 1.1.0 → 1.1.1

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
  SHA1:
3
- metadata.gz: b1640ae0f92fe785852dc5299ea740898c45e9ee
4
- data.tar.gz: 87ca2d685134998e741566bf36fb84b2be5b28b2
3
+ metadata.gz: ce3e59fc79a8548ed3c7a686fb05ff36cbc59f23
4
+ data.tar.gz: 9539c9a6a3bbb748294ee5f0b159cd3afe24aec8
5
5
  SHA512:
6
- metadata.gz: 94087dcf9563c729aa0a125e12c6ddb155c02497977c96ec6a349a8d1b7efeaa00fb565e6e0a725d5c74f5cf22b4a95bff9aade34bf7f04a1d23f1497a594d9f
7
- data.tar.gz: 8ea1e7629947d329f0e07bb1537086fd757aa1adbfa2df7b59f91abe75cf2f0df42d1cd4ce9796b3ee6806985aa918a38607862d6324b6c583683be411c1640f
6
+ metadata.gz: b62978657e0ba5d0f829b49ef32ded2507da2d14294390717647be42d5d055d7ea8c5279f0525094d1a3bacdbfeaba19e9653785ef2f7fd92d78e856a8eb0cc4
7
+ data.tar.gz: 427cf0a58cba5426dd101475b3895e620943980a36e79ad56b1a24e323ab418301f15bbb5d633a5889b893f9da79f0c2e666c6cdd7f834cd678341e784b79dc6
data/CHANGELOG.md CHANGED
@@ -44,3 +44,9 @@ __v1.0.5__ (12th January 2015)
44
44
  __v1.1.0__ (5th June 2015)
45
45
 
46
46
  * Authenticate using access tokens for the official [Genius API](https://docs.genius.com)
47
+
48
+ __v1.1.1__ (15th June 2015)
49
+
50
+ * Raise a `RapGenius::MissingAccessTokenError` when making a request if no access token has been set
51
+ * Handle authentication failures by raising a `RapGenius::AuthenticationError`
52
+ * Fix search functionality (e.g. `RapGenius.search`) so that your access token is actually sent
data/README.md CHANGED
@@ -7,29 +7,25 @@
7
7
  It's a Ruby gem for accessing songs, artists and annotations on
8
8
  [Genius](http://genius.com).
9
9
 
10
- In pre-1.0.0 versions, this gem used Nokogiri to scrape Genius' pages,
11
- but no more thanks to the new [Genius API](https://docs.genius.com), which this
12
- gem makes use of.
13
-
14
10
  ## Installation
15
11
 
16
12
  Install the gem, and you're ready to go. Simply add the following to your
17
13
  Gemfile:
18
14
 
19
15
  ```ruby
20
- gem "rapgenius", "~> 1.1.0"
16
+ gem "rapgenius", "~> 1.1.1"
21
17
  ```
22
18
 
23
19
  ## Usage
24
20
 
25
- __The best way to get a decent idea of the attributes available on `Song` and
21
+ The best way to get a decent idea of the attributes available on `Song` and
26
22
  the other objects is by checking out the API documentation at:
27
23
  https://docs.genius.com
28
24
 
29
25
  ### Authenticating
30
26
 
31
27
  You can create a client and grab an access token from
32
- http://genius.com/api-clients
28
+ <http://genius.com/api-clients>.
33
29
 
34
30
  From there, you can also generate a client access token and use it like so:
35
31
 
@@ -37,6 +33,8 @@ From there, you can also generate a client access token and use it like so:
37
33
  RapGenius::Client.access_token = 'your-access-token'
38
34
  ```
39
35
 
36
+ You'll need to have set your token in order to be able to make requests.
37
+
40
38
  ### Searching
41
39
 
42
40
  You can search for songs by various fields. All of these
@@ -55,7 +53,7 @@ in the API.
55
53
 
56
54
  ### Songs
57
55
 
58
- Songs on Rap Genius have unique identifiers. They're not especially
56
+ Songs on Genius have unique identifiers. They're not especially
59
57
  easy to find, but if you hover over the "pyong" button near the top of the page,
60
58
  you'll see the song's ID in the URL. Once you have an ID, you can load a
61
59
  song via the API:
data/lib/rapgenius.rb CHANGED
@@ -9,8 +9,10 @@ require 'rapgenius/exceptions'
9
9
  module RapGenius
10
10
  extend RapGenius::Client
11
11
 
12
- def self.search(query, options={})
13
- response = Client::HTTPClient.get("/search", query: {q: query}.merge(options))
12
+ def self.search(query, options = {})
13
+ response = fetch(build_api_url("/search"), { q: query }.merge(options))
14
+
15
+
14
16
 
15
17
  response["response"]["hits"].map do |song|
16
18
  result = song["result"]
@@ -39,4 +41,4 @@ module RapGenius
39
41
  def self.search_by_lyrics(query)
40
42
  self.search(query, field: "lyrics")
41
43
  end
42
- end
44
+ end
@@ -21,7 +21,7 @@ module RapGenius
21
21
 
22
22
  def url=(url)
23
23
  unless url =~ /^https?:\/\//
24
- @url = BASE_URL + url.gsub(/^\//, '')
24
+ @url = build_api_url(url)
25
25
  else
26
26
  @url = url
27
27
  end
@@ -31,23 +31,35 @@ module RapGenius
31
31
  @document ||= fetch(@url)
32
32
  end
33
33
 
34
- def fetch(url)
34
+ def fetch(url, params = {})
35
+ unless RapGenius::Client.access_token
36
+ raise MissingAccessTokenError, "You must specify an access token by setting " \
37
+ "RapGenius::Client.access_token"
38
+ end
39
+
35
40
  response = HTTPClient.get(url, query: {
36
41
  text_format: "#{DOM_TEXT_FORMAT},#{PLAIN_TEXT_FORMAT}"
37
- }, headers: {
42
+ }.merge(params), headers: {
38
43
  'Authorization' => "Bearer #{RapGenius::Client.access_token}",
39
44
  'User-Agent' => "rapgenius.rb v#{RapGenius::VERSION}"
40
45
  })
41
46
 
42
- if response.code != 200
43
- if response.code == 404
44
- raise RapGenius::NotFoundError
45
- else
46
- raise RapGenius::Error, "Received a #{response.code} HTTP response"
47
- end
47
+ case response.code
48
+ when 404
49
+ raise RapGenius::NotFoundError
50
+ when 401
51
+ raise RapGenius::AuthenticationError
52
+ when 200
53
+ return response.parsed_response
54
+ else
55
+ raise RapGenius::Error, "Received a #{response.code} HTTP response"
48
56
  end
57
+ end
58
+
59
+ private
49
60
 
50
- response.parsed_response
61
+ def build_api_url(path)
62
+ BASE_URL + path.gsub(/^\//, '')
51
63
  end
52
64
  end
53
65
  end
@@ -3,6 +3,11 @@ module RapGenius
3
3
  end
4
4
 
5
5
  class NotFoundError < Error
6
+ end
7
+
8
+ class AuthenticationError < Error
9
+ end
6
10
 
11
+ class MissingAccessTokenError < Error
7
12
  end
8
- end
13
+ end
@@ -1,3 +1,3 @@
1
1
  module RapGenius
2
- VERSION = "1.1.0"
2
+ VERSION = "1.1.1"
3
3
  end
@@ -1,37 +1,38 @@
1
1
  require 'spec_helper'
2
2
 
3
- module RapGenius
4
- describe Artist do
5
- context "given Drake", vcr: { cassette_name: "artist-130" } do
6
- subject(:artist) { described_class.find(130) }
3
+ describe RapGenius::Artist do
4
+ let(:access_token) { 'my-access-token' }
5
+ before { RapGenius::Client.access_token = access_token }
7
6
 
8
- its(:url) { should eq "http://genius.com/artists/Drake" }
9
- its(:name) { should eq "Drake" }
10
- its(:image) { should eq "http://images.rapgenius.com/6e996fe91d484c626f1b36686cb27d7c.450x253x70.gif" }
11
- its(:description) { should include "Drake is part of a generation of new rappers" }
7
+ context "Drake", vcr: { cassette_name: "artist-130" } do
8
+ subject(:artist) { described_class.find(130) }
12
9
 
13
- context "#songs" do
14
- subject { artist.songs }
10
+ its(:url) { should eq "http://genius.com/artists/Drake" }
11
+ its(:name) { should eq "Drake" }
12
+ its(:image) { should eq "http://images.rapgenius.com/6e996fe91d484c626f1b36686cb27d7c.450x253x70.gif" }
13
+ its(:description) { should include "Drake is part of a generation of new rappers" }
15
14
 
16
- its(:count) { should eq 20 }
17
- its(:last) { should be_a Song }
18
- its("last.title") { should eq "Amen" }
15
+ context "#songs" do
16
+ subject { artist.songs }
17
+
18
+ its(:count) { should eq 20 }
19
+ its(:last) { should be_a RapGenius::Song }
20
+ its("last.title") { should eq "Amen" }
19
21
 
20
- context "pagination" do
21
- subject { artist.songs(page: 3) }
22
+ context "pagination" do
23
+ subject { artist.songs(page: 3) }
22
24
 
23
- its(:last) { should be_a Song }
24
- its(:count) { should eq 20 }
25
- its("last.title") { should eq "Champion" }
26
- end
25
+ its(:last) { should be_a RapGenius::Song }
26
+ its(:count) { should eq 20 }
27
+ its("last.title") { should eq "Champion" }
27
28
  end
29
+ end
28
30
 
29
- context "a non-existent artist ID" do
30
- subject(:artist) { described_class.find("bahahaha") }
31
+ context "a non-existent artist ID" do
32
+ subject(:artist) { described_class.find("bahahaha") }
31
33
 
32
- it "raises an exception" do
33
- expect { artist }.to raise_exception
34
- end
34
+ it "raises an exception" do
35
+ expect { artist }.to raise_exception
35
36
  end
36
37
  end
37
38
  end
@@ -8,50 +8,67 @@ class ClientTester
8
8
  include RapGenius::Client
9
9
  end
10
10
 
11
- module RapGenius
12
- describe Client do
11
+ describe RapGenius::Client do
12
+ let(:client) { ClientTester.new }
13
13
 
14
- let(:client) { ClientTester.new }
14
+ let(:access_token) { 'my-access-token' }
15
+ before { RapGenius::Client.access_token = access_token }
15
16
 
16
- describe "#url=" do
17
- it "forms the URL with the base URL, if the current path is relative" do
18
- client.url = "foobar"
19
- client.url.should include RapGenius::Client::BASE_URL
20
- end
17
+ describe "#url=" do
18
+ it "forms the URL with the base URL, if the current path is relative" do
19
+ client.url = "foobar"
20
+ client.url.should include RapGenius::Client::BASE_URL
21
+ end
21
22
 
22
- it "leaves the URL as it is if already complete" do
23
- client.url = "http://foobar.com/baz"
24
- client.url.should eq "http://foobar.com/baz"
25
- end
23
+ it "leaves the URL as it is if already complete" do
24
+ client.url = "http://foobar.com/baz"
25
+ client.url.should eq "http://foobar.com/baz"
26
+ end
27
+ end
28
+
29
+ describe '.access_token=' do
30
+ before do
31
+ stub_request(:get, 'https://api.rapgenius.com/hello?text_format=dom,plain').
32
+ with(headers: {'Authorization' => "Bearer #{access_token}",
33
+ 'User-Agent' => "rapgenius.rb v#{RapGenius::VERSION}"})
34
+ end
35
+
36
+ it 'should send the header' do
37
+ client.fetch('/hello')
38
+ assert_requested(:get, 'https://api.rapgenius.com/hello?text_format=dom,plain')
26
39
  end
40
+ end
41
+
42
+ describe "#document" do
43
+ before { client.url = "http://foo.bar" }
27
44
 
28
- describe '.access_token=' do
29
- let(:access_token) { 'my-access-token' }
45
+ context "no access token" do
46
+ let(:access_token) { nil }
47
+
48
+ it "raises a MissingAccessToken error" do
49
+ expect { client.document }.to raise_error(RapGenius::MissingAccessTokenError)
50
+ end
51
+ end
30
52
 
53
+ context "with a 404 response" do
31
54
  before do
32
- RapGenius::Client.access_token = access_token
33
- stub_request(:get, 'https://api.rapgenius.com/hello?text_format=dom,plain').
34
- with(headers: {'Authorization' => "Bearer #{access_token}", 'User-Agent' => "rapgenius.rb v#{RapGenius::VERSION}"})
55
+ stub_request(:get, "http://foo.bar").with(query: { text_format: "dom,plain" }).
56
+ to_return({body: '', status: 404})
35
57
  end
36
58
 
37
- it 'should send the header' do
38
- client.fetch('/hello')
39
- assert_requested(:get, 'https://api.rapgenius.com/hello?text_format=dom,plain')
59
+ it "raises a ScraperError" do
60
+ expect { client.document }.to raise_error(RapGenius::NotFoundError)
40
61
  end
41
62
  end
42
63
 
43
- describe "#document" do
44
- before { client.url = "http://foo.bar" }
45
-
46
- context "with a failed request" do
47
- before do
48
- stub_request(:get, "http://foo.bar").with(query: { text_format: "dom,plain" }).
49
- to_return({body: '', status: 404})
50
- end
64
+ context "with an authentication failure" do
65
+ before do
66
+ stub_request(:get, "http://foo.bar").with(query: { text_format: "dom,plain" }).
67
+ to_return({body: '', status: 401})
68
+ end
51
69
 
52
- it "raises a ScraperError" do
53
- expect { client.document }.to raise_error(RapGenius::Error)
54
- end
70
+ it "raises a ScraperError" do
71
+ expect { client.document }.to raise_error(RapGenius::AuthenticationError)
55
72
  end
56
73
  end
57
74
  end
@@ -1,23 +1,23 @@
1
1
  require 'spec_helper'
2
2
 
3
- module RapGenius
4
- describe Line, vcr: { cassette_name: "line-2638695" } do
3
+ describe RapGenius::Line, vcr: { cassette_name: "line-2638695" } do
4
+ let(:line) { described_class.find("2638695") }
5
+ subject { line }
5
6
 
6
- let(:line) { described_class.find("2638695") }
7
- subject { line }
7
+ let(:access_token) { 'my-access-token' }
8
+ before { RapGenius::Client.access_token = access_token }
8
9
 
9
- its(:id) { should eq "2638695" }
10
- its(:song) { should be_a Song }
11
- its(:lyric) { should eq "Versace, Versace, Medusa head on me like I'm 'luminati" }
12
- its("explanations.first") { should include "Versace’s logo is the head of Medusa" }
13
- its(:explanations) { should eq line.annotations }
10
+ its(:id) { should eq "2638695" }
11
+ its(:song) { should be_a RapGenius::Song }
12
+ its(:lyric) { should eq "Versace, Versace, Medusa head on me like I'm 'luminati" }
13
+ its("explanations.first") { should include "Versace’s logo is the head of Medusa" }
14
+ its(:explanations) { should eq line.annotations }
14
15
 
15
- context "a non-existent referent ID" do
16
- let(:line) { described_class.find("bahahaha") }
16
+ context "a non-existent referent ID" do
17
+ let(:line) { described_class.find("bahahaha") }
17
18
 
18
- it "raises an exception" do
19
- expect { line }.to raise_exception
20
- end
19
+ it "raises an exception" do
20
+ expect { line }.to raise_exception
21
21
  end
22
22
  end
23
23
  end
@@ -1,19 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
- module RapGenius
4
- describe Media do
3
+ describe RapGenius::Media do
4
+ subject(:media) { described_class.new(type: "foo", url: "foo", provider: "foo") }
5
5
 
6
- subject(:media) do
7
- Media.new(
8
- type: "foo",
9
- url: "foo",
10
- provider: "foo"
11
- )
12
- end
6
+ its(:type) { should eq "foo" }
7
+ its(:url) { should eq "foo" }
8
+ its(:provider) { should eq "foo" }
13
9
 
14
- its(:type) { should eq "foo" }
15
- its(:url) { should eq "foo" }
16
- its(:provider) { should eq "foo" }
17
-
18
- end
19
- end
10
+ end
@@ -1,64 +1,65 @@
1
1
  require 'spec_helper'
2
2
 
3
- module RapGenius
4
- describe Song do
5
- context "given Migos's Versace", vcr: { cassette_name: "song-176872" } do
6
- subject(:song) { described_class.find(176872) }
3
+ describe RapGenius::Song do
4
+ context "Migos's Versace", vcr: { cassette_name: "song-176872" } do
5
+ subject(:song) { described_class.find(176872) }
7
6
 
8
- its(:url) { should eq "http://genius.com/Migos-versace-lyrics" }
9
- its(:title) { should eq "Versace" }
7
+ let(:access_token) { 'my-access-token' }
8
+ before { RapGenius::Client.access_token = access_token }
10
9
 
11
- its(:description) { should include "the song blew up" }
10
+ its(:url) { should eq "http://genius.com/Migos-versace-lyrics" }
11
+ its(:title) { should eq "Versace" }
12
12
 
13
- context "#artist" do
14
- subject { song.artist }
15
- it { should be_a Artist }
16
- its(:name) { should eq "Migos" }
17
- end
13
+ its(:description) { should include "the song blew up" }
18
14
 
19
- context "#featured_artists" do
20
- subject { song.featured_artists }
21
- its(:length) { should eq 1 }
22
- its("first.name") { should eq "Drake" }
23
- its(:first) { should be_a Artist }
24
- end
15
+ context "#artist" do
16
+ subject { song.artist }
17
+ it { should be_a RapGenius::Artist }
18
+ its(:name) { should eq "Migos" }
19
+ end
25
20
 
26
- context "#producer_artists" do
27
- subject { song.producer_artists }
28
- its(:length) { should eq 1 }
29
- its("first.name") { should eq "Zaytoven" }
30
- its(:first) { should be_a Artist }
31
- end
21
+ context "#featured_artists" do
22
+ subject { song.featured_artists }
23
+ its(:length) { should eq 1 }
24
+ its("first.name") { should eq "Drake" }
25
+ its(:first) { should be_a RapGenius::Artist }
26
+ end
32
27
 
33
- context "#media" do
34
- subject { song.media }
35
- its(:length) { should eq 2 }
36
- its(:first) { should be_a Media }
37
- its("first.provider") { should eq "soundcloud" }
38
- end
28
+ context "#producer_artists" do
29
+ subject { song.producer_artists }
30
+ its(:length) { should eq 1 }
31
+ its("first.name") { should eq "Zaytoven" }
32
+ its(:first) { should be_a RapGenius::Artist }
33
+ end
39
34
 
40
- context "#lines" do
41
- subject { song.lines }
42
- its(:count) { should eq 81 }
43
- its(:first) { should be_a Line }
44
- its("first.id") { should eq "1983907" }
45
- its("first.lyric") { should eq "[Verse 1: Drake]" }
46
- its("first.explanations.first") { should include "Versace used his verse in this runway show" }
47
- end
35
+ context "#media" do
36
+ subject { song.media }
37
+ its(:length) { should eq 2 }
38
+ its(:first) { should be_a RapGenius::Media }
39
+ its("first.provider") { should eq "soundcloud" }
40
+ end
41
+
42
+ context "#lines" do
43
+ subject { song.lines }
44
+ its(:count) { should eq 81 }
45
+ its(:first) { should be_a RapGenius::Line }
46
+ its("first.id") { should eq "1983907" }
47
+ its("first.lyric") { should eq "[Verse 1: Drake]" }
48
+ its("first.explanations.first") { should include "Versace used his verse in this runway show" }
49
+ end
48
50
 
49
- its(:images) { should include "http://s3.amazonaws.com/rapgenius/Zaytoven_1-7-2011.jpg" }
50
- its(:pyongs) { should eq 166 }
51
- its(:hot?) { should eq false }
52
- its(:views) { should eq 2159953 }
53
- its(:concurrent_viewers) { should be_nil }
51
+ its(:images) { should include "http://s3.amazonaws.com/rapgenius/Zaytoven_1-7-2011.jpg" }
52
+ its(:pyongs) { should eq 166 }
53
+ its(:hot?) { should eq false }
54
+ its(:views) { should eq 2159953 }
55
+ its(:concurrent_viewers) { should be_nil }
54
56
 
55
57
 
56
- context "a non-existent song ID" do
57
- subject(:song) { described_class.find("bahahaha") }
58
+ context "a non-existent song ID" do
59
+ subject(:song) { described_class.find("bahahaha") }
58
60
 
59
- it "raises an exception" do
60
- expect { song }.to raise_exception
61
- end
61
+ it "raises an exception" do
62
+ expect { song }.to raise_exception
62
63
  end
63
64
  end
64
65
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rapgenius
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Rogers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-05 00:00:00.000000000 Z
11
+ date: 2015-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -102,9 +102,6 @@ files:
102
102
  - lib/rapgenius/media.rb
103
103
  - lib/rapgenius/song.rb
104
104
  - lib/rapgenius/version.rb
105
- - pkg/rapgenius-0.0.1.gem
106
- - pkg/rapgenius-0.0.2.gem
107
- - pkg/rapgenius-0.0.3.gem
108
105
  - rapgenius.gemspec
109
106
  - spec/rapgenius/artist_spec.rb
110
107
  - spec/rapgenius/client_spec.rb