diff --git a/src/commands.rs b/src/commands.rs index 6586894..aa7261c 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1,4 +1,7 @@ -use crate::State; +use crate::{ + State, + scripting::{eval, exec, reload}, +}; use azalea::{ GameProfileComponent, brigadier::prelude::*, chat::ChatPacket, entity::metadata::Player, prelude::*, @@ -37,42 +40,16 @@ impl CommandSource { pub fn register(commands: &mut CommandDispatcher>) { commands.register(literal("reload").executes(|ctx: &Ctx| { let source = ctx.source.lock(); - let lua = source.state.lua.lock(); - let config_path = match lua.globals().get::("config_path") { - Ok(path) => path, - Err(error) => { - source.reply(&format!( - "failed to get config_path from lua globals: {error:?}" - )); - return 0; - } - }; - if let Err(error) = match &std::fs::read_to_string(&config_path) { - Ok(string) => lua.load(string).exec(), - Err(error) => { - source.reply(&format!("failed to read {config_path:?}: {error:?}")); - return 0; - } - } { - source.reply(&format!( - "failed to execute configuration as lua code: {error:?}" - )); - return 0; - } + source.reply(&format!("{:?}", reload(&source.state.lua.lock()))); 1 })); commands.register( - literal("eval").then(argument("expr", string()).executes(|ctx: &Ctx| { + literal("eval").then(argument("code", string()).executes(|ctx: &Ctx| { let source = ctx.source.lock(); source.reply(&format!( "{:?}", - source - .state - .lua - .lock() - .load(get_string(ctx, "expr").unwrap()) - .eval::() + eval(&source.state.lua.lock(), &get_string(ctx, "code").unwrap()) )); 1 })), @@ -83,12 +60,7 @@ pub fn register(commands: &mut CommandDispatcher>) { let source = ctx.source.lock(); source.reply(&format!( "{:?}", - source - .state - .lua - .lock() - .load(get_string(ctx, "code").unwrap()) - .exec() + exec(&source.state.lua.lock(), &get_string(ctx, "code").unwrap()) )); 1 })), diff --git a/src/http.rs b/src/http.rs index f795846..d774014 100644 --- a/src/http.rs +++ b/src/http.rs @@ -1,4 +1,7 @@ -use crate::State; +use crate::{ + State, + scripting::{eval, exec, reload}, +}; use http_body_util::{BodyExt, Empty, Full, combinators::BoxBody}; use hyper::{Method, Request, Response, StatusCode, body::Bytes}; @@ -9,57 +12,32 @@ pub async fn handle( let path = request.uri().path().to_owned(); match (request.method(), path.as_str()) { - (&Method::POST, "/reload") => { - let lua = state.lua.lock(); - let config_path = match lua.globals().get::("config_path") { - Ok(path) => path, - Err(error) => { - return Ok(status_code_response( - StatusCode::INTERNAL_SERVER_ERROR, - Some(full(format!( - "failed to get config_path from lua globals: {error:?}" - ))), - )); - } - }; - if let Err(error) = match &std::fs::read_to_string(&config_path) { - Ok(string) => lua.load(string).exec(), - Err(error) => { - return Ok(status_code_response( - StatusCode::INTERNAL_SERVER_ERROR, - Some(full(format!("failed to read {config_path:?}: {error:?}"))), - )); - } - } { - return Ok(status_code_response( - StatusCode::INTERNAL_SERVER_ERROR, - Some(full(format!( - "failed to execute configuration as lua code: {error:?}" - ))), - )); - } - - Ok(Response::new(empty())) - } + (&Method::POST, "/reload") => Ok(match reload(&state.lua.lock()) { + Ok(()) => Response::new(empty()), + Err(error) => status_code_response( + StatusCode::INTERNAL_SERVER_ERROR, + Some(full(format!("{error:?}"))), + ), + }), (&Method::POST, "/eval" | "/exec") => { let bytes = request.into_body().collect().await?.to_bytes(); - let code = match std::str::from_utf8(&bytes) { - Ok(code) => code, + Ok(match std::str::from_utf8(&bytes) { + Ok(code) => { + let lua = state.lua.lock(); + Response::new(full(match path.as_str() { + "/eval" => format!("{:?}", eval(&lua, code)), + "/exec" => format!("{:?}", exec(&lua, code)), + _ => unreachable!(), + })) + } Err(error) => { return Ok(status_code_response( StatusCode::BAD_REQUEST, Some(full(format!("invalid utf-8 data received: {error:?}"))), )); } - }; - let chunk = state.lua.lock().load(code); - - Ok(Response::new(full(match path.as_str() { - "/eval" => format!("{:?}", chunk.eval::()), - "/exec" => format!("{:?}", chunk.exec()), - _ => unreachable!(), - }))) + }) } (&Method::GET, "/ping") => Ok(Response::new(full("pong!"))), diff --git a/src/scripting/mod.rs b/src/scripting/mod.rs index 70cc1ba..498a20e 100644 --- a/src/scripting/mod.rs +++ b/src/scripting/mod.rs @@ -1,3 +1,36 @@ pub mod client; pub mod logging; pub mod position; + +use mlua::Lua; + +#[derive(Debug)] +#[allow(dead_code)] +pub enum Error { + MissingGlobal(mlua::Error), + ReadFile(std::io::Error), + LoadChunk(mlua::Error), + EvalChunk(mlua::Error), + ExecChunk(mlua::Error), +} + +pub fn reload(lua: &Lua) -> Result<(), Error> { + lua.load( + &std::fs::read_to_string( + lua.globals() + .get::("config_path") + .map_err(Error::MissingGlobal)?, + ) + .map_err(Error::ReadFile)?, + ) + .exec() + .map_err(Error::LoadChunk) +} + +pub fn eval(lua: &Lua, code: &str) -> Result { + lua.load(code).eval::().map_err(Error::EvalChunk) +} + +pub fn exec(lua: &Lua, code: &str) -> Result<(), Error> { + lua.load(code).exec().map_err(Error::ExecChunk) +}