Esempio n. 1
0
def remove_user(user_id):
    """ Delete user entry for user with specified ListenBrainz user ID.

    Args:
        user_id (int): the ListenBrainz row ID of the user
    """
    db_spotify.delete_spotify(user_id)
Esempio n. 2
0
def remove_user(user_id):
    """ Delete user entry for user with specified ListenBrainz user ID.

    Args:
        user_id (int): the ListenBrainz row ID of the user
    """
    db_spotify.delete_spotify(user_id)
Esempio n. 3
0
def refresh_user_token(spotify_user: Spotify):
    """ Refreshes the user token for the given spotify user.

    Args:
        spotify_user (domain.spotify.Spotify): the user whose token is to be refreshed

    Returns:
        user (domain.spotify.Spotify): the same user with updated tokens
        None: if the user has revoked authorization to spotify

    Raises:
        SpotifyAPIError: if unable to refresh spotify user token

    Note: spotipy eats up the json body in case of error but we need it for checking
    whether the user has revoked our authorization. hence, we use our own
    code instead of spotipy to fetch refresh token.
    """
    retries = SPOTIFY_API_RETRIES
    response = None
    while retries > 0:
        response = _get_spotify_token("refresh_token",
                                      spotify_user.refresh_token)

        if response.status_code == 200:
            break
        elif response.status_code == 400:
            error_body = response.json()
            if "error" in error_body and error_body["error"] == "invalid_grant":
                # user has revoked authorization through spotify ui or deleted their spotify account etc.
                # in any of these cases, we should delete user from our spotify db as well.
                db_spotify.delete_spotify(spotify_user.user_id)
                return None

            response = None  # some other error during request

        retries -= 1

    if response is None:
        raise SpotifyAPIError('Could not refresh API Token for Spotify user')

    response = response.json()
    access_token = response['access_token']
    if "refresh_token" in response:
        refresh_token = response['refresh_token']
    else:
        refresh_token = spotify_user.refresh_token
    expires_at = int(time.time()) + response['expires_in']
    db_spotify.update_token(spotify_user.user_id, access_token, refresh_token,
                            expires_at)
    return get_user(spotify_user.user_id)
Esempio n. 4
0
 def test_delete_spotify(self):
     token = db_spotify.get_token_for_user(self.user['id'])
     self.assertIsNotNone(token)
     db_spotify.delete_spotify(self.user['id'])
     token = db_spotify.get_token_for_user(self.user['id'])
     self.assertIsNone(token)
def process_one_user(user):
    """ Get recently played songs for this user and submit them to ListenBrainz.

    Args:
        user (spotify.Spotify): the user whose plays are to be imported.

    Raises:
        spotify.SpotifyAPIError: if we encounter errors from the Spotify API.
        spotify.SpotifyListenBrainzError: if we encounter a rate limit, even after retrying.
                                          or if we get errors while submitting the data to ListenBrainz

    """
    try:
        if user.token_expired:
            user = spotify.refresh_user_token(user)

        listenbrainz_user = db_user.get(user.user_id)

        # If there is no playback, currently_playing will be None.
        # There are two playing types, track and episode. We use only the
        # track type. Therefore, when the user's playback type is not a track,
        # Spotify will set the item field to null which becomes None after
        # parsing the JSON. Due to these reasons, we cannot simplify the
        # checks below.
        currently_playing = get_user_currently_playing(user)
        if currently_playing is not None:
            currently_playing_item = currently_playing.get('item', None)
            if currently_playing_item is not None:
                current_app.logger.debug(
                    'Received a currently playing track for %s', str(user))
                listens = parse_and_validate_spotify_plays(
                    [currently_playing_item], LISTEN_TYPE_PLAYING_NOW)
                if listens:
                    submit_listens_to_listenbrainz(
                        listenbrainz_user,
                        listens,
                        listen_type=LISTEN_TYPE_PLAYING_NOW)

        recently_played = get_user_recently_played(user)
        if recently_played is not None and 'items' in recently_played:
            listens = parse_and_validate_spotify_plays(
                recently_played['items'], LISTEN_TYPE_IMPORT)
            current_app.logger.debug('Received %d tracks for %s', len(listens),
                                     str(user))

        # if we don't have any new listens, return
        if len(listens) == 0:
            return

        latest_listened_at = max(listen['listened_at'] for listen in listens)
        submit_listens_to_listenbrainz(listenbrainz_user,
                                       listens,
                                       listen_type=LISTEN_TYPE_IMPORT)

        # we've succeeded so update the last_updated field for this user
        spotify.update_latest_listened_at(user.user_id, latest_listened_at)
        spotify.update_last_updated(user.user_id)

        current_app.logger.info('imported %d listens for %s' %
                                (len(listens), str(user)))

    except spotify.SpotifyAPIError as e:
        # if it is an error from the Spotify API, show the error message to the user
        spotify.update_last_updated(
            user_id=user.user_id,
            success=False,
            error_message=str(e),
        )
        if not current_app.config['TESTING']:
            notify_error(user.musicbrainz_row_id, str(e))
        raise spotify.SpotifyListenBrainzError(
            "Could not refresh user token from spotify")

    except spotify.SpotifyInvalidGrantError:
        if not current_app.config['TESTING']:
            notify_error(
                user.musicbrainz_row_id,
                "It seems like you've revoked permission for us to read your spotify account"
            )
        # user has revoked authorization through spotify ui or deleted their spotify account etc.
        # in any of these cases, we should delete user from our spotify db as well.
        db_spotify.delete_spotify(user.user_id)
        raise spotify.SpotifyListenBrainzError(
            "User has revoked spotify authorization")
 def test_delete_spotify(self):
     token = db_spotify.get_token_for_user(self.user['id'])
     self.assertIsNotNone(token)
     db_spotify.delete_spotify(self.user['id'])
     token = db_spotify.get_token_for_user(self.user['id'])
     self.assertIsNone(token)