Mthrfkr commited on
Commit
1e7a605
·
verified ·
1 Parent(s): 8222b3a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +43 -42
app.py CHANGED
@@ -11,7 +11,7 @@ client_ids = os.getenv("SPOTIFY_CLIENT_IDS", "").split(',')
11
  client_secrets = os.getenv("SPOTIFY_CLIENT_SECRETS", "").split(',')
12
 
13
  if not client_ids or not client_secrets:
14
- raise ValueError("Faltan variables de entorno SPOTIFY_CLIENT_IDS o SPOTIFY_CLIENT_SECRETS")
15
 
16
  # Gestión de Rotación de Clientes
17
  current_client_index = 0
@@ -22,7 +22,7 @@ def rotate_client():
22
  global current_client_index, request_counter
23
  current_client_index = (current_client_index + 1) % len(client_ids)
24
  request_counter = 0
25
- print(f"🔁 Rotando a cliente Spotify #{current_client_index + 1}")
26
 
27
  def get_spotify_token():
28
  global current_client_index
@@ -36,6 +36,7 @@ def get_spotify_token():
36
  data={'grant_type': 'client_credentials'},
37
  auth=(client_id, client_secret)
38
  )
 
39
  if response.status_code == 200:
40
  return response.json().get('access_token')
41
 
@@ -44,13 +45,12 @@ def get_spotify_token():
44
 
45
  raise Exception("🚨 Todos los clientes fallaron al obtener token")
46
 
47
- # Funciones Principales
48
  def make_spotify_request(url, params=None):
49
  global request_counter
50
  token = get_spotify_token()
51
  headers = {'Authorization': f'Bearer {token}'}
52
 
53
- for _ in range(3): # Reintentos máximos
54
  response = requests.get(url, headers=headers, params=params)
55
  request_counter += 1
56
 
@@ -70,30 +70,39 @@ def make_spotify_request(url, params=None):
70
 
71
  return None
72
 
73
- def extract_spotify_id(url, type_keyword):
74
  """Extrae ID de diferentes formatos de URLs de Spotify"""
75
- if type_keyword in url:
76
- parts = url.split(f"/{type_keyword}/")
77
- if len(parts) > 1:
78
- return parts[1].split("?")[0].split("/")[0]
 
 
79
 
80
- # Manejo de URLs complejas
81
- parts = [p for p in url.split("/") if p]
82
- for i, part in enumerate(parts):
83
- if part == type_keyword and i < len(parts)-1:
84
- return parts[i+1].split("?")[0]
85
 
86
- return url.split("/")[-1].split("?")[0]
 
 
 
 
 
 
 
87
 
88
  def get_playlist_tracks(playlist_url):
89
  playlist_id = extract_spotify_id(playlist_url, "playlist")
90
- print(f"🎧 Obteniendo playlist: {playlist_id}")
 
 
91
 
 
92
  all_tracks = []
93
  url = f'https://api.spotify.com/v1/playlists/{playlist_id}/tracks'
 
94
 
95
  while url:
96
- data = make_spotify_request(url)
97
  if not data:
98
  break
99
 
@@ -105,30 +114,23 @@ def get_playlist_tracks(playlist_url):
105
 
106
  def get_album_tracks(album_url):
107
  album_id = extract_spotify_id(album_url, "album")
108
- print(f"💿 Obteniendo álbum: {album_id}")
109
-
110
- # Obtener información básica del álbum
111
- album_data = make_spotify_request(f'https://api.spotify.com/v1/albums/{album_id}')
112
- if not album_data:
113
  return []
114
 
 
115
  all_tracks = []
116
  url = f'https://api.spotify.com/v1/albums/{album_id}/tracks'
 
117
 
118
  while url:
119
- data = make_spotify_request(url)
120
  if not data:
121
  break
122
 
123
- # Obtener detalles completos de cada track
124
  for item in data.get('items', []):
125
  track_data = make_spotify_request(f"https://api.spotify.com/v1/tracks/{item['id']}")
126
  if track_data:
127
- track_data['album'] = { # Añadir info del álbum
128
- 'name': album_data.get('name'),
129
- 'release_date': album_data.get('release_date'),
130
- 'id': album_id
131
- }
132
  all_tracks.append(track_data)
133
 
134
  url = data.get('next')
@@ -155,7 +157,6 @@ def process_tracks(urls):
155
 
156
  return all_tracks
157
 
