示例#1
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'))
示例#2
0
def visview(request, username):
    if not request.session.get('username'):
        return redirect(index)
    if username != request.session.get('username'):
        return redirect(visview, request.session['username'])
    auth_manager = SpotifyOAuth(cache_path=session_cache_path(request.session))
    if (not auth_manager.get_cached_token()) or auth_manager.is_token_expired(auth_manager.get_cached_token()):
        return redirect(index)
    context = {'username': username, 'sessionid': request.session.get('uuid')}
    return render(request, "visualizer/vis.html", context)
    def __init__(self):
        print("Authenticating with Spotify...")
        #token = util.prompt_for_user_token(spconfig.spot_username,"playlist-read-private,playlist-read-collaborative",client_id=spconfig.spot_client_id,client_secret=spconfig.spot_client_secret,redirect_uri=spconfig.spot_redirect)

        try:

            spo = SpotifyOAuth(spconfig.spot_client_id,spconfig.spot_client_secret,spconfig.spot_redirect,scope="playlist-read-private,playlist-read-collaborative",cache_path=spconfig.spot_cache)
            print("DEBUG")
            print(spo.get_cached_token())
            self.sp = spotipy.Spotify(auth=spo.get_cached_token()["access_token"])
            print(self.sp)
            print("Authenticated.")
        except:
            print("Unable to connect to spotify :(")
示例#4
0
def playlists(request):
    auth_manager = SpotifyOAuth(cache_path=session_cache_path(request.session))
    if not auth_manager.get_cached_token():
        return redirect('index')

    spotify = Spotify(auth_manager=auth_manager)
    return Response(spotify.current_user_playlists())
示例#5
0
def playlists(request):
    auth_manager = SpotifyOAuth(cache_path=session_cache_path(request.session))
    if not auth_manager.get_cached_token():
        return redirect('index')
    spotify = Spotify(auth_manager=auth_manager)
    user_playlists = spotify.current_user_playlists()
    for playlist in user_playlists["items"]:
        playlist_info = spotify.playlist_items(playlist["id"])
        playlist["track_lists"] = []
        for track in playlist_info["items"]:
            playlist["track_lists"].append({
                "added_at":
                track["added_at"],
                "album":
                track["track"]["album"]["name"],
                "artists":
                map(lambda x: x["name"], track["track"]["artists"]),
                "name":
                track["track"]["name"],
                "duration_ms":
                track["track"]["duration_ms"],
                "popularity":
                track["track"]["popularity"]
            })

    return Response(user_playlists["items"])
示例#6
0
def spot_login(request):
    if 'cache_id' not in request.session:
        #create random cache
        request.session['cache_id'] = get_random_alphanumeric_string(14)

    auth_manager = SpotifyOAuth(client_id=client_id,
                                client_secret=client_secret,
                                redirect_uri='http://localhost:8000/login/',
                                scope=scope,
                                cache_path=get_cache_path(
                                    request.session['cache_id']),
                                show_dialog=True)
    if 'code' in request.GET:
        print('Getting code')
        token = auth_manager.get_access_token(request.GET.get('code'))
        # print(token)
        return redirect('/')
    print(f'token: {auth_manager.get_cached_token()}')
    if not auth_manager.get_cached_token():
        print('Checking for Cache')
        url = auth_manager.get_authorize_url()
        return redirect(url)
    spotify_object = spotipy.Spotify(auth_manager=auth_manager)
    print('redirecting to login')
    # return HttpResponse(f'<h2><a href="{url}">Sign in</a></h2>')
    # spot = spotipy.Spotify(client_credentials_manager=SpotifyClientCredentials(client_id= client_id, client_secret=client_secret))
    return redirect('Login')
示例#7
0
def spotify_oath_login(account):
    global spotify_client, oath, username, password, cached_token
    username = accounts[account]["username"]
    password = accounts[account]["password"]

    cache_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                              ".cache-%s" % username)

    oath = SpotifyOAuth(client_id,
                        client_secret,
                        redirect_uri,
                        scope=scope,
                        cache_path=cache_path)

    cached_token = oath.get_cached_token()
    app.logger.debug("cached_token: %s", cached_token)
    if cached_token:
        spotify_client = spotipy.client.Spotify(
            auth=cached_token['access_token'])
        app.logger.debug(spotify_client.current_user())
    else:
        app.logger.info(
            "SpotifyToken can't be found. Running *** interactive **** OATH2 flow to approve application."
        )
        if sys.stdin.isatty():
            util.prompt_for_user_token(username, scope, client_id,
                                       client_secret, redirect_uri, cache_path)
        else:
            app.logger.error(
                "You must run this via a terminal, at least once.")
        exit()
    return True
