예제 #1
0
def get_target_playlist(date: dt, client: spotipy.Spotify, user: str) -> str:
    """
    ASSUMPTIONS: a user has no duplicate playlist names
    In the case that a user has a duplicate playlist name, the script will modify the one 'lower' in the user's playlist library
    Solution: no intuitive workaround
    """
    # december of 2019 looks for playlist "winter 2020"
    target_playlist_name = get_current_season(date) + " " + str(
        date.year if date.month != 12 else date.year + 1)
    chunk, offset = 50, 0
    all_playlists = {}

    # Case 1: Playlist is cached and playlist is current season
    #   Good, use it
    # Case 2: Playlist is cached but playlist is out of season
    #   Make a new playlist and cache it
    # Case 3: Playlist isnt cached
    #   Look for it

    playlist_id = ""
    try:
        playlist_id = database.get_field(user, "last_playlist")
        # case 1
        if playlist_id != '' and client.playlist(
                playlist_id)["name"] == target_playlist_name:
            return playlist_id
        # case 2
        else:
            resp = client.user_playlist_create(
                client.me()['id'],
                target_playlist_name,
                public=False,
                description=
                'AUTOMATED PLAYLIST - https://github.com/turrence/spotify-new-music-sorter'
            )
            return resp['id']
    except KeyError as e:
        # case 3: do nothing, it's not cached, hopefully this is rare
        pass

    while True:
        playlist_info = client.current_user_playlists(chunk, offset)
        for item in playlist_info['items']:
            all_playlists[item['name']] = item['id']
        if len(all_playlists) >= playlist_info['total']:
            break
        else:
            offset += chunk

    if target_playlist_name not in all_playlists:
        resp = client.user_playlist_create(
            client.me()['id'],
            target_playlist_name,
            public=False,
            description=
            'AUTOMATED PLAYLIST - https://github.com/turrence/spotify-new-music-sorter'
        )
        return resp['id']
    else:
        return all_playlists[target_playlist_name]
예제 #2
0
def update_playlist(client: spotipy.Spotify, user: str):
    target_playlist = get_target_playlist(dt.now(tz=tz.utc), client, user)
    # in utc
    last_updated = get_newest_date_in_playlist(target_playlist, client)
    songs_to_be_added = get_unadded_songs(last_updated, client)

    database.update_user(client.me()['id'], "last_playlist", target_playlist)
    if len(songs_to_be_added) < 1:
        # print("No songs to be added for", client.me()['id'])
        pass
    else:
        timestamp = dt.now(tz=tz.utc).strftime('%Y-%m-%d %H:%M:%S')
        # print(timestamp + ": Adding " + str(len(songs_to_be_added)) + " songs for", client.me()['id'])
        database.update_user(client.me()['id'], "last_update", timestamp)
        database.increment_field(client.me()['id'], "update_count")

        # we can only add 100 songs at a time, place all the songs in a queue
        # and dequeue into a chunk 100 songs at a time
        chunk = []
        while songs_to_be_added:
            chunk.append(songs_to_be_added.popleft())
            if (len(chunk) == 100):
                client.user_playlist_add_tracks(client.me()['id'],
                                                target_playlist, chunk)
                chunk.clear()
        # if the chunk isn't completely filled then add the rest of the songs
        if (len(chunk) > 0):
            client.user_playlist_add_tracks(client.me()['id'], target_playlist,
                                            chunk)
예제 #3
0
def index(request):
    if not request.session.get('uuid'):
        request.session['uuid'] = str(uuid.uuid4())

    auth_manager = SpotifyOAuth(
        scope='user-read-currently-playing',
        cache_path=session_cache_path(request.session),
        show_dialog=True)
    if request.method == 'GET':
        if request.GET.get("code"):
            # Step 3. Being redirected from Spotify auth page
            request.session['token_info'] = auth_manager.get_access_token(
                request.GET.get("code"))
            return redirect(index)

    if not auth_manager.get_cached_token():
        auth_url = auth_manager.get_authorize_url()
        return HttpResponse(f'<h2><a href="{auth_url}">Sign in</a></h2>')

    if auth_manager.is_token_expired(request.session.get('token_info')):
        request.session['token_info'] = auth_manager.refresh_access_token(
            request.session.get('token_info'))

    spotify = Spotify(auth_manager=auth_manager)
    request.session['username'] = spotify.me()['id']
    request.session['token'] = auth_manager.get_cached_token()
    return redirect(visview, request.session.get('username'))
예제 #4
0
def _login(
):  # The login button (also called for auto-login if user was logged in last time)
    global username
    global spoofy
    global logged_in
    global playlists

    username_submit.state(["disabled"])
    if logged_in:  # Logged in logging out
        print("logging out")
        username = None
        playlist_list.delete(0, playlist_list.size() - 1)
        playlists = []
        os.remove("lastuser")
        logged_in = False

    else:  # Logged out loggin in
        spoofy = Spotify(auth=authorize(username))
        user_id = spoofy.me()["id"]

        # Get who we are logged in as
        if username != user_id:
            username = user_id
            with open("lastuser", "w") as f:
                f.write(username)

        logged_in = True

    set_login_state()
    username_submit.state(["!disabled"])
예제 #5
0
def main() -> None:
    scope = "user-read-recently-played " \
            "playlist-modify-public " \
            "playlist-modify-private " \
            "user-read-currently-playing " \
            "user-library-modify " \
            "playlist-read-private " \
            "user-library-read"
    spotify_credentials = SpotifyOAuth(
        client_id=os.environ.get('SPOTIFY_WEEKLY_SAVER_CLIENT_ID'),
        client_secret=os.environ.get('SPOTIFY_WEEKLY_SAVER_CLIENT_SECRET'),
        redirect_uri="http://localhost:8000/",
        scope=scope,
    )
    spotify_instance = Spotify(auth_manager=spotify_credentials)
    spotify_handler = SpotifyHandler(spotify_instance=spotify_instance, )
    try:
        user_id = spotify_instance.me().get('id')
    except SpotifyOauthError:
        spotify_instance = Spotify(
            auth=spotify_handler.refresh_access_token(spotify_credentials), )
        user_id = spotify_instance.me().get('id')

    # get Discover Weekly playlist and its creation date
    dwp, created_at = spotify_handler.get_discover_weekly_playlist()

    # create new dwp name
    new_dwp_name = f"{dwp['name']} - {created_at.split('T')[0]}"

    # get tracks from the main dwp
    print('Getting tracks from your Discover Weekly Playlist...')
    tracks = [track['track']['id'] for track in dwp['tracks']['items']]

    # create new playlist
    print('Creating new playlist...')
    new_dwp = archive_discover_weekly_playlist(spotify_instance,
                                               spotify_handler, user_id,
                                               new_dwp_name)

    # add tracks from the main dwp to the new one
    print('Saving tracks...')
    spotify_instance.playlist_add_items(new_dwp['id'], items=tracks)
