use super::CmdResult; use crate::{config::*, core::CoreManager, log_err, wrap_err}; use anyhow::Context; use serde_yaml_ng::Mapping; use std::collections::HashMap; /// 获取运行时配置 #[tauri::command] pub async fn get_runtime_config() -> CmdResult> { Ok(Config::runtime().await.latest_ref().config.clone()) } /// 获取运行时YAML配置 #[tauri::command] pub async fn get_runtime_yaml() -> CmdResult { let runtime = Config::runtime().await; let runtime = runtime.latest_ref(); let config = runtime.config.as_ref(); wrap_err!( config .ok_or(anyhow::anyhow!("failed to parse config to yaml file")) .and_then(|config| serde_yaml_ng::to_string(config) .context("failed to convert config to yaml")) ) } /// 获取运行时存在的键 #[tauri::command] pub async fn get_runtime_exists() -> CmdResult> { Ok(Config::runtime().await.latest_ref().exists_keys.clone()) } /// 获取运行时日志 #[tauri::command] pub async fn get_runtime_logs() -> CmdResult>> { Ok(Config::runtime().await.latest_ref().chain_logs.clone()) } /// 读取运行时链式代理配置 #[tauri::command] pub async fn get_runtime_proxy_chain_config() -> CmdResult { let runtime = Config::runtime().await; let runtime = runtime.latest_ref(); let config = wrap_err!( runtime .config .as_ref() .ok_or(anyhow::anyhow!("failed to parse config to yaml file")) )?; if let ( Some(serde_yaml_ng::Value::Sequence(proxies)), Some(serde_yaml_ng::Value::Sequence(proxy_groups)), ) = (config.get("proxies"), config.get("proxy-groups")) { let mut proxy_name = None; let mut proxies_chain = Vec::new(); let proxy_chain_groups = proxy_groups .iter() .filter_map( |proxy_group| match proxy_group.get("name").and_then(|n| n.as_str()) { Some("proxy_chain") => { if let Some(serde_yaml_ng::Value::Sequence(ps)) = proxy_group.get("proxies") && let Some(x) = ps.first() { proxy_name = Some(x); //插入出口节点名字 } Some(proxy_group.to_owned()) } _ => None, }, ) .collect::>(); while let Some(proxy) = proxies.iter().find(|proxy| { if let serde_yaml_ng::Value::Mapping(proxy_map) = proxy { proxy_map.get("name") == proxy_name && proxy_map.get("dialer-proxy").is_some() } else { false } }) { proxies_chain.push(proxy.to_owned()); proxy_name = proxy.get("dialer-proxy"); } if let Some(entry_proxy) = proxies.iter().find(|proxy| proxy.get("name") == proxy_name) { proxies_chain.push(entry_proxy.to_owned()); } proxies_chain.reverse(); let mut config: HashMap> = HashMap::new(); config.insert("proxies".to_string(), proxies_chain); config.insert("proxy-groups".to_string(), proxy_chain_groups); wrap_err!(serde_yaml_ng::to_string(&config).context("YAML generation failed")) } else { wrap_err!(Err(anyhow::anyhow!( "failed to get proxies or proxy-groups".to_string() ))) } } /// 更新运行时链式代理配置 #[tauri::command] pub async fn update_proxy_chain_config_in_runtime( proxy_chain_config: Option, ) -> CmdResult<()> { { let runtime = Config::runtime().await; let mut draft = runtime.draft_mut(); draft.update_proxy_chain_config(proxy_chain_config); drop(draft); runtime.apply(); } // 生成新的运行配置文件并通知 Clash 核心重新加载 let run_path = wrap_err!(Config::generate_file(ConfigType::Run).await)?; log_err!(CoreManager::global().put_configs_force(run_path).await); Ok(()) }