Spaces:
Running
Running
import os | |
import gradio as gr | |
import spotipy | |
from spotipy.oauth2 import SpotifyOAuth | |
import random | |
# 1. Hard‐code your redirect URI here: | |
REDIRECT_URI = "https://jisaacso219-rng-shuffle.hf.space/" | |
# 2. Keep your client creds in Secrets, as before: | |
CLIENT_ID = os.environ["SPOTIFY_CLIENT_ID"] | |
CLIENT_SECRET = os.environ["SPOTIFY_CLIENT_SECRET"] | |
SCOPE = ( | |
"user-read-playback-state " | |
"user-modify-playback-state " | |
"playlist-read-private" | |
) | |
sp_oauth = SpotifyOAuth( | |
client_id=CLIENT_ID, | |
client_secret=CLIENT_SECRET, | |
redirect_uri=REDIRECT_URI, | |
scope=SCOPE, | |
show_dialog=True, | |
) | |
sp = None | |
user_playlists = {} | |
def get_auth_url(): | |
return sp_oauth.get_authorize_url() | |
def check_login(code: str): | |
global sp, user_playlists | |
token = sp_oauth.get_access_token(code, as_dict=False) | |
sp = spotipy.Spotify(auth=token) | |
# pull their first 50 playlists | |
pls = sp.current_user_playlists(limit=50)["items"] | |
user_playlists = {p["name"]: p["id"] for p in pls} | |
return ( | |
gr.update(visible=True, value="✅ Logged in! Choose a playlist below."), | |
gr.update(visible=True, choices=list(user_playlists.keys())) | |
) | |
def load_playlist_info(pl_name): | |
pid = user_playlists[pl_name] | |
data = sp.playlist(pid) | |
img = data["images"][0]["url"] if data["images"] else "" | |
owner = data["owner"]["display_name"] | |
desc = data.get("description", "") | |
html = f""" | |
<img src="{img}" width="300px" style="border-radius:10px;"/><br/> | |
<strong>{pl_name}</strong> by {owner}<br/> | |
{desc} | |
""" | |
return gr.update(visible=True, value=html), gr.update(visible=True) | |
def shuffle_and_play(pl_name): | |
pid = user_playlists[pl_name] | |
# grab all tracks | |
tracks, results = [], sp.playlist_tracks(pid) | |
tracks += results["items"] | |
while results["next"]: | |
results = sp.next(results) | |
tracks += results["items"] | |
uris = [t["track"]["uri"] for t in tracks if t["track"]] | |
random.shuffle(uris) | |
# send to their first active device | |
devs = sp.devices()["devices"] | |
if not devs: | |
return gr.update(value="⚠️ No active Spotify device found. Start Spotify on one of your devices.", visible=True) | |
sp.start_playback(device_id=devs[0]["id"], uris=uris) | |
# show the first shuffled track’s info: | |
now = sp.current_playback() | |
if now and now.get("item"): | |
it = now["item"] | |
art = it["album"]["images"][0]["url"] | |
title = it["name"] | |
artists = ", ".join(a["name"] for a in it["artists"]) | |
html = f""" | |
<img src="{art}" width="200px" style="border-radius:8px;"/><br/> | |
▶️ <strong>{title}</strong><br/> | |
by {artists} | |
""" | |
return gr.update(value=html, visible=True) | |
return gr.update(value="▶️ Playing your shuffled playlist!", visible=True) | |
with gr.Blocks() as demo: | |
gr.Markdown("## 🎵 RNG Spotify Playlist Shuffler") | |
gr.Markdown("Login, pick a playlist, then shuffle & play—all in one flow.") | |
# 1. Launch the login page | |
login_btn = gr.Button("🔐 Step 1: Login to Spotify") | |
login_btn.click( | |
lambda: get_auth_url(), None, None, | |
_js="(url) => window.open(url, '_blank')" | |
) | |
# 2. Hidden “code” container (we’ll fill it automatically via JS) | |
code_box = gr.Textbox(visible=False, elem_id="auth_code") | |
# 3. When we have a code, finish the OAuth step… | |
status = gr.Markdown(visible=False) | |
demo.load( # run on every page‐load | |
fn=check_login, | |
inputs=[code_box], | |
outputs=[status, gr.State()], | |
_js=""" | |
// on-load JS: grab ?code= from URL and stuff it into the hidden box | |
const p = new URLSearchParams(window.location.search); | |
const c = p.get("code"); | |
if(c) { | |
document | |
.getElementById("component-auth_code") | |
.querySelector("textarea").value = c; | |
} | |
""" | |
) | |
# 4. Playlist dropdown + info | |
dropdown = gr.Dropdown(choices=[], label="Step 2: Select a Playlist", visible=False) | |
info_html = gr.HTML(visible=False) | |
dropdown.change(load_playlist_info, [dropdown], [info_html, gr.update(dropdown, visible=True)]) | |
# 5. Shuffle & play | |
result = gr.HTML(visible=False) | |
shuffle_btn = gr.Button("🔀 Step 3: Shuffle & Play", visible=False) | |
shuffle_btn.click(shuffle_and_play, [dropdown], [result]) | |
if __name__ == "__main__": | |
demo.launch() | |