Mthrfkr commited on
Commit
cbc0ab8
·
verified ·
1 Parent(s): 39c3b8a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +56 -38
app.py CHANGED
@@ -1,5 +1,6 @@
1
  import os
2
  import requests
 
3
  import gradio as gr
4
 
5
  # —————————————
@@ -8,70 +9,87 @@ import gradio as gr
8
  CLIENT_ID = os.getenv("SPOTIFY_CLIENT_IDS", "").split(',')[0]
9
  CLIENT_SECRET = os.getenv("SPOTIFY_CLIENT_SECRETS", "").split(',')[0]
10
 
 
11
  def get_token():
12
  resp = requests.post(
13
  "https://accounts.spotify.com/api/token",
14
- data={"grant_type":"client_credentials"},
15
- auth=(CLIENT_ID, CLIENT_SECRET),
16
  )
17
  resp.raise_for_status()
18
  return resp.json()["access_token"]
19
 
 
20
  def extract_pid(url):
21
  return url.strip().rstrip('/').split('/')[-1].split('?')[0]
22
 
23
- # —————————————
24
- # Función full-fetch
25
- # —————————————
26
- def fetch_full_playlist(url):
 
 
 
 
 
 
 
 
 
 
 
 
27
  if not CLIENT_ID or not CLIENT_SECRET:
28
- return "❌ Faltan credenciales SPOTIFY_CLIENT_IDS o SPOTIFY_CLIENT_SECRETS"
 
29
  token = get_token()
30
  pid = extract_pid(url)
31
- if len(pid) != 22:
32
- return f"❌ ID inválido: '{pid}'"
33
  headers = {"Authorization": f"Bearer {token}"}
34
 
35
- # 1) Metadata básica
36
  meta = requests.get(f"https://api.spotify.com/v1/playlists/{pid}", headers=headers)
37
  if meta.status_code != 200:
38
- return f" Error {meta.status_code}: no es pública o no existe"
39
- info = meta.json()
40
- name = info.get("name", "–")
41
- total = info.get("tracks", {}).get("total", 0)
42
 
43
- # 2) Traer TODOS los tracks en batches de 100
44
- nombres = []
45
- limit = 100
46
  offset = 0
47
  while offset < total:
48
- ruta = f"https://api.spotify.com/v1/playlists/{pid}/tracks"
49
- params = {"limit": limit, "offset": offset}
50
- r = requests.get(ruta, headers=headers, params=params)
51
  r.raise_for_status()
52
- items = r.json().get("items", [])
53
- for it in items:
54
- track = it.get("track")
55
- if track and track.get("name"):
56
- nombres.append(track["name"])
 
 
 
 
 
 
 
 
57
  offset += limit
58
 
59
- # 3) Formatear salida
60
- # Si la lista es gigante, tal vez quieras cambiar salto de línea por comas, o paginarla.
61
- salida = [f"✅ “{name}”: {total} tracks"]
62
- salida += [f"{i+1}. {t}" for i, t in enumerate(nombres)]
63
- return "\n".join(salida)
64
 
65
- # —————————————
66
  # Interfaz Gradio
67
- # —————————————
 
 
 
68
  iface = gr.Interface(
69
- fn=fetch_full_playlist,
70
  inputs=gr.Textbox(label="URL de playlist"),
71
- outputs="text",
72
- title="🔽 Baja toda la playlist",
73
- description="Descarga el nombre y ¡TODOS! los temas de una playlist pública"
74
  )
75
 
76
- if __name__ == "__main__":
77
- iface.launch(server_name="0.0.0.0", server_port=7860)
 
1
  import os
2
  import requests
3
+ import pandas as pd
4
  import gradio as gr
5
 
6
  # —————————————
 
9
  CLIENT_ID = os.getenv("SPOTIFY_CLIENT_IDS", "").split(',')[0]
10
  CLIENT_SECRET = os.getenv("SPOTIFY_CLIENT_SECRETS", "").split(',')[0]
11
 
12
+ # Función para obtener token
13
  def get_token():
14
  resp = requests.post(
15
  "https://accounts.spotify.com/api/token",
16
+ data={"grant_type": "client_credentials"},
17
+ auth=(CLIENT_ID, CLIENT_SECRET)
18
  )
19
  resp.raise_for_status()
20
  return resp.json()["access_token"]
21
 
22
+ # Extrae el ID de playlist de la URL
23
  def extract_pid(url):
24
  return url.strip().rstrip('/').split('/')[-1].split('?')[0]
25
 
26
+ # Caché de géneros por artista
27
+ _artist_cache = {}
28
+
29
+ def get_artist_genres(aid, headers):
30
+ if aid in _artist_cache:
31
+ return _artist_cache[aid]
32
+ resp = requests.get(f"https://api.spotify.com/v1/artists/{aid}", headers=headers)
33
+ if resp.status_code == 200:
34
+ genres = resp.json().get('genres', [])
35
+ else:
36
+ genres = []
37
+ _artist_cache[aid] = genres
38
+ return genres
39
+
40
+ # Fetch y devuelve DataFrame
41
+ def fetch_playlist_table(url):
42
  if not CLIENT_ID or not CLIENT_SECRET:
43
+ return pd.DataFrame([{'Error': 'Faltan credenciales'}])
44
+
45
  token = get_token()
46
  pid = extract_pid(url)
 
 
47
  headers = {"Authorization": f"Bearer {token}"}
48
 
49
+ # Metadata de playlist
50
  meta = requests.get(f"https://api.spotify.com/v1/playlists/{pid}", headers=headers)
51
  if meta.status_code != 200:
52
+ return pd.DataFrame([{'Error': f"Playlist error {meta.status_code}: {meta.json()}"}])
53
+ total = meta.json().get('tracks', {}).get('total', 0)
 
 
54
 
55
+ # Paginación de tracks
56
+ records = []
57
+ limit = 100
58
  offset = 0
59
  while offset < total:
60
+ params = {'limit': limit, 'offset': offset}
61
+ r = requests.get(f"https://api.spotify.com/v1/playlists/{pid}/tracks", headers=headers, params=params)
 
62
  r.raise_for_status()
63
+ for item in r.json().get('items', []):
64
+ tr = item.get('track', {})
65
+ if not tr: continue
66
+ aid = tr['artists'][0]['id'] if tr.get('artists') else None
67
+ genres = get_artist_genres(aid, headers) if aid else []
68
+ records.append({
69
+ 'Artist': tr['artists'][0]['name'] if tr.get('artists') else '',
70
+ 'Title': tr.get('name', ''),
71
+ 'ISRC': tr.get('external_ids', {}).get('isrc', ''),
72
+ 'URL': tr.get('external_urls', {}).get('spotify', ''),
73
+ 'URI': tr.get('uri', ''),
74
+ 'Genres': ', '.join(genres)
75
+ })
76
  offset += limit
77
 
78
+ df = pd.DataFrame(records)
79
+ return df
 
 
 
80
 
 
81
  # Interfaz Gradio
82
+ def main(url):
83
+ df = fetch_playlist_table(url)
84
+ return df
85
+
86
  iface = gr.Interface(
87
+ fn=main,
88
  inputs=gr.Textbox(label="URL de playlist"),
89
+ outputs=gr.Dataframe(headers=['Artist','Title','ISRC','URL','URI','Genres']),
90
+ title="🎵 Tabla de Playlist Spotify",
91
+ description="Trae Artist, Title, ISRC, URL, URI y Géneros de cada track"
92
  )
93
 
94
+ if __name__ == '__main__':
95
+ iface.launch(server_name='0.0.0.0', server_port=7860)