示例#8
0
def spotify_login():
    # global session_counter # used for debugging
    # If a new user joins give random id to the user.
    if not session.get('uuid'):
        session['uuid'] = str(uuid.uuid4())
        # session_counter +=1 # for debugging
        # print(f"Session counter: {session_counter}\n Session id: {session['uuid']}") # for debugging

    sp_oauth = SpotifyOAuth(client_id=client_id,
                            client_secret=client_secret,
                            redirect_uri=REDIRECT_URI,
                            scope=scope,
                            cache_path=session_cache_path(),
                            show_dialog=True)

    # Authorization Code Flow Step 2
    if request.args.get('code'):
        auth_code = request.args.get('code')  # get the code from the url.
        sp_token = sp_oauth.get_access_token(
            auth_code)  # use that code to get a token
        return redirect("/spotify_login")

    display = "Login to Spotify"
    if sp_oauth.get_cached_token():
        # Authorization Code Flow Step 3
        # NOTE here we can get data from the Spotify API.
        spotify = spotipy.Spotify(auth_manager=sp_oauth)
        display = "User: "******"display_name"] + " (Sign Out)"
        spotify_data = spotifyData.spotify_data(spotify)
        # pp(spotify_data)
        return render_template("spotify.html",
                               display=display,
                               playlists=spotify_data["playlists"])
    return render_template("spotify_login.html", display=display)
def authenticate(username):
    '''
    authenticate with the spotify service
    '''

    oauth_manager = SpotifyOAuth(username=username, scope=SCOPE)
    sp = spotipy.Spotify(oauth_manager=oauth_manager)
    user = sp.current_user()

    token_expired = oauth_manager.is_token_expired(
        oauth_manager.get_cached_token())

    if token_expired:
        # refresh token
        logging.debug('Refreshing token for user {}'.format(user['id']))
        oauth_manager.refresh_access_token(
            oauth_manager.get_cached_token()['refresh_token'])

    return oauth_manager, sp, user
示例#10
0
def top_tracks(request, time_range):
    if time_range not in time_ranges:
        raise Http404("Time range is not valid")

    auth_manager = SpotifyOAuth(cache_path=session_cache_path(request.session))
    if not auth_manager.get_cached_token():
        return redirect('index')
    spotify = Spotify(auth_manager=auth_manager)
    track = spotify.current_user_top_tracks(time_range=time_range)
    return Response(track)
示例#11
0
 def get_token(self):
     sp_auth = SpotifyOAuth(
         client_id=self.client_id,
         client_secret=self.client_secret,
         redirect_uri=self.redirect_uri,
         scope=self.scope,
     )
     try:
         token = sp_auth.get_cached_token()
     except:
         token = sp_auth.get_access_token()
     return token["access_token"]
示例#12
0
    def get(self, request):
        now = datetime.now()

        current_time = now.strftime("%H:%M:%S")
        print("Current Time =", current_time)

        new_cache = str(uuid.uuid4())
        print('New UUID: ' + new_cache)

        try:
            cache = request.session['cache_id']
            print('cache exists')
        except KeyError:
            print('new cache')
            request.session['cache_id'] = new_cache
            cache = request.session['cache_id']

        cache_path = spotify_cache_folder + cache
        print('cache_path: ' + cache_path)

        if os.path.exists(cache_path):
            print('cache file exists')
        else:
            print('cache file does not exist')

        scope = 'user-read-email, user-top-read'

        auth_manager = SpotifyOAuth(scope=scope,
                                    cache_path=cache_path,
                                    show_dialog=True)

        code = self.request.query_params.get('code')
        print(code)
        if code:
            print('code: ' + code)
            auth_manager.get_access_token(code=code)
            print('redirecting..')
            redirect_url = prod_url + '/success.html'
            return HttpResponseRedirect(redirect_to=redirect_url)

        if not auth_manager.get_cached_token():
            url = {'url': auth_manager.get_authorize_url()}
            serializer = UrlSerializer(url)

            return Response(serializer.data, status=status.HTTP_200_OK)
        else:
            url = {'url': auth_manager.get_authorize_url()}
            serializer = UrlSerializer(url)

            return Response(serializer.data, status=status.HTTP_200_OK)

        return Response("ERROR", status=status.HTTP_400_BAD_REQUEST)
