jisaacso219 commited on
Commit
a8c78b0
Β·
verified Β·
1 Parent(s): e764825

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +54 -144
app.py CHANGED
@@ -1,12 +1,8 @@
1
- import os
2
- import json
3
- import random
4
  import gradio as gr
5
  import spotipy
6
  from spotipy.oauth2 import SpotifyOAuth
7
 
8
- # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
9
- # Configuration
10
  REDIRECT_URI = "https://jisaacso219-rng-shuffle.hf.space/"
11
  SCOPE = (
12
  "streaming "
@@ -29,182 +25,96 @@ sp = None
29
  user_playlists = {}
30
 
31
  def get_auth_url():
32
- url = sp_oauth.get_authorize_url()
33
- print("[SERVER] Auth URL:", url)
34
- return url
35
 
36
- def check_login(code: str):
37
- print("[SERVER] check_login code:", code)
38
  global sp, user_playlists
39
-
40
  if not code:
41
- # still waiting for OAuth redirect
42
- return (
43
- gr.update(visible=False), # status
44
- gr.update(visible=False), # dropdown
45
- gr.update(visible=False), # html_token
46
- )
47
-
48
- # Exchange code for token
49
  tokinfo = sp_oauth.get_access_token(code, as_dict=True)
50
  access_token = tokinfo["access_token"]
51
- print("[SERVER] Received token:", access_token[:8], "…")
52
  sp = spotipy.Spotify(auth=access_token)
53
-
54
- # Fetch playlists
55
  items = sp.current_user_playlists(limit=50)["items"]
56
  user_playlists = {p["name"]: p["id"] for p in items}
57
- print("[SERVER] Playlists:", list(user_playlists.keys()))
58
-
59
- # Inject SDK + debug scripts + iframe escape
60
  sdk_js = f"""
61
- <script>
62
- if (window.self !== window.top) {{
63
- console.log("⚠️ Busting out of iframe…");
64
- window.top.location.href = window.location.href;
65
- }}
66
- console.log("[SDK] Setting ACCESS_TOKEN");
67
- window.ACCESS_TOKEN = "{access_token}";
68
- </script>
69
  <script src="https://sdk.scdn.co/spotify-player.js"></script>
70
  <script>
71
  window.onSpotifyWebPlaybackSDKReady = () => {{
72
- console.log("[SDK] SDK Ready");
73
  const player = new Spotify.Player({{
74
  name: 'RNG Web Player',
75
  getOAuthToken: cb => cb(window.ACCESS_TOKEN),
76
  volume: 0.5
77
  }});
78
- ['initialization_error','authentication_error','account_error','playback_error']
79
- .forEach(evt => player.addListener(evt, e => console.error('[SDK ' + evt + ']', e)));
80
- player.addListener('ready', ({{ device_id }}) => {{
81
- console.log('[SDK] Player ready, device_id:', device_id);
82
- window._webDeviceId = device_id;
83
- }});
84
- player.addListener('player_state_changed', state => console.log('[SDK] state_changed', state));
85
- player.connect().then(success => console.log('[SDK] connect()', success));
86
  }};
87
  </script>
88
  """
89
-
90
  return (
91
- gr.update(visible=True, value="βœ… Logged in! Choose a playlist below."),
92
  gr.update(visible=True, choices=list(user_playlists.keys())),
93
  gr.update(visible=True, value=sdk_js),
94
  )
95
 
96
- def load_playlist_info(pl_name: str):
97
- print("[SERVER] load_playlist_info:", pl_name)
98
- pid = user_playlists[pl_name]
99
  data = sp.playlist(pid)
100
- img = data["images"][0]["url"] if data["images"] else ""
101
  owner = data["owner"]["display_name"]
102
- desc = data.get("description", "")
103
- html = f"""
104
- <img src="{img}" width="300" style="border-radius:8px;"/><br/>
105
- <strong>{pl_name}</strong> by {owner}<br/>{desc}
106
- """
107
- return html, gr.update(visible=True)
108
-
109
- def shuffle_and_play(pl_name: str):
110
- print("[SERVER] shuffle_and_play:", pl_name)
111
- pid = user_playlists.get(pl_name)
112
- if not pid:
113
- print("[SERVER] No playlist selected")
114
- return gr.update(value="⚠️ No playlist selected.", visible=True)
115
 
116
- # Gather & shuffle URIs
117
- tracks, results = [], sp.playlist_tracks(pid)
118
- tracks.extend(results["items"])
119
- while results["next"]:
120
- results = sp.next(results)
121
- tracks.extend(results["items"])
 
122
  uris = [t["track"]["uri"] for t in tracks if t["track"]]
123
  random.shuffle(uris)
124
- print(f"[SERVER] Shuffled {len(uris)} tracks")
125
-
126
  uris_json = json.dumps(uris)
127
- play_js = f"""
128
- <div id="player_debug" style="color:white;font-family:monospace;"></div>
129
- <script>
130
- console.log("[JS] Starting playback, device_id:", window._webDeviceId);
131
- console.log("[JS] URIs length:", {len(uris)});
132
- (async () => {{
133
- try {{
134
- const resp = await fetch(
135
- 'https://api.spotify.com/v1/me/player/play?device_id=' + window._webDeviceId,
136
- {{
137
- method: 'PUT',
138
- headers: {{
139
- 'Authorization': 'Bearer ' + window.ACCESS_TOKEN,
140
- 'Content-Type': 'application/json'
141
- }},
142
- body: JSON.stringify({{uris:{uris_json}}})
143
- }}
144
- );
145
- const text = await resp.text();
146
- console.log("[JS] fetch status:", resp.status, text);
147
- document.getElementById("player_debug").innerText =
148
- `[JS] fetch status: ${{resp.status}} – ${{text}}`;
149
- }} catch(e) {{
150
- console.error("[JS] Playback error:", e);
151
- document.getElementById("player_debug").innerText =
152
- "[JS] Playback error: " + e;
153
- }}
154
- }})();
155
- </script>
156
- """
157
- return gr.update(value="▢️ Now playing in-browser!" + play_js, visible=True)
158
-
159
- with gr.Blocks() as demo:
160
- # Auto-bust iframe on load
161
- gr.HTML("""
162
- <script>
163
- if (window.self !== window.top) {
164
- console.log("⚠️ Busting out of iframe on load");
165
- window.top.location.href = window.location.href;
166
- }
167
- </script>
168
- """)
169
- # Fallback link
170
- gr.HTML(
171
- '<a href="https://jisaacso219-rng-shuffle.hf.space/" '
172
- 'target="_blank" style="font-size:16px;">πŸ”— Open standalone</a>'
173
- )
174
- gr.Markdown("After opening standalone, click **Step 1: Login to Spotify**…")
175
-
176
- # OAuth button (same tab)
177
- login_btn = gr.Button("πŸ” Step 1: Login to Spotify")
178
- login_btn.click(
179
- fn=None, inputs=None, outputs=None,
180
- js=f"() => window.location.href = '{get_auth_url()}'"
181
  )
182
 
183
- code_box = gr.Textbox(visible=False, elem_id="auth_code")
184
- status = gr.Markdown(visible=False)
185
- dropdown = gr.Dropdown(choices=[], label="Step 2: Select a Playlist", visible=False)
186
- html_token = gr.HTML(visible=False)
187
-
188
- info_html = gr.HTML(visible=False)
189
- shuffle_btn= gr.Button("πŸ”€ Step 3: Shuffle & Play", visible=False)
190
- result = gr.HTML(visible=False)
 
 
 
 
 
191
 
192
  demo.load(
193
- fn=check_login,
194
- inputs=[code_box],
195
- outputs=[status, dropdown, html_token],
196
- js="""
197
- () => {
198
- const c = new URLSearchParams(window.location.search).get('code') || "";
199
- console.log("[JS] demo.load code:", c);
200
- return c;
201
- }
202
- """
203
  )
204
 
205
- dropdown.change(load_playlist_info, [dropdown], [info_html, shuffle_btn])
206
- shuffle_btn.click(shuffle_and_play, [dropdown], [result])
207
 
208
  if __name__ == "__main__":
209
- demo.launch()
210
 
 
1
+ import os, json, random
 
 
2
  import gradio as gr
3
  import spotipy
4
  from spotipy.oauth2 import SpotifyOAuth
5
 
 
 
6
  REDIRECT_URI = "https://jisaacso219-rng-shuffle.hf.space/"
7
  SCOPE = (
8
  "streaming "
 
25
  user_playlists = {}
26
 
27
  def get_auth_url():
28
+ return sp_oauth.get_authorize_url()
 
 
29
 
30
+ def check_login(code):
 
31
  global sp, user_playlists
 
32
  if not code:
33
+ return gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
 
 
 
 
 
 
 
34
  tokinfo = sp_oauth.get_access_token(code, as_dict=True)
35
  access_token = tokinfo["access_token"]
 
36
  sp = spotipy.Spotify(auth=access_token)
 
 
37
  items = sp.current_user_playlists(limit=50)["items"]
38
  user_playlists = {p["name"]: p["id"] for p in items}
39
+ # inject token + SDK
 
 
40
  sdk_js = f"""
41
+ <script>window.ACCESS_TOKEN="{access_token}";</script>
 
 
 
 
 
 
 
42
  <script src="https://sdk.scdn.co/spotify-player.js"></script>
43
  <script>
44
  window.onSpotifyWebPlaybackSDKReady = () => {{
 
45
  const player = new Spotify.Player({{
46
  name: 'RNG Web Player',
47
  getOAuthToken: cb => cb(window.ACCESS_TOKEN),
48
  volume: 0.5
49
  }});
50
+ player.addListener('ready', ({{ device_id }}) => {{ window._webDeviceId = device_id; }});
51
+ player.connect();
 
 
 
 
 
 
52
  }};
53
  </script>
54
  """
 
55
  return (
56
+ gr.update(visible=True, value="βœ… Logged in! Pick a playlist."),
57
  gr.update(visible=True, choices=list(user_playlists.keys())),
58
  gr.update(visible=True, value=sdk_js),
59
  )
60
 
61
+ def load_playlist_info(name):
62
+ pid = user_playlists[name]
 
63
  data = sp.playlist(pid)
64
+ img = data["images"][0]["url"] if data["images"] else ""
65
  owner = data["owner"]["display_name"]
66
+ desc = data.get("description","")
67
+ return (
68
+ f"<img src='{img}' width='300'/><br/><strong>{name}</strong> by {owner}<br/>{desc}",
69
+ gr.update(visible=True),
70
+ )
 
 
 
 
 
 
 
 
71
 
72
+ def shuffle_and_play(name):
73
+ pid = user_playlists[name]
74
+ tracks, res = [], sp.playlist_tracks(pid)
75
+ tracks += res["items"]
76
+ while res["next"]:
77
+ res = sp.next(res)
78
+ tracks += res["items"]
79
  uris = [t["track"]["uri"] for t in tracks if t["track"]]
80
  random.shuffle(uris)
 
 
81
  uris_json = json.dumps(uris)
82
+ return gr.update(
83
+ value=(
84
+ "▢️ Now playing in-browser!"
85
+ f"<script>(async()=>{{"
86
+ f"await fetch('https://api.spotify.com/v1/me/player/play?device_id='+window._webDeviceId,{{"
87
+ f"method:'PUT',headers:{{'Authorization':'Bearer '+window.ACCESS_TOKEN}},"
88
+ f"body:JSON.stringify({{'uris':{uris_json}}})}});"
89
+ f"}})();</script>"
90
+ ),
91
+ visible=True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  )
93
 
94
+ with gr.Blocks() as demo:
95
+ gr.Markdown("[πŸ”— Open standalone](https://jisaacso219-rng-shuffle.hf.space/)")
96
+ gr.Markdown("1) Click **Login** 2) Pick a playlist 3) Shuffle & play in-browser")
97
+ login = gr.Button("πŸ” Step 1: Login", link=get_auth_url())
98
+ code_box = gr.Textbox(visible=False, elem_id="auth_code")
99
+ status, playlist_dd, sdk_html = [
100
+ gr.Markdown(visible=False),
101
+ gr.Dropdown([], label="Select Playlist", visible=False),
102
+ gr.HTML(visible=False)
103
+ ]
104
+ info_html = gr.HTML(visible=False)
105
+ shuffle_btn = gr.Button("πŸ”€ Step 3: Shuffle & Play", visible=False)
106
+ result = gr.HTML(visible=False)
107
 
108
  demo.load(
109
+ fn=check_login,
110
+ inputs=[code_box],
111
+ outputs=[status, playlist_dd, sdk_html],
112
+ js="() => new URLSearchParams(window.location.search).get('code') || ''"
 
 
 
 
 
 
113
  )
114
 
115
+ playlist_dd.change(load_playlist_info, [playlist_dd], [info_html, shuffle_btn])
116
+ shuffle_btn.click(shuffle_and_play, [playlist_dd], [result])
117
 
118
  if __name__ == "__main__":
119
+ demo.launch(ssr_mode=False)
120