mirror of
https://github.com/clash-verge-rev/clash-verge-rev
synced 2025-05-05 04:53:44 +08:00
refacture: Mihomo API integration (#2900)
* feat: add mihomo_api crate as a workspace member Added a new mihomo_api crate to handle interactions with the Mihomo API. This modular approach provides a dedicated interface for fetching and managing proxy data from Mihomo servers. The implementation includes functionality to refresh and retrieve both proxies and provider proxies with proper error handling and timeouts. Added this crate as a workspace member and included it as a dependency in the main project. * Refactors Mihomo API integration Simplifies proxy fetching by removing the MihomoManager structure. Updates the get_proxies and get_providers_proxies functions to directly use the mihomo_api module. Removes unused Mihomo API related files and modules for cleaner codebase. Enhances overall maintainability and performance.
This commit is contained in:
parent
7ea7ca1415
commit
4ed36f6223
27
src-tauri/Cargo.lock
generated
27
src-tauri/Cargo.lock
generated
@ -1078,6 +1078,7 @@ dependencies = [
|
||||
"imageproc",
|
||||
"log",
|
||||
"log4rs",
|
||||
"mihomo_api",
|
||||
"mockito",
|
||||
"nanoid",
|
||||
"network-interface",
|
||||
@ -3723,9 +3724,9 @@ checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.25"
|
||||
version = "0.4.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
|
||||
checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@ -3896,6 +3897,16 @@ dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mihomo_api"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.17"
|
||||
@ -5996,9 +6007,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.217"
|
||||
version = "1.0.218"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
|
||||
checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
@ -6038,9 +6049,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.217"
|
||||
version = "1.0.218"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
|
||||
checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -6060,9 +6071,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.138"
|
||||
version = "1.0.140"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949"
|
||||
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
|
||||
dependencies = [
|
||||
"itoa 1.0.14",
|
||||
"memchr",
|
||||
|
@ -68,6 +68,7 @@ tokio-tungstenite = "0.26.1"
|
||||
futures = "0.3"
|
||||
sys-locale = "0.3.1"
|
||||
async-trait = "0.1.86"
|
||||
mihomo_api = { path = "./src/crate_mihomo_api" }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
runas = "=1.2.0"
|
||||
@ -126,3 +127,8 @@ crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
env_logger = "0.11.0"
|
||||
mockito = "1.2.0"
|
||||
tempfile = "3.17.1"
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
"src/crate_mihomo_api"
|
||||
]
|
||||
|
@ -1,35 +1,26 @@
|
||||
use super::CmdResult;
|
||||
use crate::module::mihomo::MihomoManager;
|
||||
use tauri::async_runtime;
|
||||
use crate::core;
|
||||
use mihomo_api;
|
||||
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_proxies() -> CmdResult<serde_json::Value> {
|
||||
let proxies = async_runtime::spawn_blocking(|| {
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
let manager = MihomoManager::new();
|
||||
{
|
||||
let mut write_guard = manager.write();
|
||||
rt.block_on(write_guard.refresh_proxies());
|
||||
}
|
||||
let read_guard = manager.read();
|
||||
read_guard.fetch_proxies().clone()
|
||||
})
|
||||
.await.map_err(|e| e.to_string())?;
|
||||
Ok(proxies)
|
||||
let (mihomo_server, _) = core::clash_api::clash_client_info().unwrap();
|
||||
let mihomo = mihomo_api::MihomoManager::new(mihomo_server);
|
||||
Ok(mihomo
|
||||
.refresh_proxies()
|
||||
.await
|
||||
.unwrap()
|
||||
.get_proxies())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_providers_proxies() -> CmdResult<serde_json::Value> {
|
||||
let providers_proxies = async_runtime::spawn_blocking(|| {
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
let manager = MihomoManager::new();
|
||||
{
|
||||
let mut write_guard = manager.write();
|
||||
rt.block_on(write_guard.refresh_providers_proxies());
|
||||
}
|
||||
let read_guard = manager.read();
|
||||
read_guard.fetch_providers_proxies().clone()
|
||||
})
|
||||
.await.map_err(|e| e.to_string())?;
|
||||
Ok(providers_proxies)
|
||||
let (mihomo_server, _) = core::clash_api::clash_client_info().unwrap();
|
||||
let mihomo = mihomo_api::MihomoManager::new(mihomo_server);
|
||||
Ok(mihomo
|
||||
.refresh_providers_proxies()
|
||||
.await
|
||||
.unwrap()
|
||||
.get_providers_proxies())
|
||||
}
|
@ -1 +0,0 @@
|
||||
pub const MIHOMO_URL: &str = concat!("http://", "127.0.0.1", ":", "9097");
|
@ -1 +0,0 @@
|
||||
pub mod mihomo;
|
@ -21,6 +21,3 @@ pub const DEFAULT_PAC: &str = r#"function FindProxyForURL(url, host) {
|
||||
return "PROXY 127.0.0.1:%mixed-port%; SOCKS5 127.0.0.1:%mixed-port%; DIRECT;";
|
||||
}
|
||||
"#;
|
||||
|
||||
|
||||
pub mod api;
|
@ -76,7 +76,7 @@ pub async fn get_proxy_delay(
|
||||
}
|
||||
|
||||
/// 根据clash info获取clash服务地址和请求头
|
||||
fn clash_client_info() -> Result<(String, HeaderMap)> {
|
||||
pub fn clash_client_info() -> Result<(String, HeaderMap)> {
|
||||
let client = { Config::clash().data().get_client_info() };
|
||||
|
||||
let server = format!("http://{}", client.server);
|
||||
|
14
src-tauri/src/crate_mihomo_api/Cargo.toml
Normal file
14
src-tauri/src/crate_mihomo_api/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "mihomo_api"
|
||||
edition = "2024"
|
||||
|
||||
[features]
|
||||
debug = []
|
||||
|
||||
[dependencies]
|
||||
reqwest = { version = "0.12.12", features = ["json"] }
|
||||
serde = { version = "1.0.218", features = ["derive"] }
|
||||
serde_json = "1.0.140"
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1.43.0", features = ["rt", "macros"] }
|
76
src-tauri/src/crate_mihomo_api/src/lib.rs
Normal file
76
src-tauri/src/crate_mihomo_api/src/lib.rs
Normal file
@ -0,0 +1,76 @@
|
||||
use std::{
|
||||
sync::{Arc, Mutex},
|
||||
time::Duration,
|
||||
};
|
||||
pub mod model;
|
||||
pub use model::{MihomoData, MihomoManager};
|
||||
|
||||
impl MihomoManager {
|
||||
pub fn new(mihomo_server: String) -> Self {
|
||||
Self {
|
||||
mihomo_server,
|
||||
data: Arc::new(Mutex::new(MihomoData {
|
||||
proxies: serde_json::Value::Null,
|
||||
providers_proxies: serde_json::Value::Null,
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
fn update_proxies(&self, proxies: serde_json::Value) {
|
||||
let mut data = self.data.lock().unwrap();
|
||||
data.proxies = proxies;
|
||||
}
|
||||
|
||||
fn update_providers_proxies(&self, providers_proxies: serde_json::Value) {
|
||||
let mut data = self.data.lock().unwrap();
|
||||
data.providers_proxies = providers_proxies;
|
||||
}
|
||||
|
||||
pub fn get_proxies(&self) -> serde_json::Value {
|
||||
let data = self.data.lock().unwrap();
|
||||
data.proxies.clone()
|
||||
}
|
||||
|
||||
pub fn get_providers_proxies(&self) -> serde_json::Value {
|
||||
let data = self.data.lock().unwrap();
|
||||
data.providers_proxies.clone()
|
||||
}
|
||||
|
||||
pub async fn refresh_proxies(&self) -> Result<&Self, String> {
|
||||
let url = format!("{}/proxies", self.mihomo_server);
|
||||
let response = reqwest::ClientBuilder::new()
|
||||
.no_proxy()
|
||||
.timeout(Duration::from_secs(3))
|
||||
.build()
|
||||
.map_err(|e| e.to_string())?
|
||||
.get(url)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| e.to_string())?
|
||||
.json::<serde_json::Value>()
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
let proxies = response;
|
||||
self.update_proxies(proxies);
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub async fn refresh_providers_proxies(&self) -> Result<&Self, String> {
|
||||
let url = format!("{}/providers/proxies", self.mihomo_server);
|
||||
let response = reqwest::ClientBuilder::new()
|
||||
.no_proxy()
|
||||
.timeout(Duration::from_secs(3))
|
||||
.build()
|
||||
.map_err(|e| e.to_string())?
|
||||
.get(url)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| e.to_string())?
|
||||
.json::<serde_json::Value>()
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
let proxies = response;
|
||||
self.update_providers_proxies(proxies);
|
||||
Ok(self)
|
||||
}
|
||||
}
|
27
src-tauri/src/crate_mihomo_api/src/model.rs
Normal file
27
src-tauri/src/crate_mihomo_api/src/model.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
pub struct MihomoData {
|
||||
pub(crate) proxies: serde_json::Value,
|
||||
pub(crate) providers_proxies: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MihomoManager {
|
||||
pub(crate) mihomo_server: String,
|
||||
pub(crate) data: Arc<Mutex<MihomoData>>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "debug")]
|
||||
impl Drop for MihomoData {
|
||||
fn drop(&mut self) {
|
||||
println!("Dropping MihomoData");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "debug")]
|
||||
impl Drop for MihomoManager {
|
||||
fn drop(&mut self) {
|
||||
println!("Dropping MihomoManager");
|
||||
}
|
||||
|
||||
}
|
28
src-tauri/src/crate_mihomo_api/tests/test_mihomo_api.rs
Normal file
28
src-tauri/src/crate_mihomo_api/tests/test_mihomo_api.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use mihomo_api;
|
||||
|
||||
#[test]
|
||||
fn test_mihomo_manager_init() {
|
||||
let manager = mihomo_api::MihomoManager::new("url".into());
|
||||
assert_eq!(manager.get_proxies(), serde_json::Value::Null);
|
||||
assert_eq!(manager.get_providers_proxies(), serde_json::Value::Null);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_refresh_proxies() {
|
||||
let manager = mihomo_api::MihomoManager::new("http://127.0.0.1:9097".into());
|
||||
let manager = manager.refresh_proxies().await.unwrap();
|
||||
let proxies = manager.get_proxies();
|
||||
let providers = manager.get_providers_proxies();
|
||||
assert_ne!(proxies, serde_json::Value::Null);
|
||||
assert_eq!(providers, serde_json::Value::Null);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_refresh_providers_proxies() {
|
||||
let manager = mihomo_api::MihomoManager::new("http://127.0.0.1:9097".into());
|
||||
let manager = manager.refresh_providers_proxies().await.unwrap();
|
||||
let proxies = manager.get_proxies();
|
||||
let providers = manager.get_providers_proxies();
|
||||
assert_eq!(proxies, serde_json::Value::Null);
|
||||
assert_ne!(providers, serde_json::Value::Null);
|
||||
}
|
@ -4,7 +4,6 @@ mod core;
|
||||
mod enhance;
|
||||
mod feat;
|
||||
mod utils;
|
||||
mod model;
|
||||
mod module;
|
||||
use crate::core::hotkey;
|
||||
use crate::utils::{resolve, resolve::resolve_scheme, server};
|
||||
|
@ -1,20 +0,0 @@
|
||||
use reqwest::Client;
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) struct ApiCaller<'a> {
|
||||
pub(crate) url: &'a str,
|
||||
pub(crate) client: Client,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_api_caller() {
|
||||
let _api_caller = ApiCaller {
|
||||
url: "https://example.com",
|
||||
client: Client::new(),
|
||||
};
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
use super::common::ApiCaller;
|
||||
|
||||
pub struct MihomoAPICaller {
|
||||
pub(crate) caller: ApiCaller<'static>,
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
pub mod common;
|
||||
pub mod mihomo;
|
@ -1 +0,0 @@
|
||||
pub mod api;
|
@ -1,70 +0,0 @@
|
||||
use crate::model::api::common::ApiCaller;
|
||||
use async_trait::async_trait;
|
||||
use reqwest::{
|
||||
header::{HeaderMap, HeaderName, HeaderValue},
|
||||
RequestBuilder,
|
||||
};
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
impl<'a> ApiCaller<'a> {
|
||||
pub async fn send_request(
|
||||
&self,
|
||||
method: &str,
|
||||
path: &str,
|
||||
body: Option<&str>,
|
||||
headers: Option<Vec<(&str, &str)>>,
|
||||
) -> Result<String, String> {
|
||||
let full_url = format!("{}{}", self.url, path); // 拼接完整 URL
|
||||
let mut request: RequestBuilder = match method {
|
||||
"GET" => self.client.get(&full_url),
|
||||
"POST" => self
|
||||
.client
|
||||
.post(&full_url)
|
||||
.body(body.unwrap_or("").to_string()),
|
||||
"PUT" => self
|
||||
.client
|
||||
.put(&full_url)
|
||||
.body(body.unwrap_or("").to_string()),
|
||||
"DELETE" => self.client.delete(&full_url),
|
||||
_ => return Err("Unsupported HTTP method".to_string()),
|
||||
};
|
||||
|
||||
// 处理 headers
|
||||
if let Some(hdrs) = headers {
|
||||
let mut header_map = HeaderMap::new();
|
||||
for (key, value) in hdrs {
|
||||
if let (Ok(header_name), Ok(header_value)) = (
|
||||
HeaderName::from_bytes(key.as_bytes()),
|
||||
HeaderValue::from_str(value),
|
||||
) {
|
||||
header_map.insert(header_name, header_value);
|
||||
}
|
||||
}
|
||||
request = request.headers(header_map);
|
||||
}
|
||||
|
||||
let response = request.send().await.map_err(|e| e.to_string())?;
|
||||
response.text().await.map_err(|e| e.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
#[async_trait]
|
||||
pub trait ApiCallerTrait: Send + Sync {
|
||||
async fn call_api<T>(
|
||||
&self,
|
||||
method: &str,
|
||||
path: &str,
|
||||
body: Option<&str>,
|
||||
headers: Option<Vec<(&str, &str)>>
|
||||
) -> Result<T, String>
|
||||
where
|
||||
T: DeserializeOwned + Send + Sync;
|
||||
|
||||
fn parse_json_response<T>(json_str: &str) -> Result<T, String>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
{
|
||||
serde_json::from_str(json_str).map_err(|e| e.to_string())
|
||||
}
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
use super::common::ApiCallerTrait;
|
||||
use crate::config::api::mihomo::MIHOMO_URL;
|
||||
use crate::model::api::common::ApiCaller;
|
||||
use crate::model::api::mihomo::MihomoAPICaller;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use once_cell::sync::OnceCell;
|
||||
use parking_lot::RwLock;
|
||||
use reqwest::Client;
|
||||
use serde::de::DeserializeOwned;
|
||||
use std::sync::Arc;
|
||||
|
||||
impl MihomoAPICaller {
|
||||
#[allow(dead_code)]
|
||||
pub fn new() -> Arc<RwLock<Self>> {
|
||||
static INSTANCE: OnceCell<Arc<RwLock<MihomoAPICaller>>> = OnceCell::new();
|
||||
INSTANCE
|
||||
.get_or_init(|| {
|
||||
let client = Client::new();
|
||||
Arc::new(RwLock::new(MihomoAPICaller {
|
||||
caller: ApiCaller {
|
||||
url: MIHOMO_URL,
|
||||
client,
|
||||
},
|
||||
}))
|
||||
})
|
||||
.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl ApiCallerTrait for MihomoAPICaller {
|
||||
async fn call_api<T>(
|
||||
&self,
|
||||
method: &str,
|
||||
path: &str,
|
||||
body: Option<&str>,
|
||||
headers: Option<Vec<(&str, &str)>>,
|
||||
) -> Result<T, String>
|
||||
where
|
||||
T: DeserializeOwned + Send + Sync,
|
||||
{
|
||||
let response = self
|
||||
.caller
|
||||
.send_request(method, path, body, headers)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
Self::parse_json_response::<T>(&response)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
impl MihomoAPICaller {
|
||||
pub async fn get_proxies() -> Result<serde_json::Value, String> {
|
||||
Self::new()
|
||||
.read()
|
||||
.call_api("GET", "/proxies", None, None)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_providers_proxies() -> Result<serde_json::Value, String> {
|
||||
Self::new()
|
||||
.read()
|
||||
.call_api("GET", "/providers/proxies", None, None)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_mihomo_api_singleton() {
|
||||
let mihomo_api_caller1 = MihomoAPICaller::new();
|
||||
let mihomo_api_caller2 = MihomoAPICaller::new();
|
||||
assert!(Arc::ptr_eq(&mihomo_api_caller1, &mihomo_api_caller2));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_mihomo_api_version() {
|
||||
let mihomo_caller = MihomoAPICaller::new();
|
||||
let response: Result<serde_json::Value, String> = mihomo_caller
|
||||
.read()
|
||||
.call_api("GET", "/version", None, None)
|
||||
.await;
|
||||
assert!(response.is_ok());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_mihomo_get_proxies() {
|
||||
let response = MihomoAPICaller::get_proxies().await;
|
||||
assert!(response.is_ok());
|
||||
if let Ok(proxies) = &response {
|
||||
assert!(!proxies.get("proxies").is_none());
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_mihomo_get_providers_proxies() {
|
||||
let response = MihomoAPICaller::get_providers_proxies().await;
|
||||
println!("{:?}", response);
|
||||
assert!(response.is_ok());
|
||||
if let Ok(providers_proxies) = &response {
|
||||
assert!(!providers_proxies.get("providers").is_none());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
pub mod common;
|
||||
pub mod mihomo;
|
@ -1,158 +0,0 @@
|
||||
use crate::model::api::mihomo::MihomoAPICaller;
|
||||
use once_cell::sync::OnceCell;
|
||||
use parking_lot::RwLock;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[allow(unused)]
|
||||
pub struct MihomoManager {
|
||||
proxies: serde_json::Value,
|
||||
providers_proxies: serde_json::Value,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
impl MihomoManager {
|
||||
pub fn new() -> Arc<RwLock<Self>> {
|
||||
static INSTANCE: OnceCell<Arc<RwLock<MihomoManager>>> = OnceCell::new();
|
||||
INSTANCE
|
||||
.get_or_init(|| {
|
||||
Arc::new(RwLock::new(MihomoManager {
|
||||
proxies: serde_json::Value::Null,
|
||||
providers_proxies: serde_json::Value::Null,
|
||||
}))
|
||||
})
|
||||
.clone()
|
||||
}
|
||||
|
||||
pub fn fetch_proxies(&self) -> &serde_json::Value {
|
||||
&self.proxies
|
||||
}
|
||||
|
||||
pub fn fetch_providers_proxies(&self) -> &serde_json::Value {
|
||||
&self.providers_proxies
|
||||
}
|
||||
|
||||
pub async fn refresh_proxies(&mut self) {
|
||||
match MihomoAPICaller::get_proxies().await {
|
||||
Ok(proxies) => {
|
||||
self.proxies = proxies;
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Failed to get proxies: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn refresh_providers_proxies(&mut self) {
|
||||
match MihomoAPICaller::get_providers_proxies().await {
|
||||
Ok(providers_proxies) => {
|
||||
self.providers_proxies = providers_proxies;
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!("Failed to get providers proxies: {}", e);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[tokio::test]
|
||||
async fn test_mihomo_manager_singleton() {
|
||||
let manager1 = MihomoManager::new();
|
||||
let manager2 = MihomoManager::new();
|
||||
|
||||
assert!(
|
||||
Arc::ptr_eq(&manager1, &manager2),
|
||||
"Should return same instance"
|
||||
);
|
||||
|
||||
let manager = manager1.read();
|
||||
assert!(manager.proxies.is_null());
|
||||
assert!(manager.providers_proxies.is_null());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_refresh_proxies() {
|
||||
let manager = MihomoManager::new();
|
||||
|
||||
// Test initial state
|
||||
{
|
||||
let data = manager.read();
|
||||
assert!(data.proxies.is_null());
|
||||
}
|
||||
|
||||
// Test refresh
|
||||
{
|
||||
let mut data = manager.write();
|
||||
data.refresh_proxies().await;
|
||||
// Note: Since this depends on external API call,
|
||||
// we can only verify that the refresh call completes
|
||||
// without panicking. For more thorough testing,
|
||||
// we would need to mock the API caller.
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_refresh_providers_proxies() {
|
||||
let manager = MihomoManager::new();
|
||||
|
||||
// Test initial state
|
||||
{
|
||||
let data = manager.read();
|
||||
assert!(data.providers_proxies.is_null());
|
||||
}
|
||||
|
||||
// Test refresh
|
||||
{
|
||||
let mut data = manager.write();
|
||||
data.refresh_providers_proxies().await;
|
||||
// Note: Since this depends on external API call,
|
||||
// we can only verify that the refresh call completes
|
||||
// without panicking. For more thorough testing,
|
||||
// we would need to mock the API caller.
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_fetch_proxies() {
|
||||
let manager = MihomoManager::new();
|
||||
|
||||
// Test initial state
|
||||
{
|
||||
let data = manager.read();
|
||||
let proxies = data.fetch_proxies();
|
||||
assert!(proxies.is_null());
|
||||
}
|
||||
|
||||
// Test after refresh
|
||||
{
|
||||
let mut data = manager.write();
|
||||
data.refresh_proxies().await;
|
||||
let _proxies = data.fetch_proxies();
|
||||
// Can only verify the method returns without panicking
|
||||
// Would need API mocking for more thorough testing
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_fetch_providers_proxies() {
|
||||
let manager = MihomoManager::new();
|
||||
|
||||
// Test initial state
|
||||
{
|
||||
let data = manager.read();
|
||||
let providers_proxies = data.fetch_providers_proxies();
|
||||
assert!(providers_proxies.is_null());
|
||||
}
|
||||
|
||||
// Test after refresh
|
||||
{
|
||||
let mut data = manager.write();
|
||||
data.refresh_providers_proxies().await;
|
||||
let _providers_proxies = data.fetch_providers_proxies();
|
||||
// Can only verify the method returns without panicking
|
||||
// Would need API mocking for more thorough testing
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1 @@
|
||||
pub mod api;
|
||||
pub mod sysinfo;
|
||||
pub mod mihomo;
|
Loading…
x
Reference in New Issue
Block a user