File size: 4,449 Bytes
52c1c26
 
 
dbdd344
9faaa03
 
dbdd344
52a6c11
9faaa03
6645382
dbdd344
3582f7d
e4f4d5f
dbdd344
 
 
 
52a6c11
 
dbdd344
7507bae
52a6c11
9faaa03
 
b414958
a8c78b0
b414958
3582f7d
2082b5c
3582f7d
 
 
 
 
 
52c1c26
6645382
dc5eb33
 
52c1c26
e4f4d5f
 
52c1c26
dc5eb33
6645382
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52c1c26
52a6c11
3582f7d
e4f4d5f
3582f7d
671016b
52a6c11
52c1c26
3582f7d
dc5eb33
3582f7d
 
8c6ab50
 
6645382
52c1c26
dc5eb33
 
 
52c1c26
 
8c6ab50
 
 
52c1c26
 
f8df622
6645382
52c1c26
 
dc5eb33
6645382
 
 
 
 
 
 
 
 
 
 
52c1c26
dc5eb33
a8c78b0
3582f7d
e5d28ac
 
 
3582f7d
 
 
 
2082b5c
3582f7d
6645382
 
52c1c26
6645382
3582f7d
6645382
52c1c26
3582f7d
 
 
 
e4f4d5f
 
dc5eb33
 
52a6c11
9faaa03
e4f4d5f
6645382
3582f7d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import os
import json
import random
import gradio as gr
import spotipy
from spotipy.oauth2 import SpotifyOAuth

CLIENT_ID     = os.environ["SPOTIFY_CLIENT_ID"]
CLIENT_SECRET = os.environ["SPOTIFY_CLIENT_SECRET"]
REDIRECT_URI  = "https://jisaacso219-rng-shuffle.hf.space/"

SCOPE = "streaming 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 complete_login(full_url):
    global sp, user_playlists

    # Extract code from full URL
    try:
        code = full_url.split("?code=")[1].split("&")[0]
    except IndexError:
        return gr.update(value="❌ No code found in URL. Please try logging in again."), gr.update(visible=False), gr.update(visible=False)

    tokinfo = sp_oauth.get_access_token(code, as_dict=True)
    access_token = tokinfo["access_token"]
    sp = spotipy.Spotify(auth=access_token)

    items = sp.current_user_playlists(limit=50)["items"]
    user_playlists = {p["name"]: p["id"] for p in items}

    sdk_js = f"""
    <script>
      window.ACCESS_TOKEN = "{access_token}";
    </script>
    <script src="https://sdk.scdn.co/spotify-player.js"></script>
    <script>
      window.onSpotifyWebPlaybackSDKReady = () => {{
        const player = new Spotify.Player({{
          name: 'RNG Web Player',
          getOAuthToken: cb => cb(window.ACCESS_TOKEN),
          volume: 0.5
        }});
        player.addListener('ready', ({ device_id }) => {{
          window._webDeviceId = device_id;
          console.log('device_id:', device_id);
        }});
        player.connect();
      }};
    </script>
    """

    return (
        gr.update(value="βœ… Logged in! Select a playlist."),
        gr.update(visible=True, choices=list(user_playlists.keys())),
        gr.update(visible=True, value=sdk_js)
    )

def load_playlist_info(playlist_name: str):
    pid = user_playlists[playlist_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="300"/><br/>
      <strong>{playlist_name}</strong> by {owner}<br/>{desc}
    """
    return html, gr.update(visible=True)

def shuffle_and_play(playlist_name: str):
    pid = user_playlists[playlist_name]
    tracks, res = [], sp.playlist_tracks(pid)
    tracks.extend(res["items"])
    while res["next"]:
        res = sp.next(res)
        tracks.extend(res["items"])
    uris = [t["track"]["uri"] for t in tracks if t["track"]]
    random.shuffle(uris)

    uris_json = json.dumps(uris)
    play_js = f"""
    <script>
      fetch('https://api.spotify.com/v1/me/player/play?device_id=' + window._webDeviceId, {{
        method: 'PUT',
        headers: {{
          'Authorization': 'Bearer ' + window.ACCESS_TOKEN,
          'Content-Type': 'application/json'
        }},
        body: JSON.stringify({{ uris: {uris_json} }})
      }});
    </script>
    """
    return gr.update(value="▢️ Now playing in-browser!" + play_js, visible=True)

with gr.Blocks() as demo:
    gr.Markdown("### RNG Spotify Playlist Shuffler 🎧")
    
    login_url = get_auth_url()
    login_btn = gr.HTML(f'<a href="{login_url}" target="_blank"><button style="width:100%; height:40px; font-size:16px;">πŸ” Login to Spotify</button></a>')

    gr.Markdown("After logging in to Spotify, copy the **full redirected URL** and paste it below to complete login.")
    redirect_url_box = gr.Textbox(label="Paste redirected URL here")
    complete_login_btn = gr.Button("βœ… Complete Login")

    status = gr.Markdown()
    playlist_dd = gr.Dropdown([], label="Select a Playlist", visible=False)
    sdk_html = gr.HTML(visible=False)

    info_html = gr.HTML(visible=False)
    shuffle_btn = gr.Button("πŸ”€ Shuffle & Play", visible=False)
    result = gr.HTML(visible=False)

    complete_login_btn.click(
        complete_login,
        inputs=[redirect_url_box],
        outputs=[status, playlist_dd, sdk_html]
    )

    playlist_dd.change(load_playlist_info, [playlist_dd], [info_html, shuffle_btn])
    shuffle_btn.click(shuffle_and_play, [playlist_dd], [result])

if __name__ == "__main__":
    demo.launch(server_name="0.0.0.0", ssr_mode=False)