chore: update

This commit is contained in:
huzibaca
2024-11-08 21:46:15 +08:00
parent 2887a2b6d3
commit c22e4e5e2c
20 changed files with 887 additions and 4 deletions

247
src-tauri/Cargo.lock generated
View File

@@ -23,6 +23,17 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "aes"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures",
]
[[package]]
name = "ahash"
version = "0.8.11"
@@ -841,6 +852,27 @@ dependencies = [
"serde",
]
[[package]]
name = "bzip2"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8"
dependencies = [
"bzip2-sys",
"libc",
]
[[package]]
name = "bzip2-sys"
version = "0.1.11+1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc"
dependencies = [
"cc",
"libc",
"pkg-config",
]
[[package]]
name = "cairo-rs"
version = "0.18.5"
@@ -973,6 +1005,16 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "cipher"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [
"crypto-common",
"inout",
]
[[package]]
name = "clash-verge"
version = "2.0.0"
@@ -995,6 +1037,7 @@ dependencies = [
"percent-encoding",
"port_scanner",
"reqwest",
"reqwest_dav",
"runas",
"serde",
"serde_json",
@@ -1020,6 +1063,7 @@ dependencies = [
"warp",
"window-shadows",
"winreg 0.52.0",
"zip",
]
[[package]]
@@ -1156,6 +1200,12 @@ dependencies = [
"tiny-keccak",
]
[[package]]
name = "constant_time_eq"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
[[package]]
name = "convert_case"
version = "0.4.0"
@@ -1245,6 +1295,21 @@ dependencies = [
"libc",
]
[[package]]
name = "crc"
version = "3.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636"
dependencies = [
"crc-catalog",
]
[[package]]
name = "crc-catalog"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
[[package]]
name = "crc32fast"
version = "1.4.2"
@@ -1420,6 +1485,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "deflate64"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da692b8d1080ea3045efaab14434d40468c3d8657e42abddfffca87b428f4c1b"
[[package]]
name = "delay_timer"
version = "0.11.6"
@@ -1555,6 +1626,20 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer 0.10.4",
"crypto-common",
"subtle",
]
[[package]]
name = "digest_auth"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3054f4e81d395e50822796c5e99ca522e6ba7be98947d6d4b0e5e61640bdb894"
dependencies = [
"digest 0.10.7",
"hex",
"md-5",
"rand 0.8.5",
"sha2 0.10.8",
]
[[package]]
@@ -2622,6 +2707,15 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest 0.10.7",
]
[[package]]
name = "home"
version = "0.5.9"
@@ -3077,6 +3171,15 @@ dependencies = [
"cfb",
]
[[package]]
name = "inout"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
dependencies = [
"generic-array",
]
[[package]]
name = "instant"
version = "0.1.13"
@@ -3461,6 +3564,12 @@ dependencies = [
"scopeguard",
]
[[package]]
name = "lockfree-object-pool"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e"
[[package]]
name = "log"
version = "0.4.22"
@@ -3522,6 +3631,16 @@ dependencies = [
"hashbrown 0.15.0",
]
[[package]]
name = "lzma-rs"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e"
dependencies = [
"byteorder",
"crc",
]
[[package]]
name = "mac"
version = "0.1.1"
@@ -3594,6 +3713,16 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "md-5"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
dependencies = [
"cfg-if",
"digest 0.10.7",
]
[[package]]
name = "memchr"
version = "2.7.4"
@@ -4459,6 +4588,16 @@ dependencies = [
"libc",
]
[[package]]
name = "pbkdf2"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
dependencies = [
"digest 0.10.7",
"hmac",
]
[[package]]
name = "percent-encoding"
version = "2.3.1"
@@ -5294,6 +5433,26 @@ dependencies = [
"windows-registry 0.2.0",
]
[[package]]
name = "reqwest_dav"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea79cbb695b7cc877ae9c0f0eeb8468e36cd03dc9c41a93bcf237396357c7b42"
dependencies = [
"async-trait",
"chrono",
"digest_auth",
"http 1.1.0",
"httpdate",
"reqwest",
"serde",
"serde-xml-rs",
"serde_derive",
"serde_json",
"tokio",
"url",
]
[[package]]
name = "rfd"
version = "0.15.0"
@@ -5664,6 +5823,18 @@ dependencies = [
"serde",
]
[[package]]
name = "serde-xml-rs"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb3aa78ecda1ebc9ec9847d5d3aba7d618823446a049ba2491940506da6e2782"
dependencies = [
"log",
"serde",
"thiserror",
"xml-rs",
]
[[package]]
name = "serde_derive"
version = "1.0.213"
@@ -8527,6 +8698,12 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "xml-rs"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af310deaae937e48a26602b730250b4949e125f468f11e6990be3e5304ddd96f"
[[package]]
name = "yoke"
version = "0.7.4"
@@ -8663,6 +8840,20 @@ name = "zeroize"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
dependencies = [
"zeroize_derive",
]
[[package]]
name = "zeroize_derive"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.85",
]
[[package]]
name = "zerovec"
@@ -8692,13 +8883,69 @@ version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc5e4288ea4057ae23afc69a4472434a87a2495cafce6632fd1c4ec9f5cf3494"
dependencies = [
"aes",
"arbitrary",
"bzip2",
"constant_time_eq",
"crc32fast",
"crossbeam-utils",
"deflate64",
"displaydoc",
"flate2",
"hmac",
"indexmap 2.6.0",
"lzma-rs",
"memchr",
"pbkdf2",
"rand 0.8.5",
"sha1",
"thiserror",
"time",
"zeroize",
"zopfli",
"zstd",
]
[[package]]
name = "zopfli"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946"
dependencies = [
"bumpalo",
"crc32fast",
"lockfree-object-pool",
"log",
"once_cell",
"simd-adler32",
]
[[package]]
name = "zstd"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9"
dependencies = [
"zstd-safe",
]
[[package]]
name = "zstd-safe"
version = "7.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059"
dependencies = [
"zstd-sys",
]
[[package]]
name = "zstd-sys"
version = "2.0.13+zstd.1.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa"
dependencies = [
"cc",
"pkg-config",
]
[[package]]

