support audio/voice/video/video_note media types and improve subprocess error diagnostics
This commit is contained in:
66
src/main.rs
66
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 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() {
|
||||||
|
|||||||
Reference in New Issue
Block a user