mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2024-11-16 11:42:21 +08:00
feat: support seq editor
Some checks are pending
Alpha Build / alpha (macos-latest, aarch64-apple-darwin) (push) Waiting to run
Alpha Build / alpha (macos-latest, x86_64-apple-darwin) (push) Waiting to run
Alpha Build / alpha (windows-latest, aarch64-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha (windows-latest, i686-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha (windows-latest, x86_64-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha-for-linux (ubuntu-latest, aarch64-unknown-linux-gnu) (push) Waiting to run
Alpha Build / alpha-for-linux (ubuntu-latest, armv7-unknown-linux-gnueabihf) (push) Waiting to run
Alpha Build / alpha-for-linux (ubuntu-latest, i686-unknown-linux-gnu) (push) Waiting to run
Alpha Build / alpha-for-linux (ubuntu-latest, x86_64-unknown-linux-gnu) (push) Waiting to run
Alpha Build / alpha-for-fixed-webview2 (arm64, windows-latest, aarch64-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha-for-fixed-webview2 (x64, windows-latest, x86_64-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha-for-fixed-webview2 (x86, windows-latest, i686-pc-windows-msvc) (push) Waiting to run
Alpha Build / Update tag (push) Blocked by required conditions
Some checks are pending
Alpha Build / alpha (macos-latest, aarch64-apple-darwin) (push) Waiting to run
Alpha Build / alpha (macos-latest, x86_64-apple-darwin) (push) Waiting to run
Alpha Build / alpha (windows-latest, aarch64-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha (windows-latest, i686-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha (windows-latest, x86_64-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha-for-linux (ubuntu-latest, aarch64-unknown-linux-gnu) (push) Waiting to run
Alpha Build / alpha-for-linux (ubuntu-latest, armv7-unknown-linux-gnueabihf) (push) Waiting to run
Alpha Build / alpha-for-linux (ubuntu-latest, i686-unknown-linux-gnu) (push) Waiting to run
Alpha Build / alpha-for-linux (ubuntu-latest, x86_64-unknown-linux-gnu) (push) Waiting to run
Alpha Build / alpha-for-fixed-webview2 (arm64, windows-latest, aarch64-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha-for-fixed-webview2 (x64, windows-latest, x86_64-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha-for-fixed-webview2 (x86, windows-latest, i686-pc-windows-msvc) (push) Waiting to run
Alpha Build / Update tag (push) Blocked by required conditions
This commit is contained in:
parent
cf61a96ef6
commit
b854b5e1ac
|
@ -13,7 +13,7 @@ pub struct IClashTemp(pub Mapping);
|
||||||
impl IClashTemp {
|
impl IClashTemp {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let template = Self::template();
|
let template = Self::template();
|
||||||
match dirs::clash_path().and_then(|path| help::read_merge_mapping(&path)) {
|
match dirs::clash_path().and_then(|path| help::read_mapping(&path)) {
|
||||||
Ok(mut map) => {
|
Ok(mut map) => {
|
||||||
template.0.keys().for_each(|key| {
|
template.0.keys().for_each(|key| {
|
||||||
if !map.contains_key(key) {
|
if !map.contains_key(key) {
|
||||||
|
|
|
@ -152,8 +152,6 @@ impl PrfItem {
|
||||||
let desc = item.desc.unwrap_or("".into());
|
let desc = item.desc.unwrap_or("".into());
|
||||||
PrfItem::from_local(name, desc, file_data, item.option)
|
PrfItem::from_local(name, desc, file_data, item.option)
|
||||||
}
|
}
|
||||||
"merge" => PrfItem::from_merge(),
|
|
||||||
"script" => PrfItem::from_script(),
|
|
||||||
typ => bail!("invalid profile item type \"{typ}\""),
|
typ => bail!("invalid profile item type \"{typ}\""),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,15 +164,15 @@ impl PrfItem {
|
||||||
file_data: Option<String>,
|
file_data: Option<String>,
|
||||||
option: Option<PrfOption>,
|
option: Option<PrfOption>,
|
||||||
) -> Result<PrfItem> {
|
) -> Result<PrfItem> {
|
||||||
let uid = help::get_uid("l");
|
let uid = help::get_uid("L");
|
||||||
let file = format!("{uid}.yaml");
|
let file = format!("{uid}.yaml");
|
||||||
let opt_ref = option.as_ref();
|
let opt_ref = option.as_ref();
|
||||||
let update_interval = opt_ref.and_then(|o| o.update_interval);
|
let update_interval = opt_ref.and_then(|o| o.update_interval);
|
||||||
let mut merge = opt_ref.and_then(|o| o.merge.clone());
|
let mut merge = opt_ref.and_then(|o| o.merge.clone());
|
||||||
let mut script = opt_ref.and_then(|o| o.script.clone());
|
let mut script = opt_ref.and_then(|o| o.script.clone());
|
||||||
let rules = opt_ref.and_then(|o| o.rules.clone());
|
let mut rules = opt_ref.and_then(|o| o.rules.clone());
|
||||||
let proxies = opt_ref.and_then(|o| o.proxies.clone());
|
let mut proxies = opt_ref.and_then(|o| o.proxies.clone());
|
||||||
let groups = opt_ref.and_then(|o| o.groups.clone());
|
let mut groups = opt_ref.and_then(|o| o.groups.clone());
|
||||||
|
|
||||||
if merge.is_none() {
|
if merge.is_none() {
|
||||||
let merge_item = PrfItem::from_merge()?;
|
let merge_item = PrfItem::from_merge()?;
|
||||||
|
@ -186,6 +184,23 @@ impl PrfItem {
|
||||||
Config::profiles().data().append_item(script_item.clone())?;
|
Config::profiles().data().append_item(script_item.clone())?;
|
||||||
script = script_item.uid;
|
script = script_item.uid;
|
||||||
}
|
}
|
||||||
|
if rules.is_none() {
|
||||||
|
let rules_item = PrfItem::from_rules()?;
|
||||||
|
Config::profiles().data().append_item(rules_item.clone())?;
|
||||||
|
rules = rules_item.uid;
|
||||||
|
}
|
||||||
|
if proxies.is_none() {
|
||||||
|
let proxies_item = PrfItem::from_proxies()?;
|
||||||
|
Config::profiles()
|
||||||
|
.data()
|
||||||
|
.append_item(proxies_item.clone())?;
|
||||||
|
proxies = proxies_item.uid;
|
||||||
|
}
|
||||||
|
if groups.is_none() {
|
||||||
|
let groups_item = PrfItem::from_groups()?;
|
||||||
|
Config::profiles().data().append_item(groups_item.clone())?;
|
||||||
|
groups = groups_item.uid;
|
||||||
|
}
|
||||||
Ok(PrfItem {
|
Ok(PrfItem {
|
||||||
uid: Some(uid),
|
uid: Some(uid),
|
||||||
itype: Some("local".into()),
|
itype: Some("local".into()),
|
||||||
|
@ -227,9 +242,9 @@ impl PrfItem {
|
||||||
let update_interval = opt_ref.and_then(|o| o.update_interval);
|
let update_interval = opt_ref.and_then(|o| o.update_interval);
|
||||||
let mut merge = opt_ref.and_then(|o| o.merge.clone());
|
let mut merge = opt_ref.and_then(|o| o.merge.clone());
|
||||||
let mut script = opt_ref.and_then(|o| o.script.clone());
|
let mut script = opt_ref.and_then(|o| o.script.clone());
|
||||||
let rules = opt_ref.and_then(|o| o.rules.clone());
|
let mut rules = opt_ref.and_then(|o| o.rules.clone());
|
||||||
let proxies = opt_ref.and_then(|o| o.proxies.clone());
|
let mut proxies = opt_ref.and_then(|o| o.proxies.clone());
|
||||||
let groups = opt_ref.and_then(|o| o.groups.clone());
|
let mut groups = opt_ref.and_then(|o| o.groups.clone());
|
||||||
let mut builder = reqwest::ClientBuilder::new().use_rustls_tls().no_proxy();
|
let mut builder = reqwest::ClientBuilder::new().use_rustls_tls().no_proxy();
|
||||||
|
|
||||||
if merge.is_none() {
|
if merge.is_none() {
|
||||||
|
@ -242,6 +257,23 @@ impl PrfItem {
|
||||||
Config::profiles().data().append_item(script_item.clone())?;
|
Config::profiles().data().append_item(script_item.clone())?;
|
||||||
script = script_item.uid;
|
script = script_item.uid;
|
||||||
}
|
}
|
||||||
|
if rules.is_none() {
|
||||||
|
let rules_item = PrfItem::from_rules()?;
|
||||||
|
Config::profiles().data().append_item(rules_item.clone())?;
|
||||||
|
rules = rules_item.uid;
|
||||||
|
}
|
||||||
|
if proxies.is_none() {
|
||||||
|
let proxies_item = PrfItem::from_proxies()?;
|
||||||
|
Config::profiles()
|
||||||
|
.data()
|
||||||
|
.append_item(proxies_item.clone())?;
|
||||||
|
proxies = proxies_item.uid;
|
||||||
|
}
|
||||||
|
if groups.is_none() {
|
||||||
|
let groups_item = PrfItem::from_groups()?;
|
||||||
|
Config::profiles().data().append_item(groups_item.clone())?;
|
||||||
|
groups = groups_item.uid;
|
||||||
|
}
|
||||||
// 使用软件自己的代理
|
// 使用软件自己的代理
|
||||||
if self_proxy {
|
if self_proxy {
|
||||||
let port = Config::verge()
|
let port = Config::verge()
|
||||||
|
@ -352,7 +384,7 @@ impl PrfItem {
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let uid = help::get_uid("r");
|
let uid = help::get_uid("R");
|
||||||
let file = format!("{uid}.yaml");
|
let file = format!("{uid}.yaml");
|
||||||
let name = name.unwrap_or(filename.unwrap_or("Remote File".into()));
|
let name = name.unwrap_or(filename.unwrap_or("Remote File".into()));
|
||||||
let data = resp.text_with_charset("utf-8").await?;
|
let data = resp.text_with_charset("utf-8").await?;
|
||||||
|
@ -436,6 +468,69 @@ impl PrfItem {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ## Rules type (enhance)
|
||||||
|
pub fn from_rules() -> Result<PrfItem> {
|
||||||
|
let uid = help::get_uid("r");
|
||||||
|
let file = format!("{uid}.yaml"); // yaml ext
|
||||||
|
|
||||||
|
Ok(PrfItem {
|
||||||
|
uid: Some(uid),
|
||||||
|
itype: Some("rules".into()),
|
||||||
|
name: None,
|
||||||
|
desc: None,
|
||||||
|
file: Some(file),
|
||||||
|
url: None,
|
||||||
|
home: None,
|
||||||
|
selected: None,
|
||||||
|
extra: None,
|
||||||
|
option: None,
|
||||||
|
updated: Some(chrono::Local::now().timestamp() as usize),
|
||||||
|
file_data: Some(tmpl::ITEM_RULES.into()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ## Proxies type (enhance)
|
||||||
|
pub fn from_proxies() -> Result<PrfItem> {
|
||||||
|
let uid = help::get_uid("p");
|
||||||
|
let file = format!("{uid}.yaml"); // yaml ext
|
||||||
|
|
||||||
|
Ok(PrfItem {
|
||||||
|
uid: Some(uid),
|
||||||
|
itype: Some("proxies".into()),
|
||||||
|
name: None,
|
||||||
|
desc: None,
|
||||||
|
file: Some(file),
|
||||||
|
url: None,
|
||||||
|
home: None,
|
||||||
|
selected: None,
|
||||||
|
extra: None,
|
||||||
|
option: None,
|
||||||
|
updated: Some(chrono::Local::now().timestamp() as usize),
|
||||||
|
file_data: Some(tmpl::ITEM_PROXIES.into()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ## Groups type (enhance)
|
||||||
|
pub fn from_groups() -> Result<PrfItem> {
|
||||||
|
let uid = help::get_uid("g");
|
||||||
|
let file = format!("{uid}.yaml"); // yaml ext
|
||||||
|
|
||||||
|
Ok(PrfItem {
|
||||||
|
uid: Some(uid),
|
||||||
|
itype: Some("groups".into()),
|
||||||
|
name: None,
|
||||||
|
desc: None,
|
||||||
|
file: Some(file),
|
||||||
|
url: None,
|
||||||
|
home: None,
|
||||||
|
selected: None,
|
||||||
|
extra: None,
|
||||||
|
option: None,
|
||||||
|
updated: Some(chrono::Local::now().timestamp() as usize),
|
||||||
|
file_data: Some(tmpl::ITEM_GROUPS.into()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// get the file data
|
/// get the file data
|
||||||
pub fn read_file(&self) -> Result<String> {
|
pub fn read_file(&self) -> Result<String> {
|
||||||
if self.file.is_none() {
|
if self.file.is_none() {
|
||||||
|
|
|
@ -246,9 +246,9 @@ impl IProfiles {
|
||||||
let mut index = None;
|
let mut index = None;
|
||||||
let mut merge_index = None;
|
let mut merge_index = None;
|
||||||
let mut script_index = None;
|
let mut script_index = None;
|
||||||
// let mut rules_index = None;
|
let mut rules_index = None;
|
||||||
// let mut proxies_index = None;
|
let mut proxies_index = None;
|
||||||
// let mut groups_index = None;
|
let mut groups_index = None;
|
||||||
|
|
||||||
// get the index
|
// get the index
|
||||||
for (i, _) in items.iter().enumerate() {
|
for (i, _) in items.iter().enumerate() {
|
||||||
|
@ -257,7 +257,6 @@ impl IProfiles {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(index) = index {
|
if let Some(index) = index {
|
||||||
if let Some(file) = items.remove(index).file {
|
if let Some(file) = items.remove(index).file {
|
||||||
let _ = dirs::app_profiles_dir().map(|path| {
|
let _ = dirs::app_profiles_dir().map(|path| {
|
||||||
|
@ -268,7 +267,6 @@ impl IProfiles {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the merge index
|
// get the merge index
|
||||||
for (i, _) in items.iter().enumerate() {
|
for (i, _) in items.iter().enumerate() {
|
||||||
if items[i].uid == merge_uid {
|
if items[i].uid == merge_uid {
|
||||||
|
@ -276,7 +274,6 @@ impl IProfiles {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(index) = merge_index {
|
if let Some(index) = merge_index {
|
||||||
if let Some(file) = items.remove(index).file {
|
if let Some(file) = items.remove(index).file {
|
||||||
let _ = dirs::app_profiles_dir().map(|path| {
|
let _ = dirs::app_profiles_dir().map(|path| {
|
||||||
|
@ -287,7 +284,6 @@ impl IProfiles {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the script index
|
// get the script index
|
||||||
for (i, _) in items.iter().enumerate() {
|
for (i, _) in items.iter().enumerate() {
|
||||||
if items[i].uid == script_uid {
|
if items[i].uid == script_uid {
|
||||||
|
@ -295,7 +291,6 @@ impl IProfiles {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(index) = script_index {
|
if let Some(index) = script_index {
|
||||||
if let Some(file) = items.remove(index).file {
|
if let Some(file) = items.remove(index).file {
|
||||||
let _ = dirs::app_profiles_dir().map(|path| {
|
let _ = dirs::app_profiles_dir().map(|path| {
|
||||||
|
@ -306,7 +301,57 @@ impl IProfiles {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// get the rules index
|
||||||
|
for (i, _) in items.iter().enumerate() {
|
||||||
|
if items[i].uid == rules_uid {
|
||||||
|
rules_index = Some(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(index) = rules_index {
|
||||||
|
if let Some(file) = items.remove(index).file {
|
||||||
|
let _ = dirs::app_profiles_dir().map(|path| {
|
||||||
|
let path = path.join(file);
|
||||||
|
if path.exists() {
|
||||||
|
let _ = fs::remove_file(path);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// get the proxies index
|
||||||
|
for (i, _) in items.iter().enumerate() {
|
||||||
|
if items[i].uid == proxies_uid {
|
||||||
|
proxies_index = Some(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(index) = proxies_index {
|
||||||
|
if let Some(file) = items.remove(index).file {
|
||||||
|
let _ = dirs::app_profiles_dir().map(|path| {
|
||||||
|
let path = path.join(file);
|
||||||
|
if path.exists() {
|
||||||
|
let _ = fs::remove_file(path);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// get the groups index
|
||||||
|
for (i, _) in items.iter().enumerate() {
|
||||||
|
if items[i].uid == groups_uid {
|
||||||
|
groups_index = Some(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(index) = groups_index {
|
||||||
|
if let Some(file) = items.remove(index).file {
|
||||||
|
let _ = dirs::app_profiles_dir().map(|path| {
|
||||||
|
let path = path.join(file);
|
||||||
|
if path.exists() {
|
||||||
|
let _ = fs::remove_file(path);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
// delete the original uid
|
// delete the original uid
|
||||||
if current == uid {
|
if current == uid {
|
||||||
self.current = match !items.is_empty() {
|
self.current = match !items.is_empty() {
|
||||||
|
@ -329,7 +374,7 @@ impl IProfiles {
|
||||||
Some(file) => dirs::app_profiles_dir()?.join(file),
|
Some(file) => dirs::app_profiles_dir()?.join(file),
|
||||||
None => bail!("failed to get the file field"),
|
None => bail!("failed to get the file field"),
|
||||||
};
|
};
|
||||||
return help::read_merge_mapping(&file_path);
|
return help::read_mapping(&file_path);
|
||||||
}
|
}
|
||||||
bail!("failed to find the current profile \"uid:{current}\"");
|
bail!("failed to find the current profile \"uid:{current}\"");
|
||||||
}
|
}
|
||||||
|
@ -364,4 +409,46 @@ impl IProfiles {
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 获取current指向的订阅的rules
|
||||||
|
pub fn current_rules(&self) -> Option<String> {
|
||||||
|
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 rules = item.option.as_ref().and_then(|e| e.rules.clone());
|
||||||
|
return rules;
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取current指向的订阅的proxies
|
||||||
|
pub fn current_proxies(&self) -> Option<String> {
|
||||||
|
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 proxies = item.option.as_ref().and_then(|e| e.proxies.clone());
|
||||||
|
return proxies;
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取current指向的订阅的groups
|
||||||
|
pub fn current_groups(&self) -> Option<String> {
|
||||||
|
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 groups = item.option.as_ref().and_then(|e| e.groups.clone());
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use super::SeqMap;
|
||||||
use crate::{
|
use crate::{
|
||||||
config::PrfItem,
|
config::PrfItem,
|
||||||
utils::{dirs, help},
|
utils::{dirs, help},
|
||||||
|
@ -15,6 +16,9 @@ pub struct ChainItem {
|
||||||
pub enum ChainType {
|
pub enum ChainType {
|
||||||
Merge(Mapping),
|
Merge(Mapping),
|
||||||
Script(String),
|
Script(String),
|
||||||
|
Rules(SeqMap),
|
||||||
|
Proxies(SeqMap),
|
||||||
|
Groups(SeqMap),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -43,7 +47,19 @@ impl From<&PrfItem> for Option<ChainItem> {
|
||||||
}),
|
}),
|
||||||
"merge" => Some(ChainItem {
|
"merge" => Some(ChainItem {
|
||||||
uid,
|
uid,
|
||||||
data: ChainType::Merge(help::read_merge_mapping(&path).ok()?),
|
data: ChainType::Merge(help::read_mapping(&path).ok()?),
|
||||||
|
}),
|
||||||
|
"rules" => Some(ChainItem {
|
||||||
|
uid,
|
||||||
|
data: ChainType::Rules(help::read_seq_map(&path).ok()?),
|
||||||
|
}),
|
||||||
|
"proxies" => Some(ChainItem {
|
||||||
|
uid,
|
||||||
|
data: ChainType::Proxies(help::read_seq_map(&path).ok()?),
|
||||||
|
}),
|
||||||
|
"groups" => Some(ChainItem {
|
||||||
|
uid,
|
||||||
|
data: ChainType::Groups(help::read_seq_map(&path).ok()?),
|
||||||
}),
|
}),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,14 @@ mod chain;
|
||||||
pub mod field;
|
pub mod field;
|
||||||
mod merge;
|
mod merge;
|
||||||
mod script;
|
mod script;
|
||||||
|
pub mod seq;
|
||||||
mod tun;
|
mod tun;
|
||||||
|
|
||||||
use self::chain::*;
|
use self::chain::*;
|
||||||
use self::field::*;
|
use self::field::*;
|
||||||
use self::merge::*;
|
use self::merge::*;
|
||||||
use self::script::*;
|
use self::script::*;
|
||||||
|
use self::seq::*;
|
||||||
use self::tun::*;
|
use self::tun::*;
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::utils::tmpl;
|
use crate::utils::tmpl;
|
||||||
|
@ -48,7 +50,7 @@ pub async fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// 从profiles里拿东西
|
// 从profiles里拿东西
|
||||||
let (mut config, merge_item, script_item) = {
|
let (mut config, merge_item, script_item, rules_item, proxies_item, groups_item) = {
|
||||||
let profiles = Config::profiles();
|
let profiles = Config::profiles();
|
||||||
let profiles = profiles.latest();
|
let profiles = profiles.latest();
|
||||||
|
|
||||||
|
@ -59,9 +61,7 @@ pub async fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
|
||||||
.and_then(<Option<ChainItem>>::from)
|
.and_then(<Option<ChainItem>>::from)
|
||||||
.unwrap_or_else(|| ChainItem {
|
.unwrap_or_else(|| ChainItem {
|
||||||
uid: "".into(),
|
uid: "".into(),
|
||||||
data: ChainType::Merge(
|
data: ChainType::Merge(Mapping::new()),
|
||||||
serde_yaml::from_str::<Mapping>(tmpl::ITEM_MERGE).unwrap_or_default(),
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
let script = profiles
|
let script = profiles
|
||||||
.get_item(&profiles.current_script().unwrap_or_default())
|
.get_item(&profiles.current_script().unwrap_or_default())
|
||||||
|
@ -71,14 +71,56 @@ pub async fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
|
||||||
uid: "".into(),
|
uid: "".into(),
|
||||||
data: ChainType::Script(tmpl::ITEM_SCRIPT.into()),
|
data: ChainType::Script(tmpl::ITEM_SCRIPT.into()),
|
||||||
});
|
});
|
||||||
|
let rules = profiles
|
||||||
|
.get_item(&profiles.current_rules().unwrap_or_default())
|
||||||
|
.ok()
|
||||||
|
.and_then(<Option<ChainItem>>::from)
|
||||||
|
.unwrap_or_else(|| ChainItem {
|
||||||
|
uid: "".into(),
|
||||||
|
data: ChainType::Rules(SeqMap::default()),
|
||||||
|
});
|
||||||
|
let proxies = profiles
|
||||||
|
.get_item(&profiles.current_proxies().unwrap_or_default())
|
||||||
|
.ok()
|
||||||
|
.and_then(<Option<ChainItem>>::from)
|
||||||
|
.unwrap_or_else(|| ChainItem {
|
||||||
|
uid: "".into(),
|
||||||
|
data: ChainType::Proxies(SeqMap::default()),
|
||||||
|
});
|
||||||
|
let groups = profiles
|
||||||
|
.get_item(&profiles.current_groups().unwrap_or_default())
|
||||||
|
.ok()
|
||||||
|
.and_then(<Option<ChainItem>>::from)
|
||||||
|
.unwrap_or_else(|| ChainItem {
|
||||||
|
uid: "".into(),
|
||||||
|
data: ChainType::Groups(SeqMap::default()),
|
||||||
|
});
|
||||||
|
|
||||||
(current, merge, script)
|
(current, merge, script, rules, proxies, groups)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result_map = HashMap::new(); // 保存脚本日志
|
let mut result_map = HashMap::new(); // 保存脚本日志
|
||||||
let mut exists_keys = use_keys(&config); // 保存出现过的keys
|
let mut exists_keys = use_keys(&config); // 保存出现过的keys
|
||||||
|
|
||||||
// 处理用户的profile
|
// 处理用户的profile
|
||||||
|
match rules_item.data {
|
||||||
|
ChainType::Rules(rules) => {
|
||||||
|
config = use_seq(rules, config.to_owned(), "rules");
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
match proxies_item.data {
|
||||||
|
ChainType::Proxies(proxies) => {
|
||||||
|
config = use_seq(proxies, config.to_owned(), "proxies");
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
match groups_item.data {
|
||||||
|
ChainType::Groups(groups) => {
|
||||||
|
config = use_seq(groups, config.to_owned(), "proxy-groups");
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
match merge_item.data {
|
match merge_item.data {
|
||||||
ChainType::Merge(merge) => {
|
ChainType::Merge(merge) => {
|
||||||
exists_keys.extend(use_keys(&merge));
|
exists_keys.extend(use_keys(&merge));
|
||||||
|
|
34
src-tauri/src/enhance/seq.rs
Normal file
34
src-tauri/src/enhance/seq.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_yaml::{Mapping, Sequence, Value};
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||||
|
pub struct SeqMap {
|
||||||
|
prepend: Sequence,
|
||||||
|
append: Sequence,
|
||||||
|
delete: Sequence,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn use_seq(seq_map: SeqMap, config: Mapping, name: &str) -> Mapping {
|
||||||
|
let prepend = seq_map.prepend;
|
||||||
|
let append = seq_map.append;
|
||||||
|
let delete = seq_map.delete;
|
||||||
|
|
||||||
|
let origin_seq = config.get(&name).map_or(Sequence::default(), |val| {
|
||||||
|
val.as_sequence().unwrap().clone()
|
||||||
|
});
|
||||||
|
let mut seq = origin_seq.clone();
|
||||||
|
|
||||||
|
for item in prepend {
|
||||||
|
seq.insert(0, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
for item in append {
|
||||||
|
seq.push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
for item in delete {
|
||||||
|
seq.retain(|x| x != &item);
|
||||||
|
}
|
||||||
|
let mut config = config.clone();
|
||||||
|
config.insert(Value::from(name), Value::from(seq));
|
||||||
|
return config;
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::enhance::seq::SeqMap;
|
||||||
use anyhow::{anyhow, bail, Context, Result};
|
use anyhow::{anyhow, bail, Context, Result};
|
||||||
use nanoid::nanoid;
|
use nanoid::nanoid;
|
||||||
use serde::{de::DeserializeOwned, Serialize};
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
|
@ -26,7 +27,7 @@ pub fn read_yaml<T: DeserializeOwned>(path: &PathBuf) -> Result<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// read mapping from yaml fix #165
|
/// read mapping from yaml fix #165
|
||||||
pub fn read_merge_mapping(path: &PathBuf) -> Result<Mapping> {
|
pub fn read_mapping(path: &PathBuf) -> Result<Mapping> {
|
||||||
let mut val: Value = read_yaml(path)?;
|
let mut val: Value = read_yaml(path)?;
|
||||||
val.apply_merge()
|
val.apply_merge()
|
||||||
.with_context(|| format!("failed to apply merge \"{}\"", path.display()))?;
|
.with_context(|| format!("failed to apply merge \"{}\"", path.display()))?;
|
||||||
|
@ -40,6 +41,13 @@ pub fn read_merge_mapping(path: &PathBuf) -> Result<Mapping> {
|
||||||
.to_owned())
|
.to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// read mapping from yaml fix #165
|
||||||
|
pub fn read_seq_map(path: &PathBuf) -> Result<SeqMap> {
|
||||||
|
let val: SeqMap = read_yaml(path)?;
|
||||||
|
|
||||||
|
Ok(val)
|
||||||
|
}
|
||||||
|
|
||||||
/// save the data to the file
|
/// save the data to the file
|
||||||
/// can set `prefix` string to add some comments
|
/// can set `prefix` string to add some comments
|
||||||
pub fn save_yaml<T: Serialize>(path: &PathBuf, data: &T, prefix: Option<&str>) -> Result<()> {
|
pub fn save_yaml<T: Serialize>(path: &PathBuf, data: &T, prefix: Option<&str>) -> Result<()> {
|
||||||
|
|
|
@ -33,3 +33,33 @@ function main(config) {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
|
|
||||||
|
/// enhanced profile
|
||||||
|
pub const ITEM_RULES: &str = "# Profile Enhancement Rules Template for Clash Verge
|
||||||
|
|
||||||
|
prepend: []
|
||||||
|
|
||||||
|
append: []
|
||||||
|
|
||||||
|
delete: []
|
||||||
|
";
|
||||||
|
|
||||||
|
/// enhanced profile
|
||||||
|
pub const ITEM_PROXIES: &str = "# Profile Enhancement Proxies Template for Clash Verge
|
||||||
|
|
||||||
|
prepend: []
|
||||||
|
|
||||||
|
append: []
|
||||||
|
|
||||||
|
delete: []
|
||||||
|
";
|
||||||
|
|
||||||
|
/// enhanced profile
|
||||||
|
pub const ITEM_GROUPS: &str = "# Profile Enhancement Groups Template for Clash Verge
|
||||||
|
|
||||||
|
prepend: []
|
||||||
|
|
||||||
|
append: []
|
||||||
|
|
||||||
|
delete: []
|
||||||
|
";
|
||||||
|
|
|
@ -105,6 +105,9 @@ export const ProfileItem = (props: Props) => {
|
||||||
}, [hasUrl, updated]);
|
}, [hasUrl, updated]);
|
||||||
|
|
||||||
const [fileOpen, setFileOpen] = useState(false);
|
const [fileOpen, setFileOpen] = useState(false);
|
||||||
|
const [rulesOpen, setRulesOpen] = useState(false);
|
||||||
|
const [proxiesOpen, setProxiesOpen] = useState(false);
|
||||||
|
const [groupsOpen, setGroupsOpen] = useState(false);
|
||||||
const [mergeOpen, setMergeOpen] = useState(false);
|
const [mergeOpen, setMergeOpen] = useState(false);
|
||||||
const [scriptOpen, setScriptOpen] = useState(false);
|
const [scriptOpen, setScriptOpen] = useState(false);
|
||||||
const [confirmOpen, setConfirmOpen] = useState(false);
|
const [confirmOpen, setConfirmOpen] = useState(false);
|
||||||
|
@ -124,6 +127,21 @@ export const ProfileItem = (props: Props) => {
|
||||||
setFileOpen(true);
|
setFileOpen(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onEditRules = () => {
|
||||||
|
setAnchorEl(null);
|
||||||
|
setRulesOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onEditProxies = () => {
|
||||||
|
setAnchorEl(null);
|
||||||
|
setProxiesOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onEditGroups = () => {
|
||||||
|
setAnchorEl(null);
|
||||||
|
setGroupsOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
const onEditMerge = () => {
|
const onEditMerge = () => {
|
||||||
setAnchorEl(null);
|
setAnchorEl(null);
|
||||||
setMergeOpen(true);
|
setMergeOpen(true);
|
||||||
|
@ -191,6 +209,21 @@ export const ProfileItem = (props: Props) => {
|
||||||
{ label: "Select", handler: onForceSelect, disabled: false },
|
{ label: "Select", handler: onForceSelect, disabled: false },
|
||||||
{ label: "Edit Info", handler: onEditInfo, disabled: false },
|
{ label: "Edit Info", handler: onEditInfo, disabled: false },
|
||||||
{ label: "Edit File", handler: onEditFile, disabled: false },
|
{ label: "Edit File", handler: onEditFile, disabled: false },
|
||||||
|
{
|
||||||
|
label: "Edit Rules",
|
||||||
|
handler: onEditRules,
|
||||||
|
disabled: option?.rules === null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Edit Proxies",
|
||||||
|
handler: onEditProxies,
|
||||||
|
disabled: option?.proxies === null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Edit Groups",
|
||||||
|
handler: onEditGroups,
|
||||||
|
disabled: option?.groups === null,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: "Edit Merge",
|
label: "Edit Merge",
|
||||||
handler: onEditMerge,
|
handler: onEditMerge,
|
||||||
|
@ -217,6 +250,21 @@ export const ProfileItem = (props: Props) => {
|
||||||
{ label: "Select", handler: onForceSelect, disabled: false },
|
{ label: "Select", handler: onForceSelect, disabled: false },
|
||||||
{ label: "Edit Info", handler: onEditInfo, disabled: false },
|
{ label: "Edit Info", handler: onEditInfo, disabled: false },
|
||||||
{ label: "Edit File", handler: onEditFile, disabled: false },
|
{ label: "Edit File", handler: onEditFile, disabled: false },
|
||||||
|
{
|
||||||
|
label: "Edit Rules",
|
||||||
|
handler: onEditRules,
|
||||||
|
disabled: option?.rules === null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Edit Proxies",
|
||||||
|
handler: onEditProxies,
|
||||||
|
disabled: option?.proxies === null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Edit Groups",
|
||||||
|
handler: onEditGroups,
|
||||||
|
disabled: option?.groups === null,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: "Edit Merge",
|
label: "Edit Merge",
|
||||||
handler: onEditMerge,
|
handler: onEditMerge,
|
||||||
|
@ -435,7 +483,34 @@ export const ProfileItem = (props: Props) => {
|
||||||
/>
|
/>
|
||||||
<EditorViewer
|
<EditorViewer
|
||||||
mode="profile"
|
mode="profile"
|
||||||
property={option?.merge ?? "123"}
|
property={option?.rules ?? ""}
|
||||||
|
open={rulesOpen}
|
||||||
|
language="yaml"
|
||||||
|
schema={undefined}
|
||||||
|
onChange={onChange}
|
||||||
|
onClose={() => setRulesOpen(false)}
|
||||||
|
/>
|
||||||
|
<EditorViewer
|
||||||
|
mode="profile"
|
||||||
|
property={option?.proxies ?? ""}
|
||||||
|
open={proxiesOpen}
|
||||||
|
language="yaml"
|
||||||
|
schema={undefined}
|
||||||
|
onChange={onChange}
|
||||||
|
onClose={() => setProxiesOpen(false)}
|
||||||
|
/>
|
||||||
|
<EditorViewer
|
||||||
|
mode="profile"
|
||||||
|
property={option?.groups ?? ""}
|
||||||
|
open={groupsOpen}
|
||||||
|
language="yaml"
|
||||||
|
schema={undefined}
|
||||||
|
onChange={onChange}
|
||||||
|
onClose={() => setGroupsOpen(false)}
|
||||||
|
/>
|
||||||
|
<EditorViewer
|
||||||
|
mode="profile"
|
||||||
|
property={option?.merge ?? ""}
|
||||||
open={mergeOpen}
|
open={mergeOpen}
|
||||||
language="yaml"
|
language="yaml"
|
||||||
schema="merge"
|
schema="merge"
|
||||||
|
|
|
@ -50,6 +50,9 @@
|
||||||
"Expire Time": "Expire Time",
|
"Expire Time": "Expire Time",
|
||||||
"Create Profile": "Create Profile",
|
"Create Profile": "Create Profile",
|
||||||
"Edit Profile": "Edit Profile",
|
"Edit Profile": "Edit Profile",
|
||||||
|
"Edit Proxies": "Edit Proxies",
|
||||||
|
"Edit Rules": "Edit Rules",
|
||||||
|
"Edit Groups": "Edit Proxy Groups",
|
||||||
"Edit Merge": "Edit Merge",
|
"Edit Merge": "Edit Merge",
|
||||||
"Edit Script": "Edit Script",
|
"Edit Script": "Edit Script",
|
||||||
"Type": "Type",
|
"Type": "Type",
|
||||||
|
|
|
@ -50,6 +50,9 @@
|
||||||
"Expire Time": "到期时间",
|
"Expire Time": "到期时间",
|
||||||
"Create Profile": "新建配置",
|
"Create Profile": "新建配置",
|
||||||
"Edit Profile": "编辑配置",
|
"Edit Profile": "编辑配置",
|
||||||
|
"Edit Proxies": "编辑代理",
|
||||||
|
"Edit Rules": "编辑规则",
|
||||||
|
"Edit Groups": "编辑代理组",
|
||||||
"Edit Merge": "编辑 Merge",
|
"Edit Merge": "编辑 Merge",
|
||||||
"Edit Script": "编辑 Script",
|
"Edit Script": "编辑 Script",
|
||||||
"Type": "类型",
|
"Type": "类型",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user