diff --git a/src-tauri/src/profiles.rs b/src-tauri/src/profiles.rs index c4f24e4..1471bee 100644 --- a/src-tauri/src/profiles.rs +++ b/src-tauri/src/profiles.rs @@ -2,55 +2,80 @@ extern crate reqwest; use crate::config::{read_profiles, save_profiles, ProfileExtra, ProfileItem}; use crate::init::app_home_dir; -use std::default::Default; use std::fs::File; use std::io::Write; use std::time::{SystemTime, UNIX_EPOCH}; +/// parse the string +fn parse_string<'a>(target: &'a str, key: &'a str) -> Option<&'a str> { + match target.find(key) { + Some(idx) => { + let idx = idx + key.len(); + let value = &target[idx..]; + match value.split(';').nth(0) { + Some(value) => Some(value.trim()), + None => Some(value.trim()), + } + } + None => None, + } +} + /// 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(); // parse the Subscription Userinfo - let mut extra = ProfileExtra::default(); - for each in value.iter() { - let each = each.clone().trim(); - if let Some(val) = each.strip_prefix("upload=") { - extra.upload = val.parse().unwrap_or(0u64); - continue; + let extra = { + let sub_info = header + .get("Subscription-Userinfo") + .unwrap() + .to_str() + .unwrap(); + + ProfileExtra { + upload: parse_string(sub_info, "upload=") + .unwrap_or("0") + .parse() + .unwrap_or(0u64), + download: parse_string(sub_info, "download=") + .unwrap_or("0") + .parse() + .unwrap_or(0u64), + total: parse_string(sub_info, "total=") + .unwrap_or("0") + .parse() + .unwrap_or(0u64), + expire: parse_string(sub_info, "expire=") + .unwrap_or("0") + .parse() + .unwrap_or(0u64), } - if let Some(val) = each.strip_prefix("download=") { - extra.download = val.parse().unwrap_or(0u64); - continue; + }; + + // parse the file name + let file_name = { + let file_name = header.get("Content-Disposition").unwrap().to_str().unwrap(); + let file_name = parse_string(file_name, "filename="); + + match file_name { + Some(f) => f.to_string(), + None => { + let cur_time = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs(); + format!("{}.yaml", cur_time) + } } - if let Some(val) = each.strip_prefix("total=") { - extra.total = val.parse().unwrap_or(0u64); - continue; - } - if let Some(val) = each.strip_prefix("expire=") { - extra.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()) @@ -58,10 +83,9 @@ pub async fn import_profile(profile_url: &str) -> Result<(), reqwest::Error> { // update profiles.yaml let mut profiles = read_profiles(); - let mut items = if profiles.items.is_some() { - profiles.items.unwrap() - } else { - vec![] + let mut items = match profiles.items { + Some(p) => p, + None => vec![], }; let profile = ProfileItem { @@ -77,14 +101,30 @@ pub async fn import_profile(profile_url: &str) -> Result<(), reqwest::Error> { .iter() .position(|x| x.name.is_some() && x.name.as_ref().unwrap().as_str() == file_name.as_str()); - if target_index.is_none() { - items.push(profile) - } else { - items[target_index.unwrap()] = profile; - } + match target_index { + Some(idx) => items[idx] = profile, + None => items.push(profile), + }; profiles.items = Some(items); save_profiles(&profiles); Ok(()) } + +#[test] +fn test_parse_value() { + let test_1 = "upload=111; download=2222; total=3333; expire=444"; + let test_2 = "attachment; filename=Clash.yaml"; + + assert_eq!(parse_string(test_1, "upload="), Some("111")); + assert_eq!(parse_string(test_1, "download="), Some("2222")); + assert_eq!(parse_string(test_1, "total="), Some("3333")); + assert_eq!(parse_string(test_1, "expire="), Some("444")); + assert_eq!(parse_string(test_2, "filename="), Some("Clash.yaml")); + + assert_eq!(parse_string(test_1, "aaa="), None); + assert_eq!(parse_string(test_1, "upload1="), None); + assert_eq!(parse_string(test_1, "expire1="), None); + assert_eq!(parse_string(test_2, "attachment="), None); +}