Browse Source

feat: reimplement enhanced mode

GyDi 2 years ago
parent
commit
38effaf740
3 changed files with 297 additions and 32 deletions
  1. 93 31
      src-tauri/Cargo.lock
  2. 1 0
      src-tauri/Cargo.toml
  3. 203 1
      src-tauri/src/core/enhance.rs

+ 93 - 31
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]]

+ 1 - 0
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" }
 

+ 203 - 1
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<String>) -> Vec<String> {
+  let mut valid_list: Vec<String> = 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<String>) -> 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<String>) -> 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<String>,
+) -> 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::<Mapping>(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::<Mapping>(merge)?;
+  let config = serde_yaml::from_str::<Mapping>(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);
+}