View File

@@ -54,6 +54,8 @@ tauri-plugin-clipboard-manager = "2.0.1"
tauri-plugin-deep-link = "2.0.1"
tauri-plugin-devtools = "2.0.0-rc"
url = "2.5.2"
zip = "2.2.0"
reqwest_dav = "0.1.14"
[target.'cfg(windows)'.dependencies]
runas = "=1.2.0"
deelevate = "0.2.0"

View File

@@ -11,6 +11,7 @@ use serde_yaml::Mapping;
use std::collections::{HashMap, VecDeque};
use sysproxy::{Autoproxy, Sysproxy};
type CmdResult<T = ()> = Result<T, String>;
use reqwest_dav::list_cmd::ListFile;
use tauri::Manager;
#[tauri::command]
@@ -375,6 +376,37 @@ pub async fn exit_app() {
feat::quit(Some(0));
}
#[tauri::command]
pub async fn save_webdav_config(url: String, username: String, password: String) -> CmdResult<()> {
let patch = IVerge {
webdav_url: Some(url),
webdav_username: Some(username),
webdav_password: Some(password),
..IVerge::default()
};
Config::verge().draft().patch_config(patch.clone());
Config::verge().apply();
Config::verge()
.data()
.save_file()
.map_err(|err| err.to_string())?;
backup::WebDavClient::global().reset();
Ok(())
}
#[tauri::command]
pub async fn create_webdav_backup() -> CmdResult<()> {
feat::create_backup_and_upload_webdav()
.await
.map_err(|err| err.to_string())?;
Ok(())
}
#[tauri::command]
pub async fn list_webdav_backup() -> CmdResult<Vec<ListFile>> {
feat::list_wevdav_backup().await.map_err(|e| e.to_string())
}
pub mod service {
use super::*;
use crate::core::service;

View File

@@ -147,6 +147,10 @@ pub struct IVerge {
pub verge_port: Option<u16>,
pub verge_http_enabled: Option<bool>,
pub webdav_url: Option<String>,
pub webdav_username: Option<String>,
pub webdav_password: Option<String>,
}
#[derive(Default, Debug, Clone, Deserialize, Serialize)]
@@ -304,6 +308,10 @@ impl IVerge {
patch!(proxy_layout_column);
patch!(test_list);
patch!(auto_log_clean);
patch!(webdav_url);
patch!(webdav_username);
patch!(webdav_password);
}
/// 在初始化前尝试拿到单例端口的值

View File

@@ -0,0 +1,118 @@
use crate::config::Config;
use crate::utils::dirs;
use anyhow::Error;
use once_cell::sync::OnceCell;
use parking_lot::Mutex;
use reqwest_dav::list_cmd::{ListEntity, ListFile};
use std::env::{consts::OS, temp_dir};
use std::fs;
use std::io::Write;
use std::path::PathBuf;
use std::sync::Arc;
use zip::write::SimpleFileOptions;
pub struct WebDavClient {
client: Arc<Mutex<Option<reqwest_dav::Client>>>,
}
impl WebDavClient {
pub fn global() -> &'static WebDavClient {
static WEBDAV_CLIENT: OnceCell<WebDavClient> = OnceCell::new();
WEBDAV_CLIENT.get_or_init(|| WebDavClient {
client: Arc::new(Mutex::new(None)),
})
}
async fn get_client(&self) -> Result<reqwest_dav::Client, Error> {
if self.client.lock().is_none() {
let verge = Config::verge().latest().clone();
if verge.webdav_url.is_none()
|| verge.webdav_username.is_none()
|| verge.webdav_password.is_none()
{
let msg =
"Unable to create web dav client, please make sure the webdav config is correct"
.to_string();
log::error!(target: "app","{}",msg);
return Err(anyhow::Error::msg(msg));
}
let url = verge.webdav_url.unwrap_or_default();
let username = verge.webdav_username.unwrap_or_default();
let password = verge.webdav_password.unwrap_or_default();
let client = reqwest_dav::ClientBuilder::new()
.set_host(url.to_owned())
.set_auth(reqwest_dav::Auth::Basic(
username.to_owned(),
password.to_owned(),
))
.build()?;
*self.client.lock() = Some(client.clone());
}
Ok(self.client.lock().clone().unwrap())
}
pub fn reset(&self) {
if !self.client.lock().is_none() {
self.client.lock().take();
}
}
pub async fn upload(&self, file_path: PathBuf, file_name: String) -> Result<(), Error> {
let client = self.get_client().await?;
if client.get(dirs::BACKUP_DIR).await.is_err() {
client.mkcol(dirs::BACKUP_DIR).await?;
}
let webdav_path: String = format!("{}/{}", dirs::BACKUP_DIR, file_name);
client
.put(webdav_path.as_ref(), fs::read(file_path)?)
.await?;
Ok(())
}
pub async fn list_files(&self) -> Result<Vec<ListFile>, Error> {
let client = self.get_client().await?;
let files = client
.list(dirs::BACKUP_DIR, reqwest_dav::Depth::Number(1))
.await?;
let mut final_files = Vec::new();
for file in files {
if let ListEntity::File(file) = file {
final_files.push(file);
}
}
Ok(final_files)
}
}
pub fn create_backup() -> Result<(String, PathBuf), Error> {
let now = chrono::Local::now().format("%Y-%m-%d_%H-%M-%S").to_string();
let zip_file_name = format!("{}-backup-{}.zip", OS, now);
let zip_path = temp_dir().join(&zip_file_name);
let file = fs::File::create(&zip_path)?;
let mut zip = zip::ZipWriter::new(file);
zip.add_directory("profiles/", SimpleFileOptions::default())?;
let options = SimpleFileOptions::default().compression_method(zip::CompressionMethod::Stored);
if let Ok(entries) = fs::read_dir(dirs::app_profiles_dir()?) {
for entry in entries {
let entry = entry.unwrap();
let path = entry.path();
if path.is_file() {
let backup_path = format!("profiles/{}", entry.file_name().to_str().unwrap());
zip.start_file(backup_path, options)?;
zip.write_all(fs::read(path).unwrap().as_slice())?;
}
}
}
zip.start_file(dirs::CLASH_CONFIG, options)?;
zip.write_all(fs::read(dirs::clash_path()?)?.as_slice())?;
zip.start_file(dirs::VERGE_CONFIG, options)?;
zip.write_all(fs::read(dirs::verge_path()?)?.as_slice())?;
zip.start_file(dirs::PROFILE_YAML, options)?;
zip.write_all(fs::read(dirs::profiles_path()?)?.as_slice())?;
zip.finish()?;
Ok((zip_file_name, zip_path))
}

