html terminal
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/bot/mod.rs | 52 | ||||
| -rw-r--r-- | src/bot/schematic.rs | 31 | ||||
| -rw-r--r-- | src/process.rs | 6 |
4 files changed, 60 insertions, 30 deletions
@@ -42,6 +42,7 @@ btparse = "0.1.1" mindus = { version = "3", features = [], default-features = false } image = { version = "0.24.6", features = ["png"], default-features = false } oxipng = { git = "https://github.com/shssoichiro/oxipng", branch = "master", features = [], default-features = false } +strip-ansi-escapes = "0.1.2" [profile.release] strip = true diff --git a/src/bot/mod.rs b/src/bot/mod.rs index 3809c4e..b56c23c 100644 --- a/src/bot/mod.rs +++ b/src/bot/mod.rs @@ -14,8 +14,8 @@ use maps::Maps; use serenity::http::Http; use serenity::prelude::*; +use std::fmt::Write; use std::fs::read_to_string; -use std::str::FromStr; use std::sync::{ atomic::{AtomicU8, Ordering}, Arc, OnceLock, @@ -121,28 +121,38 @@ async fn on_error(error: poise::FrameworkError<'_, Data, anyhow::Error>) { use poise::FrameworkError::Command; match error { Command { error, ctx } => { - ctx.say(format!("e: `{error}`")).await.unwrap(); - if let Ok(n) = std::env::var("RUST_LIB_BACKTRACE") - && let Ok(n) = u8::from_str(&n) - && n == 1 { - let mut parsed = btparse::deserialize(dbg!(error.backtrace())).unwrap(); - let mut s = vec![]; - for frame in &mut parsed.frames { - if let Some(line) = frame.line.take() - && (frame.function.contains("panel") - || frame.function.contains("poise") - || frame.function.contains("serenity")) - { - s.push(format!("l{}@{}", line, frame.function)); - } - + let mut msg; + { + let mut chain = error.chain(); + msg = format!("e: `{}`", chain.next().unwrap()); + for mut source in chain { + write!(msg, "from: `{source}`").unwrap(); + loop { + let Some(next) = source.source() else { break }; + write!(msg, "from: `{next}`").unwrap(); + source = next; } - s.truncate(15); - ctx.say(format!("trace: ```rs\n{}\n```", s.join("\n"))) - .await - .unwrap(); - + } } + let bt = error.backtrace(); + if bt.status() == std::backtrace::BacktraceStatus::Captured { + let parsed = btparse::deserialize(dbg!(error.backtrace())).unwrap(); + let mut s = vec![]; + for frame in parsed.frames { + if let Some(line) = frame.line + && (frame.function.contains("panel") + || frame.function.contains("poise") + || frame.function.contains("serenity") + || frame.function.contains("mindus") + || frame.function.contains("image")) + { + s.push(format!("l{}@{}", line, frame.function)); + } + } + s.truncate(15); + write!(msg, "trace: ```rs\n{}\n```", s.join("\n")).unwrap(); + } + ctx.say(msg).await.unwrap(); } err => poise::builtins::on_error(err).await.unwrap(), } diff --git a/src/bot/schematic.rs b/src/bot/schematic.rs index 2d618d8..2499ca9 100644 --- a/src/bot/schematic.rs +++ b/src/bot/schematic.rs @@ -1,8 +1,8 @@ use super::{strip_colors, Context, SUCCESS}; use anyhow::{anyhow, Result}; -use image::{codecs::png::PngEncoder, ImageEncoder}; use mindus::data::{DataRead, DataWrite, Serializer}; use mindus::*; +use oxipng::*; use poise::serenity_prelude::*; use regex::Regex; use std::borrow::Cow; @@ -34,7 +34,8 @@ pub async fn context_draw(ctx: Context<'_>, msg: Message) -> Result<()> { prefix_command, slash_command, category = "Info", - rename = "draw_schematic" + rename = "draw_schematic", + track_edits )] /// draw schematic. pub async fn draw(ctx: Context<'_>, schematic: String) -> Result<()> { @@ -43,10 +44,28 @@ pub async fn draw(ctx: Context<'_>, schematic: String) -> Result<()> { } async fn send(ctx: &Context<'_>, s: &Schematic<'_>, send_schematic: bool) -> Result<()> { - let mut b = vec![]; - let p = unsafe { s.render() }; - PngEncoder::new(&mut b).write_image(&p, p.width(), p.height(), image::ColorType::Rgba8)?; let n = strip_colors(s.tags.get("name").unwrap()); + let p = unsafe { s.render() }; + let p = RawImage::new( + p.width(), + p.height(), + ColorType::RGB { + transparent_color: None, + }, + BitDepth::Eight, + p.into_vec(), + ) + .unwrap(); + let p = p + .create_optimized_png(&oxipng::Options { + filter: indexset! { RowFilter::None }, + bit_depth_reduction: false, + color_type_reduction: false, + palette_reduction: false, + grayscale_reduction: false, + ..oxipng::Options::from_preset(0) + }) + .unwrap(); poise::send_reply(*ctx, |m| { if send_schematic { let mut out = DataWrite::default(); @@ -57,7 +76,7 @@ async fn send(ctx: &Context<'_>, s: &Schematic<'_>, send_schematic: bool) -> Res }); } m.attachment(AttachmentType::Bytes { - data: Cow::Owned(b), + data: Cow::Owned(p), filename: "image.png".to_string(), }) .embed(|e| { diff --git a/src/process.rs b/src/process.rs index 4639531..c13332c 100644 --- a/src/process.rs +++ b/src/process.rs @@ -51,7 +51,7 @@ impl Process { }, Ok(mut s) => { input!("{s}"); - s += "\n"; + s.push_str("\n"); self.inner.write_all(s.as_bytes()).await.unwrap(); self.inner.flush().await.unwrap(); } @@ -59,10 +59,10 @@ impl Process { let string = { let n = tokio::select! { - n = {self.inner.read(&mut stdout)} => n.unwrap(), + n = self.inner.read(&mut stdout) => n.unwrap(), _ = sleep(Duration::from_millis(500)) => continue, }; - String::from_utf8_lossy(&stdout[..n]).into_owned() + String::from_utf8_lossy(&strip_ansi_escapes::strip(&stdout[..n])).into_owned() }; for line in string.lines() { output!("{line}"); |