示例#1
0
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/')
示例#2
0
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)
示例#3
0
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')
示例#4
0
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
        )
示例#5
0
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))
示例#6
0
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))
示例#7
0
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)
示例#8
0
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)
示例#9
0
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')
示例#10
0
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)
示例#11
0
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)
示例#12
0
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')
示例#13
0
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,
        )