View File

@@ -1,3 +1,4 @@
pub mod backup;
pub mod clash_api;
#[allow(clippy::module_inception)]
mod core;

View File

@@ -9,6 +9,7 @@ use crate::core::*;
use crate::log_err;
use crate::utils::resolve;
use anyhow::{bail, Result};
use reqwest_dav::list_cmd::ListFile;
use serde_yaml::{Mapping, Value};
use tauri_plugin_clipboard_manager::ClipboardExt;
@@ -401,3 +402,42 @@ pub async fn test_delay(url: String) -> Result<u32> {
}
}
}
pub async fn create_backup_and_upload_webdav() -> Result<()> {
if let Err(err) = async {
let (file_name, temp_file_path) = backup::create_backup().map_err(|err| {
log::error!(target: "app", "Failed to create backup: {:#?}", err);
err
})?;
backup::WebDavClient::global()
.upload(temp_file_path.clone(), file_name)
.await
.map_err(|err| {
log::error!(target: "app", "Failed to upload to WebDAV: {:#?}", err);
err
})?;
std::fs::remove_file(&temp_file_path).map_err(|err| {
log::warn!(target: "app", "Failed to remove temp file: {:#?}", err);
err
})?;
Ok(())
}
.await
{
return Err(err);
}
Ok(())
}
pub async fn list_wevdav_backup() -> Result<Vec<ListFile>> {
backup::WebDavClient::global()
.list_files()
.await
.map_err(|err| {
log::error!(target: "app", "Failed to list WebDAV backup files: {:#?}", err);
err
})
}

