diff options
Diffstat (limited to 'src/theming/lua.rs')
-rw-r--r-- | src/theming/lua.rs | 39 |
1 files changed, 27 insertions, 12 deletions
diff --git a/src/theming/lua.rs b/src/theming/lua.rs index c9168cb..6bd6989 100644 --- a/src/theming/lua.rs +++ b/src/theming/lua.rs @@ -1,10 +1,10 @@ // SPDX-License-Identifier: AGPL-3.0-only use std::sync::LazyLock; -use std::ops::Deref; use std::path::Path; +use std::fs; -use tokio::sync::Mutex; -use mlua::{Lua, Compiler, StdLib, Value, LuaOptions}; +use std::sync::Mutex; +use mlua::{Lua, LuaSerdeExt, Compiler, StdLib, Value, LuaOptions, Table}; use http::StatusCode; use crate::CONFIG; @@ -37,16 +37,19 @@ static LUA: LazyLock<Mutex<Lua>> = LazyLock::new(|| { let themes = lua.create_table().expect("creating themes table"); for (k, v) in INTERNAL_THEMES { + log::info!("Registering compiled lua theme `{k}`."); let _ = themes.set(*k, lua.load(*v).into_function().expect("loading internal theme")); } if let Some(theme_dir) = CONFIG.theme_dir.as_ref() { + log::info!("Registering lua theme dir `{theme_dir}` with extension `{}`.", CONFIG.theme_ext_lua); for (k, v) in walk_dir(theme_dir.as_ref().as_ref()).expect("walking theme dir") { - let _ = themes.set(k, lua.load(v).into_function().expect("loading internal theme")); + log::info!("Registering runtime lua theme `{k}`."); + let _ = themes.set(k, lua.load(v).eval::<Value>().expect("loading internal theme")); } } - let _ = lua.globals().set("__themes", themes).unwrap(); + lua.globals().set("__themes", themes).unwrap(); lua.globals().set_readonly(true); @@ -54,7 +57,7 @@ static LUA: LazyLock<Mutex<Lua>> = LazyLock::new(|| { }); fn walk_dir(path: &Path) -> std::io::Result<Vec<(String, String)>> { - use std::fs; + let ext = CONFIG.theme_ext_lua.as_ref(); let mut path_bits = vec![]; let mut dir_readers = vec![fs::read_dir(path)?]; @@ -67,7 +70,7 @@ fn walk_dir(path: &Path) -> std::io::Result<Vec<(String, String)>> { let name = ent.file_name().into_string().expect("why do you have such FUCKED UP FILE PATHS"); let ty = ent.file_type()?; if ty.is_file() && name.ends_with(CONFIG.theme_ext_lua.as_ref()) { - ret.push((path_bits.join("") + &name, fs::read_to_string(ent.path())?)); + ret.push((path_bits.join("") + &name[..name.len() - ext.len()], fs::read_to_string(ent.path())?)); } else if ty.is_dir() { path_bits.push(name); @@ -82,10 +85,22 @@ fn walk_dir(path: &Path) -> std::io::Result<Vec<(String, String)>> { Ok(ret) } -pub fn touch() { - let _ = LUA.deref(); -} - pub fn render_theme(name: &str, ctx: &crate::ctx::Ctx) -> Option<Result<String, StatusCode>> { - return None + LUA.clear_poison(); + let lua = LUA.lock().expect("FIXME: Mutex poisoning race condition."); + let themes: Table = lua.globals().get("__themes").unwrap(); + let Ok(Value::Function(theme)) = themes.get(name) + else { + return None; + }; + + let ctx = match lua.to_value(ctx) { + Ok(ok) => ok, + Err(e) => { + log::error!("Lua context serialization error: {e}"); + return Some(Err(StatusCode::INTERNAL_SERVER_ERROR)) + } + }; + + Some(theme.call((ctx,)).map_err(|e| { log::error!("Lua theme execution error: {e}"); StatusCode::INTERNAL_SERVER_ERROR })) } |