diff --git a/src/main.rs b/src/main.rs index c6653f5..a8a9b51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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 !download_errors.is_empty() { 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 { - // clean up streaming message if we sent one + // collect stderr for diagnostics + 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 { let _ = bot - .edit_message_text(chat_id, id, format!("[error] {final_result}")) + .edit_message_text(chat_id, id, format!("[error] {err_detail}")) .await; } - anyhow::bail!("{final_result}"); + anyhow::bail!("{err_detail}"); } if final_result.is_empty() {