jisaacso219 commited on
Commit
de17c6c
Β·
verified Β·
1 Parent(s): 7507bae

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +43 -41
app.py CHANGED
@@ -6,17 +6,13 @@ from spotipy.oauth2 import SpotifyOAuth
6
  import random
7
 
8
  # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
9
- # 1) Redirect URI (must exactly match your Spotify Dashboard)
10
  REDIRECT_URI = "https://jisaacso219-rng-shuffle.hf.space/"
11
-
12
- # 2) Include `streaming` in your scopes for Web Playback SDK
13
  SCOPE = (
14
  "streaming "
15
  "user-read-playback-state "
16
  "user-modify-playback-state "
17
  "playlist-read-private"
18
  )
19
-
20
  CLIENT_ID = os.environ["SPOTIFY_CLIENT_ID"]
21
  CLIENT_SECRET = os.environ["SPOTIFY_CLIENT_SECRET"]
22
 
@@ -39,28 +35,28 @@ def get_auth_url():
39
  def check_login(code: str):
40
  print("[SERVER] check_login code:", code)
41
  global sp, user_playlists
42
-
43
  if not code:
44
- # still waiting for Spotify redirect
45
  return (
46
- gr.update(visible=False), # status
47
- gr.update(visible=False), # dropdown
48
- gr.update(visible=False), # html_token
49
  )
50
-
51
- # Exchange code for token
52
- tokinfo = sp_oauth.get_access_token(code, as_dict=True)
53
  access_token = tokinfo["access_token"]
54
  print("[SERVER] Received token:", access_token[:8], "…")
55
-
56
  sp = spotipy.Spotify(auth=access_token)
 
57
  items = sp.current_user_playlists(limit=50)["items"]
58
  user_playlists = {p["name"]: p["id"] for p in items}
59
  print("[SERVER] Playlists:", list(user_playlists.keys()))
60
 
61
- # Inject token + SDK loader + init + debug listeners
62
  sdk_js = f"""
63
  <script>
 
 
 
 
 
64
  console.log("[SDK] Setting ACCESS_TOKEN");
65
  window.ACCESS_TOKEN = "{access_token}";
66
  </script>
@@ -73,21 +69,18 @@ def check_login(code: str):
73
  getOAuthToken: cb => cb(window.ACCESS_TOKEN),
74
  volume: 0.5
75
  }});
76
-
77
- // log errors
78
  ['initialization_error','authentication_error','account_error','playback_error']
79
  .forEach(evt => player.addListener(evt, e => console.error('[SDK ' + evt + ']', e)));
80
-
81
  player.addListener('ready', ({{ device_id }}) => {{
82
  console.log('[SDK] Player ready, device_id:', device_id);
83
  window._webDeviceId = device_id;
84
  }});
85
  player.addListener('player_state_changed', state => console.log('[SDK] state_changed', state));
86
-
87
- player.connect().then(success => console.log('[SDK] connect()', success));
88
  }};
89
  </script>
90
  """
 
91
  return (
92
  gr.update(visible=True, value="βœ… Logged in! Choose a playlist below."),
93
  gr.update(visible=True, choices=list(user_playlists.keys())),
@@ -114,7 +107,6 @@ def shuffle_and_play(pl_name: str):
114
  print("[SERVER] No playlist selected")
115
  return gr.update(value="⚠️ No playlist selected.", visible=True)
116
 
117
- # Gather & shuffle URIs
118
  tracks, results = [], sp.playlist_tracks(pid)
119
  tracks.extend(results["items"])
120
  while results["next"]:
@@ -124,9 +116,8 @@ def shuffle_and_play(pl_name: str):
124
  random.shuffle(uris)
125
  print(f"[SERVER] Shuffled {len(uris)} tracks")
126
 
127
- # JS snippet with on‐UI debugging
128
  uris_json = json.dumps(uris)
129
- play_js = f"""
130
  <div id="player_debug" style="color:white;font-family:monospace;"></div>
131
  <script>
132
  console.log("[JS] Starting playback, device_id:", window._webDeviceId);
@@ -160,16 +151,26 @@ def shuffle_and_play(pl_name: str):
160
 
161
  # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
162
  with gr.Blocks() as demo:
163
- # --- Force users to pop out of the iframe ---
164
- gr.Markdown("[πŸ”— Open this app in a standalone tab](https://jisaacso219-rng-shuffle.hf.space/)")
165
- gr.Button("πŸ”— Open in New Tab", link="https://jisaacso219-rng-shuffle.hf.space/")
166
-
167
- gr.Markdown("""
168
- ⚠️ After opening in a new tab, click **Step 1: Login to Spotify**,
169
- then check your browser console for SDK logs.
 
170
  """)
171
 
172
- # Step 1: OAuth
 
 
 
 
 
 
 
 
 
173
  login_btn = gr.Button(
174
  "πŸ” Step 1: Login to Spotify",
175
  link=get_auth_url()
@@ -178,24 +179,24 @@ with gr.Blocks() as demo:
178
  code_box = gr.Textbox(visible=False, elem_id="auth_code")
179
  status = gr.Markdown(visible=False)
180
  dropdown = gr.Dropdown(choices=[], label="Step 2: Select a Playlist", visible=False)
181
- html_token = gr.HTML(visible=False) # Web Playback SDK injector
182
 
183
- # Step 2 & 3: Playlist info + Shuffle & Play
184
- info_html = gr.HTML(visible=False)
185
- shuffle_btn= gr.Button("πŸ”€ Step 3: Shuffle & Play", visible=False)
186
- result = gr.HTML(visible=False)
187
 
188
- # On each load: grab `?code=` and call check_login
189
  demo.load(
190
  fn=check_login,
191
  inputs=[code_box],
192
  outputs=[status, dropdown, html_token],
193
  js="""
194
- () => {
195
- const c = new URLSearchParams(window.location.search).get('code') || "";
196
- console.log("[JS] demo.load code:", c);
197
- return c;
198
- }
199
  """
200
  )
201
 
@@ -204,3 +205,4 @@ with gr.Blocks() as demo:
204
 
205
  if __name__ == "__main__":
206
  demo.launch()
 
 
6
  import random
7
 
8
  # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
 
9
  REDIRECT_URI = "https://jisaacso219-rng-shuffle.hf.space/"
 
 
10
  SCOPE = (
11
  "streaming "
12
  "user-read-playback-state "
13
  "user-modify-playback-state "
14
  "playlist-read-private"
15
  )
 
16
  CLIENT_ID = os.environ["SPOTIFY_CLIENT_ID"]
17
  CLIENT_SECRET = os.environ["SPOTIFY_CLIENT_SECRET"]
18
 
 
35
  def check_login(code: str):
36
  print("[SERVER] check_login code:", code)
37
  global sp, user_playlists
 
38
  if not code:
 
39
  return (
40
+ gr.update(visible=False),
41
+ gr.update(visible=False),
42
+ gr.update(visible=False),
43
  )
44
+ tokinfo = sp_oauth.get_access_token(code, as_dict=True)
 
 
45
  access_token = tokinfo["access_token"]
46
  print("[SERVER] Received token:", access_token[:8], "…")
 
47
  sp = spotipy.Spotify(auth=access_token)
48
+
49
  items = sp.current_user_playlists(limit=50)["items"]
50
  user_playlists = {p["name"]: p["id"] for p in items}
51
  print("[SERVER] Playlists:", list(user_playlists.keys()))
52
 
 
53
  sdk_js = f"""
54
  <script>
55
+ // Break out of any iframe after login
56
+ if (window.self !== window.top) {{
57
+ console.log("⚠️ Breaking out of iframe post-login");
58
+ window.top.location.href = window.location.href;
59
+ }}
60
  console.log("[SDK] Setting ACCESS_TOKEN");
61
  window.ACCESS_TOKEN = "{access_token}";
62
  </script>
 
69
  getOAuthToken: cb => cb(window.ACCESS_TOKEN),
70
  volume: 0.5
71
  }});
 
 
