smol bot
Diffstat (limited to 'src/bot/map.rs')
-rw-r--r--src/bot/map.rs73
1 files changed, 73 insertions, 0 deletions
diff --git a/src/bot/map.rs b/src/bot/map.rs
new file mode 100644
index 0000000..43165f4
--- /dev/null
+++ b/src/bot/map.rs
@@ -0,0 +1,73 @@
+use anyhow::Result;
+use mindus::{data::map::ReadError, *};
+use poise::serenity_prelude::*;
+use std::borrow::Cow;
+use std::time::Instant;
+
+use super::{strip_colors, SUCCESS};
+
+pub async fn with(msg: &Message, c: &serenity::client::Context) -> Result<()> {
+ let auth = msg.author_nick(c).await.unwrap_or(msg.author.name.clone());
+ for a in &msg.attachments {
+ if a.filename.ends_with("msav") {
+ let s = a.download().await?;
+ let then = Instant::now();
+
+ macro_rules! dang {
+ ($fmt:literal $(, $args:expr)+) => {{
+ msg.reply_ping(c, format!($fmt $(, $args)+)).await?;
+ return Ok(());
+ }};
+ }
+ // could ignore, but i think if you have a msav, you dont want to ignore failures.
+ let m = match Map::deserialize(&mut mindus::data::DataRead::new(&s)) {
+ Ok(m) => m,
+ Err(ReadError::Decompress(_) | ReadError::Header(_)) => {
+ dang!("`{}` is not a map.", a.filename)
+ }
+ Err(ReadError::NoSuchBlock(b)) => dang!(
+ "couldnt find block `{b}`. error originates from `{}`",
+ a.filename
+ ),
+ Err(ReadError::Version(v)) => {
+ dang!(
+ "unsupported version: `{v}`. supported versions: `7`. error originates from `{}`",
+ a.filename
+ )
+ }
+ Err(ReadError::Read(r)) => {
+ dang!(
+ "failed to read map. error: `{r}`. originates from `{}`",
+ a.filename
+ )
+ }
+ Err(ReadError::ReadState(r)) => {
+ dang!(
+ "failed to read dyn data in map. error: `{r}`. originates from `{}`",
+ a.filename
+ )
+ }
+ };
+ let t = msg.channel_id.start_typing(&c.http)?;
+ let deser_took = then.elapsed();
+ let name = strip_colors(m.tags.get("mapname").unwrap());
+ let (render_took, compression_took, total, png) =
+ tokio::task::spawn_blocking(move || {
+ let render_took = Instant::now();
+ let i = m.render();
+ let render_took = render_took.elapsed();
+ let compression_took = Instant::now();
+ let png = super::png(i);
+ let compression_took = compression_took.elapsed();
+ let total = then.elapsed();
+ (render_took, compression_took, total, png)
+ })
+ .await?;
+ t.stop();
+ msg.channel_id.send_message(c, |m| { m.add_file(AttachmentType::Bytes { data: Cow::from(png), filename: "map.png".to_string() }).embed(|e| e.title(&name).footer(|f| f.text(format!("render of {name} (requested by {auth}) took: {:.3}s (deser: {}ms, render: {:.3}s, compression: {:.3}s)", total.as_secs_f32(), deser_took.as_millis(), render_took.as_secs_f32(), compression_took.as_secs_f32()))).attachment("map.png").color(SUCCESS)) }).await?;
+ return Ok(());
+ }
+ }
+
+ Ok(())
+}