Chrunos commited on
Commit
d97de9d
·
verified ·
1 Parent(s): b0375ba

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -39
app.py CHANGED
@@ -146,7 +146,6 @@ def get_user_ip(request: Request) -> str:
146
  def download_track(request: Request, download_request: DownloadRequest):
147
  try:
148
  user_ip = get_user_ip(request)
149
-
150
  if rate_limiter.is_rate_limited(user_ip):
151
  current_count = rate_limiter.get_current_count(user_ip)
152
  raise HTTPException(
@@ -156,84 +155,121 @@ def download_track(request: Request, download_request: DownloadRequest):
156
  "help": "https://t.me/chrunoss"
157
  }
158
  )
 
159
  if download_request.arl is None or download_request.arl.strip() == "":
160
  ARL = ARL_TOKEN
161
  else:
162
  ARL = download_request.arl
 
163
  logger.info(f'arl: {ARL}')
164
  url = download_request.url
 
165
  if 'dzr.page' in url or 'deezer.page' in url or 'link.deezer' in url:
166
  url = convert_deezer_short_link_async(url)
167
- quality = download_request.quality
 
168
  dl = DeeLogin(arl=ARL)
169
  logger.info(f'track_url: {url}')
170
 
171
- if quality not in ["MP3_320", "MP3_128", "FLAC"]:
 
 
172
  raise HTTPException(status_code=400, detail="Invalid quality specified")
173
 
174
- # 提取 track_id 假设 url 格式为 https://api.deezer.com/track/{track_id}
175
- track_id = url.split("/")[-1]
 
176
 
177
- # Fetch track info
178
  track_info = get_track_info(track_id)
179
  track_link = track_info.get("link")
 
180
  if not track_link:
181
  raise HTTPException(status_code=404, detail="Track link not found")
182
 
183
- # Sanitize filename
184
  track_title = track_info.get("title", "track")
185
  artist_name = track_info.get("artist", {}).get("name", "unknown")
186
- file_extension = "flac" if quality == "FLAC" else "mp3"
187
- expected_filename = f"{artist_name} - {track_title}.{file_extension}".replace("/", "_") # Sanitize filename
188
 
189
- # Clear the downloads directory
190
  for root, dirs, files in os.walk("downloads"):
191
  for file in files:
192
  os.remove(os.path.join(root, file))
193
  for dir in dirs:
194
  shutil.rmtree(os.path.join(root, dir))
195
 
196
- # Download the track using deezspot
197
- try:
198
- # 下载文件的代码
199
- dl.download_trackdee(
200
- link_track=track_link,
201
- output_dir="downloads",
202
- quality_download=quality,
203
- recursive_quality=False,
204
- recursive_download=False
205
- )
206
- except Exception as e:
207
- logger.error(f"Error downloading file: {e}")
208
- raise HTTPException(status_code=500, detail="File download failed")
209
-
210
- # Recursively search for the file in the downloads directory
211
  filepath = None
212
- for root, dirs, files in os.walk("downloads"):
213
- for file in files:
214
- if file.endswith(f'.{file_extension}'):
215
- filepath = os.path.join(root, file)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  break
217
- if filepath:
218
- break
 
 
 
 
219
 
 
220
  if not filepath:
221
- raise HTTPException(status_code=500, detail=f"{file_extension} file not found after download")
222
- if filepath:
223
- file_size = os.path.getsize(filepath)
224
- logger.info(f"Downloaded file size: {file_size} bytes")
 
225
 
226
  # Return the download URL
227
  relative_path = quote(str(os.path.relpath(filepath, "downloads")))
228
- # Remove spaces from the relative path
229
- # Auto-detect base URL from request
230
  base_url = str(request.base_url).rstrip('/')
231
  download_url = f"{base_url}/downloads/{relative_path}"
232
  logger.info(f"Download successful: {download_url}")
 
233
  gc.collect()
234
- return {"download_url": download_url, "requests_remaining": rate_limiter.max_requests - rate_limiter.get_current_count(user_ip)}
 
 
 
 
 
 
 
 
 
 
 
235
  except Exception as e:
236
- logger.error(f"Error downloading track: {e}")
237
  raise HTTPException(status_code=500, detail=str(e))
238
 
239
 
 
146
  def download_track(request: Request, download_request: DownloadRequest):
147
  try:
148
  user_ip = get_user_ip(request)
 
149
  if rate_limiter.is_rate_limited(user_ip):
150
  current_count = rate_limiter.get_current_count(user_ip)
151
  raise HTTPException(
 
155
  "help": "https://t.me/chrunoss"
156
  }
157
  )
158
+
159
  if download_request.arl is None or download_request.arl.strip() == "":
160
  ARL = ARL_TOKEN
161
  else:
162
  ARL = download_request.arl
163
+
164
  logger.info(f'arl: {ARL}')
