From 3a9734e97daf53142da23783911fb50272c981bf Mon Sep 17 00:00:00 2001
From: GyDi <segydi@foxmail.com>
Date: Fri, 17 Dec 2021 02:15:40 +0800
Subject: [PATCH] feat: support set system proxy command

---
 src-tauri/src/cmd.rs            | 42 +++++++++++++++++++++++++++++++++
 src-tauri/src/config/clash.rs   |  3 +++
 src-tauri/src/config/operate.rs | 28 +++++++++++++++++++++-
 src-tauri/src/main.rs           |  1 +
 src-tauri/src/utils/sysopt.rs   |  6 ++---
 5 files changed, 76 insertions(+), 4 deletions(-)

diff --git a/src-tauri/src/cmd.rs b/src-tauri/src/cmd.rs
index 87feab9..421c724 100644
--- a/src-tauri/src/cmd.rs
+++ b/src-tauri/src/cmd.rs
@@ -8,6 +8,7 @@ use crate::{
     app_home_dir,
     clash::{self, put_clash_profile},
     fetch::fetch_profile,
+    sysopt::{set_proxy_config, SysProxyConfig},
   },
 };
 use std::fs::File;
@@ -171,3 +172,44 @@ pub async fn put_profiles(
   save_profiles(&profiles);
   put_clash_profile(&clash_info).await
 }
+
+#[tauri::command]
+/// set system proxy
+pub fn set_sys_proxy(enable: bool, clash_info: State<'_, ClashInfoState>) -> Result<(), String> {
+  let clash_info = match clash_info.0.lock() {
+    Ok(arc) => arc.clone(),
+    _ => return Err(format!("can not get clash info")),
+  };
+
+  let port = match clash_info.controller {
+    Some(ctrl) => ctrl.port,
+    None => None,
+  };
+
+  if port.is_none() {
+    return Err(format!("can not get clash core's port"));
+  }
+
+  let config = if enable {
+    let server = format!("127.0.0.1:{}", port.unwrap());
+    // todo
+    let bypass = String::from("localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*");
+
+    SysProxyConfig {
+      enable,
+      server,
+      bypass,
+    }
+  } else {
+    SysProxyConfig {
+      enable,
+      server: String::from(""),
+      bypass: String::from(""),
+    }
+  };
+
+  match set_proxy_config(&config) {
+    Ok(_) => Ok(()),
+    Err(_) => Err(format!("can not set proxy")),
+  }
+}
diff --git a/src-tauri/src/config/clash.rs b/src-tauri/src/config/clash.rs
index 4c8760d..245b846 100644
--- a/src-tauri/src/config/clash.rs
+++ b/src-tauri/src/config/clash.rs
@@ -21,6 +21,9 @@ pub struct ClashConfig {
 
 #[derive(Default, Debug, Clone, Deserialize, Serialize)]
 pub struct ClashController {
+  /// clash core port
+  pub port: Option<String>,
+
   /// same as `external-controller`
   pub server: Option<String>,
   pub secret: Option<String>,
diff --git a/src-tauri/src/config/operate.rs b/src-tauri/src/config/operate.rs
index b5c944f..388ed74 100644
--- a/src-tauri/src/config/operate.rs
+++ b/src-tauri/src/config/operate.rs
@@ -44,9 +44,31 @@ pub fn read_clash() -> Mapping {
 pub fn read_clash_controller() -> ClashController {
   let config = read_clash();
 
+  let key_port_1 = Value::String("port".to_string());
+  let key_port_2 = Value::String("mixed-port".to_string());
   let key_server = Value::String("external-controller".to_string());
   let key_secret = Value::String("secret".to_string());
 
+  let port = match config.get(&key_port_1) {
+    Some(value) => match value {
+      Value::String(val_str) => Some(val_str.clone()),
+      Value::Number(val_num) => Some(val_num.to_string()),
+      _ => None,
+    },
+    _ => None,
+  };
+  let port = match port {
+    Some(_) => port,
+    None => match config.get(&key_port_2) {
+      Some(value) => match value {
+        Value::String(val_str) => Some(val_str.clone()),
+        Value::Number(val_num) => Some(val_num.to_string()),
+        _ => None,
+      },
+      _ => None,
+    },
+  };
+
   let server = match config.get(&key_server) {
     Some(value) => match value {
       Value::String(val_str) => Some(val_str.clone()),
@@ -64,7 +86,11 @@ pub fn read_clash_controller() -> ClashController {
     _ => None,
   };
 
-  ClashController { server, secret }
+  ClashController {
+    port,
+    server,
+    secret,
+  }
 }
 
 /// Get Profiles Config
diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs
index 920ce82..3177d69 100644
--- a/src-tauri/src/main.rs
+++ b/src-tauri/src/main.rs
@@ -63,6 +63,7 @@ fn main() -> std::io::Result<()> {
       cmd::get_profiles,
       cmd::set_profiles,
       cmd::put_profiles,
+      cmd::set_sys_proxy,
     ])
     .build(tauri::generate_context!())
     .expect("error while running tauri application");
diff --git a/src-tauri/src/utils/sysopt.rs b/src-tauri/src/utils/sysopt.rs
index 4e42154..6e487cb 100644
--- a/src-tauri/src/utils/sysopt.rs
+++ b/src-tauri/src/utils/sysopt.rs
@@ -3,9 +3,9 @@ use std::io;
 
 #[derive(Debug, Deserialize, Serialize)]
 pub struct SysProxyConfig {
-  enable: bool,
-  server: String,
-  bypass: String,
+  pub enable: bool,
+  pub server: String,
+  pub bypass: String,
 }
 
 #[cfg(target_os = "windows")]
-- 
GitLab