From 1641e02a7d5eff2b940aaf8110c97067f662995d Mon Sep 17 00:00:00 2001 From: GyDi Date: Thu, 11 Aug 2022 02:55:10 +0800 Subject: [PATCH] feat: reimplement enhanced mode --- src-tauri/src/cmds.rs | 15 +- src-tauri/src/config/field.rs | 97 ++++++++++++ src-tauri/src/config/merge.rs | 99 +++++++++++++ src-tauri/src/config/mod.rs | 57 +++++++ src-tauri/src/config/script.rs | 96 ++++++++++++ src-tauri/src/core/clash.rs | 110 +++++++------- src-tauri/src/core/enhance.rs | 216 +-------------------------- src-tauri/src/core/mod.rs | 263 +++++++++++++++++---------------- src-tauri/src/main.rs | 1 + 9 files changed, 555 insertions(+), 399 deletions(-) create mode 100644 src-tauri/src/config/field.rs create mode 100644 src-tauri/src/config/merge.rs create mode 100644 src-tauri/src/config/mod.rs create mode 100644 src-tauri/src/config/script.rs diff --git a/src-tauri/src/cmds.rs b/src-tauri/src/cmds.rs index ec00eeb..c41baf5 100644 --- a/src-tauri/src/cmds.rs +++ b/src-tauri/src/cmds.rs @@ -19,7 +19,8 @@ pub fn get_profiles(core: State<'_, Core>) -> CmdResult { /// manually exec enhanced profile #[tauri::command] pub fn enhance_profiles(core: State<'_, Core>) -> CmdResult { - wrap_err!(core.activate_enhanced(false)) + // wrap_err!(core.activate_enhanced(false)) + wrap_err!(core.activate()) } /// import the profile from url @@ -69,7 +70,8 @@ pub fn select_profile(index: String, core: State<'_, Core>) -> CmdResult { drop(profiles); - wrap_err!(core.activate_enhanced(false)) + // wrap_err!(core.activate_enhanced(false)) + wrap_err!(core.activate()) } /// change the profile chain @@ -80,7 +82,8 @@ pub fn change_profile_chain(chain: Option>, core: State<'_, Core>) - drop(profiles); - wrap_err!(core.activate_enhanced(false)) + // wrap_err!(core.activate_enhanced(false)) + wrap_err!(core.activate()) } /// change the profile valid fields @@ -91,7 +94,8 @@ pub fn change_profile_valid(valid: Option>, core: State) -> Cm drop(profiles); - wrap_err!(core.activate_enhanced(false)) + // wrap_err!(core.activate_enhanced(false)) + wrap_err!(core.activate()) } /// delete profile item @@ -102,7 +106,8 @@ pub fn delete_profile(index: String, core: State<'_, Core>) -> CmdResult { if wrap_err!(profiles.delete_item(index))? { drop(profiles); - log_if_err!(core.activate_enhanced(false)); + // log_if_err!(core.activate_enhanced(false)); + log_if_err!(core.activate()); } Ok(()) diff --git a/src-tauri/src/config/field.rs b/src-tauri/src/config/field.rs new file mode 100644 index 0000000..40fcca2 --- /dev/null +++ b/src-tauri/src/config/field.rs @@ -0,0 +1,97 @@ +use serde_yaml::{Mapping, Value}; + +pub const HANDLE_FIELDS: [&str; 9] = [ + "port", + "socks-port", + "mixed-port", + "mode", + "ipv6", + "log-level", + "allow-lan", + "external-controller", + "secret", +]; + +pub const DEFAULT_FIELDS: [&str; 5] = [ + "proxies", + "proxy-groups", + "rules", + "proxy-providers", + "rule-providers", +]; + +pub const OTHERS_FIELDS: [&str; 20] = [ + "tun", + "dns", + "ebpf", + "hosts", + "script", + "profile", + "payload", + "auto-redir", + "experimental", + "interface-name", + "routing-mark", + "redir-port", + "tproxy-port", + "iptables", + "external-ui", + "bind-address", + "authentication", + "sniffer", // meta + "geodata-mode", // meta + "tcp-concurrent", // meta +]; + +pub fn use_clash_fields() -> Vec { + DEFAULT_FIELDS + .into_iter() + .chain(HANDLE_FIELDS) + .chain(OTHERS_FIELDS) + .map(|s| s.to_string()) + .collect() +} + +pub fn use_valid_fields(mut valid: Vec) -> Vec { + let others = Vec::from(OTHERS_FIELDS); + + valid.iter_mut().for_each(|s| s.make_ascii_lowercase()); + valid + .into_iter() + .filter(|s| others.contains(&s.as_str())) + .chain(DEFAULT_FIELDS.iter().map(|s| s.to_string())) + .collect() +} + +pub fn use_filter(config: Mapping, filter: Vec) -> Mapping { + let mut ret = Mapping::new(); + + for (key, value) in config.into_iter() { + key.as_str().map(|key_str| { + // change to lowercase + let mut key_str = String::from(key_str); + key_str.make_ascii_lowercase(); + + if filter.contains(&key_str) { + ret.insert(Value::from(key_str), value); + } + }); + } + ret +} + +pub fn use_sort(config: Mapping) -> Mapping { + let mut ret = Mapping::new(); + + HANDLE_FIELDS + .into_iter() + .chain(OTHERS_FIELDS) + .chain(DEFAULT_FIELDS) + .for_each(|key| { + let key = Value::from(key); + config.get(&key).map(|value| { + ret.insert(key, value.clone()); + }); + }); + ret +} diff --git a/src-tauri/src/config/merge.rs b/src-tauri/src/config/merge.rs new file mode 100644 index 0000000..e9c0093 --- /dev/null +++ b/src-tauri/src/config/merge.rs @@ -0,0 +1,99 @@ +use super::{use_filter, use_valid_fields}; +use serde_yaml::{self, Mapping, Sequence, Value}; + +#[allow(unused)] +const MERGE_FIELDS: [&str; 6] = [ + "prepend-rules", + "append-rules", + "prepend-proxies", + "append-proxies", + "prepend-proxy-groups", + "append-proxy-groups", +]; + +pub fn use_merge(merge: Mapping, mut config: Mapping, valid: Vec) -> Mapping { + let valid_list = use_valid_fields(valid); + let merge_valid = use_filter(merge.clone(), valid_list); + + // 直接覆盖原字段 + merge_valid.into_iter().for_each(|(key, value)| { + config.insert(key, value); + }); + + let merge_list = MERGE_FIELDS.iter().map(|s| s.to_string()); + let merge = use_filter(merge, merge_list.collect()); + + ["rules", "proxies", "proxy-groups"] + .iter() + .for_each(|key_str| { + let key_val = Value::from(key_str.to_string()); + + let mut list = Sequence::default(); + list = config.get(&key_val).map_or(list.clone(), |val| { + val.as_sequence().map_or(list, |v| v.clone()) + }); + + let pre_key = Value::from(format!("prepend-{key_str}")); + let post_key = Value::from(format!("append-{key_str}")); + + if let Some(pre_val) = merge.get(&pre_key) { + if pre_val.is_sequence() { + let mut pre_val = pre_val.as_sequence().unwrap().clone(); + pre_val.extend(list); + list = pre_val; + } + } + + if let Some(post_val) = merge.get(&post_key) { + if post_val.is_sequence() { + list.extend(post_val.as_sequence().unwrap().clone()); + } + } + + config.insert(key_val, Value::from(list)); + }); + + config +} + +#[test] +fn test_merge() -> anyhow::Result<()> { + let merge = r" + prepend-rules: + - prepend + - 1123123 + append-rules: + - append + prepend-proxies: + - 9999 + append-proxies: + - 1111 + rules: + - replace + proxy-groups: + - 123781923810 + tun: + enable: true + dns: + enable: true + "; + + let config = r" + rules: + - aaaaa + script1: test + "; + + let merge = serde_yaml::from_str::(merge)?; + let config = serde_yaml::from_str::(config)?; + + let result = serde_yaml::to_string(&use_merge( + merge, + config, + vec!["tun"].iter().map(|s| s.to_string()).collect(), + ))?; + + println!("{result}"); + + Ok(()) +} diff --git a/src-tauri/src/config/mod.rs b/src-tauri/src/config/mod.rs new file mode 100644 index 0000000..c1e6120 --- /dev/null +++ b/src-tauri/src/config/mod.rs @@ -0,0 +1,57 @@ +mod field; +mod merge; +mod script; + +pub(self) use self::field::*; +use self::merge::*; +use self::script::*; +use crate::core::PrfData; +use serde_yaml::Mapping; +use std::collections::HashMap; + +type ResultLog = Vec<(String, String)>; + +pub fn runtime_config( + clash_config: Mapping, + profile_config: Mapping, + profile_enhanced: Vec, + valid: Vec, + // tun_enable: bool, +) -> (Mapping, HashMap) { + let mut config = profile_config; + + let mut result_map = HashMap::new(); + + profile_enhanced.into_iter().for_each(|data| { + if data.merge.is_some() { + config = use_merge(data.merge.unwrap(), config.to_owned(), valid.clone()); + } else if data.script.is_some() { + let mut logs = vec![]; + + match use_script(data.script.unwrap(), config.to_owned(), valid.clone()) { + Ok((res_config, res_logs)) => { + config = res_config; + logs.extend(res_logs); + } + Err(err) => { + logs.push(("error".into(), err.to_string())); + } + } + + if let Some(uid) = data.item.uid { + result_map.insert(uid, logs); + } + } + }); + + config = use_filter(config, use_valid_fields(valid)); + + for (key, value) in clash_config.into_iter() { + config.insert(key, value); + } + + config = use_filter(config, use_clash_fields()); + config = use_sort(config); + + (config, result_map) +} diff --git a/src-tauri/src/config/script.rs b/src-tauri/src/config/script.rs new file mode 100644 index 0000000..9a20581 --- /dev/null +++ b/src-tauri/src/config/script.rs @@ -0,0 +1,96 @@ +use super::{use_filter, use_valid_fields}; +use anyhow::Result; +use serde_yaml::{self, Mapping}; + +pub fn use_script( + script: String, + config: Mapping, + valid: Vec, +) -> Result<(Mapping, Vec<(String, String)>)> { + use rquickjs::{Context, Func, Runtime}; + use std::sync::{Arc, Mutex}; + + let runtime = Runtime::new().unwrap(); + let context = Context::full(&runtime).unwrap(); + let outputs = Arc::new(Mutex::new(vec![])); + + let copy_outputs = outputs.clone(); + let result = context.with(|ctx| -> Result { + ctx.globals().set( + "__verge_log__", + Func::from(move |level: String, data: String| { + let mut out = copy_outputs.lock().unwrap(); + out.push((level, data)); + }), + )?; + + ctx.eval( + r#"var console = Object.freeze({ + log(data){__verge_log__("log",JSON.stringify(data))}, + info(data){__verge_log__("info",JSON.stringify(data))}, + error(data){__verge_log__("error",JSON.stringify(data))}, + debug(data){__verge_log__("debug",JSON.stringify(data))}, + });"#, + )?; + + let config_str = serde_json::to_string(&config)?; + + let code = format!("\n{script}\n;\nJSON.stringify(main({config_str})||'')"); + let result: String = ctx.eval(code.as_str())?; + if result == "\"\"" { + anyhow::bail!("main function should return object"); + } + Ok(serde_json::from_str::(result.as_str())?) + }); + + let mut out = outputs.lock().unwrap(); + match result { + Ok(config) => { + let valid = use_valid_fields(valid); + let config = use_filter(config, valid); + Ok((config, out.to_vec())) + } + Err(err) => { + out.push(("error".into(), err.to_string())); + Ok((config, out.to_vec())) + } + } +} + +#[test] +fn test_script() { + let script = r#" + function main(config) { + if (Array.isArray(config.rules)) { + config.rules = [...config.rules, "add"]; + } + console.log(config); + config.proxies = ["111"]; + return config; + } + "#; + + let config = r#" + rules: + - 111 + - 222 + tun: + enable: false + dns: + enable: false + "#; + + let config = serde_yaml::from_str(config).unwrap(); + let (config, results) = use_script( + script.into(), + config, + vec!["tun"].iter().map(|s| s.to_string()).collect(), + ) + .unwrap(); + + let config_str = serde_yaml::to_string(&config).unwrap(); + + println!("{config_str}"); + + dbg!(results); +} diff --git a/src-tauri/src/core/clash.rs b/src-tauri/src/core/clash.rs index 92c078d..e94bdd4 100644 --- a/src-tauri/src/core/clash.rs +++ b/src-tauri/src/core/clash.rs @@ -237,70 +237,70 @@ impl Clash { config } - /// only 5 default fields available (clash config fields) - /// convert to lowercase - pub fn strict_filter(config: Mapping) -> Mapping { - // Only the following fields are allowed: - // proxies/proxy-providers/proxy-groups/rule-providers/rules - let valid_keys = vec![ - "proxies", - "proxy-providers", - "proxy-groups", - "rules", - "rule-providers", - ]; + // /// only 5 default fields available (clash config fields) + // /// convert to lowercase + // pub fn strict_filter(config: Mapping) -> Mapping { + // // Only the following fields are allowed: + // // proxies/proxy-providers/proxy-groups/rule-providers/rules + // let valid_keys = vec![ + // "proxies", + // "proxy-providers", + // "proxy-groups", + // "rules", + // "rule-providers", + // ]; - let mut new_config = Mapping::new(); + // let mut new_config = Mapping::new(); - for (key, value) in config.into_iter() { - key.as_str().map(|key_str| { - // change to lowercase - let mut key_str = String::from(key_str); - key_str.make_ascii_lowercase(); + // for (key, value) in config.into_iter() { + // key.as_str().map(|key_str| { + // // change to lowercase + // let mut key_str = String::from(key_str); + // key_str.make_ascii_lowercase(); - // filter - if valid_keys.contains(&&*key_str) { - new_config.insert(Value::String(key_str), value); - } - }); - } + // // filter + // if valid_keys.contains(&&*key_str) { + // new_config.insert(Value::String(key_str), value); + // } + // }); + // } - new_config - } + // new_config + // } - /// more clash config fields available - /// convert to lowercase - pub fn loose_filter(config: Mapping) -> Mapping { - // all of these can not be revised by script or merge - // http/https/socks port should be under control - let not_allow = vec![ - "port", - "socks-port", - "mixed-port", - "allow-lan", - "mode", - "external-controller", - "secret", - "log-level", - ]; + // /// more clash config fields available + // /// convert to lowercase + // pub fn loose_filter(config: Mapping) -> Mapping { + // // all of these can not be revised by script or merge + // // http/https/socks port should be under control + // let not_allow = vec![ + // "port", + // "socks-port", + // "mixed-port", + // "allow-lan", + // "mode", + // "external-controller", + // "secret", + // "log-level", + // ]; - let mut new_config = Mapping::new(); + // let mut new_config = Mapping::new(); - for (key, value) in config.into_iter() { - key.as_str().map(|key_str| { - // change to lowercase - let mut key_str = String::from(key_str); - key_str.make_ascii_lowercase(); + // for (key, value) in config.into_iter() { + // key.as_str().map(|key_str| { + // // change to lowercase + // let mut key_str = String::from(key_str); + // key_str.make_ascii_lowercase(); - // filter - if !not_allow.contains(&&*key_str) { - new_config.insert(Value::String(key_str), value); - } - }); - } + // // filter + // if !not_allow.contains(&&*key_str) { + // new_config.insert(Value::String(key_str), value); + // } + // }); + // } - new_config - } + // new_config + // } } impl Default for Clash { diff --git a/src-tauri/src/core/enhance.rs b/src-tauri/src/core/enhance.rs index de95e24..55fed1a 100644 --- a/src-tauri/src/core/enhance.rs +++ b/src-tauri/src/core/enhance.rs @@ -1,8 +1,7 @@ use super::prfitem::PrfItem; use crate::utils::{config, dirs}; -use anyhow::Result; use serde::{Deserialize, Serialize}; -use serde_yaml::{self, Mapping, Sequence, Value}; +use serde_yaml::Mapping; use std::fs; #[derive(Default, Debug, Clone, Serialize, Deserialize)] @@ -27,13 +26,13 @@ pub struct PrfEnhancedResult { #[derive(Default, Debug, Clone, Serialize, Deserialize)] pub struct PrfData { - item: PrfItem, + pub item: PrfItem, #[serde(skip_serializing_if = "Option::is_none")] - merge: Option, + pub merge: Option, #[serde(skip_serializing_if = "Option::is_none")] - script: Option, + pub script: Option, } impl PrfData { @@ -65,210 +64,3 @@ impl PrfData { } } } - -fn get_valid_list(valid: Vec) -> Vec { - let mut valid_list: Vec = vec![ - "rules", - "proxies", - "proxy-groups", - "proxy-providers", - "rule-providers", - ] - .iter() - .map(|s| s.to_string()) - .collect(); - - valid_list.extend(valid); - valid_list -} - -fn use_valid_filter(config: Mapping, valid: Vec) -> Mapping { - let valid = get_valid_list(valid); - let mut new_config = Mapping::new(); - - valid.iter().for_each(|k| { - let k = Value::from(k.clone()); - if let Some(value) = config.get(&k) { - new_config.insert(k, value.clone()); - } - }); - new_config -} - -pub fn use_merge(merge: Mapping, config: Mapping, valid: Vec) -> Mapping { - let valid_list = get_valid_list(valid); - let mut config = config; - - valid_list.iter().for_each(|key| { - let key = Value::String(key.into()); - if let Some(value) = merge.get(&key) { - config.insert(key, value.clone()); - } - }); - - vec!["rules", "proxies", "proxy-groups"] - .iter() - .for_each(|key_str| { - let key_val = Value::from(key_str.to_string()); - - let mut list = Sequence::default(); - list = config.get(&key_val).map_or(list.clone(), |val| { - val.as_sequence().map_or(list, |v| v.clone()) - }); - - let pre_key = Value::from(format!("prepend-{key_str}")); - let post_key = Value::from(format!("append-{key_str}")); - - if let Some(pre_val) = merge.get(&pre_key) { - if pre_val.is_sequence() { - let mut pre_val = pre_val.as_sequence().unwrap().clone(); - pre_val.extend(list); - list = pre_val; - } - } - - if let Some(post_val) = merge.get(&post_key) { - if post_val.is_sequence() { - list.extend(post_val.as_sequence().unwrap().clone()); - } - } - - config.insert(key_val, Value::from(list)); - }); - - config -} - -pub fn use_script( - script: String, - config: Mapping, - valid: Vec, -) -> Result<(Mapping, Vec<(String, String)>)> { - use rquickjs::{Context, Func, Runtime}; - use std::sync::{Arc, Mutex}; - - let runtime = Runtime::new().unwrap(); - let context = Context::full(&runtime).unwrap(); - let outputs = Arc::new(Mutex::new(vec![])); - - let copy_outputs = outputs.clone(); - let result = context.with(|ctx| -> Result { - ctx.globals().set( - "__verge_log__", - Func::from(move |level: String, data: String| { - let mut out = copy_outputs.lock().unwrap(); - out.push((level, data)); - }), - )?; - - ctx.eval( - r#"var console = Object.freeze({ - log(data){__verge_log__("log",JSON.stringify(data))}, - info(data){__verge_log__("info",JSON.stringify(data))}, - error(data){__verge_log__("error",JSON.stringify(data))}, - debug(data){__verge_log__("debug",JSON.stringify(data))}, - });"#, - )?; - - let config_str = serde_json::to_string(&config)?; - - let code = format!("\n{script}\n;\nJSON.stringify(main({config_str})||'')"); - let result: String = ctx.eval(code.as_str())?; - if result == "\"\"" { - anyhow::bail!("main function should return object"); - } - Ok(serde_json::from_str::(result.as_str())?) - }); - - let mut out = outputs.lock().unwrap(); - match result { - Ok(config) => { - let config = use_valid_filter(config, valid); - Ok((config, out.to_vec())) - } - Err(err) => { - out.push(("error".into(), err.to_string())); - Ok((config, out.to_vec())) - } - } -} - -#[test] -fn test_merge() -> Result<()> { - let merge = r" - prepend-rules: - - prepend - - 1123123 - append-rules: - - append - prepend-proxies: - - 9999 - append-proxies: - - 1111 - rules: - - replace - proxy-groups: - - 123781923810 - tun: - enable: true - dns: - enable: true - "; - - let config = r" - rules: - - aaaaa - script: test - "; - - let merge = serde_yaml::from_str::(merge)?; - let config = serde_yaml::from_str::(config)?; - - let result = serde_yaml::to_string(&use_merge( - merge, - config, - vec!["tun"].iter().map(|s| s.to_string()).collect(), - ))?; - - println!("{result}"); - - Ok(()) -} - -#[test] -fn test_script() { - let script = r#" - function main(config) { - if (Array.isArray(config.rules)) { - config.rules = [...config.rules, "add"]; - } - console.log(config); - config.proxies = ["111"]; - return config; - } - "#; - - let config = r#" - rules: - - 111 - - 222 - tun: - enable: false - dns: - enable: false - "#; - - let config = serde_yaml::from_str(config).unwrap(); - let (config, results) = use_script( - script.into(), - config, - vec!["tun"].iter().map(|s| s.to_string()).collect(), - ) - .unwrap(); - - let config_str = serde_yaml::to_string(&config).unwrap(); - - println!("{config_str}"); - - dbg!(results); -} diff --git a/src-tauri/src/core/mod.rs b/src-tauri/src/core/mod.rs index 967db76..abe01fb 100644 --- a/src-tauri/src/core/mod.rs +++ b/src-tauri/src/core/mod.rs @@ -1,6 +1,7 @@ use self::notice::Notice; use self::sysopt::Sysopt; use self::timer::Timer; +use crate::config::runtime_config; use crate::core::enhance::PrfEnhancedResult; use crate::log_if_err; use crate::utils::help; @@ -24,6 +25,7 @@ mod timer; mod verge; pub use self::clash::*; +pub use self::enhance::*; pub use self::prfitem::*; pub use self::profiles::*; pub use self::service::*; @@ -114,12 +116,12 @@ impl Core { log_if_err!(self.update_systray(&app_handle)); log_if_err!(self.update_systray_clash(&app_handle)); - // wait the window setup during resolve app - let core = self.clone(); - tauri::async_runtime::spawn(async move { - sleep(Duration::from_secs(2)).await; - log_if_err!(core.activate_enhanced(true)); - }); + // // wait the window setup during resolve app + // let core = self.clone(); + // tauri::async_runtime::spawn(async move { + // sleep(Duration::from_secs(2)).await; + // log_if_err!(core.activate_enhanced(true)); + // }); // timer initialize let mut timer = self.timer.lock(); @@ -139,8 +141,8 @@ impl Core { service.restart()?; drop(service); - self.activate()?; - self.activate_enhanced(true) + self.activate() + // self.activate_enhanced(true) } /// change the clash core @@ -164,8 +166,8 @@ impl Core { service.start()?; drop(service); - self.activate()?; - self.activate_enhanced(true) + self.activate() + // self.activate_enhanced(true) } /// Patch Clash @@ -184,7 +186,7 @@ impl Core { drop(service); self.activate()?; - self.activate_enhanced(true)?; + // self.activate_enhanced(true)?; let mut sysopt = self.sysopt.lock(); let verge = self.verge.lock(); @@ -219,7 +221,8 @@ impl Core { service.start()?; drop(service); - self.activate_enhanced(false)?; + // self.activate_enhanced(false)?; + self.activate()?; } } @@ -257,7 +260,8 @@ impl Core { } if tun_mode.is_some() { - self.activate_enhanced(false)?; + // self.activate_enhanced(false)?; + self.activate()?; } Ok(()) @@ -341,127 +345,130 @@ impl Core { /// activate the profile /// auto activate enhanced profile pub fn activate(&self) -> Result<()> { - let data = { - let profiles = self.profiles.lock(); - let data = profiles.gen_activate()?; - Clash::strict_filter(data) - }; - - let mut clash = self.clash.lock(); - - let mut config = clash.config.clone(); - let info = clash.info.clone(); - - for (key, value) in data.into_iter() { - config.insert(key, value); - } - - let config = { - let verge = self.verge.lock(); - let tun_mode = verge.enable_tun_mode.unwrap_or(false); - Clash::_tun_mode(config, tun_mode) - }; - - let notice = { - let window = self.window.lock(); - Notice::from(window.clone()) - }; - - clash.set_running_config(&config); - drop(clash); - - let service = self.service.lock(); - service.set_config(info, config, notice) - } - - /// Enhanced - /// enhanced profiles mode - pub fn activate_enhanced(&self, skip: bool) -> Result<()> { - let window = self.window.lock(); - if window.is_none() { - bail!("failed to get the main window"); - } - - let event_name = help::get_uid("e"); - let event_name = format!("enhanced-cb-{event_name}"); - - // generate the payload - let payload = { - let profiles = self.profiles.lock(); - profiles.gen_enhanced(event_name.clone())? - }; - - // do not run enhanced - if payload.chain.len() == 0 { - if skip { - return Ok(()); - } - - drop(window); - return self.activate(); - } + let profiles = self.profiles.lock(); + let profile_config = profiles.gen_activate()?; + let profile_enhanced = profiles.gen_enhanced("".into())?; + drop(profiles); let tun_mode = { let verge = self.verge.lock(); verge.enable_tun_mode.unwrap_or(false) }; - let info = { - let clash = self.clash.lock(); - clash.info.clone() + let mut clash = self.clash.lock(); + let clash_config = clash.config.clone(); + + let (config, result) = runtime_config( + clash_config, + profile_config, + profile_enhanced.chain, + profile_enhanced.valid, + ); + + dbg!(result); + + let info = clash.info.clone(); + + clash.set_running_config(&config); + drop(clash); + + let notice = { + let window = self.window.lock(); + Notice::from(window.clone()) }; - let notice = Notice::from(window.clone()); - let service = self.service.clone(); - - let window = window.clone().unwrap(); - window.once(&event_name, move |event| { - let result = event.payload(); - - if result.is_none() { - log::warn!(target: "app", "event payload result is none"); - return; - } - - let result = result.unwrap(); - let result: PrfEnhancedResult = serde_json::from_str(result).unwrap(); - - if let Some(data) = result.data { - let mut config = Clash::read_config(); - let filter_data = Clash::loose_filter(data); // loose filter - - for (key, value) in filter_data.into_iter() { - config.insert(key, value); - } - - let config = Clash::_tun_mode(config, tun_mode); - - let service = service.lock(); - log_if_err!(service.set_config(info, config, notice)); - - log::info!(target: "app", "profile enhanced status {}", result.status); - } - - result.error.map(|err| log::error!(target: "app", "{err}")); - }); - - let verge = self.verge.lock(); - let silent_start = verge.enable_silent_start.clone(); - - let closable = unsafe { WINDOW_CLOSABLE }; - - if silent_start.unwrap_or(false) && closable { - unsafe { - WINDOW_CLOSABLE = false; - } - - window.emit("script-handler-close", payload).unwrap(); - } else { - window.emit("script-handler", payload).unwrap(); - } - - Ok(()) + let service = self.service.lock(); + service.set_config(info, config, notice) } + + // /// Enhanced + // /// enhanced profiles mode + // pub fn activate_enhanced(&self, skip: bool) -> Result<()> { + // let window = self.window.lock(); + // if window.is_none() { + // bail!("failed to get the main window"); + // } + + // let event_name = help::get_uid("e"); + // let event_name = format!("enhanced-cb-{event_name}"); + + // // generate the payload + // let payload = { + // let profiles = self.profiles.lock(); + // profiles.gen_enhanced(event_name.clone())? + // }; + + // // do not run enhanced + // if payload.chain.len() == 0 { + // if skip { + // return Ok(()); + // } + + // drop(window); + // return self.activate(); + // } + + // let tun_mode = { + // let verge = self.verge.lock(); + // verge.enable_tun_mode.unwrap_or(false) + // }; + + // let info = { + // let clash = self.clash.lock(); + // clash.info.clone() + // }; + + // let notice = Notice::from(window.clone()); + // let service = self.service.clone(); + + // let window = window.clone().unwrap(); + // window.once(&event_name, move |event| { + // let result = event.payload(); + + // if result.is_none() { + // log::warn!(target: "app", "event payload result is none"); + // return; + // } + + // let result = result.unwrap(); + // let result: PrfEnhancedResult = serde_json::from_str(result).unwrap(); + + // if let Some(data) = result.data { + // let mut config = Clash::read_config(); + // let filter_data = Clash::loose_filter(data); // loose filter + + // for (key, value) in filter_data.into_iter() { + // config.insert(key, value); + // } + + // let config = Clash::_tun_mode(config, tun_mode); + + // let service = service.lock(); + // log_if_err!(service.set_config(info, config, notice)); + + // log::info!(target: "app", "profile enhanced status {}", result.status); + // } + + // result.error.map(|err| log::error!(target: "app", "{err}")); + // }); + + // let verge = self.verge.lock(); + // let silent_start = verge.enable_silent_start.clone(); + + // let closable = unsafe { WINDOW_CLOSABLE }; + + // if silent_start.unwrap_or(false) && closable { + // unsafe { + // WINDOW_CLOSABLE = false; + // } + + // window.emit("script-handler-close", payload).unwrap(); + // } else { + // window.emit("script-handler", payload).unwrap(); + // } + + // Ok(()) + // } } impl Core { @@ -482,7 +489,8 @@ impl Core { // reactivate the config if Some(uid) == profiles.get_current() { drop(profiles); - return core.activate_enhanced(false); + // return core.activate_enhanced(false); + return core.activate(); } return Ok(()); @@ -505,7 +513,8 @@ impl Core { // reactivate the profile if Some(uid) == profiles.get_current() { drop(profiles); - core.activate_enhanced(false)?; + // core.activate_enhanced(false)?; + core.activate()?; } Ok(()) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index b5d3978..0277526 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -4,6 +4,7 @@ )] mod cmds; +mod config; mod core; mod utils;