use std::sync::mpsc::Receiver; use color_eyre::Result; use mlua::{Function, IntoLua as _, Lua, LuaSerdeExt}; use tokio::sync::mpsc::UnboundedSender; use crate::types::{ApiTask, Event, Message}; #[tracing::instrument(skip_all)] pub fn worker( config: String, event_rx: Receiver, api_tx: UnboundedSender, ntfy_tx: UnboundedSender, ) -> Result<()> { let lua = Lua::new(); let globals = lua.globals(); let config = lua.load(config).set_name("config"); lua.scope(|scope| { let ntfy_fn = scope.create_function_mut(|_, data: mlua::Value| { let data = lua.from_value(data)?; tracing::trace!("Sending Ntfy message: {:?}", data); match ntfy_tx.send(Message::Ntfy(data)) { Ok(_) => Ok((true, mlua::Value::Nil)), Err(_) => { let msg = lua.create_string("Failed to send message")?; Ok((false, mlua::Value::String(msg))) } } })?; let set_api_task_fn = scope.create_function_mut(|_, data: mlua::Value| { let task = lua.from_value(data)?; tracing::trace!("Sending task request: {:?}", task); match api_tx.send(task) { Ok(_) => Ok((true, mlua::Value::Nil)), Err(_) => { let msg = lua.create_string("Failed to trigger task")?; Ok((false, mlua::Value::String(msg))) } } })?; globals.set("ntfy", ntfy_fn)?; globals.set("api_task", set_api_task_fn)?; config.exec()?; let event_fn: Function = match globals.get("on_event") { Ok(f) => f, Err(err) => match err { mlua::Error::FromLuaConversionError { from, to: _, message: _ } => { let err = mlua::Error::runtime(format!("Global function 'on_event' not defined properly. Got value of type '{}'", from)); return Err(err); } err => return Err(err), }, }; // Main blocking loop. As long as we can receive events, this scope will stay active. while let Ok(event) = event_rx.recv() { tracing::trace!("Received event: {:?}", event); match event { Event::Webhook(data) => { let data = lua.to_value(&data)?; event_fn.call::<_, ()>(("webhook", data))? } Event::Api(data) => { let data = data.into_lua(&lua)?; event_fn.call::<_, ()>(("api", data))? } Event::Error(data) => { let data = lua.to_value(&data)?; event_fn.call::<_, ()>(("error", data))? } } } Ok(()) })?; Ok(()) }