rspotify 1.17.0 → 1.18.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +24 -8
- data/lib/rspotify.rb +10 -7
- data/lib/rspotify/audio_features.rb +72 -0
- data/lib/rspotify/base.rb +40 -0
- data/lib/rspotify/recommendation_seed.rb +18 -0
- data/lib/rspotify/recommendations.rb +108 -0
- data/lib/rspotify/track.rb +5 -0
- data/lib/rspotify/user.rb +36 -0
- data/lib/rspotify/version.rb +1 -1
- data/spec/lib/rspotify/album_spec.rb +47 -0
- data/spec/lib/rspotify/audio_features_spec.rb +44 -0
- data/spec/lib/rspotify/recommendations_spec.rb +52 -0
- data/spec/lib/rspotify/track_spec.rb +40 -1
- data/spec/vcr_cassettes/audio_features_find_1zHlj4dQ8ZAtrayhuDDmkY.yml +214 -0
- data/spec/vcr_cassettes/audio_features_find_multiple.yml +78 -0
- data/spec/vcr_cassettes/authenticate_client.yml +19 -19
- data/spec/vcr_cassettes/recommendations_available_genre_seeds.yml +207 -0
- data/spec/vcr_cassettes/recommendations_generate.yml +192 -0
- data/spec/vcr_cassettes/track_audio_features_3jfr0TF6DQcOLat8gGn7E2.yml +203 -0
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d1ea05cdf97229f89e4289ab13ffb98e69c9c83d
|
4
|
+
data.tar.gz: 51189c1a34623a092bbf00228dde6f74f01602ad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f3606c24acaaaa73c3bb63b4686e763517f5b75f302dec396f32389efb85d9eaba23c7fe8d06acdc21fd2d30f38a0804ba464e33e09c5dc0d3a43623fba5de3
|
7
|
+
data.tar.gz: c02ebfec2b609bcabf1b06647db8d23dba3706d63cb77d8609afa4ecb989e4d5d7ef43f06e776c83c662f2777691cb66fd24eac2c0493e9e9e4d8b45abb2d1f3
|
data/README.md
CHANGED
@@ -79,8 +79,8 @@ am.album_type #=> "single"
|
|
79
79
|
do_i_wanna_know = RSpotify::Track.find('2UzMpPKPhbcC8RbsmuURAZ')
|
80
80
|
do_i_wanna_know.album #=> (Album object)
|
81
81
|
|
82
|
-
|
83
|
-
|
82
|
+
me = RSpotify::User.find('guilhermesad')
|
83
|
+
me.uri #=> "spotify:user:guilhermesad"
|
84
84
|
|
85
85
|
# Or find several objects at once:
|
86
86
|
|
@@ -99,14 +99,14 @@ RSpotify.authenticate("<your_client_id>", "<your_client_secret>")
|
|
99
99
|
|
100
100
|
# Now you can access playlists in detail, browse featured content and more
|
101
101
|
|
102
|
-
|
103
|
-
|
102
|
+
me = RSpotify::User.find('guilhermesad')
|
103
|
+
me.playlists #=> (Playlist array)
|
104
104
|
|
105
105
|
# Find by id
|
106
|
-
playlist = RSpotify::Playlist.find('
|
107
|
-
playlist.name #=> "
|
108
|
-
playlist.description #=> "
|
109
|
-
playlist.followers['total'] #=>
|
106
|
+
playlist = RSpotify::Playlist.find('guilhermesad', '1Xi8mgiuHHPLQYOw2Q16xv')
|
107
|
+
playlist.name #=> "d33p"
|
108
|
+
playlist.description #=> "d33p h0uz"
|
109
|
+
playlist.followers['total'] #=> 1
|
110
110
|
playlist.tracks #=> (Track array)
|
111
111
|
|
112
112
|
# Search by category
|
@@ -117,6 +117,18 @@ categories = RSpotify::Category.list # See all available categories
|
|
117
117
|
# Access featured content from Spotify's Browse tab
|
118
118
|
featured_playlists = RSpotify::Playlist.browse_featured(country: 'US')
|
119
119
|
new_releases = RSpotify::Album.new_releases(country: 'ES')
|
120
|
+
|
121
|
+
# Access tracks' audio features
|
122
|
+
sorry = RSpotify::Track.search("Sorry").first
|
123
|
+
sorry.audio_features.danceability #=> 0.605
|
124
|
+
sorry.audio_features.energy #=> 0.768
|
125
|
+
sorry.audio_features.tempo #=> 100.209
|
126
|
+
|
127
|
+
# Get recommendations
|
128
|
+
recommendations = RSpotify::Recommendations.generate(seed_genres: ['blues', 'country'])
|
129
|
+
recommendations = RSpotify::Recommendations.generate(seed_tracks: my_fav_tracks.map(&:id))
|
130
|
+
recommendations = RSpotify::Recommendations.generate(seed_artists: my_fav_artists.map(&:id))
|
131
|
+
recommendations.tracks #=> (Track array)
|
120
132
|
```
|
121
133
|
|
122
134
|
## Rails + OAuth
|
@@ -196,6 +208,10 @@ class UsersController < ApplicationController
|
|
196
208
|
spotify_user.follows?(artists)
|
197
209
|
spotify_user.unfollow(users)
|
198
210
|
|
211
|
+
# Get user's top played artists and tracks
|
212
|
+
spotify_user.top_artists #=> (Artist array)
|
213
|
+
spotify_user.top_tracks(time_range: 'short_term') #=> (Track array)
|
214
|
+
|
199
215
|
# Check doc for more
|
200
216
|
end
|
201
217
|
end
|
data/lib/rspotify.rb
CHANGED
@@ -2,11 +2,14 @@ require 'rspotify/connection'
|
|
2
2
|
require 'rspotify/version'
|
3
3
|
|
4
4
|
module RSpotify
|
5
|
-
autoload :Album,
|
6
|
-
autoload :Artist,
|
7
|
-
autoload :
|
8
|
-
autoload :
|
9
|
-
autoload :
|
10
|
-
autoload :
|
11
|
-
autoload :
|
5
|
+
autoload :Album, 'rspotify/album'
|
6
|
+
autoload :Artist, 'rspotify/artist'
|
7
|
+
autoload :AudioFeatures, 'rspotify/audio_features'
|
8
|
+
autoload :Base, 'rspotify/base'
|
9
|
+
autoload :Category, 'rspotify/category'
|
10
|
+
autoload :Playlist, 'rspotify/playlist'
|
11
|
+
autoload :Recommendations, 'rspotify/recommendations'
|
12
|
+
autoload :RecommendationSeed, 'rspotify/recommendation_seed'
|
13
|
+
autoload :Track, 'rspotify/track'
|
14
|
+
autoload :User, 'rspotify/user'
|
12
15
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module RSpotify
|
2
|
+
|
3
|
+
# @attr [Float] acousticness A confidence measure from 0.0 to 1.0 of whether the track is acoustic. 1.0 represents high confidence the track is acoustic.
|
4
|
+
# @attr [String] analysis_url An HTTP URL to access the full audio analysis of this track. This URL is cryptographically signed and configured to expire after roughly 10 minutes. Do not store these URLs for later use.
|
5
|
+
# @attr [Float] danceability Danceability describes how suitable a track is for dancing based on a combination of musical elements including tempo, rhythm stability, beat strength, and overall regularity. A value of 0.0 is least danceable and 1.0 is most danceable.
|
6
|
+
# @attr [Integer] duration_ms The duration of the track in milliseconds.
|
7
|
+
# @attr [Float] energy Energy is a measure from 0.0 to 1.0 and represents a perceptual measure of intensity and activity. Typically, energetic tracks feel fast, loud, and noisy. For example, death metal has high energy, while a Bach prelude scores low on the scale. Perceptual features contributing to this attribute include dynamic range, perceived loudness, timbre, onset rate, and general entropy.
|
8
|
+
# @attr [Float] instrumentalness Predicts whether a track contains no vocals. "Ooh" and "aah" sounds are treated as instrumental in this context. Rap or spoken word tracks are clearly "vocal". The closer the instrumentalness value is to 1.0, the greater likelihood the track contains no vocal content. Values above 0.5 are intended to represent instrumental tracks, but confidence is higher as the value approaches 1.0.
|
9
|
+
# @attr [Integer] key The key the track is in. Integers map to pitches using standard {https://en.wikipedia.org/wiki/Pitch_class Pitch Class notation}. E.g. 0 = C, 1 = C♯/D♭, 2 = D, and so on.
|
10
|
+
# @attr [Float] liveness Detects the presence of an audience in the recording. Higher liveness values represent an increased probability that the track was performed live. A value above 0.8 provides strong likelihood that the track is live.
|
11
|
+
# @attr [Float] loudness The overall loudness of a track in decibels (dB). Loudness values are averaged across the entire track and are useful for comparing relative loudness of tracks. Loudness is the quality of a sound that is the primary psychological correlate of physical strength (amplitude). Values typical range between -60 and 0 db.
|
12
|
+
# @attr [Integer] mode Mode indicates the modality (major or minor) of a track, the type of scale from which its melodic content is derived. Major is represented by 1 and minor is 0.
|
13
|
+
# @attr [Float] speechiness Speechiness detects the presence of spoken words in a track. The more exclusively speech-like the recording (e.g. talk show, audio book, poetry), the closer to 1.0 the attribute value. Values above 0.66 describe tracks that are probably made entirely of spoken words. Values between 0.33 and 0.66 describe tracks that may contain both music and speech, either in sections or layered, including such cases as rap music. Values below 0.33 most likely represent music and other non-speech-like tracks.
|
14
|
+
# @attr [Float] tempo The overall estimated tempo of a track in beats per minute (BPM). In musical terminology, tempo is the speed or pace of a given piece and derives directly from the average beat duration.
|
15
|
+
# @attr [Integer] time_signature An estimated overall time signature of a track. The time signature (meter) is a notational convention to specify how many beats are in each bar (or measure).
|
16
|
+
# @attr [String] track_href A link to the Web API endpoint providing full details of the track.
|
17
|
+
# @attr [Float] valence A measure from 0.0 to 1.0 describing the musical positiveness conveyed by a track. Tracks with high valence sound more positive (e.g. happy, cheerful, euphoric), while tracks with low valence sound more negative (e.g. sad, depressed, angry).
|
18
|
+
class AudioFeatures < Base
|
19
|
+
|
20
|
+
# Retrieves AudioFeatures object(s) for the track id(s) provided
|
21
|
+
#
|
22
|
+
# @param ids [String, Array] Either a single track id or a list track ids. Maximum: 100 IDs.
|
23
|
+
# @return [AudioFeatures, Array<AudioFeatures>]
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
# audio_features = RSpotify::AudioFeatures.find('1zHlj4dQ8ZAtrayhuDDmkY')
|
27
|
+
# audio_features = RSpotify::AudioFeatures.find(['1zHlj4dQ8ZAtrayhuDDmkY', '7ouMYWpwJ422jRcDASZB7P', '4VqPOruhp5EdPBeR92t6lQ'])
|
28
|
+
def self.find(ids)
|
29
|
+
case ids
|
30
|
+
when Array
|
31
|
+
url = "audio-features?ids=#{ids.join(',')}"
|
32
|
+
response = RSpotify.get(url)
|
33
|
+
return response if RSpotify.raw_response
|
34
|
+
|
35
|
+
response['audio_features'].map { |i| AudioFeatures.new i }
|
36
|
+
when String
|
37
|
+
url = "audio-features/#{ids}"
|
38
|
+
response = RSpotify.get(url)
|
39
|
+
return response if RSpotify.raw_response
|
40
|
+
|
41
|
+
AudioFeatures.new response
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize(options = {})
|
46
|
+
@acousticness = options['acousticness']
|
47
|
+
@analysis_url = options['analysis_url']
|
48
|
+
@danceability = options['danceability']
|
49
|
+
@duration_ms = options['duration_ms']
|
50
|
+
@energy = options['energy']
|
51
|
+
@instrumentalness = options['instrumentalness']
|
52
|
+
@key = options['key']
|
53
|
+
@liveness = options['liveness']
|
54
|
+
@loudness = options['loudness']
|
55
|
+
@mode = options['mode']
|
56
|
+
@speechiness = options['speechiness']
|
57
|
+
@tempo = options['tempo']
|
58
|
+
@time_signature = options['time_signature']
|
59
|
+
@track_href = options['track_href']
|
60
|
+
@valence = options['valence']
|
61
|
+
|
62
|
+
super(options)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Spotify does not support search for audio features
|
66
|
+
def self.search(*)
|
67
|
+
warn 'Spotify API does not support search for audio features'
|
68
|
+
false
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
data/lib/rspotify/base.rb
CHANGED
@@ -121,6 +121,46 @@ module RSpotify
|
|
121
121
|
@uri = options['uri']
|
122
122
|
end
|
123
123
|
|
124
|
+
# Generate an embed code for an album, artist or track.
|
125
|
+
# @param [Hash] options
|
126
|
+
# @option options [Fixnum] :width the width of the frame
|
127
|
+
# @option options [Fixnum] :height the height of the frame
|
128
|
+
# @option options [Fixnum] :frameborder the frameborder of the frame
|
129
|
+
# @option options [Boolean] :allowtransparency toggle frame transparency
|
130
|
+
# @option options [nil|String|Symbol] :view specific view option for iframe
|
131
|
+
# @option options [nil|String|Symbol] :theme specific theme option for iframe
|
132
|
+
#
|
133
|
+
# For full documentation on widgets/embeds, check out the official documentation:
|
134
|
+
# @see https://developer.spotify.com/technologies/widgets/examples/
|
135
|
+
#
|
136
|
+
def embed(options = {})
|
137
|
+
default_options = {
|
138
|
+
width: 300,
|
139
|
+
height: 380,
|
140
|
+
frameborder: 0,
|
141
|
+
allowtransparency: true,
|
142
|
+
view: nil,
|
143
|
+
theme: nil,
|
144
|
+
}
|
145
|
+
options = default_options.merge(options)
|
146
|
+
|
147
|
+
src = "https://embed.spotify.com/?uri=#{@uri}"
|
148
|
+
src << "&view=#{options[:view]}" unless options[:view].nil?
|
149
|
+
src << "&theme=#{options[:theme]}" unless options[:theme].nil?
|
150
|
+
|
151
|
+
template = <<-HTML
|
152
|
+
<iframe
|
153
|
+
src="#{src}"
|
154
|
+
width="#{options[:width]}"
|
155
|
+
height="#{options[:height]}"
|
156
|
+
frameborder="#{options[:frameborder]}"
|
157
|
+
allowtransparency="#{options[:allowtransparency]}">
|
158
|
+
</iframe>
|
159
|
+
HTML
|
160
|
+
|
161
|
+
template.gsub(/\s+/, " ").strip
|
162
|
+
end
|
163
|
+
|
124
164
|
# When an object is obtained undirectly, Spotify usually returns a simplified version of it.
|
125
165
|
# This method updates it into a full object, with all attributes filled.
|
126
166
|
#
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module RSpotify
|
2
|
+
|
3
|
+
# @attr [Integer] after_filtering_size The number of tracks available after min_* and max_* filters have been applied.
|
4
|
+
# @attr [Integer] after_relinking_size The number of tracks available after relinking for regional availability.
|
5
|
+
# @attr [Integer] initial_pool_size The number of recommended tracks available for this seed.
|
6
|
+
class RecommendationSeed < Base
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
@after_filtering_size = options['afterFilteringSize']
|
10
|
+
@after_relinking_size = options['afterRelinkingSize']
|
11
|
+
@initial_pool_size = options['initialPoolSize']
|
12
|
+
|
13
|
+
super(options)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module RSpotify
|
2
|
+
|
3
|
+
# @attr [Array<Track>] tracks An array of {https://developer.spotify.com/web-api/object-model/#track-object-simplified track object (simplified)} ordered according to the parameters supplied.
|
4
|
+
# @attr [Array<RecommendationSeed>] seeds An array of {https://developer.spotify.com/web-api/object-model/#recommendations-seed-object recommendation seed objects}.
|
5
|
+
class Recommendations < Base
|
6
|
+
|
7
|
+
# Retrieve a list of available genres seed parameter values for recommendations.
|
8
|
+
# @return [Array<String>]
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# genres = RSpotify::Recommendations.available_genre_seeds
|
12
|
+
def self.available_genre_seeds
|
13
|
+
response = RSpotify.get('recommendations/available-genre-seeds')
|
14
|
+
return response if RSpotify.raw_response
|
15
|
+
|
16
|
+
response['genres']
|
17
|
+
end
|
18
|
+
|
19
|
+
# Create a playlist-style listening experience based on seed artists, tracks and genres
|
20
|
+
#
|
21
|
+
# @note Up to 5 seed values may be provided in any combination of seed_artists, seed_tracks and seed_genres.
|
22
|
+
#
|
23
|
+
# @param limit [Integer] The target size of the list of recommended tracks. For seeds with unusually small pools or when highly restrictive filtering is applied, it may be impossible to generate the requested number of recommended tracks. Debugging information for such cases is available in the response. Default: 20. Minimum: 1. Maximum: 100.
|
24
|
+
# @param seed_artists [Array<String>] A list of Spotify IDs for seed artists.
|
25
|
+
# @param seed_genres [Array<String>] A list of any genres in the set of {https://developer.spotify.com/web-api/get-recommendations/#available-genre-seeds available genre seeds}.
|
26
|
+
# @param seed_tracks [Array<String>] A list of Spotify IDs for seed tracks.
|
27
|
+
# @param market [String] Optional. An {https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ISO 3166-1 alpha-2 country code}. Provide this parameter if you want to apply Track Relinking. Because min_*, max_* and target_* are applied to pools before relinking, the generated results may not precisely match the filters applied. Original, non-relinked tracks are available via the linked_from attribute of the relinked track response.
|
28
|
+
# @option options [Float] :min_acousticness Hard floor on the confidence measure from 0.0 to 1.0 of whether the track is acoustic. 1.0 represents high confidence the track is acoustic.
|
29
|
+
# @option options [Float] :max_acousticness Hard ceiling on the confidence measure from 0.0 to 1.0 of whether the track is acoustic. 1.0 represents high confidence the track is acoustic.
|
30
|
+
# @option options [Float] :target_acousticness Target value on the confidence measure from 0.0 to 1.0 of whether the track is acoustic. 1.0 represents high confidence the track is acoustic.
|
31
|
+
# @option options [Float] :min_danceability Hard floor on how suitable a track is for dancing based on a combination of musical elements including tempo, rhythm stability, beat strength, and overall regularity. A value of 0.0 is least danceable and 1.0 is most danceable.
|
32
|
+
# @option options [Float] :max_danceability Hard ceiling on how suitable a track is for dancing based on a combination of musical elements including tempo, rhythm stability, beat strength, and overall regularity. A value of 0.0 is least danceable and 1.0 is most danceable.
|
33
|
+
# @option options [Float] :target_danceability Target value on how suitable a track is for dancing based on a combination of musical elements including tempo, rhythm stability, beat strength, and overall regularity. A value of 0.0 is least danceable and 1.0 is most danceable.
|
34
|
+
# @option options [Integer] :min_duration_ms Hard floor on the duration of the track in milliseconds.
|
35
|
+
# @option options [Integer] :max_duration_ms Hard ceiling on the duration of the track in milliseconds.
|
36
|
+
# @option options [Integer] :target_duration_ms Target value on the duration of the track in milliseconds.
|
37
|
+
# @option options [Float] :min_energy Hard floor on energy which is a measure from 0.0 to 1.0 and represents a perceptual measure of intensity and activity. Typically, energetic tracks feel fast, loud, and noisy. For example, death metal has high energy, while a Bach prelude scores low on the scale. Perceptual features contributing to this attribute include dynamic range, perceived loudness, timbre, onset rate, and general entropy.
|
38
|
+
# @option options [Float] :max_energy Hard ceiling on energy which is a measure from 0.0 to 1.0 and represents a perceptual measure of intensity and activity. Typically, energetic tracks feel fast, loud, and noisy. For example, death metal has high energy, while a Bach prelude scores low on the scale. Perceptual features contributing to this attribute include dynamic range, perceived loudness, timbre, onset rate, and general entropy.
|
39
|
+
# @option options [Float] :target_energy Target value on energy which is a measure from 0.0 to 1.0 and represents a perceptual measure of intensity and activity. Typically, energetic tracks feel fast, loud, and noisy. For example, death metal has high energy, while a Bach prelude scores low on the scale. Perceptual features contributing to this attribute include dynamic range, perceived loudness, timbre, onset rate, and general entropy.
|
40
|
+
# @option options [Float] :min_instrumentalness Hard floor on prediction of whether a track contains no vocals. "Ooh" and "aah" sounds are treated as instrumental in this context. Rap or spoken word tracks are clearly "vocal". The closer the instrumentalness value is to 1.0, the greater likelihood the track contains no vocal content. Values above 0.5 are intended to represent instrumental tracks, but confidence is higher as the value approaches 1.0.
|
41
|
+
# @option options [Float] :max_instrumentalness Hard ceiling on prediction of whether a track contains no vocals. "Ooh" and "aah" sounds are treated as instrumental in this context. Rap or spoken word tracks are clearly "vocal". The closer the instrumentalness value is to 1.0, the greater likelihood the track contains no vocal content. Values above 0.5 are intended to represent instrumental tracks, but confidence is higher as the value approaches 1.0.
|
42
|
+
# @option options [Float] :target_instrumentalness Target value on prediction of whether a track contains no vocals. "Ooh" and "aah" sounds are treated as instrumental in this context. Rap or spoken word tracks are clearly "vocal". The closer the instrumentalness value is to 1.0, the greater likelihood the track contains no vocal content. Values above 0.5 are intended to represent instrumental tracks, but confidence is higher as the value approaches 1.0.
|
43
|
+
# @option options [Integer] :min_key Hard floor on the key the track is in. Integers map to pitches using standard {https://en.wikipedia.org/wiki/Pitch_class Pitch Class notation}. E.g. 0 = C, 1 = C♯/D♭, 2 = D, and so on.
|
44
|
+
# @option options [Integer] :max_key Hard ceiling on the key the track is in. Integers map to pitches using standard {https://en.wikipedia.org/wiki/Pitch_class Pitch Class notation}. E.g. 0 = C, 1 = C♯/D♭, 2 = D, and so on.
|
45
|
+
# @option options [Integer] :target_key Target value on the key the track is in. Integers map to pitches using standard {https://en.wikipedia.org/wiki/Pitch_class Pitch Class notation}. E.g. 0 = C, 1 = C♯/D♭, 2 = D, and so on.
|
46
|
+
# @option options [Float] :min_liveness Hard floor on liveness, which detects the presence of an audience in the recording. Higher liveness values represent an increased probability that the track was performed live. A value above 0.8 provides strong likelihood that the track is live.
|
47
|
+
# @option options [Float] :max_liveness Hard ceiling on liveness, which detects the presence of an audience in the recording. Higher liveness values represent an increased probability that the track was performed live. A value above 0.8 provides strong likelihood that the track is live.
|
48
|
+
# @option options [Float] :target_liveness Target value on liveness, which detects the presence of an audience in the recording. Higher liveness values represent an increased probability that the track was performed live. A value above 0.8 provides strong likelihood that the track is live.
|
49
|
+
# @option options [Float] :min_loudness Hard floor on the overall loudness of a track in decibels (dB). Loudness values are averaged across the entire track and are useful for comparing relative loudness of tracks. Loudness is the quality of a sound that is the primary psychological correlate of physical strength (amplitude). Values typical range between -60 and 0 db.
|
50
|
+
# @option options [Float] :max_loudness Hard ceiling on the overall loudness of a track in decibels (dB). Loudness values are averaged across the entire track and are useful for comparing relative loudness of tracks. Loudness is the quality of a sound that is the primary psychological correlate of physical strength (amplitude). Values typical range between -60 and 0 db.
|
51
|
+
# @option options [Float] :target_loudness Target value on the overall loudness of a track in decibels (dB). Loudness values are averaged across the entire track and are useful for comparing relative loudness of tracks. Loudness is the quality of a sound that is the primary psychological correlate of physical strength (amplitude). Values typical range between -60 and 0 db.
|
52
|
+
# @option options [Integer] :min_mode Hard floor on the modality (major or minor) of a track, the type of scale from which its melodic content is derived. Major is represented by 1 and minor is 0.
|
53
|
+
# @option options [Integer] :max_mode Hard ceiling on the modality (major or minor) of a track, the type of scale from which its melodic content is derived. Major is represented by 1 and minor is 0.
|
54
|
+
# @option options [Integer] :target_mode Target value on the modality (major or minor) of a track, the type of scale from which its melodic content is derived. Major is represented by 1 and minor is 0.
|
55
|
+
# @option options [Integer] :min_popularity Hard floor on the popularity of the track. The value will be between 0 and 100, with 100 being the most popular. The popularity is calculated by algorithm and is based, in the most part, on the total number of plays the track has had and how recent those plays are.
|
56
|
+
# @option options [Integer] :max_popularity Hard ceiling on the popularity of the track. The value will be between 0 and 100, with 100 being the most popular. The popularity is calculated by algorithm and is based, in the most part, on the total number of plays the track has had and how recent those plays are.
|
57
|
+
# @option options [Integer] :target_popularity Target value on the popularity of the track. The value will be between 0 and 100, with 100 being the most popular. The popularity is calculated by algorithm and is based, in the most part, on the total number of plays the track has had and how recent those plays are.
|
58
|
+
# @option options [Float] :min_speechiness Hard floor on speechiness which detects the presence of spoken words in a track. The more exclusively speech-like the recording (e.g. talk show, audio book, poetry), the closer to 1.0 the attribute value. Values above 0.66 describe tracks that are probably made entirely of spoken words. Values between 0.33 and 0.66 describe tracks that may contain both music and speech, either in sections or layered, including such cases as rap music. Values below 0.33 most likely represent music and other non-speech-like tracks.
|
59
|
+
# @option options [Float] :max_speechiness Hard ceiling on speechiness which detects the presence of spoken words in a track. The more exclusively speech-like the recording (e.g. talk show, audio book, poetry), the closer to 1.0 the attribute value. Values above 0.66 describe tracks that are probably made entirely of spoken words. Values between 0.33 and 0.66 describe tracks that may contain both music and speech, either in sections or layered, including such cases as rap music. Values below 0.33 most likely represent music and other non-speech-like tracks.
|
60
|
+
# @option options [Float] :target_speechiness Target value on speechiness which detects the presence of spoken words in a track. The more exclusively speech-like the recording (e.g. talk show, audio book, poetry), the closer to 1.0 the attribute value. Values above 0.66 describe tracks that are probably made entirely of spoken words. Values between 0.33 and 0.66 describe tracks that may contain both music and speech, either in sections or layered, including such cases as rap music. Values below 0.33 most likely represent music and other non-speech-like tracks.
|
61
|
+
# @option options [Float] :min_tempo Hard floor on the overall estimated tempo of a track in beats per minute (BPM). In musical terminology, tempo is the speed or pace of a given piece and derives directly from the average beat duration.
|
62
|
+
# @option options [Float] :max_tempo Hard ceiling on the overall estimated tempo of a track in beats per minute (BPM). In musical terminology, tempo is the speed or pace of a given piece and derives directly from the average beat duration.
|
63
|
+
# @option options [Float] :target_tempo Target value on the overall estimated tempo of a track in beats per minute (BPM). In musical terminology, tempo is the speed or pace of a given piece and derives directly from the average beat duration.
|
64
|
+
# @option options [Integer] :min_time_signature Hard floor on the estimated overall time signature of a track. The time signature (meter) is a notational convention to specify how many beats are in each bar (or measure).
|
65
|
+
# @option options [Integer] :max_time_signature Hard ceiling on the estimated overall time signature of a track. The time signature (meter) is a notational convention to specify how many beats are in each bar (or measure).
|
66
|
+
# @option options [Integer] :target_time_signature Target value on the estimated overall time signature of a track. The time signature (meter) is a notational convention to specify how many beats are in each bar (or measure).
|
67
|
+
# @option options [Float] :min_valence Hard floor on the measure from 0.0 to 1.0 describing the musical positiveness conveyed by a track. Tracks with high valence sound more positive (e.g. happy, cheerful, euphoric), while tracks with low valence sound more negative (e.g. sad, depressed, angry).
|
68
|
+
# @option options [Float] :max_valence Hard ceiling on the measure from 0.0 to 1.0 describing the musical positiveness conveyed by a track. Tracks with high valence sound more positive (e.g. happy, cheerful, euphoric), while tracks with low valence sound more negative (e.g. sad, depressed, angry).
|
69
|
+
# @option options [Float] :target_valence Target value on the measure from 0.0 to 1.0 describing the musical positiveness conveyed by a track. Tracks with high valence sound more positive (e.g. happy, cheerful, euphoric), while tracks with low valence sound more negative (e.g. sad, depressed, angry).
|
70
|
+
# @return [Array<Recommendations>]
|
71
|
+
#
|
72
|
+
# @example
|
73
|
+
# recommendations = RSpotify::Recommendations.generate(limit: 20, seed_tracks: ['0c6xIDDpzE81m2q797ordA'])
|
74
|
+
# recommendations = RSpotify::Recommendations.generate(seed_tracks: ['0c6xIDDpzE81m2q797ordA'], seed_artists: ['4NHQUGzhtTLFvgF5SZesLK'], market: 'ES')
|
75
|
+
# recommendations = RSpotify::Recommendations.generate(seed_tracks: ['0c6xIDDpzE81m2q797ordA'], seed_genres: ['alt_rock'], seed_artists: ['4NHQUGzhtTLFvgF5SZesLK'], target_energy: 1.0)
|
76
|
+
def self.generate(limit: 20, seed_artists: [], seed_genres: [], seed_tracks: [], market: nil, **options)
|
77
|
+
url = "recommendations?limit=#{limit}"
|
78
|
+
|
79
|
+
url << "&seed_artists=#{seed_artists.join(',')}" if seed_artists.any?
|
80
|
+
url << "&seed_genres=#{seed_genres.join(',')}" if seed_genres.any?
|
81
|
+
url << "&seed_tracks=#{seed_tracks.join(',')}" if seed_tracks.any?
|
82
|
+
|
83
|
+
options.each do |option, value|
|
84
|
+
url << "&#{option}=#{value}"
|
85
|
+
end
|
86
|
+
|
87
|
+
response = if market.is_a? Hash
|
88
|
+
url << '&market=from_token'
|
89
|
+
User.oauth_get(market[:from].id, url)
|
90
|
+
else
|
91
|
+
url << "&market=#{market}" if market
|
92
|
+
RSpotify.get(url)
|
93
|
+
end
|
94
|
+
|
95
|
+
return response if RSpotify.raw_response
|
96
|
+
|
97
|
+
Recommendations.new response
|
98
|
+
end
|
99
|
+
|
100
|
+
def initialize(options = {})
|
101
|
+
@seeds = options['seeds'].map { |i| RecommendationSeed.new i }
|
102
|
+
@tracks = options['tracks'].map { |i| Track.new i }
|
103
|
+
|
104
|
+
super(options)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
data/lib/rspotify/track.rb
CHANGED
@@ -49,6 +49,11 @@ module RSpotify
|
|
49
49
|
super(query, 'track', limit: limit, offset: offset, market: market)
|
50
50
|
end
|
51
51
|
|
52
|
+
# Retrieves the audio features for the track
|
53
|
+
def audio_features
|
54
|
+
RSpotify::AudioFeatures.find(@id)
|
55
|
+
end
|
56
|
+
|
52
57
|
def initialize(options = {})
|
53
58
|
@available_markets = options['available_markets']
|
54
59
|
@disc_number = options['disc_number']
|
data/lib/rspotify/user.rb
CHANGED
@@ -366,6 +366,42 @@ module RSpotify
|
|
366
366
|
Hash[pairs]
|
367
367
|
end
|
368
368
|
|
369
|
+
# Get the current user’s top artists based on calculated affinity. Requires the *user-top-read* scope.
|
370
|
+
#
|
371
|
+
# @param limit [Integer] Optional. The number of entities to return. Default: 20. Minimum: 1. Maximum: 50.
|
372
|
+
# @param offset [Integer] Optional. The index of the first entity to return. Default: 0 (i.e., the first track). Use with limit to get the next set of entities.
|
373
|
+
# @param time_range [String] Optional. Over what time frame the affinities are computed. Valid values: long_term (calculated from several years of data and including all new data as it becomes available), medium_term (approximately last 6 months), short_term (approximately last 4 weeks). Default: medium_term.
|
374
|
+
# @return [Array<Artist>]
|
375
|
+
#
|
376
|
+
# @example
|
377
|
+
# top_artists = user.top_artists
|
378
|
+
# top_artists.size #=> 20
|
379
|
+
# top_artists.first.name #=> "Nine Inch Nails"
|
380
|
+
def top_artists(limit: 20, offset: 0, time_range: 'medium_term')
|
381
|
+
url = "me/top/artists?limit=#{limit}&offset=#{offset}&time_range=#{time_range}"
|
382
|
+
response = User.oauth_get(@id, url)
|
383
|
+
return response if RSpotify.raw_response
|
384
|
+
response['items'].map { |i| Artist.new i }
|
385
|
+
end
|
386
|
+
|
387
|
+
# Get the current user’s top tracks based on calculated affinity. Requires the *user-top-read* scope.
|
388
|
+
#
|
389
|
+
# @param limit [Integer] Optional. The number of entities to return. Default: 20. Minimum: 1. Maximum: 50.
|
390
|
+
# @param offset [Integer] Optional. The index of the first entity to return. Default: 0 (i.e., the first track). Use with limit to get the next set of entities.
|
391
|
+
# @param time_range [String] Optional. Over what time frame the affinities are computed. Valid values: long_term (calculated from several years of data and including all new data as it becomes available), medium_term (approximately last 6 months), short_term (approximately last 4 weeks). Default: medium_term.
|
392
|
+
# @return [Array<Track>]
|
393
|
+
#
|
394
|
+
# @example
|
395
|
+
# top_tracks = user.top_tracks
|
396
|
+
# top_tracks.size #=> 20
|
397
|
+
# top_tracks.first.name #=> "Ice to Never"
|
398
|
+
def top_tracks(limit: 20, offset: 0, time_range: 'medium_term')
|
399
|
+
url = "me/top/tracks?limit=#{limit}&offset=#{offset}&time_range=#{time_range}"
|
400
|
+
response = User.oauth_get(@id, url)
|
401
|
+
return response if RSpotify.raw_response
|
402
|
+
response['items'].map { |i| Track.new i }
|
403
|
+
end
|
404
|
+
|
369
405
|
# Remove the current user as a follower of one or more artists, other Spotify users or a playlist. Unfollowing artists or users require the *user-follow-modify* scope.
|
370
406
|
# Unfollowing a publicly followed playlist requires the *playlist-modify-public* scope; unfollowing a privately followed playlist requires the *playlist-modify-private* scope.
|
371
407
|
#
|
data/lib/rspotify/version.rb
CHANGED
@@ -138,4 +138,51 @@ describe RSpotify::Album do
|
|
138
138
|
expect(ES_albums.length).to eq(albums.length)
|
139
139
|
end
|
140
140
|
end
|
141
|
+
|
142
|
+
describe '.embed' do
|
143
|
+
before(:each) do
|
144
|
+
@album = VCR.use_cassette('album:find:5bU1XKYxHhEwukllT20xtk') do
|
145
|
+
RSpotify::Album.find('5bU1XKYxHhEwukllT20xtk')
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'returns the correct iframe' do
|
150
|
+
expect(@album.embed).to eq '<iframe src="https://embed.spotify.com/?uri=spotify:album:5bU1XKYxHhEwukllT20xtk" width="300" height="380" frameborder="0" allowtransparency="true"> </iframe>'
|
151
|
+
end
|
152
|
+
|
153
|
+
context 'with a coverart view' do
|
154
|
+
it 'returns the correct iframe' do
|
155
|
+
expect(@album.embed(view: :coverart)).to eq '<iframe src="https://embed.spotify.com/?uri=spotify:album:5bU1XKYxHhEwukllT20xtk&view=coverart" width="300" height="380" frameborder="0" allowtransparency="true"> </iframe>'
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
context 'with different width & height' do
|
160
|
+
it 'returns the correct iframe' do
|
161
|
+
expect(@album.embed(width: 800)).to eq '<iframe src="https://embed.spotify.com/?uri=spotify:album:5bU1XKYxHhEwukllT20xtk" width="800" height="380" frameborder="0" allowtransparency="true"> </iframe>'
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'returns the correct iframe' do
|
165
|
+
expect(@album.embed(height: 100)).to eq '<iframe src="https://embed.spotify.com/?uri=spotify:album:5bU1XKYxHhEwukllT20xtk" width="300" height="100" frameborder="0" allowtransparency="true"> </iframe>'
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context 'with frameborder' do
|
170
|
+
it 'returns the correct iframe' do
|
171
|
+
expect(@album.embed(frameborder: 10)).to eq '<iframe src="https://embed.spotify.com/?uri=spotify:album:5bU1XKYxHhEwukllT20xtk" width="300" height="380" frameborder="10" allowtransparency="true"> </iframe>'
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
context 'with allowtransparency' do
|
176
|
+
it 'returns the correct iframe' do
|
177
|
+
expect(@album.embed(allowtransparency: false)).to eq '<iframe src="https://embed.spotify.com/?uri=spotify:album:5bU1XKYxHhEwukllT20xtk" width="300" height="380" frameborder="0" allowtransparency="false"> </iframe>'
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
context 'with theme' do
|
182
|
+
it 'returns the correct iframe' do
|
183
|
+
expect(@album.embed(theme: :white)).to eq '<iframe src="https://embed.spotify.com/?uri=spotify:album:5bU1XKYxHhEwukllT20xtk&theme=white" width="300" height="380" frameborder="0" allowtransparency="true"> </iframe>'
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
141
187
|
end
|
188
|
+
|