diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 9eeec39..acf2ad1 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -64,7 +64,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -131,7 +131,7 @@ dependencies = [ "slab", "socket2", "waker-fn", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -168,7 +168,7 @@ dependencies = [ "libc", "once_cell", "signal-hook 0.3.14", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -484,7 +484,7 @@ dependencies = [ "num-integer", "num-traits", "time 0.1.44", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -504,6 +504,7 @@ dependencies = [ "open 2.1.3", "parking_lot 0.12.1", "port_scanner", + "quick-js", "reqwest", "runas", "serde", @@ -592,6 +593,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "copy_dir" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4281031634644843bd2f5aa9c48cf98fc48d6b083bd90bb11becf10deaf8b0" +dependencies = [ + "walkdir 0.1.8", +] + [[package]] name = "core-foundation" version = "0.9.3" @@ -791,7 +801,7 @@ dependencies = [ "rand 0.8.5", "shared_library", "termwiz", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -918,7 +928,7 @@ checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -929,7 +939,7 @@ checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", "redox_users", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1035,7 +1045,7 @@ checksum = "7199d965852c3bac31f779ef99cbb4537f80e952e2d6aa0ffeb30cce00f4f46e" dependencies = [ "libc", "thiserror", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1296,7 +1306,7 @@ dependencies = [ "libc", "log", "rustversion", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1364,7 +1374,7 @@ dependencies = [ "gobject-sys", "libc", "system-deps 6.0.2", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1724,7 +1734,7 @@ dependencies = [ "regex", "same-file", "thread_local", - "walkdir", + "walkdir 2.3.2", "winapi-util", ] @@ -1831,7 +1841,7 @@ dependencies = [ "jni-sys", "log", "thiserror", - "walkdir", + "walkdir 2.3.2", ] [[package]] @@ -1845,7 +1855,7 @@ dependencies = [ "jni-sys", "log", "thiserror", - "walkdir", + "walkdir 2.3.2", ] [[package]] @@ -1874,6 +1884,16 @@ dependencies = [ "treediff", ] +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "kuchiki" version = "0.8.1" @@ -1929,7 +1949,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" dependencies = [ "cfg-if 1.0.0", - "winapi", + "winapi 0.3.9", +] + +[[package]] +name = "libquickjs-sys" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f0b24e9bd171b75ae0295bd428fb8fe58410fb23156e5f34a4657a70c3cee96" +dependencies = [ + "cc", + "copy_dir", ] [[package]] @@ -1996,7 +2026,7 @@ dependencies = [ "thiserror", "thread-id", "typemap", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2475,7 +2505,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c92f2b54f081d635c77e7120862d48db8e91f7f21cef23ab1b4fe9971c59f55" dependencies = [ "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2541,7 +2571,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2778,7 +2808,7 @@ dependencies = [ "libc", "log", "wepoll-ffi", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2854,6 +2884,16 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quick-js" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19cb4cefcb00f4ab9b332664d06005a74f582ac16aa959c6ad5912957bd83e5f" +dependencies = [ + "libquickjs-sys", + "once_cell", +] + [[package]] name = "quote" version = "1.0.20" @@ -3005,7 +3045,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -3447,7 +3487,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0d94659ad3c2137fef23ae75b03d5241d633f8acded53d672decfa0e6e0caef" dependencies = [ "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -3532,7 +3572,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" dependencies = [ "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -3800,7 +3840,7 @@ dependencies = [ "thiserror", "time 0.3.11", "uuid 1.1.2", - "walkdir", + "walkdir 2.3.2", ] [[package]] @@ -3880,7 +3920,7 @@ dependencies = [ "serde_with", "thiserror", "url", - "walkdir", + "walkdir 2.3.2", "windows", ] @@ -3895,7 +3935,7 @@ dependencies = [ "libc", "redox_syscall", "remove_dir_all", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -3960,7 +4000,7 @@ dependencies = [ "ucd-trie", "unicode-segmentation", "vtparse", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -3997,7 +4037,7 @@ checksum = "5fdfe0627923f7411a43ec9ec9c39c3a9b4151be313e0922042581fb6c9b717f" dependencies = [ "libc", "redox_syscall", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -4017,7 +4057,7 @@ checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -4064,7 +4104,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -4441,6 +4481,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +[[package]] +name = "walkdir" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66c0b9792f0a765345452775f3adbd28dde9d33f30d13e5dcc5ae17cf6f3780" +dependencies = [ + "kernel32-sys", + "winapi 0.2.8", +] + [[package]] name = "walkdir" version = "2.3.2" @@ -4448,7 +4498,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" dependencies = [ "same-file", - "winapi", + "winapi 0.3.9", "winapi-util", ] @@ -4706,6 +4756,12 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee583bdc5ff1cf9db20e9db5bb3ff4c3089a8f6b8b31aff265c9aba85812db86" +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + [[package]] name = "winapi" version = "0.3.9" @@ -4716,6 +4772,12 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -4728,7 +4790,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -4886,7 +4948,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 7801b37..1dd2323 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -33,6 +33,7 @@ tokio = { version = "1", features = ["full"] } serde = { version = "1.0", features = ["derive"] } reqwest = { version = "0.11", features = ["json"] } tauri = { version = "1.0.0", features = ["process-all", "shell-all", "system-tray", "updater", "window-all"] } +quick-js = { version = "0.4.1" } window-shadows = { version = "0.1" } window-vibrancy = { version = "0.1" } diff --git a/src-tauri/src/core/enhance.rs b/src-tauri/src/core/enhance.rs index a1c79e8..2bcdc59 100644 --- a/src-tauri/src/core/enhance.rs +++ b/src-tauri/src/core/enhance.rs @@ -1,7 +1,8 @@ use super::prfitem::PrfItem; use crate::utils::{config, dirs}; +use anyhow::Result; use serde::{Deserialize, Serialize}; -use serde_yaml::Mapping; +use serde_yaml::{self, Mapping, Sequence, Value}; use std::fs; #[derive(Default, Debug, Clone, Serialize, Deserialize)] @@ -64,3 +65,204 @@ 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 quick_js::{Context, JsValue}; + use std::sync::{Arc, Mutex}; + + let context = Context::new().unwrap(); + let outputs = Arc::new(Mutex::new(vec![])); + + let copy_outputs = outputs.clone(); + context.add_callback("__verge__log__", move |level: String, data: String| { + let mut out = copy_outputs.lock().unwrap(); + out.push((level, data)); + JsValue::Undefined + })?; + + context.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))}, + });"#, + )?; + + let config_str = serde_json::to_string(&config)?; + + let code = format!("\n{script}\n;\nJSON.stringify(main({config_str}))"); + let result = context.eval(code.as_str())?; + + let mut out = outputs.lock().unwrap(); + match result.into_string() { + Some(result) => match serde_json::from_str::(result.as_str()) { + Ok(config) => { + let config = use_valid_filter(config, valid); + Ok((config, out.to_vec())) + } + Err(_) => { + out.push(("error".into(), "failed to parse json string".into())); + Ok((config, out.to_vec())) + } + }, + None => { + out.push(("error".into(), "main function should return object".into())); + 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) { + config.rules = [...config.rules, "add"]; + config.proxies = ["111"]; + console.log(config); + 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); +}