예제 #6
0
    def connect(self, response_code, redirect_uri):
        try:
            token_response = self.auth_api(redirect_uri).get_access_token(response_code)
            self.token = token_response['access_token']
            sp = Spotify(auth=self.token)
            self.username = sp.me()['id']
            self.state = self.CONNECTED
        except SpotifyOauthError:
            self.state = self.FAILED

        self.repository.save(self)
예제 #7
0
class SpotifyController(BaseController):
    @classmethod
    def app_information(cls, session_id):
        return [{
            "appId":
            cls.app_id(),
            "displayName":
            "Spotify",
            "iconUrl":
            "",
            "isIdleScreen":
            False,
            "launchedFromCloud":
            False,
            "namespaces": [
                {
                    "name": "urn:x-cast:com.spotify.chromecast.secure.v1"
                },
            ],
            "sessionId":
            session_id,
            "statusText":
            "Spotify",
            "transportId":
            session_id
        }]

    @classmethod
    def app_id(cls):
        return APP_SPOTIFY

    def __init__(self):
        super().__init__(APP_NAMESPACE)
        self._spotify = None

    def get_reply(self, message):
        message_type = message.data.get("type", "")

        if message_type == "setCredentials":
            token = message.data.get("credentials", "")
            logger.debug("received spotify token %s", token)

            self._spotify = Spotify(auth=token)
            user = self._spotify.me()
            no_value = "[n/a]"
            email = user.get("email", no_value)
            name = user.get("display_name", no_value)
            country = user.get("country", no_value)
            birthday = user.get("birthdate", no_value)
            logger.info("%s (%s from %s, born %s) launched spotify", email,
                        name, country, birthday)

        return super().get_reply(message)
예제 #8
0
def create_and_populate_playlist(playlist_name: str, track_ids: list, sp: Spotify):
    """
    Creates and populates a spotify playlist for a user
    @param playlist_name: name of the playlist
    @param track_ids: a list of song id's
    @param sp: Spotify object authenticated by a user to be used with the API queries.
    @return:
    """
    try:
        playlist = sp.user_playlist_create(sp.me()['id'], playlist_name, public=True,
                                           description='generated by '
                                                       'FindSimilarArtists')
        playlist_id = playlist['uri']
        sp.user_playlist_add_tracks(sp.me()['id'], playlist_id, track_ids)
        return playlist_id
    except SpotifyException as e:
        print(e)
        return None
    except Exception as e:
        print(e)
        return None
예제 #9
0
async def callback_for_spotify(
    code: str,
    spotipy_oauth: SpotifyOAuth = Depends(get_spotipy_oauth),
    db: Session = Depends(get_db)):
    """
    Callback for spotify api
    Redirects to /dashboard on frontend
    Creates user if not exsists
    Returns pait of jwt tokens in cookies
    """
    # auth_creds = requests.post(
    #     'https://accounts.spotify.com/api/token',
    #     data={"grant_type": "authorization_code", "code": code,
    #           "redirect_uri": os.getenv('REDIRECT_URL')},
    #     headers={
    #         "Authorization":
    #             f"Basic YjMyMzcwNDExZTcwNGE1NzkxNDRlNTVmYjY3OTgyY2U6YmMwNzljOTllMjIzNDMxNWJjZjMxY2Y2NzE2ZTI3YmY="}).json()
    auth_creds = spotipy_oauth.get_access_token(code=code, check_cache=False)
    spotify_client = Spotify(auth=auth_creds["access_token"])
    spotify_user = spotify_client.me()
    db_user = user_crud.get_user(db, spotify_id=spotify_user['id'])

    UserSchema = UserCreate if not db_user else UserUpdate
    if spotify_user and auth_creds:
        image = spotify_user['images']
        user = UserSchema(email=spotify_user['email'],
                          name=spotify_user['display_name'],
                          image_url=image[0]['url'] if len(image) else '',
                          spotify_id=spotify_user['id'],
                          access_token=auth_creds['access_token'],
                          refresh_token=auth_creds['refresh_token'],
                          token_expires=datetime.now().timestamp() +
                          float(auth_creds['expires_in']))
        if db_user:
            user_crud.update_user(db, spotify_user['id'],
                                  cast(UserUpdate, user))
        else:
            user_crud.create_user(db, cast(UserCreate, user))

    frontend_url = os.getenv('FRONTEND_URL')
    if not spotify_user and not auth_creds:
        return RedirectResponse(url=f"{frontend_url}", status_code=500)

    access_token = create_access_token(
        data=TokenData(spotify_id=spotify_user['id'],
                       spotify_expires=user.token_expires - 600).dict(),
        expires_delta=ACCESS_TOKEN_EXPIRE_MINUTES)

    return RedirectResponse(url=f"{frontend_url}/token?token={access_token}")
예제 #10
0
def auth(request):
    if not request.session.get('uuid'):
        request.session['uuid'] = str(uuid.uuid4())

    auth_manager = SpotifyOAuth(
        scope='user-read-currently-playing user-top-read',
        cache_path=session_cache_path(request.session),
        show_dialog=True)

    if request.GET.get('code'):
        auth_manager.get_access_token(request.GET.get('code'))
        return redirect('index')

    if not auth_manager.get_cached_token():
        auth_url = auth_manager.get_authorize_url()
        return Response({"auth_url": auth_url})

    spotify = Spotify(auth_manager=auth_manager)
    return Response({"name": spotify.me()["display_name"]})