示例#13
0
def get_token():
    """ returns a valid Spotify authentication token, refreshes the token if it is expired
    """
    load_dotenv()

    # Get clientID and clientSecret from .env file
    client_id = os.getenv("CLIENT_ID")
    client_secret = os.getenv("CLIENT_SECRET")
    user_id = os.getenv("SPOTIFY_USERNAME")

    scope = 'user-read-private user-read-playback-state user-modify-playback-state user-top-read user-library-read playlist-modify-public playlist-modify-private'

    auth = SpotifyOAuth(client_id,
                        client_secret,
                        'http://localhost:8050/callback',
                        cache_path=f".cache-{user_id}",
                        scope=scope)

    if auth._is_token_expired(auth.get_cached_token()):
        return auth.refresh_access_token(
            auth.get_cached_token()['refresh_token'])['access_token']
    return auth.get_cached_token()['access_token']
示例#14
0
文件: views.py 项目: Auzzy/simplay
def another():
    auth_obj = SpotifyOAuth(os.environ.get("SPOTIPY_CLIENT_ID"),
                            os.environ.get("SPOTIPY_CLIENT_SECRET"),
                            REDIRECT_URL,
                            scope="playlist-read-private")
    token_info = auth_obj.get_cached_token()

    client = spotipy.Spotify(auth=token_info["access_token"])
    result = client.user_playlists("metalnut4")
    playlist_names = [
        playlist_item["name"] for playlist_item in result["items"]
    ]
    return "<br />".join(playlist_names)
示例#15
0
def use_or_refresh_token(config):
    so = SpotifyOAuth(
        client_id=config['spotify_client']['client_id'],
        client_secret=config['spotify_client']['client_secret'],
        redirect_uri=config['spotify_client']['redirect_uri'],
        scope=scope,
        cache_path=get_token_path(config),
    )
    token = so.get_cached_token()
    # spotipy refreshes an expired token during the function call above
    access_token = token['access_token']

    return access_token
示例#16
0
def check_login():
    oauth = SpotifyOAuth(
        client_id=CLIENT_ID,
        client_secret=CLIENT_SECRET,
        redirect_uri=REDIRECT_URI,
        scope=SCOPE,
        cache_path=CACHE_PATH,
    )
    token = oauth.get_cached_token()

    if token:
        return {"logged_in": "true"}
    else:
        return {"logged_in": "false"}
示例#17
0
def get_token(token_path="cached_data/auth_token.json"):

    oauth = SpotifyOAuth(CLIENT_ID,
                         APP_SECRET,
                         REDIRECT_URI,
                         cache_path=CACHE_PATH,
                         scope=SCOPES)

    token = oauth.get_cached_token()

    if not token:
        token = authorize_application(CACHE_PATH, SCOPES)

    return token
 def get_token(self, allow_raw_input=True):
     if allow_raw_input:
         token = util.prompt_for_user_token(
             self.username, config.SCOPE, self.client_id,
             self.client_secret, self.callback_url)
     else:
         sp_oauth = SpotifyOAuth(
             self.client_id, self.client_secret, self.callback_url,
             scope=config.SCOPE, cache_path=self.cache_path)
         token_info = sp_oauth.get_cached_token()
         if token_info:
             token = token_info['access_token']
         else:
             raise Exception('need to run debug-refresh-token in a terminal')
     return token
示例#19
0
def get_spotipy_objs():
  # Returns two list array with ouath and sp object
  letters = string.ascii_lowercase
  random_string = ''.join(random.choice(letters) for i in range(10))
  oauth = SpotifyOAuth(client_id="ca077b4c1b6b4ea7a33ed0069ec3eecb",
                      client_secret="2d2baf7aa1ff4c9792822aefac0ef7e5",
                      redirect_uri="https://favorable-mark-297715.uc.r.appspot.com/form/",
                      state = random_string,
                      scope="user-read-recently-played user-modify-playback-state user-read-private",
                      cache_path=None)
  token_dict = oauth.get_cached_token()
  token = token_dict['access_token']
  refresh_token = token_dict['refresh_token']
  if oauth.is_token_expired(token_dict):
    oauth.refresh_access_token(refresh_token)
  sp = spotipy.Spotify(auth_manager=oauth)
  current_user_id = sp.current_user()['id']
  return [oauth, sp]
 def get_token(self, allow_raw_input=True):
     if allow_raw_input:
         token = util.prompt_for_user_token(self.username, config.SCOPE,
                                            self.client_id,
                                            self.client_secret,
                                            self.callback_url)
     else:
         sp_oauth = SpotifyOAuth(self.client_id,
                                 self.client_secret,
                                 self.callback_url,
                                 scope=config.SCOPE,
                                 cache_path=self.cache_path)
         token_info = sp_oauth.get_cached_token()
         if token_info:
             token = token_info['access_token']
         else:
             raise Exception(
                 'need to run debug-refresh-token in a terminal')
     return token
