Class: RSpotify::Playlist

Inherits:
Base
  • Object
show all
Defined in:
lib/rspotify/playlist.rb

Instance Attribute Summary collapse

Attributes inherited from Base

#external_urls, #href, #id, #type, #uri

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#embed, #method_missing, #respond_to?

Constructor Details

#initialize(options = {}) ⇒ Playlist

Returns a new instance of Playlist.


96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/rspotify/playlist.rb', line 96

def initialize(options = {})
  @collaborative = options['collaborative']
  @description   = options['description']
  @followers     = options['followers']
  @images        = options['images']
  @name          = options['name']
  @public        = options['public']
  @snapshot_id   = options['snapshot_id']
  @total         = options['tracks']['total']

  @owner = if options['owner']
    User.new options['owner']
  end

  tracks = options['tracks']['items'] if options['tracks']
  tracks.select! { |t| t['track'] } if tracks

  @tracks_cache = if tracks
    tracks.map { |t| Track.new t['track'] }
  end

  @tracks_added_at = hash_for(tracks, 'added_at') do |added_at|
    Time.parse added_at
  end

  @tracks_added_by = hash_for(tracks, 'added_by') do |added_by|
    User.new added_by
  end

  @tracks_is_local = hash_for(tracks, 'is_local') do |is_local|
    is_local
  end

  super(options)

  @path = "users/#{@owner.instance_variable_get('@id').gsub('?','')}/"
  @path << (@href =~ /\/starred$/ ? 'starred' : "playlists/#{@id}")
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class RSpotify::Base

Instance Attribute Details

#collaborativeBoolean

true if the owner allows other users to modify the playlist

Returns:

  • (Boolean)

    the current value of collaborative


15
16
17
# File 'lib/rspotify/playlist.rb', line 15

def collaborative
  @collaborative
end

#descriptionString

The playlist description

Returns:

  • (String)

    the current value of description


15
16
17
# File 'lib/rspotify/playlist.rb', line 15

def description
  @description
end

#followersHash

Information about the followers of the playlist

Returns:

  • (Hash)

    the current value of followers


15
16
17
# File 'lib/rspotify/playlist.rb', line 15

def followers
  @followers
end

#imagesArray<Hash>

Images for the playlist. The array may be empty or contain up to three images. The images are returned by size in descending order. If returned, the source URL for the image is temporary and will expire in less than one day.

Returns:

  • (Array<Hash>)

    the current value of images


15
16
17
# File 'lib/rspotify/playlist.rb', line 15

def images
  @images
end

#nameString

The name of the playlist

Returns:

  • (String)

    the current value of name


15
16
17
# File 'lib/rspotify/playlist.rb', line 15

def name
  @name
end

#ownerUser

The user who owns the playlist

Returns:

  • (User)

    the current value of owner


15
16
17
# File 'lib/rspotify/playlist.rb', line 15

def owner
  @owner
end

#publicBoolean

true if the playlist is not marked as secret

Returns:

  • (Boolean)

    the current value of public


15
16
17
# File 'lib/rspotify/playlist.rb', line 15

def public
  @public
end

#snapshot_idString

The version identifier for the current playlist. This attribute gets updated every time the playlist changes and can be supplied in other requests to target a specific playlist version

Returns:

  • (String)

    the current value of snapshot_id


15
16
17
# File 'lib/rspotify/playlist.rb', line 15

def snapshot_id
  @snapshot_id
end

#totalInteger

The total number of tracks in the playlist

Returns:

  • (Integer)

    the current value of total


15
16
17
# File 'lib/rspotify/playlist.rb', line 15

def total
  @total
end

#tracks_added_atHash

A hash containing the date and time each track was added to the playlist. Note: the hash is updated only when #tracks is used.

Returns:

  • (Hash)

    the current value of tracks_added_at


15
16
17
# File 'lib/rspotify/playlist.rb', line 15

def tracks_added_at
  @tracks_added_at
end

#tracks_added_byHash

A hash containing the user that added each track to the playlist. Note: the hash is updated only when #tracks is used.

Returns:

  • (Hash)

    the current value of tracks_added_by


15
16
17
# File 'lib/rspotify/playlist.rb', line 15

def tracks_added_by
  @tracks_added_by