예제 #11
0
def callback(request):
    spotify_oauth = SpotifyOAuth(
        settings.SPOTIPY_CLIENT_ID,
        settings.SPOTIPY_CLIENT_SECRET,
        settings.SPOTIPY_REDIRECT_URI,
        scope='user-read-email playlist-modify-public user-follow-modify')
    oauth_token = request.GET.get('code')
    access_token = spotify_oauth.get_access_token(oauth_token)

    spotify = Spotify(auth=access_token.get('access_token'))

    me = spotify.me()

    # Check spotify session
    current_user = None
    user = None
    try:
        current_user = SpotifySession.objects.get(username=me['id'])
        user = current_user.user
        user.backend = 'django.contrib.auth.backends.ModelBackend'
    except:
        current_user = SpotifySession(username=me.get('id'))
        # Create this
        current_user.access_token = access_token.get('access_token')
        current_user.refresh_token = access_token.get('refresh_token')
        current_user.expires_in = access_token.get('expires_in')
        password = get_random_string(length=32)
        user = User.objects.create_user(me['id'], me['email'], password)
        user.backend = 'django.contrib.auth.backends.ModelBackend'
        user.save()
        current_user.user = user
        current_user.save()

    if user is not None:
        if user.is_active:
            login(request, user)
            return HttpResponseRedirect('/dashboard')
