rapgenius 1.1.0 → 1.1.1
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 +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +6 -8
- data/lib/rapgenius.rb +5 -3
- data/lib/rapgenius/client.rb +22 -10
- data/lib/rapgenius/exceptions.rb +6 -1
- data/lib/rapgenius/version.rb +1 -1
- data/spec/rapgenius/artist_spec.rb +25 -24
- data/spec/rapgenius/client_spec.rb +48 -31
- data/spec/rapgenius/line_spec.rb +14 -14
- data/spec/rapgenius/media_spec.rb +6 -15
- data/spec/rapgenius/song_spec.rb +49 -48
- metadata +2 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ce3e59fc79a8548ed3c7a686fb05ff36cbc59f23
|
4
|
+
data.tar.gz: 9539c9a6a3bbb748294ee5f0b159cd3afe24aec8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
16
|
+
gem "rapgenius", "~> 1.1.1"
|
21
17
|
```
|
22
18
|
|
23
19
|
## Usage
|
24
20
|
|
25
|
-
|
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
|
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 =
|
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
|
data/lib/rapgenius/client.rb
CHANGED
@@ -21,7 +21,7 @@ module RapGenius
|
|
21
21
|
|
22
22
|
def url=(url)
|
23
23
|
unless url =~ /^https?:\/\//
|
24
|
-
@url =
|
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
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
61
|
+
def build_api_url(path)
|
62
|
+
BASE_URL + path.gsub(/^\//, '')
|
51
63
|
end
|
52
64
|
end
|
53
65
|
end
|
data/lib/rapgenius/exceptions.rb
CHANGED
data/lib/rapgenius/version.rb
CHANGED
@@ -1,37 +1,38 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|
-
|
9
|
-
|
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
|
-
|
14
|
-
|
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
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
21
|
-
|
22
|
+
context "pagination" do
|
23
|
+
subject { artist.songs(page: 3) }
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
30
|
-
|
31
|
+
context "a non-existent artist ID" do
|
32
|
+
subject(:artist) { described_class.find("bahahaha") }
|
31
33
|
|
32
|
-
|
33
|
-
|
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
|
-
|
12
|
-
|
11
|
+
describe RapGenius::Client do
|
12
|
+
let(:client) { ClientTester.new }
|
13
13
|
|
14
|
-
|
14
|
+
let(:access_token) { 'my-access-token' }
|
15
|
+
before { RapGenius::Client.access_token = access_token }
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
29
|
-
let(: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
|
-
|
33
|
-
|
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
|
38
|
-
client.
|
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
|
-
|
44
|
-
before
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
53
|
-
|
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
|
data/spec/rapgenius/line_spec.rb
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
describe RapGenius::Line, vcr: { cassette_name: "line-2638695" } do
|
4
|
+
let(:line) { described_class.find("2638695") }
|
5
|
+
subject { line }
|
5
6
|
|
6
|
-
|
7
|
-
|
7
|
+
let(:access_token) { 'my-access-token' }
|
8
|
+
before { RapGenius::Client.access_token = access_token }
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
16
|
-
|
16
|
+
context "a non-existent referent ID" do
|
17
|
+
let(:line) { described_class.find("bahahaha") }
|
17
18
|
|
18
|
-
|
19
|
-
|
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
|
-
|
4
|
-
|
3
|
+
describe RapGenius::Media do
|
4
|
+
subject(:media) { described_class.new(type: "foo", url: "foo", provider: "foo") }
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
-
|
15
|
-
its(:url) { should eq "foo" }
|
16
|
-
its(:provider) { should eq "foo" }
|
17
|
-
|
18
|
-
end
|
19
|
-
end
|
10
|
+
end
|
data/spec/rapgenius/song_spec.rb
CHANGED
@@ -1,64 +1,65 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|
-
|
9
|
-
|
7
|
+
let(:access_token) { 'my-access-token' }
|
8
|
+
before { RapGenius::Client.access_token = access_token }
|
10
9
|
|
11
|
-
|
10
|
+
its(:url) { should eq "http://genius.com/Migos-versace-lyrics" }
|
11
|
+
its(:title) { should eq "Versace" }
|
12
12
|
|
13
|
-
|
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
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
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
|
-
|
57
|
-
|
58
|
+
context "a non-existent song ID" do
|
59
|
+
subject(:song) { described_class.find("bahahaha") }
|
58
60
|
|
59
|
-
|
60
|
-
|
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.
|
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-
|
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
|