示例#21
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"]})
示例#22
0
文件: auth.py 项目: 5l1v3r1/soapify
def get_token(username, client_id, client_secret, redirect_uri, scope):
    sp_oauth = SpotifyOAuth(username=username,
                            client_id=client_id,
                            client_secret=client_secret,
                            redirect_uri=redirect_uri,
                            scope=scope,
                            cache_path=getenv("HOME") + "/.cache/soapify-" +
                            username)

    token_info = sp_oauth.get_cached_token()
    token = None
    if not token_info:
        auth_url = sp_oauth.get_authorize_url()
        webbrowser.open(auth_url)
        pool = ThreadPool(processes=1)
        code = pool.apply_async(CallbackServer).get().get_token()
        token_info = sp_oauth.get_access_token(code)
    if token_info:
        token = token_info['access_token']
    return token
示例#23
0
    def obtain_token(self):
        """
        Obtain token from Oauth protocol: ask user to paste the redirect uri.
        Uses a cache for avoiding ask user too many times.
        :return: Str token or raise an exception
        """
        client_id = os.getenv('SPOTIPY_CLIENT_ID')
        client_secret = os.getenv('SPOTIPY_CLIENT_SECRET')
        client_redirect_uri = os.getenv('SPOTIPY_REDIRECT_URI')
        scope = 'playlist-modify-private'

        _token = ''
        try:
            # Cache
            sp_oauth = SpotifyOAuth(client_id,
                                    client_secret,
                                    client_redirect_uri,
                                    cache_path=self.cache_path,
                                    scope=scope)
            info_token = sp_oauth.get_cached_token()
            if info_token:
                _token = info_token['access_token']

            # Prompt
            if not _token:
                _token = util.prompt_for_user_token(
                    self.username,
                    scope=scope,
                    client_id=client_id,
                    client_secret=client_secret,
                    redirect_uri=client_redirect_uri)
        except Exception as e:
            if os.path.exists(self.cache_path):
                os.remove(self.cache_path)
            print("something bad happened: " + str(e))
            sys.exit(2)

        if not _token:
            print("I can't read the auth token for username " + self.username)
            sys.exit(2)
        return _token
示例#24
0
def login():
    if request.method == 'POST':
        try:
            sp_oauth = SpotifyOAuth(client_id=client_id,
                                    client_secret=client_secret,
                                    redirect_uri=REDIRECT_URI,
                                    scope=scope,
                                    cache_path=session_cache_path(),
                                    show_dialog=True)

            # So if we have a token(which means we are logged in)
            # and the login button is clicked then we need to sign out

            if not sp_oauth.get_cached_token():
                # Authorization Code Flow Step 1
                auth_url = sp_oauth.get_authorize_url()
                return redirect(auth_url)
            return redirect("/sign_out")
        except TypeError:
            pass
    return redirect("spotify_login")
示例#25
0
    def get(self, request):
        new_cache = str(uuid.uuid4())

        cache = request.session.get('cache_id', new_cache)

        cache_path = spotify_cache_folder + cache
        print('cache_path:' + cache_path)

        scope = 'user-read-email, user-top-read'

        auth_manager = SpotifyOAuth(scope=scope,
                                    cache_path=cache_path,
                                    show_dialog=True)

        code = self.request.query_params.get('code')
        if code:
            print('code: ' + code)
            auth_manager.get_access_token(code=code)
            print('redirecting..')
            return HttpResponseRedirect(
                redirect_to='http://localhost:8080/index3.html')

        if not auth_manager.get_cached_token():
            auth_url = auth_manager.get_authorize_url()

            data = f'<h2><a href="{auth_url}">Sign in</a></h2>'
            return Response(data)

        spotify = spotipy.Spotify(auth_manager=auth_manager)
        user_result = spotify.current_user()

        display_name = user_result['display_name']
        client_url = 'https://chopshop-client.herokuapp.com/'

        data = '<html><body><h1>Hello ' + display_name + '. You are connected to Spotify :) </h1>'
        data += f'<h2><a href="{client_url}">Now click here!</a></h2>'
        data += '</body></html>'

        return Response(data)
示例#26
0
def spotify_connect(session_id, code=''):
    '''
    Connect to the Spotify API using the token associated with the given session
    ID, generating one if it does not already exist.
    '''
    token = None
    cache_path = CACHE + session_id

    sp_oauth = SpotifyOAuth(CLIENT_ID,
                            CLIENT_SECRET,
                            REDIRECT_URI,
                            scope=SCOPE,
                            cache_path=cache_path)
    token_info = sp_oauth.get_cached_token()
    if token_info:
        token = token_info['access_token']
    elif code:
        token_info = sp_oauth.get_access_token(code)
        token = token_info['access_token']

    if token:
        return Spotify(token, requests_timeout=30, retries=1)
    else:
        return sp_oauth.get_authorize_url()
    if is_token_expired(token_info):
        token_info = oauth.refresh_access_token(token_info['refresh_token'])
        token = token_info['access_token']
        sp = spotipy.Spotify(auth=token)