예제 #12
0
class AuthTestSpotipy(unittest.TestCase):
    """
    These tests require user authentication - provide client credentials using
    the following environment variables

    ::

        'SPOTIPY_CLIENT_USERNAME'
        'SPOTIPY_CLIENT_ID'
        'SPOTIPY_CLIENT_SECRET'
        'SPOTIPY_REDIRECT_URI'
    """

    playlist = "spotify:user:plamere:playlist:2oCEWyyAPbZp9xhVSxZavx"
    playlist_new_id = "spotify:playlist:7GlxpQjjxRjmbb3RP2rDqI"
    four_tracks = ["spotify:track:6RtPijgfPKROxEzTHNRiDp",
                   "spotify:track:7IHOIqZUUInxjVkko181PB",
                   "4VrWlk8IQxevMvERoX08iC",
                   "http://open.spotify.com/track/3cySlItpiPiIAzU3NyHCJf"]

    two_tracks = ["spotify:track:6RtPijgfPKROxEzTHNRiDp",
                  "spotify:track:7IHOIqZUUInxjVkko181PB"]

    other_tracks = ["spotify:track:2wySlB6vMzCbQrRnNGOYKa",
                    "spotify:track:29xKs5BAHlmlX1u4gzQAbJ",
                    "spotify:track:1PB7gRWcvefzu7t3LJLUlf"]

    album_ids = ["spotify:album:6kL09DaURb7rAoqqaA51KU",
                 "spotify:album:6RTzC0rDbvagTSJLlY7AKl"]

    bad_id = 'BAD_ID'

    @classmethod
    def setUpClass(self):
        if sys.version_info >= (3, 2):
            # >= Python3.2 only
            warnings.filterwarnings(
                "ignore",
                category=ResourceWarning,  # noqa
                message="unclosed.*<ssl.SSLSocket.*>")

        missing = list(filter(lambda var: not os.getenv(CCEV[var]), CCEV))

        if missing:
            raise Exception(
                ('Please set the client credentials for the test application'
                 ' using the following environment variables: {}').format(
                    CCEV.values()))

        self.username = os.getenv(CCEV['client_username'])

        self.scope = (
            'playlist-modify-public '
            'user-library-read '
            'user-follow-read '
            'user-library-modify '
            'user-read-private '
            'user-top-read '
            'user-follow-modify '
            'user-read-recently-played '
            'ugc-image-upload'
        )

        self.token = prompt_for_user_token(self.username, scope=self.scope)

        self.spotify = Spotify(auth=self.token)

    # Helper
    def get_or_create_spotify_playlist(self, playlist_name):
        playlists = self.spotify.user_playlists(self.username)
        while playlists:
            for item in playlists['items']:
                if item['name'] == playlist_name:
                    return item
            playlists = self.spotify.next(playlists)
        return self.spotify.user_playlist_create(
            self.username, playlist_name)

    # Helper
    def get_as_base64(self, url):
        import base64
        return base64.b64encode(requests.get(url).content).decode("utf-8")

    def test_track_bad_id(self):
        try:
            self.spotify.track(self.bad_id)
            self.assertTrue(False)
        except SpotifyException:
            self.assertTrue(True)

    def test_basic_user_profile(self):
        user = self.spotify.user(self.username)
        self.assertTrue(user['id'] == self.username.lower())

    def test_current_user(self):
        user = self.spotify.current_user()
        self.assertTrue(user['id'] == self.username.lower())

    def test_me(self):
        user = self.spotify.me()
        self.assertTrue(user['id'] == self.username.lower())

    def test_user_playlists(self):
        playlists = self.spotify.user_playlists(self.username, limit=5)
        self.assertTrue('items' in playlists)
        self.assertTrue(len(playlists['items']) == 5)

    def test_user_playlist_tracks(self):
        playlists = self.spotify.user_playlists(self.username, limit=5)
        self.assertTrue('items' in playlists)
        for playlist in playlists['items']:
            user = playlist['owner']['id']
            pid = playlist['id']
            results = self.spotify.user_playlist_tracks(user, pid)
            self.assertTrue(len(results['items']) >= 0)

    def test_current_user_saved_albums(self):
        # List
        albums = self.spotify.current_user_saved_albums()
        self.assertTrue(len(albums['items']) > 1)

        # Add
        self.spotify.current_user_saved_albums_add(self.album_ids)

        # Contains
        self.assertTrue(
            self.spotify.current_user_saved_albums_contains(
                self.album_ids) == [
                True, True])

        # Remove
        self.spotify.current_user_saved_albums_delete(self.album_ids)
        albums = self.spotify.current_user_saved_albums()
        self.assertTrue(len(albums['items']) > 1)

    def test_current_user_playlists(self):
        playlists = self.spotify.current_user_playlists(limit=10)
        self.assertTrue('items' in playlists)
        self.assertTrue(len(playlists['items']) == 10)

    def test_user_playlist_follow(self):
        self.spotify.user_playlist_follow_playlist(
            'plamere', '4erXB04MxwRAVqcUEpu30O')
        follows = self.spotify.user_playlist_is_following(
            'plamere', '4erXB04MxwRAVqcUEpu30O', [
                self.spotify.current_user()['id']])

        self.assertTrue(len(follows) == 1, 'proper follows length')
        self.assertTrue(follows[0], 'is following')
        self.spotify.user_playlist_unfollow(
            'plamere', '4erXB04MxwRAVqcUEpu30O')

        follows = self.spotify.user_playlist_is_following(
            'plamere', '4erXB04MxwRAVqcUEpu30O', [
                self.spotify.current_user()['id']])
        self.assertTrue(len(follows) == 1, 'proper follows length')
        self.assertFalse(follows[0], 'is no longer following')

    def test_current_user_saved_tracks(self):
        tracks = self.spotify.current_user_saved_tracks()
        self.assertTrue(len(tracks['items']) > 0)

    def test_current_user_save_and_unsave_tracks(self):
        tracks = self.spotify.current_user_saved_tracks()
        total = tracks['total']
        self.spotify.current_user_saved_tracks_add(self.four_tracks)

        tracks = self.spotify.current_user_saved_tracks()
        new_total = tracks['total']
        self.assertTrue(new_total - total == len(self.four_tracks))

        tracks = self.spotify.current_user_saved_tracks_delete(
            self.four_tracks)
        tracks = self.spotify.current_user_saved_tracks()
        new_total = tracks['total']
        self.assertTrue(new_total == total)

    def test_categories(self):
        response = self.spotify.categories()
        self.assertTrue(len(response['categories']) > 0)

    def test_category_playlists(self):
        response = self.spotify.categories()
        for cat in response['categories']['items']:
            cat_id = cat['id']
            response = self.spotify.category_playlists(category_id=cat_id)
            if len(response['playlists']["items"]) > 0:
                break
        self.assertTrue(True)

    def test_new_releases(self):
        response = self.spotify.new_releases()
        self.assertTrue(len(response['albums']) > 0)

    def test_featured_releases(self):
        response = self.spotify.featured_playlists()
        self.assertTrue(len(response['playlists']) > 0)

    def test_current_user_follows(self):
        response = self.spotify.current_user_followed_artists()
        artists = response['artists']
        self.assertTrue(len(artists['items']) > 0)

    def test_current_user_top_tracks(self):
        response = self.spotify.current_user_top_tracks()
        items = response['items']
        self.assertTrue(len(items) > 0)

    def test_current_user_top_artists(self):
        response = self.spotify.current_user_top_artists()
        items = response['items']
        self.assertTrue(len(items) > 0)

    def test_current_user_recently_played(self):
        # No cursor
        res = self.spotify.current_user_recently_played()
        self.assertTrue(len(res['items']) <= 50)
        played_at = res['items'][0]['played_at']

        # Using `before` gives tracks played before
        res = self.spotify.current_user_recently_played(
            before=res['cursors']['after'])
        self.assertTrue(len(res['items']) <= 50)
        self.assertTrue(res['items'][0]['played_at'] < played_at)
        played_at = res['items'][0]['played_at']

        # Using `after` gives tracks played after
        res = self.spotify.current_user_recently_played(
            after=res['cursors']['before'])
        self.assertTrue(len(res['items']) <= 50)
        self.assertTrue(res['items'][0]['played_at'] > played_at)

    def test_user_playlist_ops(self):
        sp = self.spotify
        # create empty playlist
        playlist = self.get_or_create_spotify_playlist(
            'spotipy-testing-playlist-1')
        playlist_id = playlist['id']

        # remove all tracks from it
        sp.user_playlist_replace_tracks(
            self.username, playlist_id, [])
        playlist = sp.user_playlist(self.username, playlist_id)
        self.assertTrue(playlist['tracks']['total'] == 0)
        self.assertTrue(len(playlist['tracks']['items']) == 0)

        # add tracks to it
        sp.user_playlist_add_tracks(
            self.username, playlist_id, self.four_tracks)
        playlist = sp.user_playlist(self.username, playlist_id)
        self.assertTrue(playlist['tracks']['total'] == 4)
        self.assertTrue(len(playlist['tracks']['items']) == 4)

        # remove two tracks from it

        sp.user_playlist_remove_all_occurrences_of_tracks(self.username,
                                                          playlist_id,
                                                          self.two_tracks)
        playlist = sp.user_playlist(self.username, playlist_id)
        self.assertTrue(playlist['tracks']['total'] == 2)
        self.assertTrue(len(playlist['tracks']['items']) == 2)

        # replace with 3 other tracks
        sp.user_playlist_replace_tracks(self.username,
                                        playlist_id,
                                        self.other_tracks)
        playlist = sp.user_playlist(self.username, playlist_id)
        self.assertTrue(playlist['tracks']['total'] == 3)
        self.assertTrue(len(playlist['tracks']['items']) == 3)

    def test_playlist(self):
        # New playlist ID
        pl = self.spotify.playlist(self.playlist_new_id)
        self.assertTrue(pl["tracks"]["total"] > 0)

        # Old playlist ID
        pl = self.spotify.playlist(self.playlist)
        self.assertTrue(pl["tracks"]["total"] > 0)

    def test_playlist_tracks(self):
        # New playlist ID
        pl = self.spotify.playlist_tracks(self.playlist_new_id, limit=2)
        self.assertTrue(len(pl["items"]) == 2)
        self.assertTrue(pl["total"] > 0)

        # Old playlist ID
        pl = self.spotify.playlist_tracks(self.playlist, limit=2)
        self.assertTrue(len(pl["items"]) == 2)
        self.assertTrue(pl["total"] > 0)

    def test_playlist_upload_cover_image(self):
        pl1 = self.get_or_create_spotify_playlist('spotipy-testing-playlist-1')
        plid = pl1['uri']
        old_b64 = pl1['images'][0]['url']

        # Upload random dog image
        r = requests.get('https://dog.ceo/api/breeds/image/random')
        dog_base64 = self.get_as_base64(r.json()['message'])
        self.spotify.playlist_upload_cover_image(plid, dog_base64)

        # Image must be different
        pl1 = self.spotify.playlist(plid)
        new_b64 = self.get_as_base64(pl1['images'][0]['url'])
        self.assertTrue(old_b64 != new_b64)

    def test_playlist_cover_image(self):
        pl = self.get_or_create_spotify_playlist('spotipy-testing-playlist-1')
        plid = pl['uri']
        res = self.spotify.playlist_cover_image(plid)

        self.assertTrue(len(res) > 0)
        first_image = res[0]
        self.assertTrue('width' in first_image)
        self.assertTrue('height' in first_image)
        self.assertTrue('url' in first_image)

    def test_user_follows_and_unfollows_artist(self):
        # Initially follows 1 artist
        res = self.spotify.current_user_followed_artists()
        self.assertTrue(res['artists']['total'] == 1)

        # Follow 2 more artists
        artists = ["6DPYiyq5kWVQS4RGwxzPC7", "0NbfKEOTQCcwd6o7wSDOHI"]
        self.spotify.user_follow_artists(artists)
        res = self.spotify.current_user_followed_artists()
        self.assertTrue(res['artists']['total'] == 3)

        # Unfollow these 2 artists
        self.spotify.user_unfollow_artists(artists)
        res = self.spotify.current_user_followed_artists()
        self.assertTrue(res['artists']['total'] == 1)

    def test_user_follows_and_unfollows_user(self):
        # TODO improve after implementing `me/following/contains`
        users = ["11111204", "xlqeojt6n7on0j7coh9go8ifd"]

        # Follow 2 more users
        self.spotify.user_follow_users(users)

        # Unfollow these 2 users
        self.spotify.user_unfollow_users(users)

    def test_deprecated_starred(self):
        pl = self.spotify.user_playlist(self.username)
        self.assertTrue(pl["tracks"] is None)
        self.assertTrue(pl["owner"] is None)

    def test_deprecated_user_playlist(self):
        # Test without user due to change from
        # https://developer.spotify.com/community/news/2018/06/12/changes-to-playlist-uris/
        pl = self.spotify.user_playlist(None, self.playlist)
        self.assertTrue(pl["tracks"]["total"] > 0)

    def test_deprecated_user_playlis(self):
        # Test without user due to change from
        # https://developer.spotify.com/community/news/2018/06/12/changes-to-playlist-uris/
        pl = self.spotify.user_playlist_tracks(None, self.playlist, limit=2)
        self.assertTrue(len(pl["items"]) == 2)
        self.assertTrue(pl["total"] > 0)
