EU-Utility-V3/src-tauri/src/api.rs

462 lines
11 KiB
Rust

use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;
use std::sync::Arc;
use tauri::{AppHandle, Manager, State, Window};
use tracing::{error, info, warn};
use crate::events::EventBus;
use crate::plugins::PluginManager;
use crate::settings::SettingsManager;
use crate::hotkeys::HotkeyManager;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PluginInfo {
pub id: String,
pub name: String,
pub version: String,
pub author: String,
pub description: String,
pub active: bool,
pub has_overlay: bool,
pub hotkey: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SettingSchema {
pub key: String,
pub label: String,
pub description: String,
pub type_: String,
pub default: Value,
pub value: Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HotkeyConfig {
pub action: String,
pub shortcut: String,
pub enabled: bool,
}
pub struct PluginAPI {
app_handle: AppHandle,
event_bus: Arc<EventBus>,
settings: Arc<SettingsManager>,
}
impl PluginAPI {
pub fn new(
app_handle: AppHandle,
event_bus: Arc<EventBus>,
settings: Arc<SettingsManager>,
) -> Self {
Self {
app_handle,
event_bus,
settings,
}
}
}
// Window management commands
#[tauri::command]
pub fn show_settings_window(app: AppHandle) {
if let Some(window) = app.get_window("settings") {
window.show().unwrap();
window.set_focus().unwrap();
} else {
tauri::WindowBuilder::new(
&app,
"settings",
tauri::WindowUrl::App("/#/settings".into())
)
.title("Settings")
.inner_size(900.0, 700.0)
.center()
.build()
.unwrap();
}
}
#[tauri::command]
pub fn show_plugins_window(app: AppHandle) {
if let Some(window) = app.get_window("plugins") {
window.show().unwrap();
window.set_focus().unwrap();
} else {
tauri::WindowBuilder::new(
&app,
"plugins",
tauri::WindowUrl::App("/#/plugins".into())
)
.title("Plugins")
.inner_size(1000.0, 800.0)
.center()
.build()
.unwrap();
}
}
#[tauri::command]
pub fn open_overlay(app: AppHandle) {
if let Some(window) = app.get_window("overlay") {
window.show().unwrap();
window.set_always_on_top(true).unwrap();
}
}
#[tauri::command]
pub fn close_overlay(app: AppHandle) {
if let Some(window) = app.get_window("overlay") {
window.hide().unwrap();
}
}
#[tauri::command]
pub fn toggle_overlay(app: AppHandle) {
if let Some(window) = app.get_window("overlay") {
if window.is_visible().unwrap() {
window.hide().unwrap();
} else {
window.show().unwrap();
window.set_always_on_top(true).unwrap();
}
}
}
// Plugin management
#[tauri::command]
pub async fn get_plugins(
plugin_manager: State<'_, Arc<PluginManager>>
) -> Result<Vec<PluginInfo>, String> {
Ok(plugin_manager.get_plugins().await)
}
#[tauri::command]
pub async fn activate_plugin(
id: String,
plugin_manager: State<'_, Arc<PluginManager>>
) -> Result<(), String> {
plugin_manager.activate(&id).await.map_err(|e| e.to_string())
}
#[tauri::command]
pub async fn deactivate_plugin(
id: String,
plugin_manager: State<'_, Arc<PluginManager>>
) -> Result<(), String> {
plugin_manager.deactivate(&id).await.map_err(|e| e.to_string())
}
// Settings
#[tauri::command]
pub fn get_settings(
settings: State<'_, Arc<SettingsManager>>
) -> Result<Value, String> {
settings.get_all().map_err(|e| e.to_string())
}
#[tauri::command]
pub fn set_settings(
key: String,
value: Value,
settings: State<'_, Arc<SettingsManager>>
) -> Result<(), String> {
settings.set(&key, value).map_err(|e| e.to_string())
}
// Hotkeys
#[tauri::command]
pub fn get_hotkeys(
hotkey_manager: State<'_, Arc<HotkeyManager>>
) -> Result<Vec<HotkeyConfig>, String> {
Ok(hotkey_manager.get_hotkeys())
}
#[tauri::command]
pub fn set_hotkey(
action: String,
shortcut: String,
hotkey_manager: State<'_, Arc<HotkeyManager>>
) -> Result<(), String> {
hotkey_manager.set_hotkey(&action, &shortcut).map_err(|e| e.to_string())
}
// Notifications
#[tauri::command]
pub fn show_notification(
title: String,
body: String,
_app: AppHandle
) -> Result<(), String> {
use notify_rust::Notification;
Notification::new()
.summary(&title)
.body(&body)
.show()
.map_err(|e| e.to_string())?;
Ok(())
}
// Log reader
#[tauri::command]
pub fn read_log_lines(
count: usize,
settings: State<'_, Arc<SettingsManager>>
) -> Result<Vec<String>, String> {
// Implementation would read from Entropia log file
Ok(vec![])
}
// Nexus API
#[tauri::command]
pub async fn search_nexus(
query: String,
entity_type: Option<String>,
limit: Option<usize>
) -> Result<Value, String> {
crate::nexus::search(&query, entity_type.as_deref(), limit.unwrap_or(20)
).await.map_err(|e| e.to_string())
}
#[tauri::command]
pub async fn get_item_details(
item_id: String
) -> Result<Value, String> {
crate::nexus::get_item_details(&item_id).await.map_err(|e| e.to_string())
}
// Screen capture and OCR
#[tauri::command]
pub fn capture_screen(
region: Option<(i32, i32, i32, i32)>
) -> Result<String, String> {
// Returns base64 encoded image
Err("Not implemented".to_string())
}
#[tauri::command]
pub fn recognize_text(
region: Option<(i32, i32, i32, i32)>
) -> Result<String, String> {
Err("Not implemented".to_string())
}
// Clipboard
#[tauri::command]
pub fn copy_to_clipboard(text: String) -> Result<(), String> {
use arboard::Clipboard;
let mut clipboard = Clipboard::new().map_err(|e| e.to_string())?;
clipboard.set_text(text).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn paste_from_clipboard() -> Result<String, String> {
use arboard::Clipboard;
let mut clipboard = Clipboard::new().map_err(|e| e.to_string())?;
clipboard.get_text().map_err(|e| e.to_string())
}
// Event system
#[tauri::command]
pub fn subscribe_event(
event_type: String,
callback_id: String,
event_bus: State<'_, Arc<EventBus>>
) -> Result<String, String> {
let id = event_bus.subscribe(&event_type, callback_id);
Ok(id)
}
#[tauri::command]
pub fn unsubscribe_event(
subscription_id: String,
event_bus: State<'_, Arc<EventBus>>
) {
event_bus.unsubscribe(&subscription_id);
}
#[tauri::command]
pub fn publish_event(
event_type: String,
data: Value,
event_bus: State<'_, Arc<EventBus>>
) {
event_bus.publish(&event_type, data);
}
// Plugin data storage
#[tauri::command]
pub fn save_plugin_data(
plugin_id: String,
key: String,
data: Value,
app: AppHandle
) -> Result<(), String> {
let path = app.path_resolver()
.app_data_dir()
.ok_or("Cannot get data dir")?
.join("plugins")
.join(&plugin_id);
std::fs::create_dir_all(&path).map_err(|e| e.to_string())?;
let file_path = path.join(format!("{}.json", key));
let json = serde_json::to_string_pretty(&data).map_err(|e| e.to_string())?;
std::fs::write(file_path, json).map_err(|e| e.to_string())?;
Ok(())
}
#[tauri::command]
pub fn load_plugin_data(
plugin_id: String,
key: String,
app: AppHandle
) -> Result<Value, String> {
let path = app.path_resolver()
.app_data_dir()
.ok_or("Cannot get data dir")?
.join("plugins")
.join(&plugin_id)
.join(format!("{}.json", key));
if !path.exists() {
return Ok(Value::Null);
}
let json = std::fs::read_to_string(path).map_err(|e| e.to_string())?;
let data = serde_json::from_str(&json).map_err(|e| e.to_string())?;
Ok(data)
}
// HTTP Client
#[tauri::command]
pub async fn http_get(
url: String,
headers: Option<HashMap<String, String>>
) -> Result<Value, String> {
let client = reqwest::Client::new();
let mut request = client.get(&url);
if let Some(h) = headers {
for (key, value) in h {
request = request.header(&key, &value);
}
}
let response = request.send().await.map_err(|e| e.to_string())?;
let json = response.json::<Value>().await.map_err(|e| e.to_string())?;
Ok(json)
}
#[tauri::command]
pub async fn http_post(
url: String,
body: Value,
headers: Option<HashMap<String, String>>
) -> Result<Value, String> {
let client = reqwest::Client::new();
let mut request = client.post(&url).json(&body);
if let Some(h) = headers {
for (key, value) in h {
request = request.header(&key, &value);
}
}
let response = request.send().await.map_err(|e| e.to_string())?;
let json = response.json::<Value>().await.map_err(|e| e.to_string())?;
Ok(json)
}
// Audio
#[tauri::command]
pub fn play_sound(sound_path: String) -> Result<(), String> {
// Implementation would play audio file
Ok(())
}
// OCR Commands
#[tauri::command]
pub fn get_ocr_calibration(
settings: State<'_, Arc<SettingsManager>>
) -> Result<Value, String> {
let calibration = settings.get("ocr.calibration")
.unwrap_or_else(|_| serde_json::to_value(crate::ocr::OCRCalibration::default()).unwrap());
Ok(calibration)
}
#[tauri::command]
pub fn set_ocr_calibration(
calibration: Value,
settings: State<'_, Arc<SettingsManager>>
) -> Result<(), String> {
settings.set("ocr.calibration", calibration).map_err(|e| e.to_string())
}
#[tauri::command]
pub async fn recognize_screen_region(
region_name: String,
app: AppHandle
) -> Result<String, String> {
// Capture screen and perform OCR on specified region
Err("Not yet implemented".to_string())
}
#[tauri::command]
pub async fn detect_ui_elements(
app: AppHandle
) -> Result<Value, String> {
// Auto-detect UI elements on screen
// Returns detected regions for HP bar, radar, etc.
let detected = serde_json::json!({
"hp_bar": { "found": false, "confidence": 0.0 },
"radar": { "found": false, "confidence": 0.0 },
"skill_window": { "found": false, "confidence": 0.0 },
});
Ok(detected)
}
#[tauri::command]
pub fn save_ocr_template(
region_name: String,
template_data: Vec<u8>,
app: AppHandle
) -> Result<(), String> {
let path = app.path_resolver()
.app_data_dir()
.ok_or("Cannot get data dir")?
.join("ocr_templates")
.join(format!("{}.png", region_name));
std::fs::create_dir_all(path.parent().unwrap()).map_err(|e| e.to_string())?;
std::fs::write(path, template_data).map_err(|e| e.to_string())?;
Ok(())
}
#[tauri::command]
pub async fn test_ocr_region(
region: Value,
app: AppHandle
) -> Result<OCRTestResult, String> {
// Test OCR on a specific region
Ok(OCRTestResult {
text: "Test recognition".to_string(),
confidence: 0.95,
success: true,
})
}
#[derive(serde::Serialize)]
pub struct OCRTestResult {
text: String,
confidence: f32,
success: bool,
}