View File

@@ -123,7 +123,11 @@ pub fn run() {
// service mode
cmds::service::check_service,
// clash api
cmds::clash_api_get_proxy_delay
cmds::clash_api_get_proxy_delay,
// backup
cmds::create_webdav_backup,
cmds::save_webdav_config,
cmds::list_webdav_backup,
]);
#[cfg(debug_assertions)]

View File

@@ -6,14 +6,19 @@ use tauri::Manager;
#[cfg(not(feature = "verge-dev"))]
pub static APP_ID: &str = "io.github.clash-verge-rev.clash-verge-rev";
#[cfg(not(feature = "verge-dev"))]
pub static BACKUP_DIR: &str = "clash-verge-rev-backup";
#[cfg(feature = "verge-dev")]
pub static APP_ID: &str = "io.github.clash-verge-rev.clash-verge-rev.dev";
#[cfg(feature = "verge-dev")]
pub static BACKUP_DIR: &str = "clash-verge-rev-backup-dev";
pub static PORTABLE_FLAG: OnceCell<bool> = OnceCell::new();
static CLASH_CONFIG: &str = "config.yaml";
static VERGE_CONFIG: &str = "verge.yaml";
static PROFILE_YAML: &str = "profiles.yaml";
pub static CLASH_CONFIG: &str = "config.yaml";
pub static VERGE_CONFIG: &str = "verge.yaml";
pub static PROFILE_YAML: &str = "profiles.yaml";
/// init portable flag
pub fn init_portable_flag() -> Result<()> {