recycleactor commited on
Commit
1ac196a
·
verified ·
1 Parent(s): 11db465

Upload soundcloud.rs

Browse files
Files changed (1) hide show
  1. src/soundcloud.rs +18 -104
src/soundcloud.rs CHANGED
@@ -133,13 +133,9 @@ pub async fn download(Query(params): Query<DownloadParams>) -> impl IntoResponse
133
 
134
  let quality = params.quality.as_deref().unwrap_or("best");
135
 
136
- // Формируем аргументы для yt-dlp
137
- // Приоритизируем M4A/AAC (256kbps для Go+), затем MP3
138
- let format_arg = match quality {
139
- "256" => "bestaudio[ext=m4a]/bestaudio[ext=aac]/bestaudio[abr<=256]/bestaudio",
140
- "128" => "bestaudio[abr<=128]/bestaudio",
141
- _ => "bestaudio[ext=m4a]/bestaudio[ext=aac]/bestaudio", // Приоритет M4A/AAC
142
- };
143
 
144
  tracing::info!("Using format selector: {}", format_arg);
145
 
@@ -225,22 +221,14 @@ pub async fn download(Query(params): Query<DownloadParams>) -> impl IntoResponse
225
  let actual_file = if tokio::fs::metadata(&temp_file).await.is_ok() {
226
  temp_file.clone()
227
  } else {
228
- // Пробуем найти с расширением - ВАЖНО: сначала ищем M4A/AAC, потом остальные
229
- let mut found = None;
230
- for ext in &["m4a", "aac", "opus", "webm", "mp3"] {
231
- let path = format!("{}.{}", temp_file, ext);
232
- if tokio::fs::metadata(&path).await.is_ok() {
233
- tracing::info!("Found downloaded file with extension: {}", ext);
234
- found = Some(path);
235
- break;
236
- }
237
- }
238
- match found {
239
- Some(p) => p,
240
- None => {
241
- tracing::error!("Could not find downloaded file with any extension");
242
- return (StatusCode::INTERNAL_SERVER_ERROR, "File not found").into_response();
243
- }
244
  }
245
  };
246
 
@@ -254,92 +242,18 @@ pub async fn download(Query(params): Query<DownloadParams>) -> impl IntoResponse
254
  }
255
  };
256
 
257
- // Определяем расширение оригинального файла
258
- let orig_extension = if actual_file.ends_with(".m4a") {
259
- "m4a"
260
- } else if actual_file.ends_with(".opus") {
261
- "opus"
262
- } else if actual_file.ends_with(".webm") {
263
- "webm"
264
- } else if actual_file.ends_with(".aac") {
265
- "aac"
266
- } else {
267
- "mp3"
268
- };
269
-
270
- // Определяем тип контента по расширению
271
- let content_type = if actual_file.ends_with(".m4a") || actual_file.ends_with(".aac") {
272
- "audio/mp4" // AAC обычно в контейнере M4A
273
- } else if actual_file.ends_with(".opus") {
274
- "audio/opus"
275
- } else if actual_file.ends_with(".webm") {
276
- "audio/webm"
277
- } else {
278
- "audio/mpeg"
279
- };
280
-
281
- // Telegram Bot API плохо работает с некоторыми форматами по URL.
282
- // Конвертируем OPUS, WEBM и M4A в MP3 для совместимости.
283
- let (final_data, final_content_type, final_extension) =
284
- if actual_file.ends_with(".opus") || actual_file.ends_with(".webm") || actual_file.ends_with(".m4a") || actual_file.ends_with(".aac") {
285
- let target_format = if actual_file.ends_with(".m4a") || actual_file.ends_with(".aac") {
286
- "AAC/M4A"
287
- } else if actual_file.ends_with(".opus") {
288
- "OPUS"
289
- } else {
290
- "WEBM"
291
- };
292
- tracing::info!("Converting {} to MP3 320k for Telegram compatibility", target_format);
293
-
294
- let mp3_file = format!("{}.mp3", temp_file);
295
- let convert_output = Command::new("ffmpeg")
296
- .args([
297
- "-i", &actual_file,
298
- "-vn",
299
- "-ar", "44100",
300
- "-ac", "2",
301
- "-b:a", "320k",
302
- &mp3_file,
303
- ])
304
- .stdout(Stdio::null())
305
- .stderr(Stdio::null())
306
- .output()
307
- .await;
308
-
309
- match convert_output {
310
- Ok(out) if out.status.success() => {
311
- if let Ok(mp3_data) = tokio::fs::read(&mp3_file).await {
312
- let _ = tokio::fs::remove_file(&mp3_file).await;
313
- (mp3_data, "audio/mpeg", "mp3")
314
- } else {
315
- // Если к��нвертация не удалась, отдаём оригинал
316
- (audio_data, content_type, orig_extension)
317
- }
318
- }
319
- _ => {
320
- // Если конвертация не удалась, отдаём оригинал
321
- (audio_data, content_type, orig_extension)
322
- }
323
- }
324
- } else {
325
- (audio_data, content_type, orig_extension)
326
- };
327
-
328
- // Определяем расширение для имени файла
329
- let extension = final_extension;
330
-
331
  // Удаляем временный файл