158
- # Procesamiento de Datos
159
  def create_final_dataframe(tracks, include_all_info=True):
160
  artist_cache = {}
161
 
@@ -213,38 +214,38 @@ def create_final_dataframe(tracks, include_all_info=True):
213
 
214
  return df
215
 
216
- # Interfaz Gradio
217
  def main_interface(project_name, spotify_urls, include_all_info=True):
218
- urls = [url.strip() for url in spotify_urls.strip().split('\n') if url.strip()]
 
219
 
220
  if not urls:
221
- return pd.DataFrame({"Error": ["Ingresa al menos una URL válida"]}), None
222
 
223
  print("⏳ Procesando URLs...")
224
  tracks = process_tracks(urls)
225
 
226
  if not tracks:
227
- return pd.DataFrame({"Error": ["No se encontraron tracks"]}), None
228
 
229
  print("📊 Creando dataframe...")
230
  df = create_final_dataframe(tracks, include_all_info)
231
 
232
  with NamedTemporaryFile(delete=False, suffix='.xlsx') as tmp:
233
  df.to_excel(tmp.name, index=False)
234
- final_filename = f"{project_name}.xlsx" if project_name else "spotify_tracks.xlsx"
235
  shutil.move(tmp.name, final_filename)
236
 
237
  print("✅ Proceso completado")
238
  return df, final_filename
239
 
