Spaces:
Running
Running
Upload main.rs
Browse files- src/main.rs +30 -14
src/main.rs
CHANGED
|
@@ -1083,25 +1083,41 @@ async fn send_audio(
|
|
| 1083 |
// /send_audio платил полный DNS+TLS handshake с нуля, и на "холодных"
|
| 1084 |
// контейнерах это не укладывалось в connect_timeout (лог показывал
|
| 1085 |
// ровно 10.0с — таймаут коннекта, а не медленную передачу данных).
|
| 1086 |
-
let
|
|
|
|
|
|
|
| 1087 |
let tg_http = state.tg_http.clone();
|
| 1088 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1089 |
let mut tg_json: Option<serde_json::Value> = None;
|
| 1090 |
let mut last_tg_err: Option<String> = None;
|
| 1091 |
|
| 1092 |
for attempt in 1..=3u8 {
|
| 1093 |
-
tracing::info!("Telegram
|
| 1094 |
-
|
| 1095 |
let part = reqwest::multipart::Part::bytes(dec.clone())
|
| 1096 |
.file_name(filename.clone())
|
| 1097 |
.mime_str(mime)
|
| 1098 |
.unwrap();
|
| 1099 |
let mut form = reqwest::multipart::Form::new()
|
| 1100 |
-
.text("chat_id", q.chat_id.clone())
|
| 1101 |
-
|
| 1102 |
-
|
| 1103 |
-
|
| 1104 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1105 |
|
| 1106 |
match tg_http.post(&tg_url).multipart(form).send().await {
|
| 1107 |
Ok(resp) => {
|
|
@@ -1110,7 +1126,7 @@ async fn send_audio(
|
|
| 1110 |
Ok(j) => {
|
| 1111 |
if status.is_success() && j.get("ok").and_then(|v| v.as_bool()) == Some(true) {
|
| 1112 |
tg_json = Some(j);
|
| 1113 |
-
tracing::info!("Telegram
|
| 1114 |
break;
|
| 1115 |
}
|
| 1116 |
let desc = j
|
|
@@ -1118,17 +1134,17 @@ async fn send_audio(
|
|
| 1118 |
.and_then(|v| v.as_str())
|
| 1119 |
.unwrap_or("unknown")
|
| 1120 |
.to_string();
|
| 1121 |
-
tracing::warn!("Telegram
|
| 1122 |
last_tg_err = Some(format!("Telegram {}: {}", status, desc));
|
| 1123 |
}
|
| 1124 |
Err(e) => {
|
| 1125 |
-
tracing::warn!("Telegram
|
| 1126 |
last_tg_err = Some(format!("Telegram parse: {}", e));
|
| 1127 |
}
|
| 1128 |
}
|
| 1129 |
}
|
| 1130 |
Err(e) => {
|
| 1131 |
-
tracing::warn!("Telegram
|
| 1132 |
last_tg_err = Some(format!("Telegram upload: {}", e));
|
| 1133 |
}
|
| 1134 |
}
|
|
@@ -1142,12 +1158,12 @@ async fn send_audio(
|
|
| 1142 |
Some(j) => j,
|
| 1143 |
None => {
|
| 1144 |
let err = last_tg_err.unwrap_or_else(|| "Telegram upload failed".to_string());
|
| 1145 |
-
tracing::error!("Telegram
|
| 1146 |
return json_error(StatusCode::BAD_GATEWAY, err);
|
| 1147 |
}
|
| 1148 |
};
|
| 1149 |
|
| 1150 |
-
let file_id = tg_json.pointer("/result/audio/file_id")
|
| 1151 |
.and_then(|v| v.as_str())
|
| 1152 |
.unwrap_or("")
|
| 1153 |
.to_string();
|
|
|
|
| 1083 |
// /send_audio платил полный DNS+TLS handshake с нуля, и на "холодных"
|
| 1084 |
// контейнерах это не укладывалось в connect_timeout (лог показывал
|
| 1085 |
// ровно 10.0с — таймаут коннекта, а не медленную передачу данных).
|
| 1086 |
+
let is_flac = ext == "flac";
|
| 1087 |
+
let tg_method = if is_flac { "sendDocument" } else { "sendAudio" };
|
| 1088 |
+
let tg_url = format!("https://api.telegram.org/bot{}/{}", bot_token, tg_method);
|
| 1089 |
let tg_http = state.tg_http.clone();
|
| 1090 |
|
| 1091 |
+
// sendDocument не знает полей title/performer/duration (это специфика sendAudio) —
|
| 1092 |
+
// для FLAC собираем из них caption, чтобы информация не терялась.
|
| 1093 |
+
let caption = match (&q.performer, &q.title) {
|
| 1094 |
+
(Some(p), Some(t)) => Some(format!("{} — {}", p, t)),
|
| 1095 |
+
(None, Some(t)) => Some(t.clone()),
|
| 1096 |
+
(Some(p), None) => Some(p.clone()),
|
| 1097 |
+
(None, None) => None,
|
| 1098 |
+
};
|
| 1099 |
+
|
| 1100 |
let mut tg_json: Option<serde_json::Value> = None;
|
| 1101 |
let mut last_tg_err: Option<String> = None;
|
| 1102 |
|
| 1103 |
for attempt in 1..=3u8 {
|
| 1104 |
+
tracing::info!("Telegram {} attempt {} for track {} ({} bytes)", tg_method, attempt, q.id, dec.len());
|
| 1105 |
+
|
| 1106 |
let part = reqwest::multipart::Part::bytes(dec.clone())
|
| 1107 |
.file_name(filename.clone())
|
| 1108 |
.mime_str(mime)
|
| 1109 |
.unwrap();
|
| 1110 |
let mut form = reqwest::multipart::Form::new()
|
| 1111 |
+
.text("chat_id", q.chat_id.clone());
|
| 1112 |
+
if is_flac {
|
| 1113 |
+
form = form.part("document", part);
|
| 1114 |
+
if let Some(ref c) = caption { form = form.text("caption", c.clone()); }
|
| 1115 |
+
} else {
|
| 1116 |
+
form = form.part("audio", part);
|
| 1117 |
+
if let Some(ref t) = q.title { form = form.text("title", t.clone()); }
|
| 1118 |
+
if let Some(ref p) = q.performer { form = form.text("performer", p.clone()); }
|
| 1119 |
+
if let Some(d) = q.duration { form = form.text("duration", d.to_string()); }
|
| 1120 |
+
}
|
| 1121 |
|
| 1122 |
match tg_http.post(&tg_url).multipart(form).send().await {
|
| 1123 |
Ok(resp) => {
|
|
|
|
| 1126 |
Ok(j) => {
|
| 1127 |
if status.is_success() && j.get("ok").and_then(|v| v.as_bool()) == Some(true) {
|
| 1128 |
tg_json = Some(j);
|
| 1129 |
+
tracing::info!("Telegram {} success on attempt {}", tg_method, attempt);
|
| 1130 |
break;
|
| 1131 |
}
|
| 1132 |
let desc = j
|
|
|
|
| 1134 |
.and_then(|v| v.as_str())
|
| 1135 |
.unwrap_or("unknown")
|
| 1136 |
.to_string();
|
| 1137 |
+
tracing::warn!("Telegram {} attempt {} failed: status={} desc={}", tg_method, attempt, status, desc);
|
| 1138 |
last_tg_err = Some(format!("Telegram {}: {}", status, desc));
|
| 1139 |
}
|
| 1140 |
Err(e) => {
|
| 1141 |
+
tracing::warn!("Telegram {} attempt {} parse failed: {}", tg_method, attempt, e);
|
| 1142 |
last_tg_err = Some(format!("Telegram parse: {}", e));
|
| 1143 |
}
|
| 1144 |
}
|
| 1145 |
}
|
| 1146 |
Err(e) => {
|
| 1147 |
+
tracing::warn!("Telegram {} attempt {} upload failed: {}", tg_method, attempt, e);
|
| 1148 |
last_tg_err = Some(format!("Telegram upload: {}", e));
|
| 1149 |
}
|
| 1150 |
}
|
|
|
|
| 1158 |
Some(j) => j,
|
| 1159 |
None => {
|
| 1160 |
let err = last_tg_err.unwrap_or_else(|| "Telegram upload failed".to_string());
|
| 1161 |
+
tracing::error!("Telegram {} final failure: {}", tg_method, err);
|
| 1162 |
return json_error(StatusCode::BAD_GATEWAY, err);
|
| 1163 |
}
|
| 1164 |
};
|
| 1165 |
|
| 1166 |
+
let file_id = tg_json.pointer(if is_flac { "/result/document/file_id" } else { "/result/audio/file_id" })
|
| 1167 |
.and_then(|v| v.as_str())
|
| 1168 |
.unwrap_or("")
|
| 1169 |
.to_string();
|