end

#tracks_is_localHash

A hash showing whether each track is local or not. Note: the hash is updated only when #tracks is used.

Returns:

  • (Hash)

    the current value of tracks_is_local


15
16
17
# File 'lib/rspotify/playlist.rb', line 15

def tracks_is_local
  @tracks_is_local
end

Class Method Details

Get a list of Spotify featured playlists (shown, for example, on a Spotify player’s “Browse” tab).

Examples:

playlists = RSpotify::Playlist.browse_featured
playlists = RSpotify::Playlist.browse_featured(locale: 'es_MX', limit: 10)
playlists = RSpotify::Playlist.browse_featured(country: 'US', timestamp: '2014-10-23T09:00:00')

Parameters:

  • limit (Integer) (defaults to: 20)

    Maximum number of playlists to return. Maximum: 50. Default: 20.

  • offset (Integer) (defaults to: 0)

    The index of the first playlist to return. Use with limit to get the next set of playlists. Default: 0.

  • country (String)

    Optional. A country: an ISO 3166-1 alpha-2 country code. Provide this parameter if you want the list of returned playlists to be relevant to a particular country. If omitted, the returned playlists will be relevant to all countries.

  • locale (String)

    Optional. The desired language, consisting of a lowercase ISO 639 language code and an uppercase ISO 3166-1 alpha-2 country code, joined by an underscore. For details access / here and look for the locale parameter description.

  • timestamp (String)

    Optional. A timestamp in ISO 8601 format: yyyy-MM-ddTHH:mm:ss. Use this parameter to specify the user's local time to get results tailored for that specific date and time in the day. If not provided, the response defaults to the current UTC time. Example: “2014-10-23T09:00:00” for a user whose local time is 9AM.

Returns:


30
31
32
33
34
35
36
37
38
39
# File 'lib/rspotify/playlist.rb', line 30

def self.browse_featured(limit: 20, offset: 0, **options)
  url = "browse/featured-playlists?limit=#{limit}&offset=#{offset}"
  options.each do |option, value|
    url << "&#{option}=#{value}"
  end

  response = RSpotify.get(url)
  return response if RSpotify.raw_response
  response['playlists']['items'].map { |i| Playlist.new i }
end

.find(user_id, id, market: nil) ⇒ Playlist

Returns Playlist object with user_id and id provided. If id is “starred”, returns starred playlist from user.

Examples:

playlist = RSpotify::Playlist.find('wizzler', '00wHcTN0zQiun4xri9pmvX')
playlist.class #=> RSpotify::Playlist
playlist.name  #=> "Movie Soundtrack Masterpieces"

Parameters:

  • user_id (String)
  • id (String)
  • market (String) (defaults to: nil)

    Optional. An ISO 3166-1 alpha-2 country code. Provide this parameter if you want to apply Track Relinking

Returns:


52
53
54
55
56
57
58
59
60
# File 'lib/rspotify/playlist.rb', line 52

def self.find(user_id, id, market: nil)
  url = "users/#{user_id}/"
  url << (id == 'starred' ? id : "playlists/#{id}")
  url << "?market=#{market}" if market

  response = RSpotify.resolve_auth_request(user_id, url)
  return response if RSpotify.raw_response
  Playlist.new response
end

.find_by_id(id, market: nil) ⇒ Playlist

Returns Playlist object with id provided.

Examples:

playlist = RSpotify::Playlist.find_by_id('00wHcTN0zQiun4xri9pmvX')
playlist.class #=> RSpotify::Playlist
playlist.name  #=> "Movie Soundtrack Masterpieces"

Parameters:

  • id (String)
  • market (String) (defaults to: nil)

    Optional. An ISO 3166-1 alpha-2 country code. Provide this parameter if you want to apply Track Relinking

Returns:


72
73
74
75
76
77
78
# File 'lib/rspotify/playlist.rb', line 72

def self.find_by_id(id, market: nil)
  url = "playlists/#{id}"
  url << "?market=#{market}" if market
  response = RSpotify.resolve_auth_request(nil, url)
  return response if RSpotify.raw_response
  Playlist.new response
end

.search(query, limit: 20, offset: 0) ⇒ Array<Playlist>

Returns array of Playlist objects matching the query. It's also possible to find the total number of search results for the query

