RNG_Shuffle / app.py
jisaacso219's picture
Update app.py
a7abb2d verified
raw
history blame
5.09 kB
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. Client creds in Secrets:
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():
url = sp_oauth.get_authorize_url()
print(f"[DEBUG] Generated auth URL: {url}")
return url
def check_login(code: str):
print(f"[DEBUG] check_login called with code: {code}")
global sp, user_playlists
# Hide controls if no code yet
if not code:
return gr.update(visible=False), gr.update(visible=False, choices=[])
# Exchange code for token
token = sp_oauth.get_access_token(code, as_dict=False)
sp = spotipy.Spotify(auth=token)
pls = sp.current_user_playlists(limit=50)["items"]
user_playlists = {p["name"]: p["id"] for p in pls}
print(f"[DEBUG] Retrieved playlists: {list(user_playlists.keys())}")
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: str):
print(f"[DEBUG] load_playlist_info called for: {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 html, gr.update(visible=True)
def shuffle_and_play(pl_name: str):
print(f"[DEBUG] shuffle_and_play called for: {pl_name}")
pid = user_playlists[pl_name]
tracks, results = [], sp.playlist_tracks(pid)
tracks.extend(results["items"])
while results["next"]:
results = sp.next(results)
tracks.extend(results["items"])
uris = [t["track"]["uri"] for t in tracks if t["track"]]
devices = sp.devices()["devices"]
if not devices:
print("[DEBUG] No active devices found")
return gr.update(value="⚠️ No active device. Open Spotify and try again.", visible=True)
sp.start_playback(device_id=devices[0]["id"], uris=uris)
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 html
return "▢️ Playing your shuffled playlist!"
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️⃣ Login button: redirect the TOP window out of the iframe
login_btn = gr.Button("πŸ” Step 1: Login to Spotify")
login_btn.click(
fn=None, inputs=None, outputs=None,
js=f"""
() => {{
console.log("πŸ‘‰ [JS] Login button clicked, redirecting...");
window.top.location.href = '{get_auth_url()}';
}}
"""
)
# Hidden box to capture the `code` after redirect
code_box = gr.Textbox(visible=False, elem_id="auth_code")
# Status + playlist selector (hidden until login finishes)
status = gr.Markdown(visible=False)
dropdown = gr.Dropdown(choices=[], label="Step 2: Select a Playlist", visible=False)
# Playlist info + shuffle controls
info_html = gr.HTML(visible=False)
shuffle_btn = gr.Button("πŸ”€ Step 3: Shuffle & Play", visible=False)
result = gr.HTML(visible=False)
# πŸ”„ On every page-load: pull `?code=` from URL into our hidden box and call check_login()
demo.load(
fn=check_login,
inputs=[code_box],
outputs=[status, dropdown],
js="""
() => {
const url = window.location.href;
const code = new URLSearchParams(window.location.search).get('code') || "";
console.log("🌐 [JS] Current URL:", url);
console.log("πŸ”‘ [JS] Parsed code:", code);
return code;
}
"""
)
dropdown.change(
fn=load_playlist_info,
inputs=[dropdown],
outputs=[info_html, shuffle_btn]
)
shuffle_btn.click(
fn=shuffle_and_play,
inputs=[dropdown],
outputs=[result]
)
if __name__ == "__main__":
demo.launch()