diff --git a/src-tauri/src/config/config.rs b/src-tauri/src/config/config.rs index 1ba7a1e05e9d362f54f031076b5d062e0e6a2a30..e5af8e591f30c8c3b07c5ebf39b2013308347506 100644 --- a/src-tauri/src/config/config.rs +++ b/src-tauri/src/config/config.rs @@ -84,15 +84,7 @@ impl Config { /// 生æˆé…ç½®å˜å¥½ pub fn generate() -> Result<()> { - let clash_config = { Config::clash().latest().clone() }; - - let tun_mode = { Config::verge().latest().enable_tun_mode.clone() }; - let tun_mode = tun_mode.unwrap_or(false); - - let pa = { Config::profiles().latest().gen_activate()? }; - - let (config, exists_keys, logs) = - enhance::enhance_config(clash_config.0, pa.current, pa.chain, pa.valid, tun_mode); + let (config, exists_keys, logs) = enhance::enhance(); *Config::runtime().draft() = IRuntime { config: Some(config), diff --git a/src-tauri/src/config/prfitem.rs b/src-tauri/src/config/prfitem.rs index 664ad05002a5c55cecfd4985fae118ec6c3b1698..8bf8cce51a42236a3b89a38a1f18a01d18335362 100644 --- a/src-tauri/src/config/prfitem.rs +++ b/src-tauri/src/config/prfitem.rs @@ -369,40 +369,4 @@ impl PrfItem { let path = dirs::app_profiles_dir()?.join(file); fs::write(path, data.as_bytes()).context("failed to save the file") } - - /// get the data for enhanced mode - pub fn to_enhance(&self) -> Option<ChainItem> { - let itype = self.itype.as_ref()?.as_str(); - let file = self.file.clone()?; - let uid = self.uid.clone().unwrap_or("".into()); - let path = dirs::app_profiles_dir().ok()?.join(file); - - if !path.exists() { - return None; - } - - match itype { - "script" => Some(ChainItem { - uid, - data: ChainType::Script(fs::read_to_string(path).ok()?), - }), - "merge" => Some(ChainItem { - uid, - data: ChainType::Merge(help::read_merge_mapping(&path).ok()?), - }), - _ => None, - } - } -} - -#[derive(Debug, Clone)] -pub struct ChainItem { - pub uid: String, - pub data: ChainType, -} - -#[derive(Debug, Clone)] -pub enum ChainType { - Merge(Mapping), - Script(String), } diff --git a/src-tauri/src/config/profiles.rs b/src-tauri/src/config/profiles.rs index f6a6399a3d8a2021ae9d948595c71830c0011fa7..47dfb43b0dff51fd6f2d62e0964d7d56ffdb2a25 100644 --- a/src-tauri/src/config/profiles.rs +++ b/src-tauri/src/config/profiles.rs @@ -1,4 +1,4 @@ -use super::{prfitem::PrfItem, ChainItem}; +use super::prfitem::PrfItem; use crate::utils::{dirs, help}; use anyhow::{bail, Context, Result}; use serde::{Deserialize, Serialize}; @@ -261,52 +261,20 @@ impl IProfiles { Ok(current == uid) } - /// generate the current Mapping data - fn gen_current(&self) -> Result<Mapping> { - let config = Mapping::new(); - - if self.current.is_none() || self.items.is_none() { - return Ok(config); - } - - let current = self.current.as_ref().unwrap(); - for item in self.items.as_ref().unwrap().iter() { - if item.uid.as_ref() == Some(current) { - let file_path = match item.file.as_ref() { - Some(file) => dirs::app_profiles_dir()?.join(file), - None => bail!("failed to get the file field"), - }; - - return Ok(help::read_merge_mapping(&file_path)?); + /// 获å–current指å‘çš„é…置内容 + pub fn current_mapping(&self) -> Result<Mapping> { + match (self.current.as_ref(), self.items.as_ref()) { + (Some(current), Some(items)) => { + if let Some(item) = items.iter().find(|e| e.uid.as_ref() == Some(current)) { + let file_path = match item.file.as_ref() { + Some(file) => dirs::app_profiles_dir()?.join(file), + None => bail!("failed to get the file field"), + }; + return Ok(help::read_merge_mapping(&file_path)?); + } + bail!("failed to find the current profile \"uid:{current}\""); } + _ => Ok(Mapping::new()), } - bail!("failed to find the current profile \"uid:{current}\""); } - - /// generate the data for activate clash config - pub fn gen_activate(&self) -> Result<PrfActivate> { - let current = self.gen_current()?; - let chain = match self.chain.as_ref() { - Some(chain) => chain - .iter() - .filter_map(|uid| self.get_item(uid).ok()) - .filter_map(|item| item.to_enhance()) - .collect::<Vec<ChainItem>>(), - None => vec![], - }; - let valid = self.valid.clone().unwrap_or(vec![]); - - Ok(PrfActivate { - current, - chain, - valid, - }) - } -} - -#[derive(Default, Clone)] -pub struct PrfActivate { - pub current: Mapping, - pub chain: Vec<ChainItem>, - pub valid: Vec<String>, } diff --git a/src-tauri/src/config/verge.rs b/src-tauri/src/config/verge.rs index 60143ee444568e43d3806c18d41cf73763a29991..43f175b0ee4605b045e14e3ccbc6e1260a27c1b1 100644 --- a/src-tauri/src/config/verge.rs +++ b/src-tauri/src/config/verge.rs @@ -65,6 +65,9 @@ pub struct IVerge { /// 默认的延迟测试连接 pub default_latency_test: Option<String>, + + /// 是å¦ä½¿ç”¨å†…部的脚本支æŒï¼Œé»˜è®¤ä¸ºçœŸ + pub enable_builtin_enhanced: Option<bool>, } #[derive(Default, Debug, Clone, Deserialize, Serialize)] @@ -107,6 +110,7 @@ impl IVerge { enable_proxy_guard: Some(false), proxy_guard_duration: Some(30), auto_close_connection: Some(true), + enable_builtin_enhanced: Some(true), ..Self::default() } } @@ -148,6 +152,7 @@ impl IVerge { patch!(auto_close_connection); patch!(default_latency_test); + patch!(enable_builtin_enhanced); } /// 在åˆå§‹åŒ–å‰å°è¯•æ‹¿åˆ°å•ä¾‹ç«¯å£çš„值 diff --git a/src-tauri/src/enhance/builtin/hy_alpn.js b/src-tauri/src/enhance/builtin/hy_alpn.js new file mode 100644 index 0000000000000000000000000000000000000000..da1fac0eb69743d4d21209133cd70ecd76310d30 --- /dev/null +++ b/src-tauri/src/enhance/builtin/hy_alpn.js @@ -0,0 +1,10 @@ +function main(params) { + if (Array.isArray(params.proxies)) { + params.proxies.forEach((p, i) => { + if (p.type === "hysteria" && typeof p.alpn === "string") { + params.proxies[i].alpn = [p.alpn]; + } + }); + } + return params; +} diff --git a/src-tauri/src/enhance/chain.rs b/src-tauri/src/enhance/chain.rs new file mode 100644 index 0000000000000000000000000000000000000000..1d65ba22a05f026a93359d2caa46c25004b76a9a --- /dev/null +++ b/src-tauri/src/enhance/chain.rs @@ -0,0 +1,56 @@ +use crate::{ + config::PrfItem, + utils::{dirs, help}, +}; +use serde_yaml::Mapping; +use std::fs; + +#[derive(Debug, Clone)] +pub struct ChainItem { + pub uid: String, + pub data: ChainType, +} + +#[derive(Debug, Clone)] +pub enum ChainType { + Merge(Mapping), + Script(String), +} + +impl From<&PrfItem> for Option<ChainItem> { + fn from(item: &PrfItem) -> Self { + let itype = item.itype.as_ref()?.as_str(); + let file = item.file.clone()?; + let uid = item.uid.clone().unwrap_or("".into()); + let path = dirs::app_profiles_dir().ok()?.join(file); + + if !path.exists() { + return None; + } + + match itype { + "script" => Some(ChainItem { + uid, + data: ChainType::Script(fs::read_to_string(path).ok()?), + }), + "merge" => Some(ChainItem { + uid, + data: ChainType::Merge(help::read_merge_mapping(&path).ok()?), + }), + _ => None, + } + } +} + +impl ChainItem { + /// 内建支æŒä¸€äº›è„šæœ¬ + pub fn builtin() -> Vec<ChainItem> { + // meta 1.13.2 alpn string 转 数组 + let hy_alpn = ChainItem { + uid: "verge_hy_alpn".into(), + data: ChainType::Script(include_str!("./builtin/hy_alpn.js").into()), + }; + + vec![hy_alpn] + } +} diff --git a/src-tauri/src/enhance/mod.rs b/src-tauri/src/enhance/mod.rs index 0b00035a8db5227fb88132982fdb515e2cdd044d..4cf9231b486ad5729677b3b0feed2969435d42df 100644 --- a/src-tauri/src/enhance/mod.rs +++ b/src-tauri/src/enhance/mod.rs @@ -1,32 +1,67 @@ +mod chain; mod field; mod merge; mod script; mod tun; +use self::chain::*; pub(self) use self::field::*; use self::merge::*; use self::script::*; use self::tun::*; -use crate::config::{ChainItem, ChainType}; +use crate::config::Config; use serde_yaml::Mapping; use std::collections::HashMap; use std::collections::HashSet; type ResultLog = Vec<(String, String)>; -pub fn enhance_config( - clash_config: Mapping, - profile_config: Mapping, - chain: Vec<ChainItem>, - valid: Vec<String>, - tun_mode: bool, -) -> (Mapping, Vec<String>, HashMap<String, ResultLog>) { - let mut config = profile_config; +/// Enhance mode +/// 返回最终é…ç½®ã€è¯¥é…置包å«çš„é”®ã€å’Œscript执行的结果 +pub fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) { + let clash_config = { Config::clash().latest().0.clone() }; + + let (tun_mode, enable_builtin) = { + let verge = Config::verge(); + let verge = verge.latest(); + ( + verge.enable_tun_mode.clone(), + verge.enable_builtin_enhanced.clone(), + ) + }; + + let tun_mode = tun_mode.unwrap_or(false); + let enable_builtin = enable_builtin.unwrap_or(true); + + let (mut config, mut chain, valid) = { + let profiles = Config::profiles(); + let profiles = profiles.latest(); + + let current = profiles.current_mapping().unwrap_or(Mapping::new()); + + let chain = match profiles.chain.as_ref() { + Some(chain) => chain + .iter() + .filter_map(|uid| profiles.get_item(uid).ok()) + .filter_map(|item| <Option<ChainItem>>::from(item)) + .collect::<Vec<ChainItem>>(), + None => vec![], + }; + + let valid = profiles.valid.clone().unwrap_or(vec![]); + + (current, chain, valid) + }; + let mut result_map = HashMap::new(); let mut exists_keys = use_keys(&config); let valid = use_valid_fields(valid); + if enable_builtin { + chain.extend(ChainItem::builtin().into_iter()); + } + chain.into_iter().for_each(|item| match item.data { ChainType::Merge(merge) => { exists_keys.extend(use_keys(&merge));