Mthrfkr commited on
Commit
efa5acc
Β·
verified Β·
1 Parent(s): 8f490ca

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +56 -64
app.py CHANGED
@@ -1,6 +1,7 @@
1
  import os
2
  import requests
3
  import pandas as pd
 
4
 
5
  # β€”β€”β€”β€”β€”β€” PARCHE Pydantic para FastAPI β€”β€”β€”β€”β€”β€”
6
  import pydantic
@@ -14,104 +15,95 @@ def patched_get_type(schema):
14
  if not isinstance(schema, dict):
15
  return "Any"
16
  return _orig_get_type(schema)
17
-
18
  client_utils.get_type = patched_get_type
19
  # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
20
 
21
  import gradio as gr
22
- from io import BytesIO
23
 
24
- # ConfiguraciΓ³n Spotify (Client Credentials)
25
  CLIENT_ID = os.getenv("SPOTIFY_CLIENT_IDS", "").split(',')[0]
26
  CLIENT_SECRET = os.getenv("SPOTIFY_CLIENT_SECRETS", "").split(',')[0]
27
 
28
- # FunciΓ³n para obtener token
29
  def get_token():
30
- resp = requests.post(
31
  "https://accounts.spotify.com/api/token",
32
- data={"grant_type": "client_credentials"},
33
  auth=(CLIENT_ID, CLIENT_SECRET)
34
  )
35
- resp.raise_for_status()
36
- return resp.json()["access_token"]
37
 
38
- # Extrae el ID de playlist de la URL
39
  def extract_pid(url):
40
  return url.strip().rstrip('/').split('/')[-1].split('?')[0]
41
 
42
- # CachΓ© de gΓ©neros por artista
43
  _artist_cache = {}
44
 
45
  def get_artist_genres(aid, headers):
46
  if aid in _artist_cache:
47
  return _artist_cache[aid]
48
- resp = requests.get(f"https://api.spotify.com/v1/artists/{aid}", headers=headers)
49
- genres = resp.json().get('genres', []) if resp.status_code == 200 else []
50
  _artist_cache[aid] = genres
51
  return genres
52
 
53
- # Fetch y devuelve DataFrame de toda la playlist
54
  def fetch_playlist_table(url):
55
  if not CLIENT_ID or not CLIENT_SECRET:
56
- return pd.DataFrame([{'Error': 'Faltan credenciales'}])
57
-
58
  token = get_token()
59
  pid = extract_pid(url)
60
- headers = {"Authorization": f"Bearer {token}"}
61
-
62
- # Metadata de playlist
63
  meta = requests.get(f"https://api.spotify.com/v1/playlists/{pid}", headers=headers)
64
- if meta.status_code != 200:
65
- return pd.DataFrame([{'Error': f"Playlist error {meta.status_code}: {meta.json()}"}])
66
- total = meta.json().get('tracks', {}).get('total', 0)
67
-
68
- # PaginaciΓ³n de tracks
69
- records = []
70
- limit = 100
71
- offset = 0
72
- while offset < total:
73
- params = {'limit': limit, 'offset': offset}
74
- r = requests.get(f"https://api.spotify.com/v1/playlists/{pid}/tracks", headers=headers, params=params)
 
75
  r.raise_for_status()
76
- for item in r.json().get('items', []):
77
- tr = item.get('track', {})
78
- if not tr:
79
- continue
80
- aid = tr['artists'][0]['id'] if tr.get('artists') else None
81
- genres = get_artist_genres(aid, headers) if aid else []
82
  records.append({
83
- 'Artist': tr['artists'][0]['name'] if tr.get('artists') else '',
84
- 'Title': tr.get('name', ''),
85
- 'ISRC': tr.get('external_ids', {}).get('isrc', ''),
86
- 'URL': tr.get('external_urls', {}).get('spotify', ''),
87
- 'URI': tr.get('uri', ''),
88
- 'Genres': ', '.join(genres)
89
  })
90
- offset += limit
91
-
92
- df = pd.DataFrame(records)
93
- return df
94
-
95
- # FunciΓ³n principal: retorna DataFrame y CSV en memoria
96
- def main(url):
97
- df = fetch_playlist_table(url)
98
- # Convertir DataFrame a CSV en memoria
99
- csv_buffer = BytesIO()
100
- df.to_csv(csv_buffer, index=False)
101
- csv_bytes = csv_buffer.getvalue()
102
- return df, ('playlist.csv', csv_bytes)
103
-
104
- # Interfaz Gradio con gr.Download
105
- iface = gr.Interface(
106
  fn=main,
107
- inputs=gr.Textbox(label="URL de playlist", placeholder="https://open.spotify.com/playlist/..."),
108
  outputs=[
109
- gr.Dataframe(headers=['Artist','Title','ISRC','URL','URI','Genres'], label="Tabla de Playlist Spotify"),
110
- gr.Download(label="Descargar CSV")
111
  ],
112
- title="🎡 Tabla de Playlist Spotify",
113
- description="Trae Artist, Title, ISRC, URL, URI y GΓ©neros de cada track y permite descargar CSV sin usar disco"
114
  )