예제 #13
0
 def create_playlist(session: spotipy.Spotify, name: str):
     playlist_all_data = session.user_playlist_create(
         session.me()['id'], name)
     # print(playlist_all_data)
     return playlist_all_data['id']
예제 #14
0
class AuthTestSpotipy(unittest.TestCase):
    """
    These tests require user authentication - provide client credentials using the
    following environment variables

    ::

        'SPOTIPY_CLIENT_USERNAME'
        'SPOTIPY_CLIENT_ID'
        'SPOTIPY_CLIENT_SECRET'
        'SPOTIPY_REDIRECT_URI'
    """

    playlist = "spotify:user:plamere:playlist:2oCEWyyAPbZp9xhVSxZavx"
    four_tracks = [
        "spotify:track:6RtPijgfPKROxEzTHNRiDp",
        "spotify:track:7IHOIqZUUInxjVkko181PB", "4VrWlk8IQxevMvERoX08iC",
        "http://open.spotify.com/track/3cySlItpiPiIAzU3NyHCJf"
    ]

    two_tracks = [
        "spotify:track:6RtPijgfPKROxEzTHNRiDp",
        "spotify:track:7IHOIqZUUInxjVkko181PB"
    ]

    other_tracks = [
        "spotify:track:2wySlB6vMzCbQrRnNGOYKa",
        "spotify:track:29xKs5BAHlmlX1u4gzQAbJ",
        "spotify:track:1PB7gRWcvefzu7t3LJLUlf"
    ]

    bad_id = 'BAD_ID'

    @classmethod
    def setUpClass(self):

        missing = list(filter(lambda var: not os.getenv(CCEV[var]), CCEV))

        if missing:
            raise Exception(
                'Please set the client credentials for the test application using the following environment variables: {}'
                .format(CCEV.values()))

        self.username = os.getenv(CCEV['client_username'])

        self.scope = ('playlist-modify-public '
                      'user-library-read '
                      'user-follow-read '
                      'user-library-modify '
                      'user-read-private '
                      'user-top-read')

        self.token = prompt_for_user_token(self.username, scope=self.scope)

        self.spotify = Spotify(auth=self.token)

    def test_track_bad_id(self):
        try:
            track = self.spotify.track(self.bad_id)
            self.assertTrue(False)
        except SpotifyException:
            self.assertTrue(True)

    def test_basic_user_profile(self):
        user = self.spotify.user(self.username)
        self.assertTrue(user['id'] == self.username.lower())

    def test_current_user(self):
        user = self.spotify.current_user()
        self.assertTrue(user['id'] == self.username.lower())

    def test_me(self):
        user = self.spotify.me()
        self.assertTrue(user['id'] == self.username.lower())

    def test_user_playlists(self):
        playlists = self.spotify.user_playlists(self.username, limit=5)
        self.assertTrue('items' in playlists)
        self.assertTrue(len(playlists['items']) == 5)

    def test_user_playlist_tracks(self):
        playlists = self.spotify.user_playlists(self.username, limit=5)
        self.assertTrue('items' in playlists)
        for playlist in playlists['items']:
            user = playlist['owner']['id']
            pid = playlist['id']
            results = self.spotify.user_playlist_tracks(user, pid)
            self.assertTrue(len(results['items']) >= 0)

    def user_playlist_tracks(self,
                             user,
                             playlist_id=None,
                             fields=None,
                             limit=100,
                             offset=0):

        # known API issue currently causes this test to fail
        # the issue is that the API doesn't currently respect the
        # limit paramter

        self.assertTrue(len(playlists['items']) == 5)

    def test_current_user_saved_tracks(self):
        tracks = self.spotify.current_user_saved_tracks()
        self.assertTrue(len(tracks['items']) > 0)

    def test_current_user_saved_albums(self):
        albums = self.spotify.current_user_saved_albums()
        self.assertTrue(len(albums['items']) > 0)

    def test_current_user_playlists(self):
        playlists = self.spotify.current_user_playlists(limit=10)
        self.assertTrue('items' in playlists)
        self.assertTrue(len(playlists['items']) == 10)

    def test_user_playlist_follow(self):
        self.spotify.user_playlist_follow_playlist('plamere',
                                                   '4erXB04MxwRAVqcUEpu30O')
        follows = self.spotify.user_playlist_is_following(
            'plamere', '4erXB04MxwRAVqcUEpu30O',
            [self.spotify.current_user()['id']])

        self.assertTrue(len(follows) == 1, 'proper follows length')
        self.assertTrue(follows[0], 'is following')
        self.spotify.user_playlist_unfollow('plamere',
                                            '4erXB04MxwRAVqcUEpu30O')

        follows = self.spotify.user_playlist_is_following(
            'plamere', '4erXB04MxwRAVqcUEpu30O',
            [self.spotify.current_user()['id']])
        self.assertTrue(len(follows) == 1, 'proper follows length')
        self.assertFalse(follows[0], 'is no longer following')

    def test_current_user_save_and_unsave_tracks(self):
        tracks = self.spotify.current_user_saved_tracks()
        total = tracks['total']

        self.spotify.current_user_saved_tracks_add(self.four_tracks)

        tracks = self.spotify.current_user_saved_tracks()
        new_total = tracks['total']
        self.assertTrue(new_total - total == len(self.four_tracks))

        tracks = self.spotify.current_user_saved_tracks_delete(
            self.four_tracks)
        tracks = self.spotify.current_user_saved_tracks()
        new_total = tracks['total']
        self.assertTrue(new_total == total)

    def test_categories(self):
        response = self.spotify.categories()
        self.assertTrue(len(response['categories']) > 0)

    def test_category_playlists(self):
        response = self.spotify.categories()
        for cat in response['categories']['items']:
            cat_id = cat['id']
            response = self.spotify.category_playlists(category_id=cat_id)
            if len(response['playlists']["items"]) > 0:
                break
        self.assertTrue(True)

    def test_new_releases(self):
        response = self.spotify.new_releases()
        self.assertTrue(len(response['albums']) > 0)

    def test_featured_releases(self):
        response = self.spotify.featured_playlists()
        self.assertTrue(len(response['playlists']) > 0)

    def test_current_user_follows(self):
        response = self.spotify.current_user_followed_artists()
        artists = response['artists']
        self.assertTrue(len(artists['items']) > 0)

    def test_current_user_top_tracks(self):
        response = self.spotify.current_user_top_tracks()
        items = response['items']
        self.assertTrue(len(items) > 0)

    def test_current_user_top_artists(self):
        response = self.spotify.current_user_top_artists()
        items = response['items']
        self.assertTrue(len(items) > 0)

    def get_or_create_spotify_playlist(self, playlist_name):
        playlists = self.spotify.user_playlists(self.username)
        while playlists:
            for item in playlists['items']:
                if item['name'] == playlist_name:
                    return item['id']
            playlists = self.spotify.next(playlists)
        playlist = self.spotify.user_playlist_create(self.username,
                                                     playlist_name)
        playlist_id = playlist['uri']
        return playlist_id

    def test_user_playlist_ops(self):
        # create empty playlist
        playlist_id = self.get_or_create_spotify_playlist(
            'spotipy-testing-playlist-1')

        # remove all tracks from it

        self.spotify.user_playlist_replace_tracks(self.username, playlist_id,
                                                  [])

        playlist = self.spotify.user_playlist(self.username, playlist_id)
        self.assertTrue(playlist['tracks']['total'] == 0)
        self.assertTrue(len(playlist['tracks']['items']) == 0)

        # add tracks to it

        self.spotify.user_playlist_add_tracks(self.username, playlist_id,
                                              self.four_tracks)
        playlist = self.spotify.user_playlist(self.username, playlist_id)
        self.assertTrue(playlist['tracks']['total'] == 4)
        self.assertTrue(len(playlist['tracks']['items']) == 4)

        # remove two tracks from it

        self.spotify.user_playlist_remove_all_occurrences_of_tracks(
            self.username, playlist_id, self.two_tracks)

        playlist = self.spotify.user_playlist(self.username, playlist_id)
        self.assertTrue(playlist['tracks']['total'] == 2)
        self.assertTrue(len(playlist['tracks']['items']) == 2)

        # replace with 3 other tracks
        self.spotify.user_playlist_replace_tracks(self.username, playlist_id,
                                                  self.other_tracks)

        playlist = self.spotify.user_playlist(self.username, playlist_id)
        self.assertTrue(playlist['tracks']['total'] == 3)
        self.assertTrue(len(playlist['tracks']['items']) == 3)