332
  let _ = tokio::fs::remove_file(&actual_file).await;
333
 
334
  // Формируем имя файла
335
  let filename = if let Some(ref title) = params.title {
336
  if let Some(ref performer) = params.performer {
337
- format!("{} - {}.{}", performer, title, extension)
338
  } else {
339
- format!("{}.{}", title, extension)
340
  }
341
  } else {
342
- format!("soundcloud_track.{}", extension)
343
  };
344
 
345
  let filename_safe = filename
@@ -348,12 +262,12 @@ pub async fn download(Query(params): Query<DownloadParams>) -> impl IntoResponse
348
  .take(200)
349
  .collect::<String>();
350
 
351
- tracing::info!("Sending SoundCloud file: {} ({} bytes, {})", filename_safe, final_data.len(), final_content_type);
352
 
353
  let mut response = axum::response::Response::builder()
354
  .status(200)
355
- .header("Content-Type", final_content_type)
356
- .header("Content-Length", final_data.len().to_string())
357
  .header("Content-Disposition", format!("inline; filename=\"{}\"", filename_safe))
358
  .header("Accept-Ranges", "bytes")
359
  .header("Access-Control-Allow-Origin", "*")
@@ -365,7 +279,7 @@ pub async fn download(Query(params): Query<DownloadParams>) -> impl IntoResponse
365
  }
366
 
367
  response
368
- .body(axum::body::Body::from(final_data))
369
  .unwrap()
370
  .into_response()
371
  }
 
133
 
134
  let quality = params.quality.as_deref().unwrap_or("best");
135
 
136
+ // Скачиваем ТОЛЬКО MP3 в максимальном доступном качестве
137
+ // SoundCloud обычно отдаёт 128kbps MP3 (стандарт) или 256kbps (Go+, редко)
138
+ let format_arg = "bestaudio[ext=mp3]/bestaudio";
 
 
 
 
139
 
140
  tracing::info!("Using format selector: {}", format_arg);
141
 
 
221
  let actual_file = if tokio::fs::metadata(&temp_file).await.is_ok() {
222
  temp_file.clone()
223
  } else {
224
+ // Ищем файл с расширением .mp3
225
+ let mp3_path = format!("{}.mp3", temp_file);
226
+ if tokio::fs::metadata(&mp3_path).await.is_ok() {
227
+ tracing::info!("Found downloaded MP3 file");
228
+ mp3_path
229
+ } else {
230
+ tracing::error!("Could not find downloaded MP3 file");
231
+ return (StatusCode::INTERNAL_SERVER_ERROR, "File not found").into_response();
 
 
 
 
 
 
 
 
232
  }
233
  };
234
 
 
242
  }
243
  };
244
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  // Удаляем временный файл
246
  let _ = tokio::fs::remove_file(&actual_file).await;
247
 
248
  // Формируем имя файла
249
  let filename = if let Some(ref title) = params.title {
250
  if let Some(ref performer) = params.performer {
251
+ format!("{} - {}.mp3", performer, title)
252
  } else {
253
+ format!("{}.mp3", title)
254
  }
255
  } else {
256
+ "soundcloud_track.mp3".to_string()
257
  };
258
 
259
  let filename_safe = filename
 
262
  .take(200)
263
  .collect::<String>();
264
 
265
+ tracing::info!("Sending SoundCloud file: {} ({} bytes, audio/mpeg)", filename_safe, audio_data.len());
266
 
267
  let mut response = axum::response::Response::builder()
268
  .status(200)
269
+ .header("Content-Type", "audio/mpeg")
270
+ .header("Content-Length", audio_data.len().to_string())
271
  .header("Content-Disposition", format!("inline; filename=\"{}\"", filename_safe))
272
  .header("Accept-Ranges", "bytes")
273
  .header("Access-Control-Allow-Origin", "*")
 
279
  }
280
 
281
  response
282
+ .body(axum::body::Body::from(audio_data))
283
  .unwrap()
284
  .into_response()
285
  }