From b0dabbe55a8980fabe00467d0fe4d9645c2969b3 Mon Sep 17 00:00:00 2001 From: GyDi Date: Mon, 13 Dec 2021 02:29:48 +0800 Subject: [PATCH] feat: import profile support --- src-tauri/src/clash.rs | 14 ------ src-tauri/src/cmd.rs | 7 +-- src-tauri/src/init.rs | 14 +++++- src-tauri/src/main.rs | 6 ++- src-tauri/src/profiles.rs | 90 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 110 insertions(+), 21 deletions(-) create mode 100644 src-tauri/src/profiles.rs diff --git a/src-tauri/src/clash.rs b/src-tauri/src/clash.rs index ef25ff1..c727ffd 100644 --- a/src-tauri/src/clash.rs +++ b/src-tauri/src/clash.rs @@ -1,6 +1,4 @@ extern crate log; -extern crate reqwest; -extern crate serde_yaml; use crate::init::app_home_dir; use tauri::api::process::{Command, CommandEvent}; @@ -29,15 +27,3 @@ pub fn run_clash_bin() { } }); } - -pub async fn fetch_url(profile_url: &str) -> Result<(), reqwest::Error> { - let resp = reqwest::get(profile_url).await?; - println!("{:#?}", resp); - - let header = resp.headers().clone(); - println!("{:?}", header); - - let data = resp.text_with_charset("utf-8").await?; - println!("{:#?}", data); - Ok(()) -} diff --git a/src-tauri/src/cmd.rs b/src-tauri/src/cmd.rs index 9b02ca1..7629a44 100644 --- a/src-tauri/src/cmd.rs +++ b/src-tauri/src/cmd.rs @@ -1,15 +1,16 @@ use crate::clash; +use crate::profiles; use tauri::api::process::kill_children; #[tauri::command] -pub fn restart_sidebar() { +pub fn cmd_restart_sidebar() { kill_children(); clash::run_clash_bin(); } #[tauri::command] -pub async fn get_config_data(url: String) -> Result { - match clash::fetch_url(&url).await { +pub async fn cmd_import_profile(url: String) -> Result { + match profiles::import_profile(&url).await { Ok(_) => Ok(String::from("success")), Err(_) => Err(String::from("error")), } diff --git a/src-tauri/src/init.rs b/src-tauri/src/init.rs index 7e77c08..374a170 100644 --- a/src-tauri/src/init.rs +++ b/src-tauri/src/init.rs @@ -13,6 +13,8 @@ use std::time::{SystemTime, UNIX_EPOCH}; use tauri::api::path::{home_dir, resource_dir}; use tauri::PackageInfo; +use crate::config::verge::VergeConfig; + /// get the verge app home dir pub fn app_home_dir() -> PathBuf { home_dir() @@ -120,8 +122,16 @@ pub fn read_clash_config() -> Mapping { } /// Get the user config of verge -pub fn read_verge_config() -> Mapping { +pub fn read_verge_config() -> VergeConfig { let yaml_path = app_home_dir().join("verge.yaml"); let yaml_str = fs::read_to_string(yaml_path).unwrap(); - serde_yaml::from_str::(&yaml_str).unwrap() + serde_yaml::from_str::(&yaml_str).unwrap() +} + +/// Save the user config of verge +pub fn save_verge_config(verge_config: &VergeConfig) { + let yaml_path = app_home_dir().join("verge.yaml"); + let yaml_str = serde_yaml::to_string(&verge_config).unwrap(); + let yaml_str = String::from("# Config File for Clash Verge\n\n") + &yaml_str; + fs::write(yaml_path, yaml_str.as_bytes()).unwrap(); } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 97da2ab..6cb2839 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -7,7 +7,9 @@ extern crate tauri; mod clash; mod cmd; +mod config; mod init; +mod profiles; mod sysopt; use tauri::{ @@ -54,8 +56,8 @@ fn main() -> std::io::Result<()> { _ => {} }) .invoke_handler(tauri::generate_handler![ - cmd::get_config_data, - cmd::restart_sidebar, + cmd::cmd_import_profile, + cmd::cmd_restart_sidebar, ]) .build(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/src-tauri/src/profiles.rs b/src-tauri/src/profiles.rs new file mode 100644 index 0000000..4dfab5f --- /dev/null +++ b/src-tauri/src/profiles.rs @@ -0,0 +1,90 @@ +extern crate reqwest; + +use crate::config::verge::{ProfileData, ProfileUserInfo}; +use crate::init::{app_home_dir, read_verge_config, save_verge_config}; +use std::default::Default; +use std::fs::File; +use std::io::Write; +use std::time::{SystemTime, UNIX_EPOCH}; + +/// Todo: log +/// Import the Profile from url +/// save to the `verge.yaml` file +pub async fn import_profile(profile_url: &str) -> Result<(), reqwest::Error> { + let resp = reqwest::get(profile_url).await?; + let header = resp.headers().clone(); + let value = header + .get("Subscription-Userinfo") + .unwrap() + .to_str() + .unwrap(); + let value: Vec<&str> = value.clone().split(';').collect(); + + let mut user_info = ProfileUserInfo::default(); + + for each in value.iter() { + let each = each.clone().trim(); + if let Some(val) = each.strip_prefix("upload=") { + user_info.upload = val.parse().unwrap_or(0u64); + continue; + } + if let Some(val) = each.strip_prefix("download=") { + user_info.download = val.parse().unwrap_or(0u64); + continue; + } + if let Some(val) = each.strip_prefix("total=") { + user_info.total = val.parse().unwrap_or(0u64); + continue; + } + if let Some(val) = each.strip_prefix("expire=") { + user_info.expire = val.parse().unwrap_or(0u64); + continue; + } + } + + // save file + let file_data = resp.text_with_charset("utf-8").await?; + let cur_time = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs(); + let file_name = format!("{}.yaml", cur_time); + let file_path = app_home_dir().join("profiles").join(&file_name); + + File::create(file_path) + .unwrap() + .write(file_data.as_bytes()) + .unwrap(); + + let mut verge = read_verge_config(); + + let mut profiles = if verge.profiles.is_some() { + verge.profiles.unwrap() + } else { + vec![] + }; + + let profile = ProfileData { + name: Some(file_name.clone()), + file: Some(file_name.clone()), + mode: Some(String::from("rule")), + url: Some(String::from(profile_url)), + selected: Some(vec![]), + user_info: Some(user_info), + }; + + let target_index = profiles + .iter() + .position(|x| x.name.is_some() && x.name.as_ref().unwrap().as_str() == file_name.as_str()); + + if target_index.is_none() { + profiles.push(profile) + } else { + profiles[target_index.unwrap()] = profile; + } + + verge.profiles = Some(profiles); + save_verge_config(&verge); + + Ok(()) +}