예제 #15
0
def backup_all_playlists(sp: spotipy.Spotify, file=None):
    all_playlists = []
    all_tracks = get_track_index()
    playlists_offset = 0

    while True:
        playlists = sp.current_user_playlists(limit=50,
                                              offset=playlists_offset)
        for playlist in playlists['items']:
            current_list = {
                'name': playlist['name'],
                'collaborative': playlist['collaborative'],
                'public': playlist['public'],
                'uri': playlist['uri'],
                'owner_id': playlist['owner']['id'],
                'tracks': []
            }

            tracks_offset = 0
            while True:
                playlist_tracks = sp.user_playlist_tracks(
                    user=current_list['owner_id'],
                    playlist_id=playlist['id'],
                    fields='items(is_local,track(uri,id,name,artists.name,'
                    'album.name)),next',
                    limit=100,
                    offset=tracks_offset)
                for playlist_item in playlist_tracks['items']:
                    track = playlist_item['track']
                    track_id = track['id']

                    # Local tracks doesn't have a Spotify ID, so we'll use its Spotify URI as an ID instead
                    if playlist_item['is_local']:
                        track_id = track['uri']

                    current_list['tracks'].append(track_id)
                    if track_id not in all_tracks:
                        print('Adding new track {} to track index'.format(
                            track['name']))
                        all_tracks[track_id] = {
                            'name':
                            track['name'],
                            'artists':
                            [artist['name'] for artist in track['artists']],
                            'album':
                            track['album']['name'],
                        }

                if playlist_tracks['next'] is None:
                    break
                tracks_offset += 100

            print('List {} has {} tracks'.format(current_list['name'],
                                                 len(current_list['tracks'])))
            all_playlists.append(current_list)

        if playlists['next'] is None:
            break
        playlists_offset += 50

    print('Total num lists: {}'.format(len(all_playlists)))
    print('Total num unique tracks: {}'.format(len(all_tracks)))

    def json_dump_compact(obj, fp):
        json.dump(obj=obj, fp=fp, separators=(',', ':'))

    if file is None:
        user_id = sp.me()['id']
        with open(
                'spotify_backup_{}_{}.json'.format(
                    user_id,
                    datetime.now().strftime('%Y-%m-%d_%H%M')), 'w') as file:
            json_dump_compact(all_playlists, file)
    else:
        json_dump_compact(all_playlists, file)

    with open('spotify_track_index.json', 'w') as track_index_file:
        json_dump_compact(all_tracks, track_index_file)
