support audio/voice/video/video_note media types and improve subprocess error diagnostics

This commit is contained in:
Fam Zheng
2026-04-09 09:15:46 +01:00
parent ca2a48c081
commit 765ff2c51d

View File

@@ -258,6 +258,40 @@ async fn handle_inner(
} }
} }
if let Some(audio) = msg.audio() {
let fallback = format!("audio_{}.ogg", Local::now().format("%H%M%S"));
let name = audio.file_name.as_deref().unwrap_or(&fallback);
match download_tg_file(bot, &audio.file.id, name).await {
Ok(p) => uploaded.push(p),
Err(e) => download_errors.push(format!("audio: {e:#}")),
}
}
if let Some(voice) = msg.voice() {
let name = format!("voice_{}.ogg", Local::now().format("%H%M%S"));
match download_tg_file(bot, &voice.file.id, &name).await {
Ok(p) => uploaded.push(p),
Err(e) => download_errors.push(format!("voice: {e:#}")),
}
}
if let Some(video) = msg.video() {
let fallback = format!("video_{}.mp4", Local::now().format("%H%M%S"));
let name = video.file_name.as_deref().unwrap_or(&fallback);
match download_tg_file(bot, &video.file.id, name).await {
Ok(p) => uploaded.push(p),
Err(e) => download_errors.push(format!("video: {e:#}")),
}
}
if let Some(vn) = msg.video_note() {
let name = format!("videonote_{}.mp4", Local::now().format("%H%M%S"));
match download_tg_file(bot, &vn.file.id, &name).await {
Ok(p) => uploaded.push(p),
Err(e) => download_errors.push(format!("video_note: {e:#}")),
}
}
if text.is_empty() && uploaded.is_empty() { if text.is_empty() && uploaded.is_empty() {
if !download_errors.is_empty() { if !download_errors.is_empty() {
let err_msg = format!("[文件下载失败]\n{}", download_errors.join("\n")); let err_msg = format!("[文件下载失败]\n{}", download_errors.join("\n"));
@@ -516,16 +550,38 @@ async fn run_claude_streaming(
} }
} }
let _ = child.wait().await; // read stderr before waiting (in case child already exited)
let stderr_handle = child.stderr.take();
let status = child.wait().await;
if is_error { // collect stderr for diagnostics
// clean up streaming message if we sent one let stderr_text = if let Some(mut se) = stderr_handle {
let mut buf = String::new();
let _ = tokio::io::AsyncReadExt::read_to_string(&mut se, &mut buf).await;
buf
} else {
String::new()
};
// determine error: explicit is_error from stream, or non-zero exit with no result
let has_error = is_error
|| (final_result.is_empty()
&& status.as_ref().map(|s| !s.success()).unwrap_or(true));
if has_error {
let err_detail = if !final_result.is_empty() {
final_result.clone()
} else if !stderr_text.is_empty() {
stderr_text.trim().to_string()
} else {
format!("claude exited: {:?}", status)
};
if let Some(id) = msg_id { if let Some(id) = msg_id {
let _ = bot let _ = bot
.edit_message_text(chat_id, id, format!("[error] {final_result}")) .edit_message_text(chat_id, id, format!("[error] {err_detail}"))
.await; .await;
} }
anyhow::bail!("{final_result}"); anyhow::bail!("{err_detail}");
} }
if final_result.is_empty() { if final_result.is_empty() {