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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ec64ebb3e63e640a69c4fc621b98927e493340b2
4
- data.tar.gz: 1f2586292e73e9af6d7ff149a7a872e28e9d6f65
3
+ metadata.gz: d1ea05cdf97229f89e4289ab13ffb98e69c9c83d
4
+ data.tar.gz: 51189c1a34623a092bbf00228dde6f74f01602ad
5
5
  SHA512:
6
- metadata.gz: 1e5845de63d4bf7153726d24eda36de52306a798d6f439970434bc0850befbfeea4af4f149c7c87cf2e2aa2b3192530f916231f84760bdef6e1deb4e70438630
7
- data.tar.gz: aca1f97b5fb3d2bd385eb96cd11b18c1093965af878ee1aaf3951040075a72c5c90848ffc58157bbfed40f586b6a4dd5bfcf313fefba2074b6e89ba4edf6dd74
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
- wizzler = RSpotify::User.find('wizzler')
83
- wizzler.uri #=> "spotify:user:wizzler"
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
- wizzler = RSpotify::User.find('wizzler')
103
- wizzler.playlists #=> (Playlist array)
102
+ me = RSpotify::User.find('guilhermesad')
103
+ me.playlists #=> (Playlist array)
104
104
 
105
105
  # Find by id
106
- playlist = RSpotify::Playlist.find('wizzler', '00wHcTN0zQiun4xri9pmvX')
107
- playlist.name #=> "Movie Soundtrack Masterpieces"
108
- playlist.description #=> "Iconic soundtracks featured..."
109
- playlist.followers['total'] #=> 13
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
@@ -2,11 +2,14 @@ require 'rspotify/connection'
2
2
  require 'rspotify/version'
3
3
 
4
4
  module RSpotify
5
- autoload :Album, 'rspotify/album'
6
- autoload :Artist, 'rspotify/artist'
7
- autoload :Base, 'rspotify/base'
8
- autoload :Category, 'rspotify/category'
9
- autoload :Playlist, 'rspotify/playlist'
10
- autoload :Track, 'rspotify/track'
11
- autoload :User, 'rspotify/user'
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
@@ -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
@@ -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']
@@ -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
  #
@@ -1,3 +1,3 @@
1
1
  module RSpotify
2
- VERSION = '1.17.0'
2
+ VERSION = '1.18.0'
3
3
  end
@@ -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
+