예제 #16
0
파일: test_auth.py 프로젝트: ritiek/spotipy
class AuthTestSpotipy(unittest.TestCase):
    """
    These tests require user authentication - provide client credentials using
    the following environment variables

    ::

        'SPOTIPY_CLIENT_USERNAME'
        'SPOTIPY_CLIENT_ID'
        'SPOTIPY_CLIENT_SECRET'
        'SPOTIPY_REDIRECT_URI'
    """

    playlist = "spotify:user:plamere:playlist:2oCEWyyAPbZp9xhVSxZavx"
    playlist_new_id = "spotify:playlist:7GlxpQjjxRjmbb3RP2rDqI"
    four_tracks = ["spotify:track:6RtPijgfPKROxEzTHNRiDp",
                   "spotify:track:7IHOIqZUUInxjVkko181PB",
                   "4VrWlk8IQxevMvERoX08iC",
                   "http://open.spotify.com/track/3cySlItpiPiIAzU3NyHCJf"]

    two_tracks = ["spotify:track:6RtPijgfPKROxEzTHNRiDp",
                  "spotify:track:7IHOIqZUUInxjVkko181PB"]

    other_tracks = ["spotify:track:2wySlB6vMzCbQrRnNGOYKa",
                    "spotify:track:29xKs5BAHlmlX1u4gzQAbJ",
                    "spotify:track:1PB7gRWcvefzu7t3LJLUlf"]

    album_ids = ["spotify:album:6kL09DaURb7rAoqqaA51KU",
                 "spotify:album:6RTzC0rDbvagTSJLlY7AKl"]

    bad_id = 'BAD_ID'

    @classmethod
    def setUpClass(self):

        missing = list(filter(lambda var: not os.getenv(CCEV[var]), CCEV))

        if missing:
            raise Exception(
                ('Please set the client credentials for the test application'
                 ' using the following environment variables: {}').format(
                    CCEV.values()))

        self.username = os.getenv(CCEV['client_username'])

        self.scope = (
            'playlist-modify-public '
            'user-library-read '
            'user-follow-read '
            'user-library-modify '
            'user-read-private '
            'user-top-read '
            'user-follow-modify'
        )

        self.token = prompt_for_user_token(self.username, scope=self.scope)

        self.spotify = Spotify(auth=self.token)

    def test_track_bad_id(self):
        try:
            self.spotify.track(self.bad_id)
            self.assertTrue(False)
        except SpotifyException:
            self.assertTrue(True)

    def test_basic_user_profile(self):
        user = self.spotify.user(self.username)
        self.assertTrue(user['id'] == self.username.lower())

    def test_current_user(self):
        user = self.spotify.current_user()
        self.assertTrue(user['id'] == self.username.lower())

    def test_me(self):
        user = self.spotify.me()
        self.assertTrue(user['id'] == self.username.lower())

    def test_user_playlists(self):
        playlists = self.spotify.user_playlists(self.username, limit=5)
        self.assertTrue('items' in playlists)
        self.assertTrue(len(playlists['items']) == 5)

    def test_user_playlist_tracks(self):
        playlists = self.spotify.user_playlists(self.username, limit=5)
        self.assertTrue('items' in playlists)
        for playlist in playlists['items']:
            user = playlist['owner']['id']
            pid = playlist['id']
            results = self.spotify.user_playlist_tracks(user, pid)
            self.assertTrue(len(results['items']) >= 0)

    # known API issue currently causes this test to fail
    # the issue is that the API doesn't currently respect the
    # limit parameter
    # def user_playlist_tracks(self, user, playlist_id=None, fields=None,
    #                          limit=100, offset=0):
    #     self.assertTrue(len(playlists['items']) == 5)

    def test_current_user_saved_albums(self):
        # List
        albums = self.spotify.current_user_saved_albums()
        self.assertTrue(len(albums['items']) == 1)

        # Add
        self.spotify.current_user_saved_albums_add(self.album_ids)

        # Contains
        self.assertTrue(
            self.spotify.current_user_saved_albums_contains(
                self.album_ids) == [
                True, True])

        # Remove
        self.spotify.current_user_saved_albums_delete(self.album_ids)
        albums = self.spotify.current_user_saved_albums()
        self.assertTrue(len(albums['items']) == 1)

    def test_current_user_playlists(self):
        playlists = self.spotify.current_user_playlists(limit=10)
        self.assertTrue('items' in playlists)
        self.assertTrue(len(playlists['items']) == 10)

    def test_user_playlist_follow(self):
        self.spotify.user_playlist_follow_playlist(
            'plamere', '4erXB04MxwRAVqcUEpu30O')
        follows = self.spotify.user_playlist_is_following(
            'plamere', '4erXB04MxwRAVqcUEpu30O', [
                self.spotify.current_user()['id']])

        self.assertTrue(len(follows) == 1, 'proper follows length')
        self.assertTrue(follows[0], 'is following')
        self.spotify.user_playlist_unfollow(
            'plamere', '4erXB04MxwRAVqcUEpu30O')

        follows = self.spotify.user_playlist_is_following(
            'plamere', '4erXB04MxwRAVqcUEpu30O', [
                self.spotify.current_user()['id']])
        self.assertTrue(len(follows) == 1, 'proper follows length')
        self.assertFalse(follows[0], 'is no longer following')

    def test_current_user_saved_tracks(self):
        tracks = self.spotify.current_user_saved_tracks()
        self.assertTrue(len(tracks['items']) > 0)

    def test_current_user_save_and_unsave_tracks(self):
        tracks = self.spotify.current_user_saved_tracks()
        total = tracks['total']
        self.spotify.current_user_saved_tracks_add(self.four_tracks)

        tracks = self.spotify.current_user_saved_tracks()
        new_total = tracks['total']
        self.assertTrue(new_total - total == len(self.four_tracks))

        tracks = self.spotify.current_user_saved_tracks_delete(
            self.four_tracks)
        tracks = self.spotify.current_user_saved_tracks()
        new_total = tracks['total']
        self.assertTrue(new_total == total)

    def test_categories(self):
        response = self.spotify.categories()
        self.assertTrue(len(response['categories']) > 0)

    def test_category_playlists(self):
        response = self.spotify.categories()
        for cat in response['categories']['items']:
            cat_id = cat['id']
            response = self.spotify.category_playlists(category_id=cat_id)
            if len(response['playlists']["items"]) > 0:
                break
        self.assertTrue(True)

    def test_new_releases(self):
        response = self.spotify.new_releases()
        self.assertTrue(len(response['albums']) > 0)

    def test_featured_releases(self):
        response = self.spotify.featured_playlists()
        self.assertTrue(len(response['playlists']) > 0)

    def test_current_user_follows(self):
        response = self.spotify.current_user_followed_artists()
        artists = response['artists']
        self.assertTrue(len(artists['items']) > 0)

    def test_current_user_top_tracks(self):
        response = self.spotify.current_user_top_tracks()
        items = response['items']
        self.assertTrue(len(items) > 0)

    def test_current_user_top_artists(self):
        response = self.spotify.current_user_top_artists()
        items = response['items']
        self.assertTrue(len(items) > 0)

    def get_or_create_spotify_playlist(self, playlist_name):
        playlists = self.spotify.user_playlists(self.username)
        while playlists:
            for item in playlists['items']:
                if item['name'] == playlist_name:
                    return item['id']
            playlists = self.spotify.next(playlists)
        playlist = self.spotify.user_playlist_create(
            self.username, playlist_name)
        playlist_id = playlist['uri']
        return playlist_id

    def test_user_playlist_ops(self):
        sp = self.spotify
        # create empty playlist
        playlist_id = self.get_or_create_spotify_playlist(
            'spotipy-testing-playlist-1')

        # remove all tracks from it
        sp.user_playlist_replace_tracks(
            self.username, playlist_id, [])
        playlist = sp.user_playlist(self.username, playlist_id)
        self.assertTrue(playlist['tracks']['total'] == 0)
        self.assertTrue(len(playlist['tracks']['items']) == 0)

        # add tracks to it
        sp.user_playlist_add_tracks(
            self.username, playlist_id, self.four_tracks)
        playlist = sp.user_playlist(self.username, playlist_id)
        self.assertTrue(playlist['tracks']['total'] == 4)
        self.assertTrue(len(playlist['tracks']['items']) == 4)

        # remove two tracks from it

        sp.user_playlist_remove_all_occurrences_of_tracks(self.username,
                                                          playlist_id,
                                                          self.two_tracks)
        playlist = sp.user_playlist(self.username, playlist_id)
        self.assertTrue(playlist['tracks']['total'] == 2)
        self.assertTrue(len(playlist['tracks']['items']) == 2)

        # replace with 3 other tracks
        sp.user_playlist_replace_tracks(self.username,
                                        playlist_id,
                                        self.other_tracks)
        playlist = sp.user_playlist(self.username, playlist_id)
        self.assertTrue(playlist['tracks']['total'] == 3)
        self.assertTrue(len(playlist['tracks']['items']) == 3)

    def test_playlist(self):
        # New playlist ID
        pl = self.spotify.playlist(self.playlist_new_id)
        self.assertTrue(pl["tracks"]["total"] > 0)

        # Old playlist ID
        pl = self.spotify.playlist(self.playlist)
        self.assertTrue(pl["tracks"]["total"] > 0)

    def test_user_follows_and_unfollows_artist(self):
        # Initially follows 1 artist
        res = self.spotify.current_user_followed_artists()
        self.assertTrue(res['artists']['total'] == 1)

        # Follow 2 more artists
        artists = ["6DPYiyq5kWVQS4RGwxzPC7", "0NbfKEOTQCcwd6o7wSDOHI"]
        self.spotify.user_follow_artists(artists)
        res = self.spotify.current_user_followed_artists()
        self.assertTrue(res['artists']['total'] == 3)

        # Unfollow these 2 artists
        self.spotify.user_unfollow_artists(artists)
        res = self.spotify.current_user_followed_artists()
        self.assertTrue(res['artists']['total'] == 1)

    def test_user_follows_and_unfollows_user(self):
        # TODO improve after implementing `me/following/contains`
        users = ["11111204", "xlqeojt6n7on0j7coh9go8ifd"]

        # Follow 2 more users
        self.spotify.user_follow_users(users)

        # Unfollow these 2 users
        self.spotify.user_unfollow_users(users)