import os import random import gradio as gr import spotipy from spotipy.oauth2 import SpotifyOAuth # Set credentials from environment (Hugging Face Secrets) CLIENT_ID = os.environ["SPOTIFY_CLIENT_ID"] CLIENT_SECRET = os.environ["SPOTIFY_CLIENT_SECRET"] REDIRECT_URI = "https://jisaacso219-rng-shuffle.hf.space/" SCOPE = "user-read-playback-state user-modify-playback-state playlist-read-private" # Initialize Spotify auth sp_oauth = SpotifyOAuth( client_id=CLIENT_ID, client_secret=CLIENT_SECRET, redirect_uri=REDIRECT_URI, scope=SCOPE, show_dialog=True, ) sp = None user_playlists = {} device_map = {} def get_auth_url(): return sp_oauth.get_authorize_url() def try_login(current_url): global sp, user_playlists, device_map if "?code=" not in current_url: return ( gr.update(value="🔐 Please login to Spotify."), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), ) code = current_url.split("?code=")[1].split("&")[0] token_info = sp_oauth.get_access_token(code, as_dict=True) access_token = token_info["access_token"] sp = spotipy.Spotify(auth=access_token) # Get playlists playlists = sp.current_user_playlists(limit=50)["items"] user_playlists = {p["name"]: p["id"] for p in playlists} # Get devices devices = sp.devices()["devices"] device_map = {d["name"]: d["id"] for d in devices} if not device_map: return ( gr.update(value="⚠️ No active Spotify devices found. Open Spotify on your phone or PC."), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), ) return ( gr.update(value="✅ Logged in! Pick a playlist and device."), gr.update(visible=True, choices=list(user_playlists.keys())), gr.update(visible=True, choices=list(device_map.keys())), gr.update(visible=True), ) def shuffle_and_play(playlist_name, device_name): pid = user_playlists.get(playlist_name) device_id = device_map.get(device_name) if not pid or not device_id: return "❌ Invalid playlist or device selection." tracks = [] res = sp.playlist_tracks(pid) tracks.extend(res["items"]) while res["next"]: res = sp.next(res) tracks.extend(res["items"]) uris = [t["track"]["uri"] for t in tracks if t["track"]] random.shuffle(uris) try: sp.start_playback(device_id=device_id, uris=uris) return f"▶️ Now playing: **{playlist_name}** on **{device_name}**" except Exception as e: return f"❌ Playback failed: {str(e)}" with gr.Blocks() as demo: gr.Markdown("## 🎵 RNG Spotify Playlist Shuffler") gr.HTML(f'') url_state = gr.Textbox(visible=False) status = gr.Markdown() playlist_dd = gr.Dropdown(label="Select a Playlist", visible=False) device_dd = gr.Dropdown(label="Select a Device", visible=False) shuffle_btn = gr.Button("🔀 Shuffle & Play", visible=False) result = gr.Markdown() demo.load( fn=try_login, inputs=[url_state], outputs=[status, playlist_dd, device_dd, shuffle_btn], js="() => window.location.href" ) shuffle_btn.click(shuffle_and_play, [playlist_dd, device_dd], [result]) if __name__ == "__main__": demo.launch(server_name="0.0.0.0", ssr_mode=False)