jisaacso219 commited on
Commit
f8df622
·
verified ·
1 Parent(s): 34a8257

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +61 -45
app.py CHANGED
@@ -4,10 +4,11 @@ import spotipy
4
  from spotipy.oauth2 import SpotifyOAuth
5
  import random
6
 
7
- # 1. Hard‐code your redirect URI here:
 
8
  REDIRECT_URI = "https://jisaacso219-rng-shuffle.hf.space/"
9
 
10
- # 2. Keep your client creds in Secrets, as before:
11
  CLIENT_ID = os.environ["SPOTIFY_CLIENT_ID"]
12
  CLIENT_SECRET = os.environ["SPOTIFY_CLIENT_SECRET"]
13
  SCOPE = (
@@ -30,88 +31,99 @@ user_playlists = {}
30
  def get_auth_url():
31
  return sp_oauth.get_authorize_url()
32
 
 
33
  def check_login(code: str):
 
34
  global sp, user_playlists
 
 
 
 
 
35
  token = sp_oauth.get_access_token(code, as_dict=False)
36
  sp = spotipy.Spotify(auth=token)
37
- # pull their first 50 playlists
38
  pls = sp.current_user_playlists(limit=50)["items"]
39
  user_playlists = {p["name"]: p["id"] for p in pls}
40
  return (
41
  gr.update(visible=True, value="✅ Logged in! Choose a playlist below."),
42
- gr.update(visible=True, choices=list(user_playlists.keys()))
43
  )
44
 
45
- def load_playlist_info(pl_name):
 
46
  pid = user_playlists[pl_name]
47
  data = sp.playlist(pid)
48
- img = data["images"][0]["url"] if data["images"] else ""
49
  owner = data["owner"]["display_name"]
50
- desc = data.get("description", "")
51
  html = f"""
52
  <img src="{img}" width="300px" style="border-radius:10px;"/><br/>
53
  <strong>{pl_name}</strong> by {owner}<br/>
54
  {desc}
55
  """
56
- return gr.update(visible=True, value=html), gr.update(visible=True)
57
 
58
- def shuffle_and_play(pl_name):
 
59
  pid = user_playlists[pl_name]
60
- # grab all tracks
61
  tracks, results = [], sp.playlist_tracks(pid)
62
- tracks += results["items"]
63
  while results["next"]:
64
  results = sp.next(results)
65
- tracks += results["items"]
66
- uris = [t["track"]["uri"] for t in tracks if t["track"]]
67
- random.shuffle(uris)
68
 
69
- # send to their first active device
70
- devs = sp.devices()["devices"]
71
- if not devs:
72
- return gr.update(value="⚠️ No active Spotify device found. Start Spotify on one of your devices.", visible=True)
73
- sp.start_playback(device_id=devs[0]["id"], uris=uris)
74
 
75
- # show the first shuffled track’s info:
76
  now = sp.current_playback()
77
  if now and now.get("item"):
78
- it = now["item"]
79
- art = it["album"]["images"][0]["url"]
80
- title = it["name"]
81
  artists = ", ".join(a["name"] for a in it["artists"])
82
  html = f"""
83
  <img src="{art}" width="200px" style="border-radius:8px;"/><br/>
84
  ▶️ <strong>{title}</strong><br/>
85
  by {artists}
86
  """
87
- return gr.update(value=html, visible=True)
88
- return gr.update(value="▶️ Playing your shuffled playlist!", visible=True)
 
89
 
90
  with gr.Blocks() as demo:
91
  gr.Markdown("## 🎵 RNG Spotify Playlist Shuffler")
92
  gr.Markdown("Login, pick a playlist, then shuffle & play—all in one flow.")
93
 
94
- # 1. Launch the login page
95
- login_btn = gr.Button("🔐 Step 1: Login to Spotify")
96
- login_btn.click(
97
- lambda: get_auth_url(), None, None,
98
- _js="(url) => window.open(url, '_blank')"
99
  )
100
 
101
- # 2. Hidden “code” container (we’ll fill it automatically via JS)
102
  code_box = gr.Textbox(visible=False, elem_id="auth_code")
103
 
104
- # 3. When we have a code, finish the OAuth step…
105
- status = gr.Markdown(visible=False)
106
- demo.load( # run on every page‐load
 
 
 
 
 
 
 
 
107
  fn=check_login,
108
  inputs=[code_box],
109
- outputs=[status, gr.State()],
110
  _js="""
111
- // on-load JS: grab ?code= from URL and stuff it into the hidden box
112
  const p = new URLSearchParams(window.location.search);
113
  const c = p.get("code");
114
- if(c) {
115
  document
116
  .getElementById("component-auth_code")
117
  .querySelector("textarea").value = c;
@@ -119,15 +131,19 @@ with gr.Blocks() as demo:
119
  """
120
  )
121
 
122
- # 4. Playlist dropdown + info
123
- dropdown = gr.Dropdown(choices=[], label="Step 2: Select a Playlist", visible=False)
124
- info_html = gr.HTML(visible=False)
125
- dropdown.change(load_playlist_info, [dropdown], [info_html, gr.update(dropdown, visible=True)])
 
 
126
 
127
- # 5. Shuffle & play
128
- result = gr.HTML(visible=False)
129
- shuffle_btn = gr.Button("🔀 Step 3: Shuffle & Play", visible=False)
130
- shuffle_btn.click(shuffle_and_play, [dropdown], [result])
 
 
131
 
132
  if __name__ == "__main__":
133
  demo.launch()
 
4
  from spotipy.oauth2 import SpotifyOAuth
5
  import random
6
 
7
+ # ——————————————————————————————
8
+ # 1. Hard-code your Redirect URI here:
9
  REDIRECT_URI = "https://jisaacso219-rng-shuffle.hf.space/"
10
 
11
+ # 2. Keep only your client creds in Secrets:
12
  CLIENT_ID = os.environ["SPOTIFY_CLIENT_ID"]
13
  CLIENT_SECRET = os.environ["SPOTIFY_CLIENT_SECRET"]
14
  SCOPE = (
 
31
  def get_auth_url():
32
  return sp_oauth.get_authorize_url()
33
 
34
+
35
  def check_login(code: str):
36
+ """Called on every page-load to see if Spotify has redirected us back with ?code=…"""
37
  global sp, user_playlists
38
+ if not code:
39
+ return (
40
+ gr.update(visible=False), # hide status until code arrives
41
+ gr.update(visible=False, choices=[]),
42
+ )
43
  token = sp_oauth.get_access_token(code, as_dict=False)
44
  sp = spotipy.Spotify(auth=token)
 
45
  pls = sp.current_user_playlists(limit=50)["items"]
46
  user_playlists = {p["name"]: p["id"] for p in pls}
47
  return (
48
  gr.update(visible=True, value="✅ Logged in! Choose a playlist below."),
49
+ gr.update(visible=True, choices=list(user_playlists.keys())),
50
  )
51
 
52
+
53
+ def load_playlist_info(pl_name: str):
54
  pid = user_playlists[pl_name]
55
  data = sp.playlist(pid)
56
+ img = data["images"][0]["url"] if data["images"] else ""
57
  owner = data["owner"]["display_name"]
58
+ desc = data.get("description", "")
59
  html = f"""
60
  <img src="{img}" width="300px" style="border-radius:10px;"/><br/>
61
  <strong>{pl_name}</strong> by {owner}<br/>
62
  {desc}
63
  """
64
+ return html, gr.update(visible=True)
65
 
66
+
67
+ def shuffle_and_play(pl_name: str):
68
  pid = user_playlists[pl_name]
 
69
  tracks, results = [], sp.playlist_tracks(pid)
70
+ tracks.extend(results["items"])
71
  while results["next"]:
72
  results = sp.next(results)
73
+ tracks.extend(results["items"])
 
 
74
 
75
+ uris = [t["track"]["uri"] for t in tracks if t["track"]]
76
+ devices = sp.devices()["devices"]
77
+ if not devices:
78
+ return gr.update(value="⚠️ No active device. Open Spotify and try again.", visible=True)
 
79
 
80
+ sp.start_playback(device_id=devices[0]["id"], uris=uris)
81
  now = sp.current_playback()
82
  if now and now.get("item"):
83
+ it = now["item"]
84
+ art = it["album"]["images"][0]["url"]
85
+ title = it["name"]
86
  artists = ", ".join(a["name"] for a in it["artists"])
87
  html = f"""
88
  <img src="{art}" width="200px" style="border-radius:8px;"/><br/>
89
  ▶️ <strong>{title}</strong><br/>
90
  by {artists}
91
  """
92
+ return html
93
+ return "▶️ Playing your shuffled playlist!"
94
+
95
 
96
  with gr.Blocks() as demo:
97
  gr.Markdown("## 🎵 RNG Spotify Playlist Shuffler")
98
  gr.Markdown("Login, pick a playlist, then shuffle & play—all in one flow.")
99
 
100
+ # Step 1: Login button using `link=` (Gradio ≥5.14.0)
101
+ login_btn = gr.Button(
102
+ "🔐 Step 1: Login to Spotify",
103
+ link=get_auth_url()
 
104
  )
105
 
106
+ # Hidden container for the ?code=… Spotify will append on redirect
107
  code_box = gr.Textbox(visible=False, elem_id="auth_code")
108
 
109
+ # Status message + playlist dropdown (populated after login)
110
+ status = gr.Markdown(visible=False)
111
+ dropdown = gr.Dropdown(choices=[], label="Step 2: Select a Playlist", visible=False)
112
+
113
+ # Playlist info + shuffle controls
114
+ info_html = gr.HTML(visible=False)
115
+ shuffle_btn = gr.Button("🔀 Step 3: Shuffle & Play", visible=False)
116
+ result = gr.HTML(visible=False)
117
+
118
+ # Run on every page-load: grab ?code=… via JS and call check_login
119
+ demo.load(
120
  fn=check_login,
121
  inputs=[code_box],
122
+ outputs=[status, dropdown],
123
  _js="""
 
124
  const p = new URLSearchParams(window.location.search);
125
  const c = p.get("code");
126
+ if (c) {
127
  document
128
  .getElementById("component-auth_code")
129
  .querySelector("textarea").value = c;
 
131
  """
132
  )
133
 
134
+ # When user picks a playlist, show its artwork/info and reveal the shuffle button
135
+ dropdown.change(
136
+ fn=load_playlist_info,
137
+ inputs=[dropdown],
138
+ outputs=[info_html, shuffle_btn]
139
+ )
140
 
141
+ # Shuffle & start playback, then show track info
142
+ shuffle_btn.click(
143
+ fn=shuffle_and_play,
144
+ inputs=[dropdown],
145
+ outputs=[result]
146
+ )
147
 
148
  if __name__ == "__main__":
149
  demo.launch()