diff options
| author | salmonik <salmonik@tuta.io> | 2026-11-04 01:11:50 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-11-04 01:11:50 +0100 |
| commit | fd93334a21907f959018e1b1f5df747a98d186c8 (patch) | |
| tree | 259e595a570b42a5ea082f596e1cb97e5011cfba | |
| parent | http: add connect and request timeouts (diff) | |
| download | senator-sperma-fd93334a21907f959018e1b1f5df747a98d186c8.tar.gz senator-sperma-fd93334a21907f959018e1b1f5df747a98d186c8.zip | |
processes: add timeouts and keep decoding off the runtime
| -rw-r--r-- | src/commands/math.rs | 19 | ||||
| -rw-r--r-- | src/commands/qr.rs | 12 | ||||
| -rw-r--r-- | src/commands/utilities.rs | 15 | ||||
| -rw-r--r-- | src/voice/mod.rs | 36 |
4 files changed, 53 insertions, 29 deletions
diff --git a/src/commands/math.rs b/src/commands/math.rs index 43a7de8..25ddaab 100644 --- a/src/commands/math.rs +++ b/src/commands/math.rs | |||
| @@ -57,11 +57,20 @@ pub async fn math( | |||
| 57 | return Ok(()); | 57 | return Ok(()); |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | let output = tokio::process::Command::new("qalc") | 60 | let output = match tokio::time::timeout( |
| 61 | .arg(&equation) | 61 | std::time::Duration::from_secs(5), |
| 62 | .output() | 62 | tokio::process::Command::new("qalc") |
| 63 | .await | 63 | .arg(&equation) |
| 64 | .map_err(|e| Error::Custom(lang::fmt_math_qalc_err(&e)))?; | 64 | .output(), |
| 65 | ) | ||
| 66 | .await | ||
| 67 | { | ||
| 68 | Ok(result) => result.map_err(|e| Error::Custom(lang::fmt_math_qalc_err(&e)))?, | ||
| 69 | Err(_) => { | ||
| 70 | ctx.say(lang::L_MATH_NO_RESULT).await?; | ||
| 71 | return Ok(()); | ||
| 72 | } | ||
| 73 | }; | ||
| 65 | 74 | ||
| 66 | let result = String::from_utf8_lossy(&output.stdout).trim().to_string(); | 75 | let result = String::from_utf8_lossy(&output.stdout).trim().to_string(); |
| 67 | if result.is_empty() { | 76 | if result.is_empty() { |
diff --git a/src/commands/qr.rs b/src/commands/qr.rs index 26232ee..c0b8af0 100644 --- a/src/commands/qr.rs +++ b/src/commands/qr.rs | |||
| @@ -61,10 +61,14 @@ pub async fn dekodowanie( | |||
| 61 | .await? | 61 | .await? |
| 62 | .bytes() | 62 | .bytes() |
| 63 | .await?; | 63 | .await?; |
| 64 | let img = image::load_from_memory(&img_data)?; | 64 | // Decoding is CPU-heavy: keep it off the async runtime. |
| 65 | let gray = img.to_luma8(); | 65 | let img_data = img_data.to_vec(); |
| 66 | 66 | let decoded = tokio::task::spawn_blocking(move || { | |
| 67 | let decoded = decode_qr_simple(&gray); | 67 | let img = image::load_from_memory(&img_data).ok()?; |
| 68 | let gray = img.to_luma8(); | ||
| 69 | decode_qr_simple(&gray) | ||
| 70 | }) | ||
| 71 | .await?; | ||
| 68 | match decoded { | 72 | match decoded { |
| 69 | Some(text) => { | 73 | Some(text) => { |
| 70 | ctx.say(lang::fmt_qr_decoded(&text)).await?; | 74 | ctx.say(lang::fmt_qr_decoded(&text)).await?; |
diff --git a/src/commands/utilities.rs b/src/commands/utilities.rs index bf93491..c26fd0e 100644 --- a/src/commands/utilities.rs +++ b/src/commands/utilities.rs | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | use std::time::Duration; | ||
| 2 | |||
| 1 | use poise::serenity_prelude as serenity; | 3 | use poise::serenity_prelude as serenity; |
| 2 | use tracing::warn; | 4 | use tracing::warn; |
| 3 | 5 | ||
| @@ -524,10 +526,15 @@ async fn run_download( | |||
| 524 | } | 526 | } |
| 525 | cmd.arg("--").arg(sanitize_yt_url(url)); | 527 | cmd.arg("--").arg(sanitize_yt_url(url)); |
| 526 | 528 | ||
| 527 | let output = cmd | 529 | let output = match tokio::time::timeout(Duration::from_secs(600), cmd.output()).await { |
| 528 | .output() | 530 | Ok(result) => result.map_err(|e| Error::Custom(lang::fmt_ytdlp_err(&e)))?, |
| 529 | .await | 531 | Err(_) => { |
| 530 | .map_err(|e| Error::Custom(lang::fmt_ytdlp_err(&e)))?; | 532 | let _ = tokio::fs::remove_dir_all(&dl_dir).await; |
| 533 | ctx.say(lang::fmt_download_failed("download timed out after 10 minutes")) | ||
| 534 | .await?; | ||
| 535 | return Ok(()); | ||
| 536 | } | ||
| 537 | }; | ||
| 531 | if !output.status.success() { | 538 | if !output.status.success() { |
| 532 | let stderr = String::from_utf8_lossy(&output.stderr); | 539 | let stderr = String::from_utf8_lossy(&output.stderr); |
| 533 | // Keep the full yt-dlp trace in the logs; the user only sees the | 540 | // Keep the full yt-dlp trace in the logs; the user only sees the |
diff --git a/src/voice/mod.rs b/src/voice/mod.rs index a6baa64..5043508 100644 --- a/src/voice/mod.rs +++ b/src/voice/mod.rs | |||
| @@ -237,22 +237,26 @@ fn decode_stream(mss: MediaSourceStream) -> Result<songbird::input::Input> { | |||
| 237 | /// Download audio via yt-dlp, collect stdout into memory, return the raw bytes. | 237 | /// Download audio via yt-dlp, collect stdout into memory, return the raw bytes. |
| 238 | /// Works for both finite media and live streams (yt-dlp handles the difference). | 238 | /// Works for both finite media and live streams (yt-dlp handles the difference). |
| 239 | pub async fn ytdlp_download(url: &str) -> Result<Vec<u8>> { | 239 | pub async fn ytdlp_download(url: &str) -> Result<Vec<u8>> { |
| 240 | let output = tokio::process::Command::new("yt-dlp") | 240 | let output = tokio::time::timeout( |
| 241 | .args([ | 241 | Duration::from_secs(600), |
| 242 | "--ignore-config", | 242 | tokio::process::Command::new("yt-dlp") |
| 243 | "-f", | 243 | .args([ |
| 244 | "bestaudio", | 244 | "--ignore-config", |
| 245 | "-o", | 245 | "-f", |
| 246 | "-", | 246 | "bestaudio", |
| 247 | "--no-playlist", | 247 | "-o", |
| 248 | "--", | 248 | "-", |
| 249 | url, | 249 | "--no-playlist", |
| 250 | ]) | 250 | "--", |
| 251 | .stdout(std::process::Stdio::piped()) | 251 | url, |
| 252 | .stderr(std::process::Stdio::piped()) | 252 | ]) |
| 253 | .output() | 253 | .stdout(std::process::Stdio::piped()) |
| 254 | .await | 254 | .stderr(std::process::Stdio::piped()) |
| 255 | .map_err(|e| Error::Custom(lang::fmt_voice_ytdlp_launch(&e)))?; | 255 | .output(), |
| 256 | ) | ||
| 257 | .await | ||
| 258 | .map_err(|_| Error::Custom("yt-dlp timed out after 10 minutes".into()))? | ||
| 259 | .map_err(|e| Error::Custom(lang::fmt_voice_ytdlp_launch(&e)))?; | ||
| 256 | 260 | ||
| 257 | if !output.status.success() { | 261 | if !output.status.success() { |
| 258 | let stderr = String::from_utf8_lossy(&output.stderr); | 262 | let stderr = String::from_utf8_lossy(&output.stderr); |
