feat: adjust fetch profile url

This commit is contained in:
GyDi 2022-02-19 00:09:36 +08:00
parent 3a9a392a77
commit c60578f5b5
No known key found for this signature in database
GPG Key ID: 1C95E0D3467B3084
3 changed files with 46 additions and 54 deletions

View File

@ -34,13 +34,9 @@ pub async fn import_profile(
with_proxy: bool, with_proxy: bool,
profiles_state: State<'_, ProfilesState>, profiles_state: State<'_, ProfilesState>,
) -> Result<(), String> { ) -> Result<(), String> {
match fetch_profile(&url, with_proxy).await { let result = fetch_profile(&url, with_proxy).await?;
Some(result) => { let mut profiles = profiles_state.0.lock().unwrap();
let mut profiles = profiles_state.0.lock().unwrap(); profiles.import_from_url(url, result)
profiles.import_from_url(url, result)
}
None => Err(format!("failed to fetch profile from `{}`", url)),
}
} }
/// new a profile /// new a profile
@ -82,23 +78,22 @@ pub async fn update_profile(
Err(_) => return Err("failed to get profiles lock".into()), Err(_) => return Err("failed to get profiles lock".into()),
}; };
match fetch_profile(&url, with_proxy).await { let result = fetch_profile(&url, with_proxy).await?;
Some(result) => match profiles_state.0.lock() {
Ok(mut profiles) => {
profiles.update_item(index, result)?;
// reactivate the profile match profiles_state.0.lock() {
let current = profiles.current.clone().unwrap_or(0); Ok(mut profiles) => {
if current == index { profiles.update_item(index, result)?;
let clash = clash_state.0.lock().unwrap();
profiles.activate(&clash) // reactivate the profile
} else { let current = profiles.current.clone().unwrap_or(0);
Ok(()) if current == index {
} let clash = clash_state.0.lock().unwrap();
profiles.activate(&clash)
} else {
Ok(())
} }
Err(_) => Err("failed to get profiles lock".into()), }
}, Err(_) => Err("failed to get profiles lock".into()),
None => Err(format!("failed to fetch profile from `{}`", url)),
} }
} }

View File

@ -60,7 +60,7 @@ pub struct ProfileResponse {
pub name: String, pub name: String,
pub file: String, pub file: String,
pub data: String, pub data: String,
pub extra: ProfileExtra, pub extra: Option<ProfileExtra>,
} }
static PROFILE_YAML: &str = "profiles.yaml"; static PROFILE_YAML: &str = "profiles.yaml";
@ -117,7 +117,7 @@ impl Profiles {
mode: Some(format!("rule")), mode: Some(format!("rule")),
url: Some(url), url: Some(url),
selected: Some(vec![]), selected: Some(vec![]),
extra: Some(result.extra), extra: result.extra,
updated: Some(now as usize), updated: Some(now as usize),
}); });
@ -194,7 +194,7 @@ impl Profiles {
File::create(file_path).unwrap().write(file_data).unwrap(); File::create(file_path).unwrap().write(file_data).unwrap();
items[index].name = Some(result.name); items[index].name = Some(result.name);
items[index].extra = Some(result.extra); items[index].extra = result.extra;
items[index].updated = Some(now); items[index].updated = Some(now);
self.items = Some(items); self.items = Some(items);

View File

@ -22,36 +22,35 @@ fn parse_string<T: FromStr>(target: &str, key: &str) -> Option<T> {
} }
} }
/// fetch and parse the profile /// fetch and parse the profile url
pub async fn fetch_profile(url: &str, with_proxy: bool) -> Option<ProfileResponse> { /// maybe it contains some Subscription infomations, maybe not
pub async fn fetch_profile(url: &str, with_proxy: bool) -> Result<ProfileResponse, String> {
let builder = reqwest::ClientBuilder::new(); let builder = reqwest::ClientBuilder::new();
let client = match with_proxy { let client = match with_proxy {
true => builder.build(), true => builder.build(),
false => builder.no_proxy().build(), false => builder.no_proxy().build(),
}; };
let resp = match client {
Ok(client) => match client.get(url).send().await { let resp = match client.unwrap().get(url).send().await {
Ok(res) => res, Ok(res) => res,
Err(_) => return None, Err(_) => return Err("failed to create https client".into()),
},
Err(_) => return None,
}; };
let header = resp.headers(); let header = resp.headers();
// parse the Subscription Userinfo // parse the Subscription Userinfo
let extra = { let extra = match header.get("Subscription-Userinfo") {
let sub_info = match header.get("Subscription-Userinfo") { Some(value) => {
Some(value) => value.to_str().unwrap_or(""), let sub_info = value.to_str().unwrap_or("");
None => "",
};
ProfileExtra { Some(ProfileExtra {
upload: parse_string(sub_info, "upload=").unwrap_or(0), upload: parse_string(sub_info, "upload=").unwrap_or(0),
download: parse_string(sub_info, "download=").unwrap_or(0), download: parse_string(sub_info, "download=").unwrap_or(0),
total: parse_string(sub_info, "total=").unwrap_or(0), total: parse_string(sub_info, "total=").unwrap_or(0),
expire: parse_string(sub_info, "expire=").unwrap_or(0), expire: parse_string(sub_info, "expire=").unwrap_or(0),
})
} }
None => None,
}; };
let file = { let file = {
@ -71,17 +70,15 @@ pub async fn fetch_profile(url: &str, with_proxy: bool) -> Option<ProfileRespons
}; };
// get the data // get the data
let data = match resp.text_with_charset("utf-8").await { match resp.text_with_charset("utf-8").await {
Ok(d) => d, Ok(data) => Ok(ProfileResponse {
Err(_) => return None, file,
}; name,
data,
Some(ProfileResponse { extra,
file, }),
name, Err(_) => Err("failed to parse the response data".into()),
data, }
extra,
})
} }
#[test] #[test]