from flask import Flask, request, redirect import spotipy from spotipy.oauth2 import SpotifyOAuth import threading import os import sys import time import requests from datetime import datetime import subprocess import logging app = Flask(__name__) stop_flask = threading.Event() logger = logging.getLogger('flask') logger.setLevel(logging.ERROR) # Set to ERROR to ignore lower levels client_id = "c0020cc0e05245efb2ddb61b7045e4f2" client_secret = "2e2e7c98f849403fbacc219c1f01c17d" redirect_uri = "https://elease-uncapsuled-yosef.ngrok-free.dev/callback" # Hardcoded ngrok URL sp_oauth = SpotifyOAuth(client_id=client_id, client_secret=client_secret, redirect_uri=redirect_uri, scope="playlist-modify-private user-library-read") # This will store whether the access token was acquired access_token_obtained = threading.Event() @app.route('/') def index(): return "Welcome! Login to Spotify" @app.route('/login') def login(): return redirect(sp_oauth.get_authorize_url()) @app.route('/callback') def callback(): code = request.args.get('code') token_info = sp_oauth.get_access_token(code) access_token = token_info['access_token'] with open("access_token.txt", "w") as f: f.write(access_token) #print("Authorization complete. You can close this window.", file=sys.stderr) # Signal that the access token has been obtained access_token_obtained.set() return "Authorization complete. You can close this window." def create_playlist(): if not os.path.exists("access_token.txt"): print("No access token found.", file=sys.stderr) return with open("access_token.txt", "r") as f: access_token = f.read().strip() sp = spotipy.Spotify(auth=access_token) print("Fetching liked songs...", file=sys.stderr) liked_songs = [] results = sp.current_user_saved_tracks() while results: for item in results['items']: liked_songs.append(item['track']['id']) if results['next']: results = sp.next(results) else: break playlist_name = datetime.now().strftime("Liked Songs Collection - %Y-%m-%d %H-%M-%S") user_id = sp.me()['id'] new_playlist = sp.user_playlist_create(user_id, playlist_name, public=False) print(f"Created playlist: {playlist_name}", file=sys.stderr) for i in range(0, len(liked_songs), 100): batch = liked_songs[i:i + 100] sp.playlist_add_items(new_playlist['id'], batch) print(f"Added {len(batch)} songs...", file=sys.stderr) playlist_url = new_playlist['external_urls']['spotify'] print(f"Playlist URL: {playlist_url}", file=sys.stderr) return playlist_url def run_flask(): with open(os.devnull, 'w') as fnull: # Redirect both stdout and stderr to devnull #sys.stdout = fnull sys.stderr = fnull # COMMENT FOR DEBUG subprocess.run(["xdg-open", "http://192.168.0.100:8888"]) app.run(host="0.0.0.0", port=8888, use_reloader=False) # sys.stdout = sys.__stdout__ # Restore original stdout # sys.stderr = sys.__stderr__ # Restore original stderr def kill_ngrok(): try: # Find ngrok process and kill it subprocess.call(["pkill", "ngrok"]) except Exception as e: print(f"Error stopping ngrok: {str(e)}", file=sys.stderr) def main(): kill_ngrok() # Start Flask in a background thread flask_thread = threading.Thread(target=run_flask, daemon=True) flask_thread.start() # Allow some time for Flask to start time.sleep(2) # Start ngrok dynamically os.system("ngrok http 8888 &") # Allow time for ngrok to initialize time.sleep(5) # Print out the hardcoded ngrok URL print(f"Ngrok URL: {redirect_uri}", file=sys.stderr ) print("Please authorize access via the following URL:", sp_oauth.get_authorize_url(), file=sys.stderr) # Wait for the access token to be acquired access_token_obtained.wait() # Wait until the access token is provided # Now that we have the token, proceed with creating the playlist playlist_url = create_playlist() print(playlist_url) stop_flask.set() # Signal Flask to stop flask_thread.join() # Wait for the Flask thread to complete sys.exit(0) if __name__ == "__main__": main()