scope = 'playlist-modify-public'
id = os.environ['ClientID']
secret = os.environ['ClientSecret']
# id = config.ClientID
# secret = config.ClientSecret
oauth = SpotifyOAuth(client_id=id,
                     client_secret=secret,
                     redirect_uri='http://localhost/',
                     scope=scope)
token_info = oauth.get_cached_token()
if not token_info:
    auth_url = oauth.get_authorize_url()
    st.write(auth_url)
    response = st.text_input(
        'Click the above link, then paste the redirect url here and hit enter: '
    )
    st.write(
        '*The BadAuth error below should go away after entering the redirect url'
    )
    # response = input('Paste the above link into your browser, then paste the redirect url here: ')
    if response == "":
        time.sleep(5)
    code = oauth.parse_response_code(response)
    token_info = oauth.get_access_token(code)
    token = token_info['access_token']
示例#28
0
class SpotifyAuthManager():
    """
        A class used to handle Spotify Oauth.
        Refreshable user authentication.

        Owned by Playlist & ArtistManager.

        Args:

        Instance Attributes

        Class Attributes:

    """

    username = os.environ['SPOTIFY_USERNAME']
    client_id = os.environ['SPOTIFY_CLIENT_ID']
    client_secret = os.environ['SPOTIFY_CLIENT_SECRET']
    scope = os.environ['SPOTIFY_SCOPE']
    redirect_uri = os.environ['SPOTIFY_REDIRECT_URI']

    def __init__(self, session=None):

        self.token_info = None
        self.response_code = None
        self.client_mgr = None

        self.session = session
        # use same session
        # self.session = session

    def create_client_mgr(self):
        """
        Create SpotifyOauth object.

        Args:
            client_id
            client_secret
            redirect_uri
            scope
            cache_path

        """

        cache_path = WindowsPath("__pycache__") / fr'.cache-{self.username}'
        self.client_mgr = SpotifyOAuth(self.client_id,
                                       self.client_secret,
                                       self.redirect_uri,
                                       scope=self.scope,
                                       cache_path=cache_path)
        return self

    def get_auth_token(self):
        """
        Get oauth token from cache or prompt for new token.
        """

        try:
            self.token_info = self.client_mgr.get_cached_token()
            logger.info(
                f"Token expires at {time.strftime('%c', time.localtime(self.token_info['expires_at']))}"
            )
            return self
        # TODO: add specific exceptions
        except Exception:
            logger.info("No token in cache. Getting new token.", exc_info=True)
            auth_url = self.client_mgr.get_authorize_url()
            user_auth = self.session.get(auth_url).url
            response_code = input(f'Use Browser to authenticate: {user_auth}')
            code = self.client_mgr.parse_response_code(response_code)
            self.token_info = self.client_mgr.get_access_token(code)

            with open(self.client_mgr.cache_path, 'w') as f:
                f.write(json.dumps(self.token_info))

    def refresh_auth_token(self):
        """
            Refresh authentication token.

            Same spotify obect used throughout. How to call from owning classes.
        """

        self.client_mgr.refresh_access_token(self.token_info['refresh_token'])
        logger.info(
            f"Token refreshed, expires at: {time.strftime('%c', time.localtime(self.token_info['expires_at']))}"
        )

    def create_spotify(self):
        """
        Create Spotify object for Authorization Code flow.

        Args: token, session, client_mgr
        """

        try:
            auth_info = {
                'auth': self.token_info['access_token'],
                'requests_session': self.session,
                'client_credentials_manager': self.client_mgr
            }
            return catch(spotipy.Spotify, auth_info)
        except TypeError:
            # Why TypeError?
            logger.error("Token error.", exc_info=True)
