presence module & update_status

This commit is contained in:
2026-02-16 00:52:38 +08:00
parent 44556ca3a1
commit c76e436529
7 changed files with 61 additions and 17 deletions

View File

@@ -0,0 +1,113 @@
use tauri::Manager;
use tracing::{error, info, warn};
use crate::{get_app_handle, lock_w};
use serde::{Deserialize, Serialize};
use serde_json;
use std::fs;
pub mod models;
pub mod runtime;
#[derive(Serialize, Deserialize, Debug)]
pub struct ModuleMetadata {
pub name: String,
pub version: String,
pub description: Option<String>,
}
fn get_module_metadata(path: &std::path::Path) -> Option<ModuleMetadata> {
let metadata_path = path.join("metadata.json");
if metadata_path.exists() {
match fs::read_to_string(&metadata_path) {
Ok(content) => match serde_json::from_str::<ModuleMetadata>(&content) {
Ok(metadata) => {
info!(
"Loaded module metadata: {} v{} - {:?}",
metadata.name, metadata.version, metadata.description
);
return Some(metadata);
}
Err(e) => {
warn!("Failed to parse metadata.json in {}: {}", path.display(), e);
None
}
},
Err(e) => {
warn!("Failed to read metadata.json in {}: {}", path.display(), e);
None
}
}
} else {
None
}
}
/// Initialize installed modules
pub fn init_modules() {
let modules_path = get_app_handle()
.path()
.app_data_dir()
.expect("App data directory is unavailable.")
.join("modules");
if !modules_path.exists() {
if let Err(e) = fs::create_dir_all(&modules_path) {
error!("Failed to create modules directory: {}", e);
return;
}
return;
}
let entries = match fs::read_dir(&modules_path) {
Ok(entries) => entries,
Err(e) => {
error!("Failed to read app data directory: {}", e);
return;
}
};
let state = lock_w!(crate::state::FDOLL);
let mut state_guard = match state.module_handles.lock() {
Ok(guard) => guard,
Err(e) => {
error!("Failed to lock module handles: {}", e);
return;
}
};
for entry in entries {
let entry = match entry {
Ok(entry) => entry,
Err(e) => {
warn!("Failed to read directory entry: {}", e);
continue;
}
};
let path = entry.path();
if path.is_dir() {
let module_metadata = match get_module_metadata(&path) {
Some(metadata) => metadata,
None => continue,
};
let script_path = path.join("main.lua");
if script_path.exists() {
match runtime::spawn_lua_runtime_from_path(&script_path) {
Ok(handle) => {
state_guard.push(handle);
}
Err(e) => {
error!(
"Failed to spawn runtime for module {}: {}",
module_metadata.name, e
);
}
}
} else {
warn!("Module {} has no main.lua script", module_metadata.name);
}
}
}
}

View File

@@ -0,0 +1,11 @@
use serde::{Deserialize, Serialize};
use ts_rs::TS;
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct PresenceStatus {
pub title: Option<String>,
pub subtitle: Option<String>,
pub graphics_b64: Option<String>,
}

View File

@@ -0,0 +1,57 @@
use mlua::{Lua, LuaSerdeExt, UserData, UserDataMethods, Value};
use std::{path::Path, thread, time::Duration};
use tracing::{error, info};
use super::models::PresenceStatus;
pub struct Engine;
impl UserData for Engine {
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
methods.add_method("log", |_, _, message: String| {
info!("{}", message);
Ok(())
});
methods.add_method("sleep", |_, _, seconds: u64| {
thread::sleep(Duration::from_secs(seconds));
Ok(())
});
methods.add_method("update_status", |lua, _, value: Value| {
let status: PresenceStatus = lua.from_value(value)?;
dbg!(status);
Ok(())
});
}
}
fn load_script(path: &Path) -> Result<String, std::io::Error> {
std::fs::read_to_string(path)
}
fn setup_engine_globals(lua: &Lua) -> Result<(), mlua::Error> {
let globals = lua.globals();
globals.set("engine", Engine)
}
pub fn spawn_lua_runtime(script: &str) -> thread::JoinHandle<()> {
let script = script.to_string();
thread::spawn(move || {
let lua = Lua::new();
if let Err(e) = setup_engine_globals(&lua) {
error!("Failed to set engine global: {}", e);
return;
}
if let Err(e) = lua.load(&script).exec() {
error!("Failed to execute lua script: {}", e);
return;
}
})
}
pub fn spawn_lua_runtime_from_path(path: &Path) -> Result<thread::JoinHandle<()>, std::io::Error> {
let script = load_script(path)?;
Ok(spawn_lua_runtime(&script))
}