def get_playlists(self, limit=const.MAX_PLAYLISTS): """ Args: limit (int): The max number of items to return. Must be between 1 and 100,000 inclusive. Default is 100,000. Returns: List[Playlist]: The playlists the user has in their library. Could be empty. Note: This includes both playlists owned by this user and playlists that this user follows but are owned by others. Required token scopes: - playlist-read-private - playlist-read-collaborative Calls endpoints: - GET /v1/users/{user_id}/playlists To get only playlists this user follows, use get_following(sp.PLAYLISTS) """ # Validate inputs if limit <= 0 or limit > const.MAX_PLAYLISTS: raise ValueError(limit) endpoint = Endpoints.USER_PLAYLISTS % self.spotify_id() return utils.paginate_get(self._session, limit=limit, return_class=Playlist, endpoint=endpoint, uri_params={}, body=None)
def top(self, top_type, limit, time_range=const.MEDIUM): """ Get the top artists or tracks for the user over a time range. Args: top_type: Get top items of this type. One of: - sp.ARTISTS - sp.TRACKS limit (int): Max number of items to return. Must be positive. time_range: get top items for this time range. One of: - sp.LONG (several years) - sp.MEDIUM (about 6 months) - sp.SHORT (about 4 weeks) Returns: A list of artists or a list of tracks, depending on top_type. Could return an empty list. Required token scopes: - user-top-read Calls endpoints: - GET /v1/me/top/{type} Note: Spotify defines "top items" using internal metrics. """ # Validate arguments if top_type not in [const.ARTISTS, const.TRACKS]: raise TypeError(top_type) if time_range not in [const.LONG, const.MEDIUM, const.SHORT]: raise TypeError(time_range) if limit <= 0: raise ValueError(limit) # Parse arguments time_ranges = { const.LONG: 'long_term', const.MEDIUM: 'medium_term', const.SHORT: 'short_term', } uri_params = {'time_range': time_ranges[time_range]} endpoint_type = 'artists' if top_type == const.ARTISTS else 'tracks' return_class = Artist if top_type == const.ARTISTS else Track # Execute requests return utils.paginate_get(self._session, limit=limit, return_class=return_class, endpoint=Endpoints.USER_TOP % endpoint_type, uri_params=uri_params, body=None)
def tracks(self, start=0, num_tracks=None, market=const.TOKEN_REGION): """ Returns one or more tracks in the playlist. Returns the specified number of tracks in the playlist starting at the given position. Returns all of the tracks in the playlist when called with the default parameters. Args: start: An integer specifying the 0-indexed position of the first track to return. A negative integer will be evaluated from the end of the playlist as negative indices behave in lists. This must be a valid index into a list of length len(playlist). Can be omitted to return tracks starting from the first song in the playlist. num_tracks: A nonnegative integer specifying the number of tracks to return. If num_tracks is greater than len(playlist) or if num_tracks is omitted, returns as many tracks as are present at start. market: A 2 letter country code as defined here: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 Used for track relinking: https://developer.spotify.com/documentation/general/guides/track-relinking-guide/ If omitted, will use the appropriate country code based on the auth token and location. Returns: List[Track]: The tracks specified by the arguments. Calls endpoints: - GET /v1/playlists/{playlist_id}/tracks """ endpoint = Endpoints.PLAYLIST_TRACKS % self.spotify_id() if not isinstance(start, int): raise TypeError('The start index must be an integer') original_start = start if start < 0: start += len(self) if start < 0 or start >= len(self): raise ValueError(f'Invalid start: {original_start}') if num_tracks: if not isinstance(num_tracks, int): raise TypeError('The number of tracks must be an integer') if num_tracks < 0: raise ValueError(f'Invalid num_tracks: {num_tracks}') if not num_tracks: num_tracks = sys.maxsize uri_params = {} uri_params['market'] = market tracks = utils.paginate_get(self._session, num_tracks, Track, endpoint, uri_params=uri_params) return tracks[start:]
def get_saved(self, saved_type, limit=None, market=const.TOKEN_REGION): """ Get all saved_type objects the user has saved to their library. Args: saved_type: one of: - sp.ALBUMS - sp.TRACKS limit (int): the max number of items to return. If None, will return all. Must be positive. market (str): a :term:`market code <Market>` used for :term:`track relinking <Track Relinking>`. Only used if saved_type is sp.TRACKS (relinked albums are not yet supported by spotifython). Returns: List of saved_type objects. Could be empty. Required token scopes: - user-library-read Calls endpoints: - GET /v1/me/albums - GET /v1/me/tracks """ # Validate inputs if saved_type not in [const.ALBUMS, const.TRACKS]: raise TypeError(saved_type) if limit is None: # Lists can't be longer than sys.maxsize in python limit = sys.maxsize if limit <= 0: raise ValueError(limit) # Make request endpoint_type = 'albums' if saved_type == const.ALBUMS else 'tracks' return_class = Album if saved_type == const.ALBUMS else Track uri_params = {'market': market} return utils.paginate_get(self._session, limit=limit, return_class=return_class, endpoint=Endpoints.USER_SAVED % endpoint_type, uri_params=uri_params, body=None)
def _update_tracks(self): """ Update self._tracks using the album id. Calls endpoints: - GET /v1/albums/{id}/tracks """ # Only populate tracks if necessary if self._tracks is not None: return self._tracks = utils.paginate_get( session=self._session, limit=sys.maxsize, return_class=Track, endpoint=Endpoints.ALBUM_DATA % self.spotify_id() )
def albums(self, search_limit=None, include_groups=None, market=const.TOKEN_REGION): """ Get the albums associated with the artist. Args: search_limit (int): the maximum number of results to return. If None, return all items. include_groups (List[]): a list of keywords that will be used to filter the response. If not supplied, all album types will be returned. Valid values are: - sp.ARTIST_ALBUM - sp.ARTIST_SINGLE - sp.ARTIST_APPEARS_ON - sp.ARTIST_COMPILATION market (str): a :term:`market code <Market>` or sp.TOKEN_REGION, used for :term:`track relinking <Track Relinking>`. Note: If market is None, results will be returned for all countries and you are likely to get duplicate results per album, one for each country in which the album is available! Returns: List[Album]: The artist's albums. Calls endpoints: - GET /v1/artists/{id}/albums """ # Validation if (search_limit is not None and not isinstance(search_limit, int)) or \ (isinstance(search_limit, int) and search_limit < 1): raise TypeError('search_limit should be None or an int > 0') if include_groups is not None and \ not all(isinstance(x, str) for x in include_groups): raise TypeError('include_groups should be None or str') if market is not None and not isinstance(market, str): raise TypeError('market should be None or str') # Lazy loading check search_query = (search_limit, include_groups, market) if search_query == self._albums_query_params: return self._albums # Construct params for API call endpoint = Endpoints.ARTIST_ALBUMS % self.spotify_id() uri_params = dict() if include_groups is not None and len(include_groups) > 0: uri_params['include_groups'] = ','.join(include_groups) if market is not None: uri_params['market'] = market # Update stored params for lazy loading self._albums = utils.paginate_get(session=self._session, limit=search_limit, return_class=Album, endpoint=endpoint, uri_params=uri_params ) self._albums_query_params = search_query return self._albums