示例#29
0
class Muzik:
    def __init__(self, public_api=False):
        self.__create_cache_dir()
        self.ids = self.__read_cached_ids()
        if public_api:
            self.__sp = self.__connect_spotify()
        self.__sp_user = self.__connect_spotify_user()
        self.__user_id = self.__sp_user.me()["id"]

    def __create_cache_dir(self):
        """
        Create cache dir at `CACHE_DIR` if doesn't already exists
        """
        if not os.path.isdir(CACHE_DIR):
            os.mkdir(CACHE_DIR)

    def __read_cached_ids(self) -> pd.Series:
        """
        Read the cached already fetched ids from the cache folder
        either returns the cached pd.Series, or empty series if
        no file there
        """
        path = CACHE_DIR + ACH_IDS
        if os.path.exists(path):
            print(f"Reading data from cache file {path}")
            df = pd.read_pickle(path)
        else:
            df = pd.Series()
        print(f"Local library contains {len(df)} songs")
        return df

    def __read_credentials(self):
        """
        Opens and return the content of `CRED_PATH_SPOTIFY` as
        a python dict
        """
        with open(CRED_PATH_SPOTIFY, 'r') as handle:
            data = json.load(handle)
        return data

    def __connect_spotify_user(self):
        """
        Connect to the API using the spotify user credentials
        needs more informations than the other method, but can
        access to personnal informations (including playlists :o)
        of the user
        """
        data = self.__read_credentials()
        # generate a unique random number to prevent csrf
        state = hashlib.sha256(os.urandom(1024)).hexdigest()
        self.__user_credentials = SpotifyOAuth(
            **data,
            state=state,
        )
        return self.__get_spotify_user(
            self.__user_credentials.get_access_token(as_dict=(False)))

    def __get_spotify_user(self, token):
        """
        Returns a Spotify client authentified with the provided
        token
        """
        return spotipy.Spotify(auth=token)

    def __connect_spotify(self):
        """
        Connect to the public API of Spotify, useful to fetch songs ids
        since the API limite rate is higher here, however not really
        useful to create playlists and stuff
        """
        data = self.__read_credentials()
        auth = {}
        auth["client_id"] = data["client_id"]
        auth["client_secret"] = data["client_secret"]
        return spotipy.Spotify(auth_manager=SpotifyClientCredentials(**auth))

    def __refresh_token(self):
        """
        Refreshes the tokenn if it has expired or not
        and updates the sp_user Spotify Interface with
        the new token
        """
        cached = self.__user_credentials.get_cached_token()
        refreshed = self.__user_credentials.refresh_access_token(
            cached["refresh_token"])
        self.__sp_user = self.__get_spotify_user(refreshed["access_token"])

    def __update_token(self):
        """
        Updates the token if it has expired
        !! may not work flawlessely (probably not in fact),
        hard to test since the token lasts for 1 hour haha
        """
        # built-in function, does not work always good
        cached = self.__user_credentials.get_cached_token()
        if self.__user_credentials.is_token_expired(cached):
            print("Token expired, refreshing now")
            self.__refresh_token()
        # handmade function just in case the one above fails
        try:
            _ = self.__sp_user.me()
        except SpotifyException as e:
            if e.http_status == UNAUTHORIZED_ST_CODE:
                print("Token expired, refreshing now")
                self.__refresh_token()

    def __search_strings(self, row):
        """
        Creates the search string for the Spotify API based on
        the information of the row
        Returns a list of multiple strings, to take into account
        if there is special characters (like "'")
        or multiple markets
        input:
            - row : pd.Series with genre, artists, songs,...
        output:
            - searches : list of tuples (search string, market)
        """
        search = ""
        # artists
        artists = list(map(str.strip, row.artist.split(",")))
        if len(artists) > 1:
            sep = '" AND "'
            search += f"artist:\"{sep.join(artists)}\""
        else:
            search += f"artist:\"{artists[0]}\""
        # album
        if row.album != "N/A":
            search += f" album:\"{row.album}\""
        # track name
        search += f" track:\"{row.song}\""
        # dealing with "'""
        # sometimes it will work with the "'" and sometimes not
        if "'" in search:
            searches_s = [search, search.replace("'", "")]
        else:
            searches_s = [search]
        searches = []
        for market in MARKETS:
            for search in searches_s:
                searches.append((search, market))
        return searches

    def __fetch_id(self, df):
        """
        Fetches the Spotify songs id for each provided songs
        If it cannot find ids for a song, it will be set to None
        input:
            - df : a pd.DataFrame with a random index and the
                   song specific columns (genre, artist, ...)
        """
        # small hack to access the data from the index & the columns
        indexs = pd.MultiIndex.from_frame(df)
        songs = pd.DataFrame(data=df.values, index=indexs, columns=df.columns)
        ids = pd.Series(index=indexs, dtype=str, name="ids")
        bad_formats = []
        # chosing the endpoint
        # by default try to take the public one, if doesn't exists
        # (public_api = False), use the private one
        try:
            endpoint = self.__sp
        except AttributeError:
            endpoint = self.__sp_user
        # format string padding used for the debug output
        str_format = int(math.log(len(songs), 10)) + 1
        for idx, (_, content) in enumerate(songs.iterrows()):
            searches = self.__search_strings(content)
            bad_format = []
            for search, market in searches:
                try:
                    res = endpoint.search(search, market=market)
                    track = res['tracks']['items'][0]
                except IndexError:
                    bad_format.append((search, market))
                else:
                    # succeed to fetch an id
                    break
            else:
                # did not managed to find an id with all the search strings
                # provided, set the id of the song to None
                bad_formats.append(bad_format)
                ids.iloc[idx] = None
                print(f"{Color.FAIL}"
                      f"{idx + 1:<{str_format}}/{len(df)}"
                      f"{Color.ENDC}"
                      f" : {search} not in Spotify")
                continue
            album = track['album']['name']
            name = track['name']
            artist = track['artists'][0]['name']
            id = track['id']
            ids.iloc[idx] = id
            print(f"{Color.OKGREEN}"
                  f"{idx + 1:<{str_format}}/{len(df)}"
                  f"{Color.ENDC}"
                  f" : {id} {name} {artist} {album}")
        return ids

    def __update_missing_list(self):
        """
        Create a csv file containing every tracks that were not
        available on spotify
        """
        missing = self.ids[self.ids.isnull()]
        missing.index.to_frame(index=False).to_csv(CACHE_DIR + MISSING_IDS)

    def __create_user_playlist(self):
        """
        Creates a new playlist using PLAYLIST_NAME, PLAYLIST_DESC
        also pushes playlist cover PLAYLIST_COVER
        return:
            - playlist_id : string containing the id of the playlist
        """
        # create the playlist with name, description, visibility
        print(f"Creating {PLAYLIST_NAME}...")
        ret = self.__sp_user.user_playlist_create(user=self.__user_id,
                                                  name=PLAYLIST_NAME,
                                                  public=True,
                                                  description=PLAYLIST_DESC)
        playlist_id = ret["id"]
        # most important, upload the playlist image
        print(f"Uploading playlist cover from {PLAYLIST_COVER}")
        with open(PLAYLIST_COVER, "rb") as image_file:
            cover = base64.b64encode(image_file.read())
        ret = self.__sp_user.playlist_upload_cover_image(playlist_id, cover)
        return playlist_id

    def __get_playlist_id(self):
        """
        Returns the playlist id of PLAYLIST_NAME
        if the playlist doesn't exists yet, it will create it
        and return the id of the newly created playlist
        """
        # check if the playlist already exists
        user_playlists = self.__sp_user.user_playlists(self.__user_id)
        playlist_id = None
        if len(user_playlists["items"]) > 0:
            for user_pl in user_playlists["items"]:
                if user_pl["name"] == PLAYLIST_NAME:
                    playlist_id = user_pl["id"]
                    break
        # at this point, if the playlist exists, the id is stored in
        # playlist_id, otherwise we have still a None value
        if playlist_id is None:
            print(f"Playlist {PLAYLIST_NAME} doesn't exists yet")
            playlist_id = self.__create_user_playlist()
        print(f"Using playlist {PLAYLIST_NAME} : {playlist_id}")
        return playlist_id

    def update(self, ach):
        """
        updates the known list of ids with the newer version of the
        ach musik sheet
        input:
            - ach : raw sheet from google with multiindex
        """
        self.__update_token()
        # turn the index to DataFrame objects
        new_songs = ach.index.to_frame().reset_index(drop=True)
        if self.ids.empty:
            # in case the cached list was empty, simply fetch the whole
            # list
            self.ids = self.__fetch_id(new_songs)
        else:
            old_songs = self.ids.index.to_frame().reset_index(drop=True)
            # get the list of the common values
            common_songs = new_songs.merge(old_songs, how='inner')
            # remove the songs that are not anymore in the cached df
            depr = pd.concat([common_songs,
                              old_songs]).drop_duplicates(keep=False)
            to_remove = pd.MultiIndex.from_frame(depr)
            if len(to_remove) > 0:
                self.ids = self.ids.drop(to_remove)
            # adds the new songs from the ach sheet
            news = pd.concat([common_songs,
                              new_songs]).drop_duplicates(keep=False)
            if len(news) > 0:
                new_ids = self.__fetch_id(news)
                self.ids = pd.concat([self.ids, new_ids])
            else:
                print("Local list already updated")
        # save updated list in cache
        self.ids.to_pickle(CACHE_DIR + ACH_IDS)
        # also updates missing ID list
        self.__update_missing_list()

    def create_playlist(self, playlist):
        """
        Create (or replace) a playlist containing all the songs provided
        in the playlists DataFrame
        input:
            - playlist : pd.DataFrame indexed by a MultiIndex with
                         genre, artist, song, ...
        """
        self.__update_token()
        # get the playlist id of PLAYLIST_NAME
        playlist_id = self.__get_playlist_id()
        # get the tracks
        tracks_all = self.ids[playlist.index]
        tracks_results = tracks_all.isnull().value_counts()
        print(f"Adding {tracks_results[False]} tracks,"
              f" Missing {tracks_results[True]} tracks")
        tracks_id = tracks_all.dropna().values
        print(f"Inserting {len(tracks_id)} songs in the playlist...")
        # spotify api "only" handles 100 tracks by requests
        # so here we split the data
        batch_size = int(len(tracks_id) / MAX_TRACK_PER_REQUESTS) + 1
        batches = np.array_split(tracks_id, batch_size)
        str_format = int(math.log(len(batches), 10)) + 1
        print(f"{0:<{str_format}}/{len(batches)} batch inserting...")
        # the first call `replace_tracks` clear the playlist AND
        # adds the supplied tracks
        self.__sp_user.user_playlist_replace_tracks(self.__user_id,
                                                    playlist_id=playlist_id,
                                                    tracks=batches[0])
        if len(batches) > 1:
            for idx, batch in enumerate(batches[1:]):
                print(f"{idx+2:<{str_format}}/{len(batches)}"
                      " batch inserting...")
                # add the rest of the tracks
                self.__sp_user.user_playlist_add_tracks(
                    self.__user_id, playlist_id=playlist_id, tracks=batch)

        print("Playlist done")

    def get_playlists(self):
        self.__update_token()
        return self.__sp_user.user_playlists(self.__user_id)