165
  url = download_request.url
166
+
167
  if 'dzr.page' in url or 'deezer.page' in url or 'link.deezer' in url:
168
  url = convert_deezer_short_link_async(url)
169
+
170
+ requested_quality = download_request.quality
171
  dl = DeeLogin(arl=ARL)
172
  logger.info(f'track_url: {url}')
173
 
174
+ # 1. 定义降级序列 (从高到低)
175
+ QUALITY_HIERARCHY = ["FLAC", "MP3_320", "MP3_128"]
176
+ if requested_quality not in QUALITY_HIERARCHY:
177
  raise HTTPException(status_code=400, detail="Invalid quality specified")
178
 
179
+ # 确定需要尝试的音质列表从用户指定的音质开始,截取列表后半段
180
+ start_index = QUALITY_HIERARCHY.index(requested_quality)
181
+ qualities_to_try = QUALITY_HIERARCHY[start_index:]
182
 
183
+ track_id = url.split("/")[-1]
184
  track_info = get_track_info(track_id)
185
  track_link = track_info.get("link")
186
+
187
  if not track_link:
188
  raise HTTPException(status_code=404, detail="Track link not found")
189
 
 
190
  track_title = track_info.get("title", "track")
191
  artist_name = track_info.get("artist", {}).get("name", "unknown")
 
 
192
 
193
+ # Clear the downloads directory (保持原样,在下载前清空一次即可)
194
  for root, dirs, files in os.walk("downloads"):
195
  for file in files:
196
  os.remove(os.path.join(root, file))
197
  for dir in dirs:
198
  shutil.rmtree(os.path.join(root, dir))
199
 
200
+ # 2. 循环尝试下载降级队列中的音质
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  filepath = None
202
+ actual_quality_downloaded = None
203
+ actual_extension = None
204
+
205
+ for current_quality in qualities_to_try:
206
+ try:
207
+ logger.info(f"Attempting download with quality: {current_quality}")
208
+
209
+ # 执行下载
210
+ dl.download_trackdee(
211
+ link_track=track_link,
212
+ output_dir="downloads",
213
+ quality_download=current_quality,
214
+ recursive_quality=False,
215
+ recursive_download=False
216
+ )
217
+
218
+ # 下载完成后,立即在目录下查找文件是否真的生成了
219
+ temp_extension = "flac" if current_quality == "FLAC" else "mp3"
220
+ found_path = None
221
+
222
+ for root, dirs, files in os.walk("downloads"):
223
+ for file in files:
224
+ if file.endswith(f'.{temp_extension}'):
225
+ found_path = os.path.join(root, file)
226
+ break
227
+ if found_path:
228
+ break
229
+
230
+ # 如果文件找到了,说明这一档的音质下载成功,跳出循环
231
+ if found_path:
232
+ filepath = found_path
233
+ actual_quality_downloaded = current_quality
234
+ actual_extension = temp_extension
235
+ logger.info(f"Successfully downloaded in {current_quality}")
236
  break
237
+ else:
238
+ logger.warning(f"Download command executed but .{temp_extension} file not found for {current_quality}. Trying next lower quality...")
239
+
240
+ except Exception as e:
241
+ logger.warning(f"Error downloading {current_quality}: {e}. Falling back to next lower quality...")
242
+ # 出现异常,继续循环体,尝试下一种音质
243
 
244
+ # 如果循环结束 filepath 还是 None,说明所有音质都失败了
245
  if not filepath:
246
+ logger.error(f"All download attempts failed for track: {track_link}")
247
+ raise HTTPException(status_code=500, detail="File download failed for all available qualities")
248
+
249
+ file_size = os.path.getsize(filepath)
250
+ logger.info(f"Downloaded file size: {file_size} bytes")
251
 
252
  # Return the download URL
253
  relative_path = quote(str(os.path.relpath(filepath, "downloads")))
 
 
254
  base_url = str(request.base_url).rstrip('/')
255
  download_url = f"{base_url}/downloads/{relative_path}"
256
  logger.info(f"Download successful: {download_url}")
257
+
258
  gc.collect()
259
+
260
+ # 3. 建议在返回值中加上实际下载的音质,方便客户端/前端知道是否发生了降级
261
+ return {
262
+ "download_url": download_url,
263
+ "requested_quality": requested_quality,
264
+ "actual_quality": actual_quality_downloaded, # 告知客户端实际下到的音质
265
+ "requests_remaining": rate_limiter.max_requests - rate_limiter.get_current_count(user_ip)
266
+ }
267
+
268
+ except HTTPException:
269
+ # FastAPI 自带的 HTTPException 直接抛出,不经过下面的通用异常处理
270
+ raise
271
  except Exception as e:
272
+ logger.error(f"Error processing track download: {e}")
273
  raise HTTPException(status_code=500, detail=str(e))
274
 
275