feat: import profile support

This commit is contained in:
GyDi 2021-12-13 02:29:48 +08:00
parent 5b826a3767
commit b0dabbe55a
5 changed files with 110 additions and 21 deletions

View File

@ -1,6 +1,4 @@
extern crate log; extern crate log;
extern crate reqwest;
extern crate serde_yaml;
use crate::init::app_home_dir; use crate::init::app_home_dir;
use tauri::api::process::{Command, CommandEvent}; 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(())
}

View File

@ -1,15 +1,16 @@
use crate::clash; use crate::clash;
use crate::profiles;
use tauri::api::process::kill_children; use tauri::api::process::kill_children;
#[tauri::command] #[tauri::command]
pub fn restart_sidebar() { pub fn cmd_restart_sidebar() {
kill_children(); kill_children();
clash::run_clash_bin(); clash::run_clash_bin();
} }
#[tauri::command] #[tauri::command]
pub async fn get_config_data(url: String) -> Result<String, String> { pub async fn cmd_import_profile(url: String) -> Result<String, String> {
match clash::fetch_url(&url).await { match profiles::import_profile(&url).await {
Ok(_) => Ok(String::from("success")), Ok(_) => Ok(String::from("success")),
Err(_) => Err(String::from("error")), Err(_) => Err(String::from("error")),
} }

View File

@ -13,6 +13,8 @@ use std::time::{SystemTime, UNIX_EPOCH};
use tauri::api::path::{home_dir, resource_dir}; use tauri::api::path::{home_dir, resource_dir};
use tauri::PackageInfo; use tauri::PackageInfo;
use crate::config::verge::VergeConfig;
/// get the verge app home dir /// get the verge app home dir
pub fn app_home_dir() -> PathBuf { pub fn app_home_dir() -> PathBuf {
home_dir() home_dir()
@ -120,8 +122,16 @@ pub fn read_clash_config() -> Mapping {
} }
/// Get the user config of verge /// 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_path = app_home_dir().join("verge.yaml");
let yaml_str = fs::read_to_string(yaml_path).unwrap(); let yaml_str = fs::read_to_string(yaml_path).unwrap();
serde_yaml::from_str::<Mapping>(&yaml_str).unwrap() serde_yaml::from_str::<VergeConfig>(&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();
} }

View File

@ -7,7 +7,9 @@ extern crate tauri;
mod clash; mod clash;
mod cmd; mod cmd;
mod config;
mod init; mod init;
mod profiles;
mod sysopt; mod sysopt;
use tauri::{ use tauri::{
@ -54,8 +56,8 @@ fn main() -> std::io::Result<()> {
_ => {} _ => {}
}) })
.invoke_handler(tauri::generate_handler![ .invoke_handler(tauri::generate_handler![
cmd::get_config_data, cmd::cmd_import_profile,
cmd::restart_sidebar, cmd::cmd_restart_sidebar,
]) ])
.build(tauri::generate_context!()) .build(tauri::generate_context!())
.expect("error while running tauri application"); .expect("error while running tauri application");

90
src-tauri/src/profiles.rs Normal file
View File

@ -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(())
}