115
 
116
- if __name__ == '__main__':
117
- iface.launch(server_name='0.0.0.0', server_port=7860)
 
1
  import os
2
  import requests
3
  import pandas as pd
4
+ from io import BytesIO
5
 
6
  # β€”β€”β€”β€”β€”β€” PARCHE Pydantic para FastAPI β€”β€”β€”β€”β€”β€”
7
  import pydantic
 
15
  if not isinstance(schema, dict):
16
  return "Any"
17
  return _orig_get_type(schema)
 
18
  client_utils.get_type = patched_get_type
19
  # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
20
 
21
  import gradio as gr
 
22
 
23
+ # Config Spotify (Client Credentials)
24
  CLIENT_ID = os.getenv("SPOTIFY_CLIENT_IDS", "").split(',')[0]
25
  CLIENT_SECRET = os.getenv("SPOTIFY_CLIENT_SECRETS", "").split(',')[0]
26
 
27
+ # Obtiene token
28
  def get_token():
29
+ r = requests.post(
30
  "https://accounts.spotify.com/api/token",
31
+ data={"grant_type":"client_credentials"},
32
  auth=(CLIENT_ID, CLIENT_SECRET)
33
  )
34
+ r.raise_for_status()
35
+ return r.json()["access_token"]
36
 
37
+ # Extrae ID de playlist
38
  def extract_pid(url):
39
  return url.strip().rstrip('/').split('/')[-1].split('?')[0]
40
 
41
+ # Cache gΓ©neros
42
  _artist_cache = {}
43
 
44
  def get_artist_genres(aid, headers):
45
  if aid in _artist_cache:
46
  return _artist_cache[aid]
47
+ r = requests.get(f"https://api.spotify.com/v1/artists/{aid}", headers=headers)
48
+ genres = r.json().get('genres', []) if r.status_code==200 else []
49
  _artist_cache[aid] = genres
50
  return genres
51
 
52
+ # Trae tabla
53
  def fetch_playlist_table(url):
54
  if not CLIENT_ID or not CLIENT_SECRET:
55
+ return pd.DataFrame([{'Error':'Faltan credenciales'}])
 
56
  token = get_token()
57
  pid = extract_pid(url)
58
+ headers={"Authorization":f"Bearer {token}"}
 
 
59
  meta = requests.get(f"https://api.spotify.com/v1/playlists/{pid}", headers=headers)
60
+ if meta.status_code!=200:
61
+ return pd.DataFrame([{'Error':f"Playlist error {meta.status_code}"}])
62
+ total = meta.json().get('tracks',{}).get('total',0)
63
+ records=[]
64
+ limit=100
65
+ offset=0
66
+ while offset<total:
67
+ r = requests.get(
68
+ f"https://api.spotify.com/v1/playlists/{pid}/tracks",
69
+ headers=headers,
70
+ params={'limit':limit,'offset':offset}
71
+ )
72
  r.raise_for_status()
73
+ for item in r.json().get('items',[]):
74
+ tr=item.get('track',{})
75
+ if not tr: continue
76
+ aid=tr['artists'][0]['id'] if tr.get('artists') else None
77
+ genres=get_artist_genres(aid,headers) if aid else []
 
78
  records.append({
79
+ 'Artist':tr['artists'][0]['name'] if tr.get('artists') else '',
80
+ 'Title':tr.get('name',''),
81
+ 'ISRC':tr.get('external_ids',{}).get('isrc',''),
82
+ 'URL':tr.get('external_urls',{}).get('spotify',''),
83
+ 'URI':tr.get('uri',''),
84
+ 'Genres':', '.join(genres)
85
  })
86
+ offset+=limit
87
+ return pd.DataFrame(records)
88
+
89
+ # FunciΓ³n principal: retorna DataFrame y bytes para descargar
90
+ ndef main(url):
91
+ df=fetch_playlist_table(url)
92
+ buf=BytesIO()
93
+ df.to_csv(buf,index=False)
94
+ buf.seek(0)
95
+ return df, ("playlist.csv", buf.getvalue())
96
+
97
+ iface=gr.Interface(
 
 
 
 
98
  fn=main,
99
+ inputs=gr.Textbox(label="URL de playlist"),
100
  outputs=[
101
+ gr.Dataframe(headers=['Artist','Title','ISRC','URL','URI','Genres'], label="Tabla Spotify"),
102
+ gr.File(label="Descargar CSV")
103
  ],
104
+ title="🎡 Spotify Playlist Table",
105
+ description="Muestra y descarga CSV sin usar disco"
106
  )
107
 
108
+ if __name__=='__main__':
109
+ iface.launch(server_name='0.0.0.0',server_port=7860)