genius 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +21 -0
- data/README.md +147 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/genius.gemspec +31 -0
- data/lib/genius.rb +22 -0
- data/lib/genius/account.rb +41 -0
- data/lib/genius/annotation.rb +19 -0
- data/lib/genius/artist.rb +27 -0
- data/lib/genius/errors.rb +6 -0
- data/lib/genius/referent.rb +46 -0
- data/lib/genius/resource.rb +83 -0
- data/lib/genius/song.rb +67 -0
- data/lib/genius/version.rb +3 -0
- data/lib/genius/web_page.rb +33 -0
- metadata +177 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 99591718ba879a8d777a77d36774ba38902a5fc2
|
4
|
+
data.tar.gz: 611a7e528d428f6ff2d539f5163a9f7481aa7d11
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bb7182b7640f26ed6b7cde30fd3004968ce89ee4374b1355c5ca6aadfb5cca3f94f7e620928bb1885ee006b4978263087f84d0cbb8c8d46f9dd72170c9f1485a
|
7
|
+
data.tar.gz: 71f6e64bd982c826384c99a07ad5dbff0263ae3052ed8d145532001363baf99d5fc0f0531e44a15bbef9bd72f185aec5dfa2b4f5e0d8a3fcdcb836d6ddccd6e7
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
4
|
+
|
5
|
+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
|
6
|
+
|
7
|
+
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
8
|
+
|
9
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
|
10
|
+
|
11
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
12
|
+
|
13
|
+
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Tim Rogers
|
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
|
13
|
+
all 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
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
# Genius
|
2
|
+
|
3
|
+
![Genius logo](http://assets.rapgenius.com/images/apple-touch-icon.png?1432674944)
|
4
|
+
|
5
|
+
## What does this do?
|
6
|
+
|
7
|
+
It's a Ruby gem for accessing songs, artists and annotations on
|
8
|
+
[Genius](http://genius.com), based on the original [rapgenius](https://github.com/timrogers/rapgenius) gem.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Install the gem, and you're ready to go. Simply add the following to your Gemfile:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
gem "genius", "~> 0.1.0"
|
16
|
+
```
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
The best way to get a decent idea of the attributes available on `Song` and
|
21
|
+
the other objects is by checking out the API documentation at:
|
22
|
+
https://docs.genius.com
|
23
|
+
|
24
|
+
### Authentication
|
25
|
+
|
26
|
+
You'll need to set your access token before using the library. You can create a client and grab an access token from
|
27
|
+
<http://genius.com/api-clients>. You can then use that like so:
|
28
|
+
|
29
|
+
``` ruby
|
30
|
+
Genius.access_token = 'your-access-token'
|
31
|
+
```
|
32
|
+
|
33
|
+
At the moment, this library isn't set up for a traditional multi-user OAuth setup - despite the Genius API being [based](https://docs.genius.com/#/authentication-h1) on OAuth. It's built for the use case of just accessing the API with your account. This may change in future.
|
34
|
+
|
35
|
+
### Configuration
|
36
|
+
|
37
|
+
The library has one configuration option letting you choose between response formats between `plain`, `html` and `dom` - this is the [`text_format` option in the API](https://docs.genius.com/#/response-format-h1).
|
38
|
+
|
39
|
+
It'll default to `plain`, meaning you'll get back plain texts from API fields which return rich resources (artists' descriptions or annotations' contents). You can change this like so:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
Genius.text_format = "html"
|
43
|
+
```
|
44
|
+
|
45
|
+
### Songs
|
46
|
+
|
47
|
+
You can find a song by name, or using it's unique ID.
|
48
|
+
|
49
|
+
To find a song by name, use `Genius::Song.search` like this:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
songs = Genius::Song.search("The Hills") # Returns an array of Song objects
|
53
|
+
the_hills = songs.first
|
54
|
+
the_hills.title # => "The Hills"
|
55
|
+
the_hills.primary_artist.name # => "The Weeknd"
|
56
|
+
```
|
57
|
+
|
58
|
+
Alternatively, you can find a song by it's unique ID. They're not especially easy to find, but if you hover over the "PYONG!" button near the top of the page, you'll see the song's ID in the URL. Once you have an ID, you can load a song via the API:
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
song = Genius::Song.find(176872)
|
62
|
+
song.title # => "Versace"
|
63
|
+
song.primary_artist.name # => "Migos"
|
64
|
+
```
|
65
|
+
|
66
|
+
Once you've found the song you're looking for, there are plenty of other useful details you can access:
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
song.title
|
70
|
+
# => "Versace"
|
71
|
+
|
72
|
+
song.url
|
73
|
+
# => "http://genius.com/Migos-versace-lyrics"
|
74
|
+
|
75
|
+
song.pyongs_count
|
76
|
+
# => 198
|
77
|
+
|
78
|
+
song.description
|
79
|
+
# => "Released in June 2013, not only did they take the beat from Soulja Boy’s OMG part 2 but they absolutely killed it."
|
80
|
+
```
|
81
|
+
|
82
|
+
Check out [song.rb](https://github.com/timrogers/genius/blob/master/lib/genius/song.rb) or the [Genius API documentation](https://docs.genius.com/#songs-h2) for a full list of available fields.
|
83
|
+
|
84
|
+
### Artist
|
85
|
+
|
86
|
+
You can find artists from their songs (e.g. `Song#primary_artist`) and a couple of other places, or you can find them by their ID. As with songs, artists' IDs are pretty tricky to find, but you can get them by hovering over the "Follow" button on an artist's page on the Genius site.
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
the_hills = Genius::Song.find(727466)
|
90
|
+
the_weeknd = the_hills.primary_artist
|
91
|
+
|
92
|
+
# or...
|
93
|
+
|
94
|
+
the_weeknd = Genius::Artist.find(2358)
|
95
|
+
```
|
96
|
+
|
97
|
+
Once you've found the artist you're looking for, you can then query its attributes:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
artist.name
|
101
|
+
# => "The Weeknd"
|
102
|
+
|
103
|
+
artist.description
|
104
|
+
# => "Abel Tesfaye (otherwise known as The Weeknd)..."
|
105
|
+
|
106
|
+
# You can even find the artist's songs with the #songs method
|
107
|
+
artist.songs # => [<Genius::Song...]
|
108
|
+
```
|
109
|
+
|
110
|
+
Check out [artist.rb](https://github.com/timrogers/genius/blob/master/lib/genius/artist.rb) or the [Genius API documentation](https://docs.genius.com/#artists-h2) for a full list of available fields.
|
111
|
+
|
112
|
+
### Account
|
113
|
+
|
114
|
+
You can access your user profile with the `Genius::Account.me` method:
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
me = Genius::Account.me
|
118
|
+
```
|
119
|
+
|
120
|
+
From there, you can get access to a range of attributes:
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
me.name
|
124
|
+
# => "timrogers"
|
125
|
+
|
126
|
+
me.iq
|
127
|
+
# => 1691
|
128
|
+
```
|
129
|
+
|
130
|
+
Check out [account.rb](https://github.com/timrogers/genius/blob/master/lib/genius/account.rb) or the [Genius API documentation](https://docs.genius.com/#account-h2) for a full list of available fields.
|
131
|
+
|
132
|
+
|
133
|
+
## Contributing
|
134
|
+
|
135
|
+
If you'd like to contribute anything else, go ahead or better still, make an issue and we can talk it over and spec it out! A few quick tips:
|
136
|
+
|
137
|
+
* Don't update the version numbers before your pull request - I'll sort that part out for you.
|
138
|
+
* Make sure you write specs, then run them with `$ bundle exec rake`
|
139
|
+
* Update this README.md file so I, and users, know how your changes work
|
140
|
+
|
141
|
+
## Copyright
|
142
|
+
|
143
|
+
Copyright (c) 2015 Tim Rogers. See LICENSE for details.
|
144
|
+
|
145
|
+
## Get in touch
|
146
|
+
|
147
|
+
Any questions, thoughts or comments? Email me at <me@timrogers.co.uk> or create an issue.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "genius"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/genius.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'genius/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "genius"
|
8
|
+
spec.version = Genius::VERSION
|
9
|
+
spec.authors = ["Tim Rogers"]
|
10
|
+
spec.email = ["tim@gocardless.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{A Ruby client for the Genius API (<http://genius.com/developers>).}
|
13
|
+
spec.description = %q{A Ruby client for the Genius API (<http://genius.com/developers>).}
|
14
|
+
spec.homepage = "https://github.com/timrogers/genius"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
spec.add_development_dependency "rspec", "~> 3.3.0"
|
25
|
+
spec.add_development_dependency "rspec-its", "~> 1.1.0"
|
26
|
+
spec.add_development_dependency "mocha", "~> 0.14.0"
|
27
|
+
spec.add_development_dependency "webmock", "~> 1.11.0"
|
28
|
+
spec.add_development_dependency "vcr", "~> 2.5.0"
|
29
|
+
|
30
|
+
spec.add_runtime_dependency "httparty", "~> 0.11.0"
|
31
|
+
end
|
data/lib/genius.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require "genius/version"
|
2
|
+
require "genius/errors"
|
3
|
+
require "genius/resource"
|
4
|
+
require "genius/artist"
|
5
|
+
require "genius/song"
|
6
|
+
require "genius/web_page"
|
7
|
+
require "genius/account"
|
8
|
+
require "genius/annotation"
|
9
|
+
require "genius/referent"
|
10
|
+
|
11
|
+
module Genius
|
12
|
+
class << self
|
13
|
+
attr_accessor :access_token
|
14
|
+
attr_writer :text_format
|
15
|
+
|
16
|
+
PLAIN_TEXT_FORMAT = "plain".freeze
|
17
|
+
|
18
|
+
def text_format
|
19
|
+
@text_format || PLAIN_TEXT_FORMAT
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Genius
|
2
|
+
class Account < Resource
|
3
|
+
resource_name "user"
|
4
|
+
|
5
|
+
attr_reader :unread_messages_count, :artist, :role_for_display, :iq,
|
6
|
+
:unread_main_activity_inbox_count, :avatar, :about_me,
|
7
|
+
:tracking_paths, :id, :current_user_metadata, :login, :name
|
8
|
+
|
9
|
+
def parse_resource!
|
10
|
+
@unread_messages_count = resource["unread_messages_count"]
|
11
|
+
@artist = resource["artist"]
|
12
|
+
@role_for_display = resource["role_for_display"]
|
13
|
+
@unread_main_activity_inbox_count = resource["unread_main_activity_inbox_count"]
|
14
|
+
@avatar = resource["avatar"]
|
15
|
+
@about_me = formatted_attribute("about_me")
|
16
|
+
@identities = resource["identities"]
|
17
|
+
@name = resource["name"]
|
18
|
+
@tracking_paths = resource["tracking_paths"]
|
19
|
+
@id = resource["id"]
|
20
|
+
@current_user_metadata = resource["current_user_metadata"]
|
21
|
+
@iq = resource["iq"]
|
22
|
+
@login = resource["login"]
|
23
|
+
end
|
24
|
+
|
25
|
+
def reload
|
26
|
+
raise NotReloadableError, "An Account cannot be reloaded"
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.find(id, params: {}, headers: {})
|
30
|
+
raise NotImplementedError, "An Account cannot be loaded by its ID in the public API"
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.me(params = {})
|
34
|
+
headers = default_headers.merge(params.delete(:headers) || {})
|
35
|
+
params = default_params.merge(params)
|
36
|
+
|
37
|
+
new(http_get("/account", query: params, headers: headers),
|
38
|
+
text_format: params[:text_format])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Genius
|
2
|
+
class Annotation < Resource
|
3
|
+
attr_reader :verified_by, :share_url, :body, :votes_total, :comment_count,
|
4
|
+
:state, :authors, :current_user_metadata, :id, :url
|
5
|
+
|
6
|
+
def parse_resource!
|
7
|
+
@verified_by = Account.from_hash(resource["verified_by"])
|
8
|
+
@share_url = resource["share_url"]
|
9
|
+
@body = formatted_attribute("body")
|
10
|
+
@votes_total = resource["votes_total"]
|
11
|
+
@comment_count = resource["comment_count"]
|
12
|
+
@authors = resource["authors"]
|
13
|
+
@state = resource["state"]
|
14
|
+
@current_user_metadata = resource["current_user_metadata"]
|
15
|
+
@id = resource["id"]
|
16
|
+
@url = resource["url"]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Genius
|
2
|
+
class Artist < Resource
|
3
|
+
attr_reader :name, :image_url, :id, :url, :user, :tracking_paths, :description
|
4
|
+
|
5
|
+
def parse_resource!
|
6
|
+
@id = resource["id"]
|
7
|
+
@name = resource["name"]
|
8
|
+
@image_url = resource["image_url"]
|
9
|
+
@url = resource["url"]
|
10
|
+
@user = Account.from_hash(resource["user"])
|
11
|
+
@description = formatted_attribute("description")
|
12
|
+
@tracking_paths = resource["tracking_paths"]
|
13
|
+
end
|
14
|
+
|
15
|
+
def songs(params: {}, headers: {})
|
16
|
+
headers = self.class.default_headers.merge(headers)
|
17
|
+
params = self.class.default_params.merge(id: id).merge(params)
|
18
|
+
|
19
|
+
response = self.class.http_get("/#{resource_name}s/#{id}/songs", query: params,
|
20
|
+
headers: headers)
|
21
|
+
|
22
|
+
response.parsed_response["response"]["songs"].map do |song|
|
23
|
+
Song.from_hash(song, text_format: text_format)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Genius
|
2
|
+
class Referent < Resource
|
3
|
+
attr_reader :id, :url, :song_id, :annotator_id, :fragment, :range, :classification,
|
4
|
+
:annotatable, :annotations
|
5
|
+
|
6
|
+
def self.find(id, params: {}, headers: {})
|
7
|
+
raise NotImplementedError, "A Referent cannot be loaded by its ID in the public API"
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.where(params = {})
|
11
|
+
headers = default_headers.merge(params.delete(:headers) || {})
|
12
|
+
params = default_params.merge(params)
|
13
|
+
|
14
|
+
response = http_get("/#{resource_name}s/", query: params, headers: headers)
|
15
|
+
|
16
|
+
response.parsed_response["response"]["referents"].map do |referent|
|
17
|
+
self.from_hash(referent, text_format: params[:text_format])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def reload
|
22
|
+
raise NotReloadableError, "A Referent cannot be reloaded"
|
23
|
+
end
|
24
|
+
|
25
|
+
def parse_resource!
|
26
|
+
@url = resource["url"]
|
27
|
+
|
28
|
+
@annotations = resource["annotations"].map do |annotation|
|
29
|
+
Annotation.from_hash(annotation)
|
30
|
+
end
|
31
|
+
|
32
|
+
@song_id = resource["song_id"]
|
33
|
+
@annotator_id = resource["annotator_id"]
|
34
|
+
@fragment = resource["fragment"]
|
35
|
+
@range = resource["range"]
|
36
|
+
@classification = resource["classification"]
|
37
|
+
@annotatable = resource["annotatable"]
|
38
|
+
@id = resource["id"]
|
39
|
+
end
|
40
|
+
|
41
|
+
def song
|
42
|
+
return nil unless song_id
|
43
|
+
Song.find(song_id)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
module Genius
|
4
|
+
class Resource
|
5
|
+
include HTTParty
|
6
|
+
|
7
|
+
base_uri 'https://api.genius.com'
|
8
|
+
format :json
|
9
|
+
|
10
|
+
attr_reader :raw_response, :resource
|
11
|
+
|
12
|
+
def self.resource_name(resource_name = nil)
|
13
|
+
if resource_name
|
14
|
+
@resource_name = resource_name
|
15
|
+
end
|
16
|
+
|
17
|
+
@resource_name || name.downcase.split("::").last
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.find(id, params: {}, headers: {})
|
21
|
+
params = default_params.merge(params)
|
22
|
+
headers = default_headers.merge(headers)
|
23
|
+
|
24
|
+
new(http_get("/#{resource_name}s/#{id}", query: params, headers: headers),
|
25
|
+
text_format: params[:text_format])
|
26
|
+
end
|
27
|
+
|
28
|
+
def reload
|
29
|
+
self.class.find(id, params: { text_format: text_format })
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.http_get(path, query: {}, headers: {})
|
33
|
+
response = get(path, query: query, headers: headers)
|
34
|
+
|
35
|
+
case response.code
|
36
|
+
when 404 then raise NotFoundError
|
37
|
+
when 401, 403 then raise AuthenticationError
|
38
|
+
else response
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.default_params
|
43
|
+
{
|
44
|
+
text_format: Genius.text_format
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.default_headers
|
49
|
+
{
|
50
|
+
'Authorization' => "Bearer #{Genius.access_token}",
|
51
|
+
'User-Agent' => "genius.rb v#{Genius::VERSION}"
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
def initialize(response, text_format: Genius.text_format, resource: nil)
|
56
|
+
@raw_response = response
|
57
|
+
@resource = resource || response.parsed_response["response"][resource_name]
|
58
|
+
@text_format = text_format
|
59
|
+
|
60
|
+
parse_resource!
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.from_hash(attributes, text_format: Genius.text_format)
|
64
|
+
return nil unless attributes
|
65
|
+
new(nil, text_format: text_format, resource: attributes)
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
attr_reader :text_format
|
71
|
+
|
72
|
+
def resource_name
|
73
|
+
self.class.resource_name
|
74
|
+
end
|
75
|
+
|
76
|
+
# Fetches an attribute that uses the API's Text Formatting feature, which means that
|
77
|
+
# the attribute will be nested inside a key naming the format (plain/html/dom)
|
78
|
+
def formatted_attribute(attribute)
|
79
|
+
return nil unless resource[attribute]
|
80
|
+
resource[attribute][text_format]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/lib/genius/song.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
module Genius
|
2
|
+
class Song < Resource
|
3
|
+
attr_reader :id, :url, :title, :media, :description_annotation, :annotation_count,
|
4
|
+
:tracking_paths, :description, :bop_url, :header_image_url,
|
5
|
+
:updated_by_human_at, :lyrics_updated_at, :pyongs_count, :stats,
|
6
|
+
:current_user_metadata, :verified_annotations_by
|
7
|
+
|
8
|
+
def self.search(query, params: {}, headers: {})
|
9
|
+
headers = default_headers.merge(headers)
|
10
|
+
params = default_params.merge(q: query).merge(params)
|
11
|
+
|
12
|
+
response = http_get("/search", query: params, headers: headers)
|
13
|
+
|
14
|
+
response["response"]["hits"].map do |hit|
|
15
|
+
self.from_hash(hit["result"], text_format: params[:text_format])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse_resource!
|
20
|
+
@id = resource["id"]
|
21
|
+
@url = resource["url"]
|
22
|
+
@title = resource["title"]
|
23
|
+
@media = resource["media"]
|
24
|
+
@description_annotation = resource["description_annotation"]
|
25
|
+
@annotation_count = resource["annotation_count"]
|
26
|
+
@tracking_paths = resource["tracking_paths"]
|
27
|
+
@description = formatted_attribute("description")
|
28
|
+
@bop_url = resource["bop_url"]
|
29
|
+
@header_image_url = resource["header_image_url"]
|
30
|
+
|
31
|
+
if resource["updated_by_human_at"]
|
32
|
+
@updated_by_human_at = Time.at(resource["updated_by_human_at"])
|
33
|
+
end
|
34
|
+
|
35
|
+
if resource["lyrics_updated_at"]
|
36
|
+
@lyrics_updated_at = Time.at(resource["lyrics_updated_at"])
|
37
|
+
end
|
38
|
+
|
39
|
+
@pyongs_count = resource["pyongs_count"]
|
40
|
+
@stats = resource["stats"]
|
41
|
+
@current_user_metadata = resource["current_user_metadata"]
|
42
|
+
@verified_annotations_by = resource["verified_annotations_by"]
|
43
|
+
end
|
44
|
+
|
45
|
+
def featured_artists
|
46
|
+
@featured_artists ||= resource["featured_artists"].map do |artist|
|
47
|
+
Artist.from_hash(artist)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def producer_artists
|
52
|
+
@featured_artists ||= resource["producer_artists"].map do |artist|
|
53
|
+
Artist.from_hash(artist)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def writer_artists
|
58
|
+
@featured_artists ||= resource["writer_artists"].map do |artist|
|
59
|
+
Artist.from_hash(artist)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def primary_artist
|
64
|
+
@primary_artist ||= Artist.from_hash(resource["primary_artist"])
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Genius
|
2
|
+
class WebPage < Resource
|
3
|
+
resource_name "web_page"
|
4
|
+
|
5
|
+
attr_reader :id, :url, :title, :normalized_url, :domain, :share_url, :annotation_count
|
6
|
+
|
7
|
+
def parse_resource!
|
8
|
+
@id = resource["id"]
|
9
|
+
@url = resource["url"]
|
10
|
+
@title = resource["title"]
|
11
|
+
@normalized_url = resource["normalized_url"]
|
12
|
+
@domain = resource["domain"]
|
13
|
+
@share_url = resource["share_url"]
|
14
|
+
@annotation_count = resource["annotation_count"]
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.find(id, params: {}, headers: {})
|
18
|
+
raise NotImplementedError, "A Web Page cannot be loaded by its ID in the public API"
|
19
|
+
end
|
20
|
+
|
21
|
+
def reload
|
22
|
+
raise NotReloadableError, "A Web Page cannot be reloaded"
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.lookup(params = {})
|
26
|
+
headers = default_headers.merge(params.delete(:headers) || {})
|
27
|
+
params = default_params.merge(params)
|
28
|
+
|
29
|
+
new(http_get("/#{resource_name}s/lookup", query: params, headers: headers),
|
30
|
+
text_format: params[:text_format])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: genius
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tim Rogers
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-06-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.10'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.3.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.3.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-its
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.1.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.1.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mocha
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.14.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.14.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: webmock
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.11.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.11.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: vcr
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 2.5.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 2.5.0
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: httparty
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.11.0
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 0.11.0
|
125
|
+
description: A Ruby client for the Genius API (<http://genius.com/developers>).
|
126
|
+
email:
|
127
|
+
- tim@gocardless.com
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- ".rspec"
|
134
|
+
- ".travis.yml"
|
135
|
+
- CODE_OF_CONDUCT.md
|
136
|
+
- Gemfile
|
137
|
+
- LICENSE.txt
|
138
|
+
- README.md
|
139
|
+
- Rakefile
|
140
|
+
- bin/console
|
141
|
+
- bin/setup
|
142
|
+
- genius.gemspec
|
143
|
+
- lib/genius.rb
|
144
|
+
- lib/genius/account.rb
|
145
|
+
- lib/genius/annotation.rb
|
146
|
+
- lib/genius/artist.rb
|
147
|
+
- lib/genius/errors.rb
|
148
|
+
- lib/genius/referent.rb
|
149
|
+
- lib/genius/resource.rb
|
150
|
+
- lib/genius/song.rb
|
151
|
+
- lib/genius/version.rb
|
152
|
+
- lib/genius/web_page.rb
|
153
|
+
homepage: https://github.com/timrogers/genius
|
154
|
+
licenses:
|
155
|
+
- MIT
|
156
|
+
metadata: {}
|
157
|
+
post_install_message:
|
158
|
+
rdoc_options: []
|
159
|
+
require_paths:
|
160
|
+
- lib
|
161
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - ">="
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
167
|
+
requirements:
|
168
|
+
- - ">="
|
169
|
+
- !ruby/object:Gem::Version
|
170
|
+
version: '0'
|
171
|
+
requirements: []
|
172
|
+
rubyforge_project:
|
173
|
+
rubygems_version: 2.4.7
|
174
|
+
signing_key:
|
175
|
+
specification_version: 4
|
176
|
+
summary: A Ruby client for the Genius API (<http://genius.com/developers>).
|
177
|
+
test_files: []
|