72
  ['initialization_error','authentication_error','account_error','playback_error']
73
  .forEach(evt => player.addListener(evt, e => console.error('[SDK ' + evt + ']', e)));
 
74
  player.addListener('ready', ({{ device_id }}) => {{
75
  console.log('[SDK] Player ready, device_id:', device_id);
76
  window._webDeviceId = device_id;
77
  }});
78
  player.addListener('player_state_changed', state => console.log('[SDK] state_changed', state));
79
+ player.connect().then(s => console.log('[SDK] connect()', s));
 
80
  }};
81
  </script>
82
  """
83
+
84
  return (
85
  gr.update(visible=True, value="βœ… Logged in! Choose a playlist below."),
86
  gr.update(visible=True, choices=list(user_playlists.keys())),
 
107
  print("[SERVER] No playlist selected")
108
  return gr.update(value="⚠️ No playlist selected.", visible=True)
109
 
 
110
  tracks, results = [], sp.playlist_tracks(pid)
111
  tracks.extend(results["items"])
112
  while results["next"]:
 
116
  random.shuffle(uris)
117
  print(f"[SERVER] Shuffled {len(uris)} tracks")
118
 
 
119
  uris_json = json.dumps(uris)
120
+ play_js = f"""
121
  <div id="player_debug" style="color:white;font-family:monospace;"></div>
122
  <script>
123
  console.log("[JS] Starting playback, device_id:", window._webDeviceId);
 
151
 
152
  # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
153
  with gr.Blocks() as demo:
154
+ # 1) Auto-breakout for any iframe
155
+ gr.HTML("""
156
+ <script>
157
+ if (window.self !== window.top) {
158
+ console.log("⚠️ Auto-busting out of iframe");
159
+ window.top.location.href = window.location.href;
160
+ }
161
+ </script>
162
  """)
163
 
164
+ # 2) Fallback link with target="_blank"
165
+ gr.HTML(
166
+ '<a href="https://jisaacso219-rng-shuffle.hf.space/" target="_blank" '
167
+ 'style="font-size:16px;">πŸ”— Open in a standalone tab</a>'
168
+ )
169
+
170
+ # 3) Instructions
171
+ gr.Markdown("After opening in its own tab, click **Step 1: Login to Spotify**…")
172
+
173
+ # 4) OAuth
174
  login_btn = gr.Button(
175
  "πŸ” Step 1: Login to Spotify",
176
  link=get_auth_url()
 
179
  code_box = gr.Textbox(visible=False, elem_id="auth_code")
180
  status = gr.Markdown(visible=False)
181
  dropdown = gr.Dropdown(choices=[], label="Step 2: Select a Playlist", visible=False)
182
+ html_token = gr.HTML(visible=False)
183
 
184
+ # 5) Playlist info & Shuffle
185
+ info_html = gr.HTML(visible=False)
186
+ shuffle_btn = gr.Button("πŸ”€ Step 3: Shuffle & Play", visible=False)
187
+ result = gr.HTML(visible=False)
188
 
189
+ # 6) demo.load for OAuth callback
190
  demo.load(
191
  fn=check_login,
192
  inputs=[code_box],
193
  outputs=[status, dropdown, html_token],
194
  js="""
195
+ () => {
196
+ const c = new URLSearchParams(window.location.search).get('code') || "";
197
+ console.log("[JS] demo.load code:", c);
198
+ return c;
199
+ }
200
  """
201
  )
202
 
 
205
 
206
  if __name__ == "__main__":
207
  demo.launch()
208
+