html terminal
-rw-r--r--Cargo.toml3
-rw-r--r--src/bot/logic.rs102
-rw-r--r--src/bot/maps.rs2
-rw-r--r--src/bot/mod.rs2
-rw-r--r--src/bot/schematic.rs2
-rw-r--r--src/bot/usage.md10
6 files changed, 117 insertions, 4 deletions
diff --git a/Cargo.toml b/Cargo.toml
index c6aef00..9b461a6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -34,7 +34,7 @@ poise = "0.5.5"
anyhow = "1.0.75"
regex = { version = "1.8.4", features = ["std"], default-features = false }
minify-js = "0.5.6"
-itertools = "0.10.5"
+itertools = "0.11"
convert_case = "0.6.0"
parse_duration = "2.1.1"
serde = "1.0"
@@ -44,6 +44,7 @@ mindus = { version = "4", features = [], default-features = false }
oxipng = { git = "https://github.com/shssoichiro/oxipng", branch = "master", features = [], default-features = false }
strip-ansi-escapes = "0.2.0"
dashmap = "5.5.1"
+lemu = { features = ["diagnose", "__send__"], default-features = false, version = "0.2.0" }
[profile.release]
strip = true
diff --git a/src/bot/logic.rs b/src/bot/logic.rs
new file mode 100644
index 0000000..0aba81b
--- /dev/null
+++ b/src/bot/logic.rs
@@ -0,0 +1,102 @@
+use super::{Context, Result};
+use lemu::Executor;
+use poise::{serenity_prelude::AttachmentType, KeyValueArgs};
+use regex::Regex;
+use std::{borrow::Cow, sync::LazyLock};
+
+#[poise::command(prefix_command, category = "Misc", track_edits, rename = "eval")]
+pub async fn run(
+ ctx: Context<'_>,
+ #[description = "number of iterations"] kv: KeyValueArgs,
+ #[rest]
+ #[description = "Script"]
+ from: String,
+) -> Result<()> {
+ let _ = ctx.channel_id().start_typing(&ctx.serenity_context().http);
+
+ static RE: LazyLock<Regex> =
+ LazyLock::new(|| Regex::new(r#"```(arm|x86asm)?([^`]+)```"#).unwrap());
+
+ let lemu::Output {
+ output: Some(output),
+ displays,
+ ..
+ } = ({
+ let mat = RE
+ .captures(&from)
+ .ok_or(anyhow::anyhow!(r#"no code found (use \`\`\`arm...\`\`\`."#))?;
+ let script = mat.get(2).unwrap().as_str();
+ match Executor::with_output(vec![])
+ .display()
+ .limit_iterations(
+ kv.get("iters")
+ .map_or(1, |v| v.parse::<usize>().unwrap_or(1).clamp(1, 50)),
+ )
+ .limit_instructions(30000)
+ .program(&script)
+ {
+ Ok(mut v) => {
+ v.run();
+ v.output()
+ }
+ Err(e) => {
+ let s = format!("{}", e.diagnose(script)).replace("`", "\u{200b}`");
+ ctx.send(|c| {
+ c.allowed_mentions(|a| a.empty_parse())
+ .content(format!("```ansi\n{s}\n```"))
+ })
+ .await?;
+ return Ok(());
+ }
+ }
+ })
+ else {
+ unreachable!()
+ };
+ let displays: Box<[_; 1]> = displays.try_into().unwrap();
+ let [display] = *displays;
+
+ ctx.send(|c| {
+ let mut empty = true;
+ if !output.is_empty() {
+ c.content(format!(
+ "```\n{}\n```",
+ String::from_utf8_lossy(&output).replace('`', "\u{200b}`")
+ ));
+ empty = false;
+ }
+ if display.buffer().iter().any(|&n| n != 0) {
+ let p = oxipng::RawImage::new(
+ display.width(),
+ display.height(),
+ oxipng::ColorType::RGBA,
+ oxipng::BitDepth::Eight,
+ display.take_buffer(),
+ )
+ .unwrap();
+ let p = p
+ .create_optimized_png(&oxipng::Options {
+ filter: oxipng::indexset! { oxipng::RowFilter::None },
+ bit_depth_reduction: false,
+ color_type_reduction: false,
+ palette_reduction: false,
+ grayscale_reduction: false,
+ ..oxipng::Options::from_preset(0)
+ })
+ .unwrap();
+ c.attachment(AttachmentType::Bytes {
+ data: Cow::from(p),
+ filename: "display1.png".to_string(),
+ });
+ c.embed(|e| e.attachment("display1.png"));
+ empty = false;
+ }
+ if empty {
+ c.content("no output");
+ }
+ c.allowed_mentions(|a| a.empty_parse())
+ })
+ .await?;
+
+ Ok(())
+}
diff --git a/src/bot/maps.rs b/src/bot/maps.rs
index 55b32da..fa00f58 100644
--- a/src/bot/maps.rs
+++ b/src/bot/maps.rs
@@ -112,7 +112,7 @@ impl MapImage {
transparent_color: None,
},
BitDepth::Eight,
- i.buffer,
+ i.take_buffer(),
)
.unwrap();
*lock = i
diff --git a/src/bot/mod.rs b/src/bot/mod.rs
index 81d259d..1a79f2e 100644
--- a/src/bot/mod.rs
+++ b/src/bot/mod.rs
@@ -2,6 +2,7 @@ mod admin;
mod bans;
mod config;
mod js;
+mod logic;
pub mod maps;
mod player;
mod schematic;
@@ -234,6 +235,7 @@ impl Bot {
voting::list(),
start(),
end(),
+ logic::run(),
help(),
],
event_handler: |c, e, _, d| {
diff --git a/src/bot/schematic.rs b/src/bot/schematic.rs
index 2e1856c..2172927 100644
--- a/src/bot/schematic.rs
+++ b/src/bot/schematic.rs
@@ -89,7 +89,7 @@ pub fn to_png(s: &Schematic<'_>) -> Vec<u8> {
transparent_color: None,
},
BitDepth::Eight,
- p.buffer,
+ p.take_buffer(),
)
.unwrap();
p.create_optimized_png(&oxipng::Options {
diff --git a/src/bot/usage.md b/src/bot/usage.md
index 625ec42..a036e7e 100644
--- a/src/bot/usage.md
+++ b/src/bot/usage.md
@@ -1,4 +1,12 @@
## Usage
upload a file, with a msch extension (eg `24tpi_imp.msch`) and a schematic preview will be generated.
-you may instead upload a message containing a base64 encoded schematic. \ No newline at end of file
+you may instead upload a message containing a base64 encoded schematic.
+
+## Eval
+
+type```
+>eval ​`​`​`arm
+print "xd"
+​`​`​`
+```for the bot to evaluate your MLOG \ No newline at end of file