240
- # Configuración de la UI
241
  iface = gr.Interface(
242
  fn=main_interface,
243
  inputs=[
244
  gr.Textbox(label="Nombre del Proyecto", placeholder="Mi Colección Musical"),
245
  gr.Textbox(
246
- label="URLs de Spotify (1 por línea)",
247
- placeholder="Pega aquí URLs de playlists, álbumes o canciones...",
248
  lines=5
249
  ),
250
  gr.Checkbox(label="Incluir toda la información", value=True)
@@ -253,11 +254,11 @@ iface = gr.Interface(
253
  gr.Dataframe(label="Resultados"),
254
  gr.File(label="Descargar Excel")
255
  ],
256
- title="🟢 Spotify Track Collector PRO",
257
- description="Extrae información detallada de múltiples URLs de Spotify (playlists, álbumes, canciones) y genera un Excel unificado.",
258
  examples=[
259
- ["Mi Playlist", "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M", True],
260
- ["Álbum Clásico", "https://open.spotify.com/album/1R5BORZZxNUg8QMgbqt0nd", False]
261
  ],
262
  allow_flagging="never",
263
  theme=gr.themes.Soft()
 
11
  client_secrets = os.getenv("SPOTIFY_CLIENT_SECRETS", "").split(',')
12
 
13
  if not client_ids or not client_secrets:
14
+ raise ValueError("❌ Faltan variables de entorno SPOTIFY_CLIENT_IDS o SPOTIFY_CLIENT_SECRETS")
15
 
16
  # Gestión de Rotación de Clientes
17
  current_client_index = 0
 
22
  global current_client_index, request_counter
23
  current_client_index = (current_client_index + 1) % len(client_ids)
24
  request_counter = 0
25
+ print(f"🔄 Rotando a cliente Spotify #{current_client_index + 1}")
26
 
27
  def get_spotify_token():
28
  global current_client_index
 
36
  data={'grant_type': 'client_credentials'},
37
  auth=(client_id, client_secret)
38
  )
39
+
40
  if response.status_code == 200:
41
  return response.json().get('access_token')
42
 
 
45
 
46
  raise Exception("🚨 Todos los clientes fallaron al obtener token")
47
 
 
48
  def make_spotify_request(url, params=None):
49
  global request_counter
50
  token = get_spotify_token()
51
  headers = {'Authorization': f'Bearer {token}'}
52
 
53
+ for _ in range(3): # 3 intentos por cliente
54
  response = requests.get(url, headers=headers, params=params)
55
  request_counter += 1
56
 
 
70
 
71
  return None
72
 
73
+ def extract_spotify_id(url, resource_type):
74
  """Extrae ID de diferentes formatos de URLs de Spotify"""
75
+ clean_url = url.strip().split('?')[0].replace("https://open.spotify.com/", "")
76
+
77
+ # Manejar URLs con /intl-xx/
78
+ if "/intl-" in clean_url:
79
+ parts = clean_url.split("/")
80
+ return parts[-1]
81
 
82
+ parts = clean_url.split("/")
 
 
 
 
83
 
84
+ try:
85
+ index = parts.index(resource_type)
86
+ return parts[index + 1] if index + 1 < len(parts) else None
87
+ except ValueError:
88
+ for part in parts:
89
+ if len(part) == 22 and resource_type in url:
90
+ return part
91
+ return None
92
 
93
  def get_playlist_tracks(playlist_url):
94
  playlist_id = extract_spotify_id(playlist_url, "playlist")
95
+ if not playlist_id or len(playlist_id) != 22:
96
+ print(f"❌ ID de playlist inválido: {playlist_id}")
97
+ return []
98
 
99
+ print(f"🎧 Obteniendo playlist: {playlist_id}")
100
  all_tracks = []
101
  url = f'https://api.spotify.com/v1/playlists/{playlist_id}/tracks'
102
+ params = {'market': 'US', 'limit': 100}
103
 
104
  while url:
105
+ data = make_spotify_request(url, params)
106
  if not data:
107
  break
108
 
 
114
 
115
  def get_album_tracks(album_url):
116
  album_id = extract_spotify_id(album_url, "album")
117
+ if not album_id or len(album_id) != 22:
118
+ print(f"❌ ID de álbum inválido: {album_id}")
 
 
 
119
  return []
120
 
121
+ print(f"💿 Obteniendo álbum: {album_id}")
122
  all_tracks = []
123
  url = f'https://api.spotify.com/v1/albums/{album_id}/tracks'
124
+ params = {'market': 'US', 'limit': 50}
125
 
126
  while url:
127
+ data = make_spotify_request(url, params)
128
  if not data:
129
  break
130
 
 
131
  for item in data.get('items', []):
132
  track_data = make_spotify_request(f"https://api.spotify.com/v1/tracks/{item['id']}")
133
  if track_data:
 
 
 
 
 
134
  all_tracks.append(track_data)
135
 
136
  url = data.get('next')
 
157
 
158
  return all_tracks
159
 
 
160
  def create_final_dataframe(tracks, include_all_info=True):
161
  artist_cache = {}
162
 
 
214
 
215
  return df
216
 
 
217
  def main_interface(project_name, spotify_urls, include_all_info=True):
218
+ # Convertir URLs separadas por comas o saltos de línea
219
+ urls = [url.strip() for url in spotify_urls.replace('\n', ',').split(',') if url.strip()]
220
 
221
  if not urls:
222
+ return pd.DataFrame({"Error": ["❌ Ingresa al menos una URL válida"]}), None
223
 
224
  print("⏳ Procesando URLs...")
225
  tracks = process_tracks(urls)
226
 
227
  if not tracks:
228
+ return pd.DataFrame({"Error": ["❌ No se encontraron tracks"]}), None
229
 
230
  print("📊 Creando dataframe...")
231
  df = create_final_dataframe(tracks, include_all_info)
232
 
233
  with NamedTemporaryFile(delete=False, suffix='.xlsx') as tmp:
234
  df.to_excel(tmp.name, index=False)
235
+ final_filename = f"{project_name or 'spotify_tracks'}.xlsx"
236
  shutil.move(tmp.name, final_filename)
237
 
238
  print("✅ Proceso completado")
239
  return df, final_filename
240
 
241
+ # Configuración de la Interfaz
242
  iface = gr.Interface(
243
  fn=main_interface,
244
  inputs=[
245
  gr.Textbox(label="Nombre del Proyecto", placeholder="Mi Colección Musical"),
246
  gr.Textbox(
247
+ label="URLs de Spotify",
248
+ placeholder="Pega URLs separadas por comas o saltos de línea (playlists, álbumes, canciones)...",
249
  lines=5
250
  ),
251
  gr.Checkbox(label="Incluir toda la información", value=True)
 
254
  gr.Dataframe(label="Resultados"),
255
  gr.File(label="Descargar Excel")
256
  ],
257
+ title="🎵 Spotify Track Collector PRO",
258
+ description="Extrae información detallada de múltiples URLs de Spotify y genera un Excel unificado",
259
  examples=[
260
+ ["Rock Clásico", "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M, https://open.spotify.com/album/1R5BORZZxNUg8QMgbqt0nd", True],
261
+ ["Éxitos Actuales", "https://open.spotify.com/playlist/37i9dQZEtDXc8QFRQ4qegR", False]
262
  ],
263
  allow_flagging="never",
264
  theme=gr.themes.Soft()