genius_fixed 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 590e1b590fa8778243a391fc22c2433989b8338df70c8c6cd76a3d3837a3a1f3
4
+ data.tar.gz: 4c99574b8a7898ed147caa87fadf449d6f1112f473daa4b9b78be684cb10d288
5
+ SHA512:
6
+ metadata.gz: dd57a105e4689f40e01dbe84555cf00a8f47324e7d26e8959a82f86291a08170b19ea9ebaf3c953dce113a445156ead68e2334a3675dd14ecfbe45b1a01892ec
7
+ data.tar.gz: b052f957c632b2f408e6aa5823462386b9790e469c53355b684bb1f8208186d8cce7dcb38c32320d0b110731aa0aaaf304357ef04d4da6d5700ecf8bb8660b38
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,56 @@
1
+ # For all options see https://github.com/bbatsov/rubocop/tree/master/config
2
+
3
+ inherit_from: .rubocop_todo.yml
4
+
5
+ AllCops:
6
+ RunRailsCops: false
7
+ Include:
8
+ - Rakefile
9
+ Exclude:
10
+ - .*/**/*
11
+
12
+ # Limit lines to 80 characters.
13
+ LineLength:
14
+ Max: 90
15
+
16
+ ClassLength:
17
+ Enabled: false
18
+
19
+ ModuleLength:
20
+ Enabled: false
21
+
22
+ # Avoid methods longer than 30 lines of code
23
+ MethodLength:
24
+ CountComments: false # count full line comments?
25
+ Max: 87
26
+
27
+ # Avoid single-line methods.
28
+ SingleLineMethods:
29
+ AllowIfMethodIsEmpty: true
30
+
31
+ StringLiterals:
32
+ Enabled: false
33
+
34
+ GlobalVars:
35
+ Enabled: false # We use them Redis + StatsD (though maybe we shouldn't?)
36
+
37
+ # Wants underscores in all large numbers. Pain in the ass for things like
38
+ # unix timestamps.
39
+ NumericLiterals:
40
+ Enabled: false
41
+
42
+ # Wants you to use the same argument names for every reduce. This seems kinda
43
+ # naff compared to naming them semantically
44
+ SingleLineBlockParams:
45
+ Enabled: false
46
+
47
+ Style/SignalException:
48
+ EnforcedStyle: 'only_raise'
49
+
50
+ # Use trailing rather than leading dots on multi-line call chains
51
+ Style/DotPosition:
52
+ EnforcedStyle: trailing
53
+
54
+ # Allow non-ASCII characters (e.g. £) in comments
55
+ Style/AsciiComments:
56
+ Enabled: false
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,117 @@
1
+ # This configuration was generated by `rubocop --auto-gen-config`
2
+ # on 2015-06-06 22:47:07 +0100 using RuboCop version 0.32.0.
3
+ # The point is for the user to remove these configuration records
4
+ # one by one as the offenses are removed from the code base.
5
+ # Note that changes in the inspected code, or installation of new
6
+ # versions of RuboCop, may require this file to be generated again.
7
+
8
+ # Offense count: 50
9
+ # Cop supports --auto-correct.
10
+ Lint/UnusedBlockArgument:
11
+ Enabled: false
12
+
13
+ # Offense count: 187
14
+ Metrics/AbcSize:
15
+ Max: 61
16
+
17
+ # Offense count: 26
18
+ Metrics/CyclomaticComplexity:
19
+ Max: 10
20
+
21
+ # Offense count: 11
22
+ Metrics/PerceivedComplexity:
23
+ Max: 10
24
+
25
+ # Offense count: 12
26
+ Style/AccessorMethodName:
27
+ Enabled: false
28
+
29
+ # Offense count: 164
30
+ # Cop supports --auto-correct.
31
+ # Configuration parameters: EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle, SupportedLastArgumentHashStyles.
32
+ Style/AlignHash:
33
+ Enabled: false
34
+
35
+ # Offense count: 3
36
+ # Cop supports --auto-correct.
37
+ # Configuration parameters: EnforcedStyle, SupportedStyles, ProceduralMethods, FunctionalMethods, IgnoredMethods.
38
+ Style/BlockDelimiters:
39
+ Enabled: false
40
+
41
+ # Offense count: 128
42
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
43
+ Style/ClassAndModuleChildren:
44
+ Enabled: false
45
+
46
+ # Offense count: 21
47
+ # Cop supports --auto-correct.
48
+ Style/ClosingParenthesisIndentation:
49
+ Enabled: false
50
+
51
+ # Offense count: 13
52
+ # Cop supports --auto-correct.
53
+ # Configuration parameters: Keywords.
54
+ Style/CommentAnnotation:
55
+ Enabled: false
56
+
57
+ # Offense count: 743
58
+ Style/Documentation:
59
+ Enabled: false
60
+
61
+ # Offense count: 9
62
+ Style/DoubleNegation:
63
+ Enabled: false
64
+
65
+ # Offense count: 109
66
+ # Configuration parameters: MinBodyLength.
67
+ Style/GuardClause:
68
+ Enabled: false
69
+
70
+ # Offense count: 48
71
+ # Cop supports --auto-correct.
72
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
73
+ Style/IndentHash:
74
+ Enabled: false
75
+
76
+ # Offense count: 70
77
+ # Cop supports --auto-correct.
78
+ Style/Lambda:
79
+ Enabled: false
80
+
81
+ # Offense count: 577
82
+ # Cop supports --auto-correct.
83
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
84
+ Style/MultilineOperationIndentation:
85
+ Enabled: false
86
+
87
+ # Offense count: 21
88
+ # Configuration parameters: NamePrefix, NamePrefixBlacklist.
89
+ Style/PredicateName:
90
+ Enabled: false
91
+
92
+ # Offense count: 4
93
+ # Cop supports --auto-correct.
94
+ Style/Proc:
95
+ Enabled: false
96
+
97
+ # Offense count: 173
98
+ # Cop supports --auto-correct.
99
+ Style/RedundantSelf:
100
+ Enabled: false
101
+
102
+ # Offense count: 28
103
+ # Cop supports --auto-correct.
104
+ Style/SingleSpaceBeforeFirstArg:
105
+ Enabled: false
106
+
107
+ # Offense count: 3
108
+ # Cop supports --auto-correct.
109
+ # Configuration parameters: MultiSpaceAllowedForOperators.
110
+ Style/SpaceAroundOperators:
111
+ Enabled: false
112
+
113
+ # Offense count: 5
114
+ # Cop supports --auto-correct.
115
+ # Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, Whitelist.
116
+ Style/TrivialAccessors:
117
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.0
4
+ - 2.0.0
5
+ before_install: gem install bundler -v 1.10.4
6
+ script:
7
+ - bundle exec rubocop
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ ## 0.1.1 (3rd July 2015)
2
+
3
+ * Support for new Annotations APIs
4
+
5
+ ## 0.1.0 (26th June 2015)
6
+
7
+ * Initial release
@@ -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
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
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,153 @@
1
+ # Genius
2
+
3
+ [![Build Status](https://travis-ci.org/timrogers/genius.svg)](https://travis-ci.org/timrogers/genius)
4
+ [![Gem Version](https://badge.fury.io/rb/genius.svg)](http://badge.fury.io/rb/genius)
5
+
6
+ ![Genius logo](http://assets.rapgenius.com/images/apple-touch-icon.png?1432674944)
7
+
8
+ ## What does this do?
9
+
10
+ It's a Ruby gem for accessing songs, artists and annotations on
11
+ [Genius](http://genius.com), based on the original [rapgenius](https://github.com/timrogers/rapgenius) gem.
12
+
13
+ ## Installation
14
+
15
+ Install the gem, and you're ready to go. Simply add the following to your Gemfile:
16
+
17
+ ```ruby
18
+ gem "genius", "~> 0.1.1"
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ The best way to get a decent idea of the attributes available on `Song` and
24
+ the other objects is by checking out the API documentation at:
25
+ https://docs.genius.com
26
+
27
+ ### Authentication
28
+
29
+ You'll need to set your access token before using the library. You can create a client and grab an access token from
30
+ <http://genius.com/api-clients>. You can then use that like so:
31
+
32
+ ``` ruby
33
+ Genius.access_token = 'your-access-token'
34
+ ```
35
+
36
+ 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.
37
+
38
+ ### Configuration
39
+
40
+ 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).
41
+
42
+ 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:
43
+
44
+ ```ruby
45
+ Genius.text_format = "html"
46
+ ```
47
+
48
+ ### Songs
49
+
50
+ You can find a song by name, or using it's unique ID.
51
+
52
+ To find a song by name, use `Genius::Song.search` like this:
53
+
54
+ ```ruby
55
+ songs = Genius::Song.search("The Hills") # Returns an array of Song objects
56
+ the_hills = songs.first
57
+ the_hills.title # => "The Hills"
58
+ the_hills.primary_artist.name # => "The Weeknd"
59
+ ```
60
+
61
+ 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:
62
+
63
+ ```ruby
64
+ song = Genius::Song.find(176872)
65
+ song.title # => "Versace"
66
+ song.primary_artist.name # => "Migos"
67
+ ```
68
+
69
+ Once you've found the song you're looking for, there are plenty of other useful details you can access:
70
+
71
+ ```ruby
72
+ song.title
73
+ # => "Versace"
74
+
75
+ song.url
76
+ # => "http://genius.com/Migos-versace-lyrics"
77
+
78
+ song.pyongs_count
79
+ # => 198
80
+
81
+ song.description
82
+ # => "Released in June 2013, not only did they take the beat from Soulja Boy’s OMG part 2 but they absolutely killed it."
83
+ ```
84
+
85
+ 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.
86
+
87
+ ### Artist
88
+
89
+ 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.
90
+
91
+ ```ruby
92
+ the_hills = Genius::Song.find(727466)
93
+ the_weeknd = the_hills.primary_artist
94
+
95
+ # or...
96
+
97
+ the_weeknd = Genius::Artist.find(2358)
98
+ ```
99
+
100
+ Once you've found the artist you're looking for, you can then query its attributes:
101
+
102
+ ```ruby
103
+ artist.name
104
+ # => "The Weeknd"
105
+
106
+ artist.description
107
+ # => "Abel Tesfaye (otherwise known as The Weeknd)..."
108
+
109
+ # You can even find the artist's songs with the #songs method
110
+ artist.songs # => [<Genius::Song...]
111
+ ```
112
+
113
+ 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.
114
+
115
+ ### Account
116
+
117
+ You can access your user profile with the `Genius::Account.me` method:
118
+
119
+ ```ruby
120
+ me = Genius::Account.me
121
+ ```
122
+
123
+ From there, you can get access to a range of attributes:
124
+
125
+ ```ruby
126
+ me.name
127
+ # => "timrogers"
128
+
129
+ me.iq
130
+ # => 1691
131
+ ```
132
+
133
+ 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.
134
+
135
+ ### Other resources
136
+
137
+ The API library also supports working with web pages, annotations and referents in the API. See the [Genius API documentation](https://docs.genius.com/#account-h2) and the library [source](https://github.com/timrogers/genius/tree/master/lib/genius).
138
+
139
+ ## Contributing
140
+
141
+ 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:
142
+
143
+ * Don't update the version numbers before your pull request - I'll sort that part out for you.
144
+ * Make sure you write specs, then run them with `$ bundle exec rake`. When running tests, you'll want to set `GENIUS_ACCESS_TOKEN` so your requests can be authenticated - don't worry, your token will be filtered out of the `vcr` cassettes.
145
+ * Update this README.md file so I, and users, know how your changes work
146
+
147
+ ## Copyright
148
+
149
+ Copyright (c) 2015 Tim Rogers. See LICENSE for details.
150
+
151
+ ## Get in touch
152
+
153
+ Any questions, thoughts or comments? Email me at <me@timrogers.co.uk> or create an issue.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
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
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/genius.gemspec ADDED
@@ -0,0 +1,32 @@
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_fixed"
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>). [Forked version, from https://github.com/Homologist/genius.git — none of the credit goes to me (jltml)!]}
14
+ spec.homepage = "https://github.com/Homologist/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
+ spec.add_development_dependency "rubocop", "~> 0.31.0"
30
+
31
+ spec.add_runtime_dependency "httparty", ">= 0.14.0"
32
+ 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,42 @@
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(*)
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,
38
+ headers: headers),
39
+ text_format: params[:text_format])
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,58 @@
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
+
19
+ def update!(body = {})
20
+ response = self.class.http_put("/annotations/#{id}",
21
+ body: body,
22
+ headers: self.class.default_headers)
23
+
24
+ self.class.new(response, text_format: text_format)
25
+ end
26
+
27
+ def destroy!
28
+ self.class.http_delete("/annotations/#{id}", headers: self.class.default_headers)
29
+
30
+ true
31
+ end
32
+
33
+ def upvote!
34
+ self.class.http_put("/annotations/#{id}/upvote",
35
+ headers: self.class.default_headers)
36
+
37
+ true
38
+ end
39
+
40
+ def unvote!
41
+ self.class.http_put("/annotations/#{id}/unvote",
42
+ headers: self.class.default_headers)
43
+
44
+ true
45
+ end
46
+
47
+ def downvote!
48
+ self.class.http_put("/annotations/#{id}/downvote",
49
+ headers: self.class.default_headers)
50
+
51
+ true
52
+ end
53
+
54
+ def self.create!(body = {})
55
+ new(http_post("/annotations", body: body, headers: default_headers))
56
+ end
57
+ end
58
+ 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,7 @@
1
+ module Genius
2
+ class Error < StandardError; end
3
+ class NotFoundError < Error; end
4
+ class AuthenticationError < Error; end
5
+ class MissingAccessTokenError < Error; end
6
+ class NotReloadableError < Error; end
7
+ 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(*)
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,100 @@
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
+ @resource_name = resource_name if resource_name
14
+ @resource_name || name.downcase.split("::").last
15
+ end
16
+
17
+ def self.find(id, params: {}, headers: {})
18
+ params = default_params.merge(params)
19
+ headers = default_headers.merge(headers)
20
+
21
+ new(http_get("/#{resource_name}s/#{id}",
22
+ query: params,
23
+ headers: headers),
24
+ text_format: params[:text_format])
25
+ end
26
+
27
+ def reload
28
+ self.class.find(id, params: { text_format: text_format })
29
+ end
30
+
31
+ def self.http_get(path, query: {}, headers: {})
32
+ response = get(path, query: query, headers: headers)
33
+ handle_response(response)
34
+ end
35
+
36
+ def self.http_post(path, body: {}, headers: {})
37
+ response = post(path, body: body, headers: headers)
38
+ handle_response(response)
39
+ end
40
+
41
+ def self.http_put(path, body: {}, headers: {})
42
+ response = put(path, body: body, headers: headers)
43
+ handle_response(response)
44
+ end
45
+
46
+ def self.http_delete(path, headers: {})
47
+ response = delete(path, headers: headers)
48
+ handle_response(response)
49
+ end
50
+
51
+ def self.handle_response(response)
52
+ case response.code
53
+ when 404 then raise NotFoundError
54
+ when 401, 403 then raise AuthenticationError
55
+ else response
56
+ end
57
+ end
58
+
59
+ def self.default_params
60
+ {
61
+ text_format: Genius.text_format
62
+ }
63
+ end
64
+
65
+ def self.default_headers
66
+ {
67
+ 'Authorization' => "Bearer #{Genius.access_token}",
68
+ 'User-Agent' => "genius.rb v#{Genius::VERSION}"
69
+ }
70
+ end
71
+
72
+ def initialize(response, text_format: Genius.text_format, resource: nil)
73
+ @raw_response = response
74
+ @resource = resource || response.parsed_response["response"][resource_name]
75
+ @text_format = text_format
76
+
77
+ parse_resource!
78
+ end
79
+
80
+ def self.from_hash(attributes, text_format: Genius.text_format)
81
+ return nil unless attributes
82
+ new(nil, text_format: text_format, resource: attributes)
83
+ end
84
+
85
+ private
86
+
87
+ attr_reader :text_format
88
+
89
+ def resource_name
90
+ self.class.resource_name
91
+ end
92
+
93
+ # Fetches an attribute that uses the API's Text Formatting feature, which means that
94
+ # the attribute will be nested inside a key naming the format (plain/html/dom)
95
+ def formatted_attribute(attribute)
96
+ return nil unless resource[attribute]
97
+ resource[attribute][text_format]
98
+ end
99
+ end
100
+ end
@@ -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,3 @@
1
+ module Genius
2
+ VERSION = "0.1.2"
3
+ end
@@ -0,0 +1,35 @@
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(*)
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",
30
+ query: params,
31
+ headers: headers),
32
+ text_format: params[:text_format])
33
+ end
34
+ end
35
+ end
metadata ADDED
@@ -0,0 +1,195 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: genius_fixed
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Tim Rogers
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-06-22 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: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 0.31.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.31.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: httparty
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: 0.14.0
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: 0.14.0
139
+ description: A Ruby client for the Genius API (<http://genius.com/developers>). [Forked
140
+ version, from https://github.com/Homologist/genius.git — none of the credit goes
141
+ to me (jltml)!]
142
+ email:
143
+ - tim@gocardless.com
144
+ executables: []
145
+ extensions: []
146
+ extra_rdoc_files: []
147
+ files:
148
+ - ".gitignore"
149
+ - ".rspec"
150
+ - ".rubocop.yml"
151
+ - ".rubocop_todo.yml"
152
+ - ".travis.yml"
153
+ - CHANGELOG.md
154
+ - CODE_OF_CONDUCT.md
155
+ - Gemfile
156
+ - LICENSE.txt
157
+ - README.md
158
+ - Rakefile
159
+ - bin/console
160
+ - bin/setup
161
+ - genius.gemspec
162
+ - lib/genius.rb
163
+ - lib/genius/account.rb
164
+ - lib/genius/annotation.rb
165
+ - lib/genius/artist.rb
166
+ - lib/genius/errors.rb
167
+ - lib/genius/referent.rb
168
+ - lib/genius/resource.rb
169
+ - lib/genius/song.rb
170
+ - lib/genius/version.rb
171
+ - lib/genius/web_page.rb
172
+ homepage: https://github.com/Homologist/genius
173
+ licenses:
174
+ - MIT
175
+ metadata: {}
176
+ post_install_message:
177
+ rdoc_options: []
178
+ require_paths:
179
+ - lib
180
+ required_ruby_version: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ version: '0'
185
+ required_rubygems_version: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - ">="
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ requirements: []
191
+ rubygems_version: 3.2.17
192
+ signing_key:
193
+ specification_version: 4
194
+ summary: A Ruby client for the Genius API (<http://genius.com/developers>).
195
+ test_files: []