Chrunos commited on
Commit
3f5439c
·
verified ·
1 Parent(s): cf5846e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +133 -1
app.py CHANGED
@@ -14,6 +14,8 @@ from typing import Optional, Dict, Tuple
14
  import urllib.parse
15
  from fastapi.responses import JSONResponse
16
  import re
 
 
17
 
18
  # Configure logging
19
  logging.basicConfig(
@@ -105,6 +107,23 @@ def get_spotify_token() -> str:
105
  logger.error(f"Unexpected error during token request: {str(e)}")
106
  raise HTTPException(status_code=500, detail="Internal server error")
107
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  def extract_album_id(album_url: str) -> str:
109
  """Extract album ID from Spotify URL."""
110
  try:
@@ -112,6 +131,39 @@ def extract_album_id(album_url: str) -> str:
112
  except Exception as e:
113
  logger.error(f"Failed to extract album ID from URL {album_url}: {str(e)}")
114
  raise HTTPException(status_code=400, detail="Invalid Spotify album URL format")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
 
116
 
117
  @app.post("/album")
@@ -290,7 +342,7 @@ def get_url(track_data, cookie):
290
  except:
291
  return None
292
 
293
-
294
  @app.get("/{track_id}")
295
  async def download_track(track_id: str):
296
  cookie = get_cookie()
@@ -306,11 +358,91 @@ async def download_track(track_id: str):
306
  return {"error": "Failed to get download URL"}, 500
307
 
308
  return {"url": download_link}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
 
 
 
 
310
 
 
311
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
 
313
 
 
 
 
 
 
 
 
 
 
 
 
314
 
315
  @app.get("/")
316
  async def health_check():
 
14
  import urllib.parse
15
  from fastapi.responses import JSONResponse
16
  import re
17
+ from ytmusicapi import YTMusic
18
+
19
 
20
  # Configure logging
21
  logging.basicConfig(
 
107
  logger.error(f"Unexpected error during token request: {str(e)}")
108
  raise HTTPException(status_code=500, detail="Internal server error")
109
 
110
+ async def get_download_url(url):
111
+ loop = asyncio.get_running_loop()
112
+ url = "https://chrunos-ytdl2.hf.space/download"
113
+ data = {"url": url}
114
+ try:
115
+ response = await loop.run_in_executor(None, requests.post, url, {'json': data})
116
+ if response.status_code == 200:
117
+ result = response.json()
118
+ return result.get('download_url')
119
+ else:
120
+ logger.error(f"请求失败,状态码: {response.status_code}")
121
+ return None
122
+ except requests.RequestException as e:
123
+ logger.error(f"发生客户端错误: {e}")
124
+ return None
125
+
126
+
127
  def extract_album_id(album_url: str) -> str:
128
  """Extract album ID from Spotify URL."""
129
  try:
 
131
  except Exception as e:
132
  logger.error(f"Failed to extract album ID from URL {album_url}: {str(e)}")
133
  raise HTTPException(status_code=400, detail="Invalid Spotify album URL format")
134
+
135
+
136
+ async def fetch_spotify_track_info(track_id: str) -> Dict:
137
+ """
138
+ Asynchronously fetch Spotify track title, artist, and cover art URL.
139
+ """
140
+ token = get_spotify_token()
141
+ headers = {
142
+ 'Authorization': f'Bearer {token}'
143
+ }
144
+ url = f"{SPOTIFY_API_URL}/tracks/{track_id}"
145
+ try:
146
+ loop = asyncio.get_running_loop()
147
+ response = await loop.run_in_executor(None, requests.get, url, {'headers': headers})
148
+ if response.status_code == 200:
149
+ track_data = response.json()
150
+ title = track_data.get('name')
151
+ artists = [artist.get('name') for artist in track_data.get('artists', [])]
152
+ cover_art_url = track_data.get('album', {}).get('images', [{}])[0].get('url')
153
+
154
+ return {
155
+ 'title': title,
156
+ 'artists': artists,
157
+ 'cover_art_url': cover_art_url
158
+ }
159
+ else:
160
+ raise SpotifyAPIError(f"Failed to fetch track information: {response.text}")
161
+ except requests.exceptions.RequestException as e:
162
+ logger.error(f"Network error during track information request: {str(e)}")
163
+ raise HTTPException(status_code=503, detail="Spotify API service unavailable")
164
+ except Exception as e:
165
+ logger.error(f"Unexpected error during track information request: {str(e)}")
166
+ raise HTTPException(status_code=500, detail="Internal server error")
167
 
168
 
169
  @app.post("/album")
 
342
  except:
343
  return None
344
 
345
+ '''
346
  @app.get("/{track_id}")
347
  async def download_track(track_id: str):
348
  cookie = get_cookie()
 
358
  return {"error": "Failed to get download URL"}, 500
359
 
360
  return {"url": download_link}
361
+ '''
362
+
363
+ @app.get("/{track_id}")
364
+ async def download_track(track_id: str):
365
+ url = f'https://open.spotify.com/track/{track_id}'
366
+ track_data = get_song_link_info(url)
367
+ if not track_data:
368
+ track_data = fetch_spotify_track_info(track_id)
369
+ title = track_data["title"]
370
+ artist = track_data["artist"]
371
+ query = f'{title}+{artist}'
372
+ logger.info(f"search query: {query}")
373
+ search_results = ytmusic.search(query, filter="songs")
374
+ first_song = next((song for song in search_results if 'videoId' in song and song['videoId']), {}) if search_results else {}
375
+ if 'videoId' in first_song:
376
+ videoId = first_song["videoId"]
377
+ ym_url = f'https://www.youtube.com/watch?v={videoId}'
378
+ d_data = get_download_url(ym_url)
379
+ track_data['download_url'] = d_data
380
+ return track_data
381
+ else:
382
+ yt_url = track_data['url']
383
+ d_data = get_download_url(yt_url)
384
+ track_data['download_url'] = d_data
385
+ return track_data
386
+
387
 
388
+ download_link = get_url(track_data, cookie)
389
+ if not download_link:
390
+ return {"error": "Failed to get download URL"}, 500
391
 
392
+ return {"url": download_link}
393
 
394
+ # Function to get track info from Song.link API
395
+ def get_song_link_info(url: str):
396
+ # Check if the URL is from Amazon Music
397
+ if "music.amazon.com" in url:
398
+ track_id = extract_amazon_track_id(url)
399
+ if track_id:
400
+ # Use the working format for Amazon Music tracks
401
+ api_url = f"https://api.song.link/v1-alpha.1/links?type=song&platform=amazonMusic&id={track_id}&userCountry=US"
402
+ else:
403
+ # If no track ID is found, use the original URL
404
+ api_url = f"https://api.song.link/v1-alpha.1/links?url={url}&userCountry=US"
405
+ else:
406
+ # For non-Amazon Music URLs, use the standard format
407
+ api_url = f"https://api.song.link/v1-alpha.1/links?url={url}&userCountry=US"
408
+
409
+ # Make the API call
410
+ response = requests.get(api_url)
411
+ if response.status_code == 200:
412
+ track_info = response
413
+ if not track_info:
414
+ raise HTTPException(status_code=404, detail="Could not fetch track info")
415
+ entityUniqueId = track_info["entityUniqueId"]
416
+ title = track_info["entitiesByUniqueId"][entityUniqueId]["title"]
417
+ artist = track_info["entitiesByUniqueId"][entityUniqueId]["artistName"]
418
+ filename = f"{title} - {artist}"
419
+
420
+ #extract YouTube URL
421
+ youtube_url = extract_url(track_info["linksByPlatform"], "youtube")
422
+ if youtube_url:
423
+
424
+ if title and artist:
425
+ filename = f"{title} - {artist}"
426
+ return {"url": youtube_url, "filename": filename}
427
+ else:
428
+ return {"url": youtube_url, "filename": "Unknown Track - Unknown Artist"}
429
+ else:
430
+ return None
431
+ else:
432
+ return None
433
 
434
 
435
+ '''
436
+ else:
437
+ query = f'{title}+{artist}'
438
+ logger.info(f"search query: {query}")
439
+ search_results = ytmusic.search(query, filter="songs")
440
+ first_song = next((song for song in search_results if 'videoId' in song and song['videoId']), {}) if search_results else {}
441
+ if 'videoId' in first_song:
442
+ videoId = first_song["videoId"]
443
+ ym_url = f'https://www.youtube.com/watch?v={videoId}'
444
+ return {"filename": filename, "url": ym_url, "track_id": videoId}
445
+ '''
446
 
447
  @app.get("/")
448
  async def health_check():