class SpotifyUser(SpotifyBase): @send_and_process(single(PublicUser)) def user(self, user_id: str) -> PublicUser: """ Get a user's profile. Parameters ---------- user_id user ID Returns ------- PublicUser public user information """ return self._get('users/' + user_id) @send_and_process(single(PrivateUser)) def current_user(self) -> PrivateUser: """ Get current user's profile. Requires the user-read-private scope to return user's country and product subscription level. Requires the user-read-email scope to return user's email. Returns ------- PrivateUser private user information """ return self._get('me/')
class SpotifyEpisode(SpotifyBase): @send_and_process(single(FullEpisode)) def episode(self, episode_id: str, market: str = None) -> FullEpisode: """ Get information for an episode. Parameters ---------- episode_id episode ID market an ISO 3166-1 alpha-2 country code. If a user token is used to authenticate, the country associated with it overrides this parameter. If an application token is used and no market is specified, the episode is considered unavailable. Returns ------- FullEpisode episode object """ return self._get('episodes/' + episode_id, market=market) @chunked('episode_ids', 1, 50, join_lists) @send_and_process(model_list(FullEpisode, 'episodes')) def episodes(self, episode_ids: list, market: str = None) -> ModelList: """ Get information for multiple episodes. Parameters ---------- episode_ids the episode IDs, max 50 without chunking market an ISO 3166-1 alpha-2 country code. If a user token is used to authenticate, the country associated with it overrides this parameter. If an application token is used and no market is specified, the episode is considered unavailable. Returns ------- ModelList list of episode objects """ return self._get('episodes/?ids=' + ','.join(episode_ids), market=market)
class SpotifyBrowse(SpotifyBase): @send_and_process(multiple( top_item('message'), single(SimplePlaylistPaging, from_item='playlists') )) @maximise_limit(50) def featured_playlists( self, country: str = None, locale: str = None, timestamp: str = None, limit: int = 20, offset: int = 0 ) -> Tuple[str, SimplePlaylistPaging]: """ Get a list of Spotify featured playlists. Parameters ---------- country an ISO 3166-1 alpha-2 country code locale 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 timestamp Timestamp in ISO 8601 format: yyyy-MM-ddTHH:mm:ss. Used to specify the user's local time to get results tailored for that specific date and time in the day. limit the number of items to return (1..50) offset the index of the first item to return Returns ------- tuple (str, SimplePlaylistPaging): message for the playlists and a list of simplified playlist objects wrapped in a paging object """ return self._get( 'browse/featured-playlists', locale=locale, country=country, timestamp=timestamp, limit=limit, offset=offset ) @send_and_process(single(SimpleAlbumPaging, from_item='albums')) @maximise_limit(50) def new_releases( self, country: str = None, limit: int = 20, offset: int = 0 ) -> SimpleAlbumPaging: """ Get a list of new album releases featured in Spotify. Parameters ---------- country an ISO 3166-1 alpha-2 country code limit the number of items to return (1..50) offset the index of the first item to return Returns ------- SimpleAlbumPaging paging containing simplified album objects """ return self._get( 'browse/new-releases', country=country, limit=limit, offset=offset ) @send_and_process(single(CategoryPaging, from_item='categories')) @maximise_limit(50) def categories( self, country: str = None, locale: str = None, limit: int = 20, offset: int = 0 ) -> CategoryPaging: """ Get a list of categories used to tag items in Spotify. Parameters ---------- country an ISO 3166-1 alpha-2 country code locale 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 limit the number of items to return (1..50) offset the index of the first item to return Returns ------- CategoryPaging paging object containing a list of categories """ return self._get( 'browse/categories', country=country, locale=locale, limit=limit, offset=offset ) @send_and_process(single(Category)) def category( self, category_id: str, country: str = None, locale: str = None ) -> Category: """ Get a single category used to tag items in Spotify. Parameters ---------- category_id category ID country an ISO 3166-1 alpha-2 country code locale 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 Returns ------- Category category object """ return self._get( 'browse/categories/' + category_id, country=country, locale=locale ) @send_and_process(single(SimplePlaylistPaging, from_item='playlists')) @maximise_limit(50) def category_playlists( self, category_id: str, country: str = None, limit: int = 20, offset: int = 0 ) -> SimplePlaylistPaging: """ Get a list of Spotify playlists tagged with a particular category. Parameters ---------- category_id category ID country an ISO 3166-1 alpha-2 country code limit the number of items to return (1..50) offset the index of the first item to return Returns ------- SimplePlaylistPaging paging object containing a list of simplified playlist objects """ return self._get( f'browse/categories/{category_id}/playlists', country=country, limit=limit, offset=offset ) @send_and_process(single(Recommendations)) @maximise_limit(100) def recommendations( self, artist_ids: list = None, genres: list = None, track_ids: list = None, limit: int = 20, market: str = None, **attributes ) -> Recommendations: """ Get a list of recommended tracks for seeds. Up to 5 seed values may be provided as artists, genres and tracks. Parameters ---------- artist_ids list of seed artist IDs genres list of seed genre names track_ids list of seed artist IDs limit the number of items to return (1..100) market an ISO 3166-1 alpha-2 country code or 'from_token' attributes min/max/target_<attribute> - For all tuneable track attributes see :class:`tekore.model.recommendations.RecommendationAttribute`, these values provide filters and targeting on results. Returns ------- Recommendations recommendations object containing track recommendations and seeds """ params = dict(limit=limit) if artist_ids is not None: params['seed_artists'] = ','.join(artist_ids) if genres is not None: params['seed_genres'] = ','.join(genres) if track_ids is not None: params['seed_tracks'] = ','.join(track_ids) if market is not None: params['market'] = market validate_attributes(attributes) params.update(attributes) return self._get('recommendations', **params) @send_and_process(top_item('genres')) def recommendation_genre_seeds(self) -> List[str]: """ Get a list of available genre seeds. Returns ------- list list of genres to use as seeds """ return self._get('recommendations/available-genre-seeds')
class SpotifyPersonalisation(SpotifyBase): @send_and_process(single(FullArtistOffsetPaging)) @maximise_limit(50) def current_user_top_artists( self, time_range: str = 'medium_term', limit: int = 20, offset: int = 0 ) -> FullArtistOffsetPaging: """ Get the current user's top artists. Requires the user-top-read scope. Parameters ---------- time_range Over what time frame are the affinities computed. Valid-values: short_term, medium_term, long_term limit the number of items to return (1..50) offset the index of the first item to return Returns ------- FullArtistOffsetPaging paging object containing artists """ return self._get( 'me/top/artists', time_range=time_range, limit=limit, offset=offset ) @send_and_process(single(FullTrackPaging)) @maximise_limit(50) def current_user_top_tracks( self, time_range: str = 'medium_term', limit: int = 20, offset: int = 0 ) -> FullTrackPaging: """ Get the current user's top tracks. Requires the user-top-read scope. Parameters ---------- time_range Over what time frame are the affinities computed. Valid-values: short_term, medium_term, long_term limit the number of items to return (1..50) offset the index of the first item to return Returns ------- FullTrackPaging paging object containing full tracks """ return self._get( 'me/top/tracks', time_range=time_range, limit=limit, offset=offset )
class SpotifyFollow(SpotifyBase): @chunked('user_ids', 2, 5, join_lists) @send_and_process(nothing) def playlist_is_following(self, playlist_id: str, user_ids: list) -> List[bool]: """ Check to see if the given users are following a playlist. Requires the playlist-read-private scope to check private playlists. Parameters ---------- playlist_id playlist ID user_ids list of user IDs, max 5 without chunking Returns ------- list list of booleans in the same order that the user IDs were given """ return self._get(f'playlists/{playlist_id}/followers/contains', ids=','.join(user_ids)) @send_and_process(nothing) def playlist_follow(self, playlist_id: str, public: bool = True) -> None: """ Follow a playlist as current user. Requires the playlist-modify-public scope. Following privately requires the playlist-modify-private scope. Parameters ---------- playlist_id playlist ID public follow publicly """ payload = {'public': public} return self._put(f'playlists/{playlist_id}/followers', payload=payload) @send_and_process(nothing) def playlist_unfollow(self, playlist_id: str) -> None: """ Unfollow a playlist as current user. Requires the playlist-modify-public scope. Unfollowing a privately followed playlist requires the playlist-modify-private scope. Parameters ---------- playlist_id playlist ID """ return self._delete(f'playlists/{playlist_id}/followers') @send_and_process(single(FullArtistCursorPaging, from_item='artists')) @maximise_limit(50) def followed_artists(self, limit: int = 20, after: str = None) -> FullArtistCursorPaging: """ Get artists followed by the current user. Requires the user-follow-read scope. Parameters ---------- limit the number of items to return (1..50) after the last artist ID retrieved from the previous request Returns ------- FullArtistCursorPaging cursor-based paging object containing a list of full artist objects """ return self._get('me/following', type='artist', limit=limit, after=after) @chunked('artist_ids', 1, 50, join_lists) @send_and_process(nothing) def artists_is_following(self, artist_ids: list) -> List[bool]: """ Check if current user follows artists. Requires the user-follow-read scope. Parameters ---------- artist_ids list of artist IDs, max 50 without chunking Returns ------- list list of booleans in the same order that the artist IDs were given """ return self._get('me/following/contains', type='artist', ids=','.join(artist_ids)) @chunked('artist_ids', 1, 50, return_none) @send_and_process(nothing) def artists_follow(self, artist_ids: list) -> None: """ Follow artists as current user. Requires the user-follow-modify scope. Parameters ---------- artist_ids list of artist IDs, max 50 without chunking """ return self._put('me/following', type='artist', ids=','.join(artist_ids)) @chunked('artist_ids', 1, 50, return_none) @send_and_process(nothing) def artists_unfollow(self, artist_ids: list) -> None: """ Unfollow artists as current user. Requires the user-follow-modify scope. Parameters ---------- artist_ids list of artist IDs, max 50 without chunking """ return self._delete('me/following', type='artist', ids=','.join(artist_ids)) @chunked('user_ids', 1, 50, join_lists) @send_and_process(nothing) def users_is_following(self, user_ids: list) -> List[bool]: """ Check if current user follows users. Requires the user-follow-read scope. Parameters ---------- user_ids list of user IDs, max 50 without chunking Returns ------- list list of booleans in the same order that the user IDs were given """ return self._get('me/following/contains', type='user', ids=','.join(user_ids)) @chunked('user_ids', 1, 50, return_none) @send_and_process(nothing) def users_follow(self, user_ids: list) -> None: """ Follow users as current user. Requires the user-follow-modify scope. Parameters ---------- user_ids list of user IDs, max 50 without chunking """ return self._put('me/following', type='user', ids=','.join(user_ids)) @chunked('user_ids', 1, 50, return_none) @send_and_process(nothing) def users_unfollow(self, user_ids: list) -> None: """ Unfollow users as current user. Requires the user-follow-modify scope. Parameters ---------- user_ids list of user IDs, max 50 without chunking """ return self._delete('me/following', type='user', ids=','.join(user_ids))
class SpotifyTrack(SpotifyBase): @send_and_process(single(FullTrack)) def track(self, track_id: str, market: str = None) -> FullTrack: """ Get information for a track. Parameters ---------- track_id track ID market an ISO 3166-1 alpha-2 country code or 'from_token' Returns ------- FullTrack track object """ return self._get('tracks/' + track_id, market=market) @chunked('track_ids', 1, 50, join_lists) @send_and_process(model_list(FullTrack, 'tracks')) def tracks(self, track_ids: list, market: str = None) -> ModelList: """ Get information for multiple tracks. Parameters ---------- track_ids the track IDs, max 50 without chunking market an ISO 3166-1 alpha-2 country code or 'from_token' Returns ------- ModelList list of track objects """ return self._get('tracks/?ids=' + ','.join(track_ids), market=market) @send_and_process(single(AudioAnalysis)) def track_audio_analysis(self, track_id: str) -> AudioAnalysis: """ Get a detailed audio analysis for a track. The analysis describes the track's structure and musical content, including rythm, pitch and timbre. Returns ------- AudioAnalysis audio analysis """ return self._get('audio-analysis/' + track_id) @send_and_process(single(AudioFeatures)) def track_audio_features(self, track_id: str) -> AudioFeatures: """ Get audio feature information for a track. Returns ------- AudioFeatures audio features object """ return self._get('audio-features/' + track_id) @chunked('track_ids', 1, 100, join_lists) @send_and_process(model_list(AudioFeatures, 'audio_features')) def tracks_audio_features(self, track_ids: list) -> ModelList: """ Get audio feature information for multiple tracks. Feature information for a track may be ``None`` if not available. Parameters ---------- track_ids track IDs, max 100 without chunking Returns ------- ModelList list of audio features objects """ return self._get('audio-features?ids=' + ','.join(track_ids))
class SpotifyAlbum(SpotifyBase): @send_and_process(single(FullAlbum)) def album(self, album_id: str, market: str = None) -> FullAlbum: """ Get an album. Parameters ---------- album_id album ID market an ISO 3166-1 alpha-2 country code or 'from_token' Returns ------- FullAlbum full album object """ return self._get('albums/' + album_id, market=market) @send_and_process(single(SimpleTrackPaging)) @maximise_limit(50) def album_tracks(self, album_id: str, market: str = None, limit: int = 20, offset: int = 0) -> SimpleTrackPaging: """ Get tracks on album. Parameters ---------- album_id album ID market an ISO 3166-1 alpha-2 country code or 'from_token' limit the number of items to return (1..50) offset the index of the first item to return Returns ------- SimpleTrackPaging paging containing simplified track objects """ return self._get(f'albums/{album_id}/tracks', market=market, limit=limit, offset=offset) @chunked('album_ids', 1, 20, join_lists) @send_and_process(model_list(FullAlbum, 'albums')) def albums(self, album_ids: list, market: str = None) -> ModelList: """ Get multiple albums. Parameters ---------- album_ids list of album IDs, max 20 without chunking market an ISO 3166-1 alpha-2 country code or 'from_token' Returns ------- ModelList list of full album objects """ return self._get('albums/?ids=' + ','.join(album_ids), market=market)
class SpotifyShow(SpotifyBase): @send_and_process(single(FullShow)) def show(self, show_id: str, market: str = None) -> FullShow: """ Get information for a show. Reading the user's episode resume points requires the user-read-playback-position scope. Parameters ---------- show_id show ID market an ISO 3166-1 alpha-2 country code. If a user token is used to authenticate, the country associated with it overrides this parameter. If an application token is used and no market is specified, the show is considered unavailable. Returns ------- FullShow show object """ return self._get('shows/' + show_id, market=market) @chunked('show_ids', 1, 50, join_lists) @send_and_process(model_list(FullShow, 'shows')) def shows(self, show_ids: list, market: str = None) -> ModelList: """ Get information for multiple shows. Reading the user's episode resume points requires the user-read-playback-position scope. Parameters ---------- show_ids the show IDs, max 50 without chunking market an ISO 3166-1 alpha-2 country code. If a user token is used to authenticate, the country associated with it overrides this parameter. If an application token is used and no market is specified, the show is considered unavailable. Returns ------- ModelList list of show objects """ return self._get('shows/?ids=' + ','.join(show_ids), market=market) @send_and_process(single(SimpleEpisodePaging)) @maximise_limit(50) def show_episodes(self, show_id: str, market: str = None, limit: int = 20, offset: int = 0) -> SimpleEpisodePaging: """ Get episodes of a show. Parameters ---------- show_id show ID market an ISO 3166-1 alpha-2 country code. If a user token is used to authenticate, the country associated with it overrides this parameter. If an application token is used and no market is specified, the show is considered unavailable. limit the number of items to return (1..50) offset the index of the first item to return Returns ------- SimpleEpisodePaging paging containing simplified episode objects """ return self._get(f'shows/{show_id}/episodes', market=market, limit=limit, offset=offset)
class SpotifyArtist(SpotifyBase): @send_and_process(single(FullArtist)) def artist(self, artist_id: str) -> FullArtist: """ Get information for an artist. Parameters ---------- artist_id artist ID Returns ------- FullArtist full artist object """ return self._get('artists/' + artist_id) @chunked('artist_ids', 1, 50, join_lists) @send_and_process(model_list(FullArtist, 'artists')) def artists(self, artist_ids: list) -> ModelList: """ Get information for multiple artists. Parameters ---------- artist_ids list of artist IDs, max 50 without chunking Returns ------- ModelList list of full artist objects """ return self._get('artists/?ids=' + ','.join(artist_ids)) @send_and_process(single(SimpleAlbumPaging)) @maximise_limit(50) def artist_albums(self, artist_id: str, include_groups: List[Union[str, AlbumGroup]] = None, market: str = None, limit: int = 20, offset: int = 0) -> SimpleAlbumPaging: """ Get an artist's albums. Parameters ---------- artist_id the artist ID include_groups album groups to include in the response market an ISO 3166-1 alpha-2 country code or 'from_token' limit the number of items to return (1..50) offset the index of the first item to return Returns ------- SimpleAlbumPaging paging containing simple album objects """ if include_groups is not None: include_groups = ','.join(str(g) for g in include_groups) return self._get(f'artists/{artist_id}/albums', include_groups=include_groups, market=market, limit=limit, offset=offset) @send_and_process(model_list(FullTrack, 'tracks')) def artist_top_tracks(self, artist_id: str, market: str) -> ModelList: """ Get an artist's top 10 tracks by country. Parameters ---------- artist_id the artist ID market an ISO 3166-1 alpha-2 country code or 'from_token' Returns ------- ModelList list of full track objects """ return self._get(f'artists/{artist_id}/top-tracks', country=market) @send_and_process(model_list(FullArtist, 'artists')) def artist_related_artists(self, artist_id: str) -> ModelList: """ Get artists similar to an identified artist. Similarity is based on analysis of the Spotify community's listening history. Parameters ---------- artist_id artist ID Returns ------- ModelList list of full artist objects """ return self._get(f'artists/{artist_id}/related-artists')
class SpotifyPlaylistModify(SpotifyBase): @send_and_process(nothing) def playlist_cover_image_upload(self, playlist_id: str, image: str) -> None: """ Upload a custom playlist cover image. Requires the playlist-modify-public scope. To modify private playlists the playlist-modify-private scope is required. Parameters ---------- playlist_id playlist ID image image data as a base64-encoded string """ return Request(method='PUT', url=build_url(f'playlists/{playlist_id}/images'), headers=self._create_headers(content_type='image/jpeg'), data=image) @send_and_process(single(FullPlaylist)) def playlist_create(self, user_id: str, name: str, public: bool = True, description: str = '') -> FullPlaylist: """ Create a playlist. Requires the playlist-modify-public scope. To create a private playlist the playlist-modify-private scope is required. Parameters ---------- user_id user ID name the name of the playlist public is the created playlist public description the description of the playlist Returns ------- FullPlaylist created playlist """ payload = {'name': name, 'public': public, 'description': description} return self._post(f'users/{user_id}/playlists', payload=payload) @send_and_process(nothing) def playlist_change_details(self, playlist_id: str, name: str = None, public: bool = None, collaborative: bool = None, description: str = None) -> None: """ Change a playlist's details. Requires the playlist-modify-public scope. To modify private playlists the playlist-modify-private scope is required. Parameters ---------- playlist_id playlist ID name name of the playlist public is the playlist public collaborative is the playlist collaborative description description of the playlist """ payload = { 'name': name, 'public': public, 'collaborative': collaborative, 'description': description, } payload = {k: v for k, v in payload.items() if v is not None} return self._put('playlists/' + playlist_id, payload=payload)
class SpotifyLibrary(SpotifyBase): @send_and_process(single(SavedAlbumPaging)) @maximise_limit(50) def saved_albums(self, market: str = None, limit: int = 20, offset: int = 0) -> SavedAlbumPaging: """ Get a list of the albums saved in the current user's Your Music library. Requires the user-library-read scope. Parameters ---------- market an ISO 3166-1 alpha-2 country code or 'from_token' limit the number of items to return (1..50) offset the index of the first item to return Returns ------- SavedAlbumPaging paging object containing saved albums """ return self._get('me/albums', market=market, limit=limit, offset=offset) @chunked('album_ids', 1, 50, join_lists) @send_and_process(nothing) def saved_albums_contains(self, album_ids: list) -> List[bool]: """ Check if user has saved albums. Requires the user-library-read scope. Parameters ---------- album_ids list of album IDs, max 50 without chunking Returns ------- list list of booleans in the same order the album IDs were given """ return self._get('me/albums/contains?ids=' + ','.join(album_ids)) @chunked('album_ids', 1, 50, return_none) @send_and_process(nothing) def saved_albums_add(self, album_ids: list) -> None: """ Save albums for current user. Requires the user-library-modify scope. Parameters ---------- album_ids list of album IDs, max 50 without chunking """ return self._put('me/albums?ids=' + ','.join(album_ids)) @chunked('album_ids', 1, 50, return_none) @send_and_process(nothing) def saved_albums_delete(self, album_ids: list) -> None: """ Remove albums for current user. Requires the user-library-modify scope. Parameters ---------- album_ids list of album IDs, max 50 without chunking """ return self._delete('me/albums?ids=' + ','.join(album_ids)) @send_and_process(single(SavedTrackPaging)) @maximise_limit(50) def saved_tracks(self, market: str = None, limit: int = 20, offset: int = 0) -> SavedTrackPaging: """ Get a list of the songs saved in the current user's Your Music library. Requires the user-library-read scope. Parameters ---------- market an ISO 3166-1 alpha-2 country code or 'from_token' limit the number of items to return (1..50) offset the index of the first item to return Returns ------- SavedTrackPaging paging object containing saved tracks """ return self._get('me/tracks', market=market, limit=limit, offset=offset) @chunked('track_ids', 1, 50, join_lists) @send_and_process(nothing) def saved_tracks_contains(self, track_ids: list) -> List[bool]: """ Check if user has saved tracks. Requires the user-library-read scope. Parameters ---------- track_ids list of track IDs, max 50 without chunking Returns ------- list list of booleans in the same order the track IDs were given """ return self._get('me/tracks/contains?ids=' + ','.join(track_ids)) @chunked('track_ids', 1, 50, return_none) @send_and_process(nothing) def saved_tracks_add(self, track_ids: list) -> None: """ Save tracks for current user. Requires the user-library-modify scope. Parameters ---------- track_ids list of track IDs, max 50 without chunking """ return self._put('me/tracks/?ids=' + ','.join(track_ids)) @chunked('track_ids', 1, 50, return_none) @send_and_process(nothing) def saved_tracks_delete(self, track_ids: list) -> None: """ Remove tracks for current user. Requires the user-library-modify scope. Parameters ---------- track_ids list of track IDs, max 50 without chunking """ return self._delete('me/tracks/?ids=' + ','.join(track_ids)) @send_and_process(single(SavedShowPaging)) @maximise_limit(50) def saved_shows(self, market: str = None, limit: int = 20, offset: int = 0) -> SavedShowPaging: """ Get a list of the shows saved in the current user's Your Music library. Requires the user-library-read scope. Parameters ---------- market an ISO 3166-1 alpha-2 country code or 'from_token' limit the number of items to return (1..50) offset the index of the first item to return Returns ------- SavedShowPaging paging object containing saved shows """ return self._get('me/shows', market=market, limit=limit, offset=offset) @chunked('show_ids', 1, 50, join_lists) @send_and_process(nothing) def saved_shows_contains(self, show_ids: list) -> List[bool]: """ Check if user has saved shows. Requires the user-library-read scope. Parameters ---------- show_ids list of show IDs, max 50 without chunking Returns ------- list list of booleans in the same order the show IDs were given """ return self._get('me/shows/contains?ids=' + ','.join(show_ids)) @chunked('show_ids', 1, 50, return_none) @send_and_process(nothing) def saved_shows_add(self, show_ids: list) -> None: """ Save shows for current user. Requires the user-library-modify scope. Parameters ---------- show_ids list of show IDs, max 50 without chunking """ return self._put('me/shows/?ids=' + ','.join(show_ids)) @chunked('show_ids', 1, 50, return_none) @send_and_process(nothing) def saved_shows_delete(self, show_ids: list, market: str = None) -> None: """ Remove shows for current user. Requires the user-library-modify scope. Parameters ---------- show_ids list of show IDs, max 50 without chunking market an ISO 3166-1 alpha-2 country code, only remove shows that are available in the specified market, overrided by token's country """ return self._delete('me/shows/?ids=' + ','.join(show_ids), market=market)
class SpotifyPlayerView(SpotifyBase): @send_and_process(single(CurrentlyPlayingContext)) def playback(self, market: str = None, tracks_only: bool = False) -> CurrentlyPlayingContext: """ Get information about user's current playback. Requires the user-read-playback-state scope. Parameters ---------- market an ISO 3166-1 alpha-2 country code or 'from_token' tracks_only return only tracks in the currently playing item, if True, episodes have None as the currently playing item Returns ------- CurrentlyPlayingContext information about current playback """ if tracks_only is True: additional_types = None else: additional_types = 'episode' return self._get('me/player', market=market, additional_types=additional_types) @send_and_process(single(CurrentlyPlaying)) def playback_currently_playing( self, market: str = None, tracks_only: bool = False) -> CurrentlyPlaying: """ Get user's currently playing track. Requires the user-read-playback-state or the user-read-currently-playing scope. Parameters ---------- market an ISO 3166-1 alpha-2 country code or 'from_token' tracks_only return only tracks in the currently playing item, if True, episodes have None as the currently playing item Returns ------- CurrentlyPlaying information about the current track playing """ if tracks_only is True: additional_types = None else: additional_types = 'episode' return self._get('me/player/currently-playing', market=market, additional_types=additional_types) @send_and_process(single(PlayHistoryPaging)) @maximise_limit(50) def playback_recently_played(self, limit: int = 20, after: int = None, before: int = None) -> PlayHistoryPaging: """ Get tracks from the current user's recently played tracks. Only after or before should be specified at one time. Requires the user-read-recently-played scope. Parameters ---------- limit the number of items to return (1..50) after a unix timestamp in milliseconds, must not be specified with 'before' before a unix timestamp in milliseconds, must not be specified with 'after' Returns ------- PlayHistoryPaging cursor-based paging containing play history objects """ return self._get('me/player/recently-played', limit=limit, after=after, before=before) @send_and_process(model_list(Device, 'devices')) def playback_devices(self) -> List[Device]: """ Get a user's available devices. Requires the user-read-playback-state scope. Returns ------- ModelList list of device objects """ return self._get('me/player/devices')
class SpotifyPlaylistView(SpotifyBase): @send_and_process(single(SimplePlaylistPaging)) @maximise_limit(50) def followed_playlists(self, limit: int = 20, offset: int = 0) -> SimplePlaylistPaging: """ Get a list of the playlists owned or followed by the current user. Requires the playlist-read-private scope to return private playlists. Requires the playlist-read-collaborative scope to return collaborative playlists. Parameters ---------- limit the number of items to return (1..50) offset the index of the first item to return Returns ------- SimplePlaylistPaging paging object containing simplified playlists """ return self._get('me/playlists', limit=limit, offset=offset) @send_and_process(single(SimplePlaylistPaging)) @maximise_limit(50) def playlists(self, user_id: str, limit: int = 20, offset: int = 0) -> SimplePlaylistPaging: """ Get a list of the playlists owned or followed by a user. Requires the playlist-read-private scope to return private playlists. Requires the playlist-read-collaborative scope to return collaborative playlists. Collaborative playlists are only returned for current user. Parameters ---------- user_id user ID limit the number of items to return (1..50) offset the index of the first item to return Returns ------- SimplePlaylistPaging paging object containing simplified playlists """ return self._get(f'users/{user_id}/playlists', limit=limit, offset=offset) @process_if_not_specified(single(FullPlaylist), ('fields', 2), ('episodes_as_tracks', 4)) @send_and_process(nothing) def playlist( self, playlist_id: str, fields: str = None, market: str = None, episodes_as_tracks: bool = False, ) -> Union[FullPlaylist, dict]: """ Get playlist of a user. Parameters ---------- playlist_id playlist ID fields which fields to return, see the Web API documentation for details market an ISO 3166-1 alpha-2 country code or 'from_token' when using a user token to authenticate. For episodes in the playlist, if a user token is used, the country associated with it overrides this parameter. If an application token is used and no market is specified, episodes are considered unavailable and returned as None. episodes_as_tracks if True, return episodes with track-like fields Returns ------- Union[FullPlaylist, dict] playlist object, or raw dictionary if ``fields`` or ``episodes_as_tracks`` was specified """ if episodes_as_tracks is True: additional_types = None else: additional_types = 'track,episode' return self._get( 'playlists/' + playlist_id, fields=fields, market=market, additional_types=additional_types, ) @send_and_process(model_list(Image)) def playlist_cover_image(self, playlist_id: str) -> ModelList: """ Get cover image of a playlist. Note: returns a list of images. Parameters ---------- playlist_id playlist ID Returns ------- ModelList list of cover images """ return self._get(f'playlists/{playlist_id}/images') @process_if_not_specified(single(PlaylistTrackPaging), ('fields', 2), ('episodes_as_tracks', 4)) @send_and_process(nothing) def playlist_tracks(self, playlist_id: str, fields: str = None, market: str = None, episodes_as_tracks: bool = False, limit: int = 100, offset: int = 0) -> Union[PlaylistTrackPaging, dict]: """ Get full details of the tracks of a playlist owned by a user. Parameters ---------- playlist_id playlist ID fields which fields to return, see the Web API documentation for details market an ISO 3166-1 alpha-2 country code or 'from_token' when using a user token to authenticate. For episodes in the playlist, if a user token is used, the country associated with it overrides this parameter. If an application token is used and no market is specified, episodes are considered unavailable and returned as None. episodes_as_tracks if True, return episodes with track-like fields limit the number of items to return (1..100) offset the index of the first item to return Returns ------- Union[PlaylistTrackPaging, dict] paging object containing playlist tracks, or raw dictionary if ``fields`` or ``episodes_as_tracks`` was specified """ if episodes_as_tracks is True: additional_types = None else: additional_types = 'track,episode' return self._get( f'playlists/{playlist_id}/tracks', limit=limit, offset=offset, fields=fields, market=market, additional_types=additional_types, )