recycleactor commited on
Commit
2bfd3a5
·
verified ·
1 Parent(s): e85ab36

Upload main.rs

Browse files
Files changed (1) hide show
  1. src/main.rs +69 -28
src/main.rs CHANGED
@@ -47,7 +47,6 @@ struct CdnCacheEntry {
47
  expires_at: std::time::Instant,
48
  }
49
 
50
- #[derive(Clone)]
51
  struct AppState {
52
  api: Arc<Mutex<APIClient>>,
53
  api_by_arl: Arc<RwLock<HashMap<String, Arc<Mutex<APIClient>>>>>,
@@ -943,34 +942,76 @@ async fn send_audio(
943
  let mime = if ext == "flac" { "audio/flac" } else { "audio/mpeg" };
944
  let filename = format!("track_{}.{}", q.id, ext);
945
 
946
- // Загружаем в Telegram через multipart
 
 
 
947
  let tg_url = format!("https://api.telegram.org/bot{}/sendAudio", bot_token);
948
- let part = reqwest::multipart::Part::bytes(dec)
949
- .file_name(filename)
950
- .mime_str(mime)
951
- .unwrap();
952
- let mut form = reqwest::multipart::Form::new()
953
- .text("chat_id", q.chat_id.clone())
954
- .part("audio", part);
955
- if let Some(ref t) = q.title { form = form.text("title", t.clone()); }
956
- if let Some(ref p) = q.performer { form = form.text("performer", p.clone()); }
957
- if let Some(d) = q.duration { form = form.text("duration", d.to_string()); }
958
-
959
- let tg_resp = match http.post(&tg_url).multipart(form).send().await {
960
- Ok(r) => r,
961
- Err(e) => return json_error(StatusCode::BAD_GATEWAY, format!("Telegram upload: {}", e)),
962
- };
963
-
964
- let tg_json: serde_json::Value = match tg_resp.json().await {
965
- Ok(j) => j,
966
- Err(e) => return json_error(StatusCode::BAD_GATEWAY, format!("Telegram parse: {}", e)),
967
- };
968
-
969
- if tg_json.get("ok").and_then(|v| v.as_bool()) != Some(true) {
970
- let desc = tg_json.get("description").and_then(|v| v.as_str()).unwrap_or("unknown");
971
- tracing::error!("Telegram sendAudio error: {}", desc);
972
- return json_error(StatusCode::BAD_GATEWAY, format!("Telegram: {}", desc));
973
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
974
 
975
  let file_id = tg_json.pointer("/result/audio/file_id")
976
  .and_then(|v| v.as_str())
 
47
  expires_at: std::time::Instant,
48
  }
49
 
 
50
  struct AppState {
51
  api: Arc<Mutex<APIClient>>,
52
  api_by_arl: Arc<RwLock<HashMap<String, Arc<Mutex<APIClient>>>>>,
 
942
  let mime = if ext == "flac" { "audio/flac" } else { "audio/mpeg" };
943
  let filename = format!("track_{}.{}", q.id, ext);
944
 
945
+ // Загружаем в Telegram через отдельный клиент.
946
+ // Для api.telegram.org в некоторых средах HF прямое соединение с no_proxy()
947
+ // падает на TLS handshake, поэтому здесь даем reqwest использовать env proxy
948
+ // и принудительно уходим на HTTP/1.1 с короткими ретраями.
949
  let tg_url = format!("https://api.telegram.org/bot{}/sendAudio", bot_token);
950
+ let tg_http = reqwest::Client::builder()
951
+ .http1_only()
952
+ .connect_timeout(Duration::from_secs(20))
953
+ .timeout(Duration::from_secs(180))
954
+ .tcp_keepalive(Duration::from_secs(30))
955
+ .build()
956
+ .unwrap();
957
+
958
+ let mut tg_json: Option<serde_json::Value> = None;
959
+ let mut last_tg_err: Option<String> = None;
960
+
961
+ for attempt in 1..=3u8 {
962
+ let part = reqwest::multipart::Part::bytes(dec.clone())
963
+ .file_name(filename.clone())
964
+ .mime_str(mime)
965
+ .unwrap();
966
+ let mut form = reqwest::multipart::Form::new()
967
+ .text("chat_id", q.chat_id.clone())
968
+ .part("audio", part);
969
+ if let Some(ref t) = q.title { form = form.text("title", t.clone()); }
970
+ if let Some(ref p) = q.performer { form = form.text("performer", p.clone()); }
971
+ if let Some(d) = q.duration { form = form.text("duration", d.to_string()); }
972
+
973
+ match tg_http.post(&tg_url).multipart(form).send().await {
974
+ Ok(resp) => {
975
+ let status = resp.status();
976
+ match resp.json::<serde_json::Value>().await {
977
+ Ok(j) => {
978
+ if status.is_success() && j.get("ok").and_then(|v| v.as_bool()) == Some(true) {
979
+ tg_json = Some(j);
980
+ break;
981
+ }
982
+ let desc = j
983
+ .get("description")
984
+ .and_then(|v| v.as_str())
985
+ .unwrap_or("unknown")
986
+ .to_string();
987
+ tracing::warn!("Telegram sendAudio attempt {} failed: status={} desc={}", attempt, status, desc);
988
+ last_tg_err = Some(format!("Telegram {}: {}", status, desc));
989
+ }
990
+ Err(e) => {
991
+ tracing::warn!("Telegram sendAudio attempt {} parse failed: {}", attempt, e);
992
+ last_tg_err = Some(format!("Telegram parse: {}", e));
993
+ }
994
+ }
995
+ }
996
+ Err(e) => {
997
+ tracing::warn!("Telegram sendAudio attempt {} upload failed: {}", attempt, e);
998
+ last_tg_err = Some(format!("Telegram upload: {}", e));
999
+ }
1000
+ }
1001
+
1002
+ if attempt < 3 {
1003
+ tokio::time::sleep(Duration::from_secs((attempt as u64) * 2)).await;
1004
+ }
1005
+ }
1006
+
1007
+ let tg_json = match tg_json {
1008
+ Some(j) => j,
1009
+ None => {
1010
+ let err = last_tg_err.unwrap_or_else(|| "Telegram upload failed".to_string());
1011
+ tracing::error!("Telegram sendAudio final failure: {}", err);
1012
+ return json_error(StatusCode::BAD_GATEWAY, err);
1013
+ }
1014
+ };
1015
 
1016
  let file_id = tg_json.pointer("/result/audio/file_id")
1017
  .and_then(|v| v.as_str())