示例#30
0
class Spotify:
    def __init__(self, public=True, cache_path="spotify_tokens.json"):
        self.public = public
        scope = ("playlist-modify-private", "playlist-modify-public")[self.public]
        scope += " user-read-private"
        self.OAuth = SpotifyOAuth(scope=scope, cache_path=cache_path)
        self.sp = spotipy.Spotify(auth_manager=self.OAuth)
        self.user_id = self.sp.current_user()["id"]
        self.access_token = self.OAuth.get_cached_token()["access_token"]
        self.playlist_id = None

    def make_playlist(
        self, name="Youtube Playlist", collaborative=False, description=""
    ):
        """
        Does the same thing as user_playlist_create() but it utilizes the request library/http reqests. 

        :param
         - name: name of playlist
            defaultis Youtube Playlist
        """
        payload = json.dumps(
            {
                "name": name,
                "public": self.public,
                "collaborative": collaborative,
                "description": description,
            }
        )
        headers = {
            "Authorization": f"Bearer {self.access_token}",
            "Content-Type": "application/json",
        }
        r = requests.post(
            f"https://api.spotify.com/v1/users/{self.user_id}/playlists",
            data=payload,
            headers=headers,
        )
        self.playlist_id = r.json()["id"]

    def search_tracks(self, track):
        """
        Searches for a track on Spotify

        :param
         - track: The track to search for
        """
        q = track.replace(" ", "+")
        # Encode the track title
        response = self.sp.search(q, limit=5, type="track")
        # Get the first song's uri from the search
        try:
            self.track_uri = response["tracks"]["items"][0]["uri"]
        except:
            self.track_uri = False

    def add_tracks(self, playlist_name, tracks, failed, succ=[], mode="w"):
        """
        Tries to add tracks onto Spotify playlist

        :param
         - tracks: tracks to add
         - failed: Will contain songs that could not have been added
         - mode: "w" when making playlist. "a" when updating playlist
        """
        for track in tracks:
            self.search_tracks(track)
            if self.track_uri:
                self.sp.user_playlist_add_tracks(
                    self.user_id, self.playlist_id, [self.track_uri]
                )
                succ.append(track)
                else:
                    # Have failed to find tracks for user to see
                    failed.append(track)
        with open(f"succ {playlist_name}.txt", mode) as f:
            for i in succ:
                f.write(f"i, ")
        with open(f"failed {playlist_name}.txt", mode) as f:
            for i in failed:
                f.write(f"{i}, ")
示例#31
0
import json
import spotipy
from spotipy.oauth2 import SpotifyOAuth

with open('track_ids.json', 'r') as f:
    ids = json.load(f)

id_list = ids.values()

scope = "playlist-modify-public"

OAuth = SpotifyOAuth(scope=scope,
                     redirect_uri='http://localhost:8888',
                     cache_path='../cache.txt')
token = OAuth.get_cached_token()

sp = spotipy.Spotify(auth_manager=OAuth)

user_id = sp.current_user()['id']

playlist = sp.user_playlist_create(user=user_id,
                                   name='Regression Playlist',
                                   description='I might like it, I might not')

sp.user_playlist_add_tracks(user=user_id,
                            playlist_id=playlist['id'],
                            tracks=id_list)