Examples:

playlists = RSpotify::Playlist.search('Indie')
playlists = RSpotify::Playlist.search('Indie', limit: 10)

RSpotify::Playlist.search('Indie').total #=> 14653

Parameters:

  • query (String)

    The search query's keywords. See the q description in here for details.

  • limit (Integer) (defaults to: 20)

    Maximum number of playlists to return. Maximum: 50. Default: 20.

  • offset (Integer) (defaults to: 0)

    The index of the first playlist to return. Use with limit to get the next set of playlists. Default: 0.

Returns:


92
93
94
# File 'lib/rspotify/playlist.rb', line 92

def self.search(query, limit: 20, offset: 0)
  super(query, 'playlist', limit: limit, offset: offset)
end

Instance Method Details

#add_tracks!(tracks, position: nil) ⇒ Array<Track>

Adds one or more tracks to a playlist in user's Spotify account. This method is only available when the current user has granted access to the playlist-modify-public and playlist-modify-private scopes.

Examples:

tracks = RSpotify::Track.search('Know', 30)
playlist = user.create_playlist!('my-awesome-playlist')

playlist.add_tracks!(tracks)
playlist.tracks.size       #=> 30
playlist.tracks.first.name #=> "Somebody That I Used To Know"

playlist.add_tracks!(tracks, position: 20)
playlist.tracks[20].name #=> "Somebody That I Used To Know"

Parameters:

  • tracks (Array<Track>, Array<String>)

    Tracks to be added. Either array of Tracks or strings where each string is a valid spotify track uri. Maximum: 100 per request

  • position (Integer, NilClass) (defaults to: nil)

    The position to insert the tracks, a zero-based index. Default: tracks are appended to the playlist

Returns:

  • (Array<Track>)

    The tracks added


152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/rspotify/playlist.rb', line 152

def add_tracks!(tracks, position: nil)
  track_uris = nil
  if tracks.first.is_a? String
    track_uris = tracks.join(',')
  else
    track_uris = tracks.map(&:uri).join(',')
  end
  url = "#{@path}/tracks?uris=#{track_uris}"
  url << "&position=#{position}" if position

  response = User.oauth_post(@owner.id, url, {}.to_json)
  @total += tracks.size
  @tracks_cache = nil

  if RSpotify::raw_response
    @snapshot_id = JSON.parse(response)['snapshot_id']
    return response
  end

  @snapshot_id = response['snapshot_id']
  tracks
end

#change_details!(**data) ⇒ Playlist

Change name and public/private state of playlist in user's Spotify account. Changing a public playlist requires the playlist-modify-public scope; changing a private playlist requires the playlist-modify-private scope.

Examples:

playlist.name   #=> "Movie Soundtrack Masterpieces"
playlist.public #=> true

playlist.change_details!(name: 'Movie Tracks', public: false)

playlist.name   #=> "Movie Tracks"
playlist.public #=> false

Parameters:

  • name (String)

    Optional. The new name for the playlist.

  • public (Boolean)

    Optional. If true the playlist will be public, if false it will be private.

Returns:


190
191
192
193
194
195
196
197
# File 'lib/rspotify/playlist.rb', line 190

def change_details!(**data)
  User.oauth_put(@owner.id, @path, data.to_json)
  data.each do |field, value|
    instance_variable_set("@#{field}", value)
  end
  @snapshot_id = nil
  self
end

#complete!Object

Note:

It is seldom necessary to use this method explicitly, since RSpotify takes care of it automatically when needed (see Base#method_missing)

When an object is obtained undirectly, Spotify usually returns a simplified version of it. This method updates it into a full object, with all attributes filled.

Examples:

playlist = user.playlists.first
playlist.instance_variable_get("@description") #=> nil
playlist.complete!
playlist.instance_variable_get("@description") #=> "Iconic soundtracks..."

209
210
211
# File 'lib/rspotify/playlist.rb', line 209

def complete!
  initialize RSpotify.resolve_auth_request(@owner.id, @path)
end

#is_followed_by?(users) ⇒ Array<Boolean>

Check if one or more Spotify users are following a specified playlist. Checking if the user is privately following a playlist is only possible if he/she has granted access to the playlist-read-private scope.

Examples:

user1 = RSpotify::User.find('<some-id>')
user2 = RSpotify::User.find('<some-other-id>')
playlist.is_followed_by?([user1, user2]) #=> [true, true] (Users publicly following playlist)

oauth-user = RSpotify::User.new(request.env['omniauth.auth']) # (See OAuth section in readme)
playlist.is_followed_by?([oauth-user]) #=> [true] (User publicly or privately following playlist)

Parameters:

  • users (Array<User>)

    The users to check. Maximum: 5.

Returns:

  • (Array<Boolean>)

226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/rspotify/playlist.rb', line 226

def is_followed_by?(users)
  user_ids = users.map(&:id).join(',')
  url = "#{@path}/followers/contains?ids=#{user_ids}"

  users_credentials = if User.class_variable_defined?('@@users_credentials')
    User.class_variable_get('@@users_credentials')
  end

  auth_users = users.select do |user|
    users_credentials[user.id]
  end if users_credentials

  if auth_users && auth_users.any?
    User.oauth_get(auth_users.first.id, url)
  else
    RSpotify.get(url)
  end
end

#remove_tracks!(tracks, snapshot_id: nil) ⇒ Playlist

Remove one or more tracks from a user’s playlist. Removing from a public playlist requires the playlist-modify-public scope; removing from a private playlist requires the playlist-modify-private scope.

Examples:

# Remove all occurrences of one or more tracks
love_tracks = RSpotify::Track.search('Love')
playlist.remove_tracks!(love_tracks)

# Remove specific occurrences of one or more tracks
track = RSpotify::Track.find('tR3oH...')
playlist.remove_tracks!([{track: track, positions: [0,3]}, other_track])

# Remove tracks based only on their positions (requires snapshot id)
positions = [0,3,8]
playlist.remove_tracks!(positions, snapshot_id: '0ZvtH...')

Parameters:

  • tracks (Array<Track,Hash>, Array<Integer>)

    Tracks to be removed. Maximum: 100 per request

  • snapshot_id (String) (defaults to: nil)

    Optional. The playlist's snapshot ID against which you want to make the changes.

Returns:


305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'lib/rspotify/playlist.rb', line 305

def remove_tracks!(tracks, snapshot_id: nil)
  positions = tracks if tracks.first.is_a? Integer

  tracks = tracks.map do |track|
    next { uri: track.uri } if track.is_a? Track
    {
      uri: track[:track].uri,
      positions: track[:positions]
    }
  end unless positions

  params = {
    method: :delete,
    url: URI::encode(RSpotify::API_URI + @path + '/tracks'),
    headers: User.send(:oauth_header, @owner.id),
    payload: positions ? { positions: positions } : { tracks: tracks }
  }

  params[:payload][:snapshot_id] = snapshot_id if snapshot_id
  params[:payload] = params[:payload].to_json
  response = RestClient::Request.execute(params)

  @snapshot_id = JSON.parse(response)['snapshot_id']
  @tracks_cache = nil
  self
end

#reorder_tracks!(range_start, insert_before, **options) ⇒ Playlist

Reorder a track or a group of tracks in a playlist. Changing a public playlist requires the playlist-modify-public scope; changing a private playlist requires the playlist-modify-private scope.

Examples:

range_start = 10
insert_before = 0
# Move the tracks at index 10-14 to the start of the playlist
playlist.reorder_tracks!(range_start, insert_before, range_length: 5)

Parameters:

  • range_start (Integer)

    The position of the first track to be reordered.

  • insert_before (Integer)

    The position where the tracks should be inserted. To reorder the tracks to the end of the playlist, simply set insert_before to the position after the last track.

  • range_length (Integer)

    Optional. The amount of tracks to be reordered. Default: 1.

  • snapshot_id (String)

    Optional. The playlist's snapshot ID against which you want to make the changes.

Returns:


346
347
348
349
350
351
352
353
354
355
356
357
358
359
# File 'lib/rspotify/playlist.rb', line 346

def reorder_tracks!(range_start, insert_before, **options)
  url = "#{@path}/tracks"
  data = {
    range_start: range_start,
    insert_before: insert_before
  }.merge options

  response = User.oauth_put(@owner.id, url, data.to_json)
  json = RSpotify.raw_response ? JSON.parse(response) : response

  @snapshot_id = json['snapshot_id']
  @tracks_cache = nil
  self
end

#replace_image!(image, content_type) ⇒ NilClass

Replace the image used to represent a specific playlist. Requires ugc-image-upload scope. Changing a public playlist requires the playlist-modify-public scope; changing a private playlist requires the playlist-modify-private scope.

Examples:

playlist.replace_image!('SkZJRgABA...', 'image/jpeg')

Parameters:

  • image (String)

    Base64 encoded JPEG image data, maximum payload size is 256 KB

  • content_type (String)

    The content type of the request body, e.g. “image/jpeg”

Returns:

  • (NilClass)

    When the image has been provided, Spofity forwards it on to their transcoder service in order to generate the three sizes provided in the playlist’s images object. This operation takes some time, that's why nothing is returned for this method.


370
371
372
373
374
375
376
377
# File 'lib/rspotify/playlist.rb', line 370

def replace_image!(image, content_type)
  url = "#{@path}/images"
  headers = {
    'Content-Type' => content_type
  }
  User.oauth_put(@owner.id, url, image, { headers: headers })
  nil
end

#replace_tracks!(tracks) ⇒ Array<Track>

Replace all the tracks in a playlist, overwriting its existing tracks. Changing a public playlist requires the playlist-modify-public scope; changing a private playlist requires the playlist-modify-private scope.

Examples:

playlist.tracks.map(&:name) #=> ["All of Me", "Wasted Love", "Love Runs Out"]
tracks = RSpotify::Track.search('Know', limit: 2)
playlist.replace_tracks!(tracks)
playlist.tracks.map(&:name) #=> ["Somebody That I Used To Know", "Do I Wanna Know?"]

Parameters:

  • tracks (Array<Track>)

    The tracks that will replace the existing ones. Maximum: 100 per request

Returns:

  • (Array<Track>)

    The tracks that were added.


390
391
392
393
394
395
396
397
398
399
# File 'lib/rspotify/playlist.rb', line 390

def replace_tracks!(tracks)
  track_uris = tracks.map(&:uri).join(',')
  url = "#{@path}/tracks?uris=#{track_uris}"
  User.oauth_put(@owner.id, url, {}.to_json)

  @total = tracks.size
  @tracks_cache = nil
  @snapshot_id = nil
  tracks
end

#tracks(limit: 100, offset: 0, market: nil) ⇒ Array<Track>

Returns array of tracks from the playlist

Examples:

playlist = RSpotify::Playlist.find('wizzler', '00wHcTN0zQiun4xri9pmvX')
playlist.tracks.first.name #=> "Main Theme from Star Wars - Instrumental"

Parameters:

  • limit (Integer) (defaults to: 100)

    Maximum number of tracks to return. Maximum: 100. Default: 100.

  • offset (Integer) (defaults to: 0)

    The index of the first track to return. Use with limit to get the next set of objects. Default: 0.

  • market (String) (defaults to: nil)

    Optional. An ISO 3166-1 alpha-2 country code. Provide this parameter if you want to apply Track Relinking

Returns:


255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
# File 'lib/rspotify/playlist.rb', line 255

def tracks(limit: 100, offset: 0, market: nil)
  last_track = offset + limit - 1
  if @tracks_cache && last_track < 100 && !RSpotify.raw_response
    return @tracks_cache[offset..last_track]
  end

  url = "#{@href}/tracks?limit=#{limit}&offset=#{offset}"
  url << "&market=#{market}" if market
  response = RSpotify.resolve_auth_request(@owner.id, url)

  json = RSpotify.raw_response ? JSON.parse(response) : response
  tracks = json['items'].select { |i| i['track'] }

  @tracks_added_at = hash_for(tracks, 'added_at') do |added_at|
    Time.parse added_at
  end

  @tracks_added_by = hash_for(tracks, 'added_by') do |added_by|
    User.new added_by
  end

  @tracks_is_local = hash_for(tracks, 'is_local') do |is_local|
    is_local
  end

  tracks.map! { |t| Track.new t['track'] }
  @tracks_cache = tracks if limit == 100 && offset == 0
  return response if RSpotify.raw_response
  tracks
end