From e3b4e621f26ed59bcb4caf793027f8b08be15c3e Mon Sep 17 00:00:00 2001 From: spencerwooo Date: Mon, 15 Jan 2024 23:15:37 +0800 Subject: [PATCH 1/3] feat: add support for geodata updates --- Cargo.toml | 4 ++-- src/cmd.rs | 2 ++ src/config.rs | 27 +++++++++++++++++++++++++ src/main.rs | 1 + src/mihoro.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++++----- 5 files changed, 82 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6b38120..121c4e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "mihoro" description = "Mihomo CLI client on Linux." -version = "0.3.0" +version = "0.4.0" edition = "2021" readme = "README.md" license = "MIT" @@ -29,4 +29,4 @@ futures-util = "0.3" indicatif = "0.17" tokio = { version = "1.34", features = ["full"] } truncatable = "0.1" -anyhow = "1.0.77" +anyhow = "1.0" diff --git a/src/cmd.rs b/src/cmd.rs index f1dec1c..fc23f5a 100644 --- a/src/cmd.rs +++ b/src/cmd.rs @@ -16,6 +16,8 @@ pub enum Commands { Setup, /// Update mihomo remote config and restart mihomo.service Update, + /// Update mihomo geodata + UpdateGeodata, /// Apply mihomo config overrides and restart mihomo.service Apply, /// Start mihomo.service with systemctl diff --git a/src/config.rs b/src/config.rs index d5335ca..25334aa 100644 --- a/src/config.rs +++ b/src/config.rs @@ -32,6 +32,10 @@ pub struct MihomoConfig { external_controller: Option, external_ui: Option, secret: Option, + pub geodata_mode: Option, + pub geo_auto_update: Option, + pub geo_update_interval: Option, + pub geox_url: Option, } #[derive(Serialize, Deserialize, Debug, Clone)] @@ -58,6 +62,13 @@ pub enum MihomoLogLevel { Debug, } +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct GeoxUrl { + pub geoip: String, + pub geosite: String, + pub mmdb: String, +} + impl Config { pub fn new() -> Config { Config { @@ -66,6 +77,8 @@ impl Config { mihomo_binary_path: String::from("~/.local/bin/mihomo"), mihomo_config_root: String::from("~/.config/mihomo"), user_systemd_root: String::from("~/.config/systemd/user"), + + // https://wiki.metacubex.one/config/general mihomo_config: MihomoConfig { port: 7890, socks_port: 7891, @@ -77,6 +90,20 @@ impl Config { external_controller: Some(String::from("0.0.0.0:9090")), external_ui: Some(String::from("ui")), secret: None, + geodata_mode: Some(false), + geo_auto_update: Some(true), + geo_update_interval: Some(24), + geox_url: Some(GeoxUrl { + geoip: String::from( + "https://cdn.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geoip.dat", + ), + geosite: String::from( + "https://cdn.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geosite.dat", + ), + mmdb: String::from( + "https://cdn.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/country.mmdb", + ), + }), }, } } diff --git a/src/main.rs b/src/main.rs index 62f8ebc..0887e25 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,6 +35,7 @@ async fn cli() -> Result<()> { match &args.command { Some(Commands::Setup) => mihoro.setup(client).await?, Some(Commands::Update) => mihoro.update(client).await?, + Some(Commands::UpdateGeodata) => mihoro.update_geodata(client).await?, Some(Commands::Apply) => mihoro.apply().await?, Some(Commands::Uninstall) => mihoro.uninstall()?, Some(Commands::Proxy { proxy }) => mihoro.proxy_commands(proxy)?, diff --git a/src/mihoro.rs b/src/mihoro.rs index 8b53eec..ca214d4 100644 --- a/src/mihoro.rs +++ b/src/mihoro.rs @@ -44,7 +44,7 @@ impl Mihoro { }); } - pub async fn setup(self, client: Client) -> Result<()> { + pub async fn setup(&self, client: Client) -> Result<()> { println!( "{} Setting up mihomo's binary, config, and systemd service...", &self.prefix.cyan() @@ -85,6 +85,9 @@ impl Mihoro { .await?; apply_mihomo_override(&self.mihomo_target_config_path, &self.config.mihomo_config)?; + // Download geodata + self.update_geodata(client).await?; + // Create mihomo.service systemd file create_mihomo_service( &self.mihomo_target_binary_path, @@ -98,7 +101,7 @@ impl Mihoro { Ok(()) } - pub async fn update(self, client: Client) -> Result<()> { + pub async fn update(&self, client: Client) -> Result<()> { // Download remote mihomo config and apply override download_file( &client, @@ -118,7 +121,49 @@ impl Mihoro { Ok(()) } - pub async fn apply(self) -> Result<()> { + pub async fn update_geodata(&self, client: Client) -> Result<()> { + match self.config.mihomo_config.geox_url.clone() { + Some(geox_url) => { + // Download geodata files based on `geodata_mode` + let geodata_mode = self.config.mihomo_config.geodata_mode.unwrap_or(false); + if geodata_mode { + download_file( + &client, + &geox_url.geoip, + format!("{}/geoip.dat", &self.mihomo_target_config_root).as_str(), + ) + .await?; + download_file( + &client, + &geox_url.geosite, + format!("{}/geosite.dat", &self.mihomo_target_config_root).as_str(), + ) + .await?; + } else { + download_file( + &client, + &geox_url.mmdb, + format!("{}/country.mmdb", &self.mihomo_target_config_root).as_str(), + ) + .await?; + } + + println!("{} Downloaded and updated geodata", self.prefix.green()); + } + None => { + println!( + "{} `geox_url` undefined, refer to {}", + self.prefix.yellow(), + "'https://wiki.metacubex.one/config/general/#geo_3'" + .bold() + .underline() + ); + } + } + Ok(()) + } + + pub async fn apply(&self) -> Result<()> { // Apply mihomo config override apply_mihomo_override(&self.mihomo_target_config_path, &self.config.mihomo_config).map( |_| { @@ -139,7 +184,7 @@ impl Mihoro { Ok(()) } - pub fn uninstall(self) -> Result<()> { + pub fn uninstall(&self) -> Result<()> { Systemctl::new().stop("mihomo.service").execute()?; Systemctl::new().disable("mihomo.service").execute()?; @@ -165,7 +210,7 @@ impl Mihoro { Ok(()) } - pub fn proxy_commands(self, proxy: &Option) -> Result<()> { + pub fn proxy_commands(&self, proxy: &Option) -> Result<()> { match proxy { Some(ProxyCommands::Export) => { println!( From b800f83f91b877da241a9e37677933b4e217b4bb Mon Sep 17 00:00:00 2001 From: spencerwooo Date: Mon, 15 Jan 2024 23:48:51 +0800 Subject: [PATCH 2/3] refactor: better unwrap handling --- src/mihoro.rs | 69 ++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/src/mihoro.rs b/src/mihoro.rs index ca214d4..9c36413 100644 --- a/src/mihoro.rs +++ b/src/mihoro.rs @@ -122,43 +122,40 @@ impl Mihoro { } pub async fn update_geodata(&self, client: Client) -> Result<()> { - match self.config.mihomo_config.geox_url.clone() { - Some(geox_url) => { - // Download geodata files based on `geodata_mode` - let geodata_mode = self.config.mihomo_config.geodata_mode.unwrap_or(false); - if geodata_mode { - download_file( - &client, - &geox_url.geoip, - format!("{}/geoip.dat", &self.mihomo_target_config_root).as_str(), - ) - .await?; - download_file( - &client, - &geox_url.geosite, - format!("{}/geosite.dat", &self.mihomo_target_config_root).as_str(), - ) - .await?; - } else { - download_file( - &client, - &geox_url.mmdb, - format!("{}/country.mmdb", &self.mihomo_target_config_root).as_str(), - ) - .await?; - } - - println!("{} Downloaded and updated geodata", self.prefix.green()); - } - None => { - println!( - "{} `geox_url` undefined, refer to {}", - self.prefix.yellow(), - "'https://wiki.metacubex.one/config/general/#geo_3'" - .bold() - .underline() - ); + if let Some(geox_url) = self.config.mihomo_config.geox_url.clone() { + // Download geodata files based on `geodata_mode` + let geodata_mode = self.config.mihomo_config.geodata_mode.unwrap_or(false); + if geodata_mode { + download_file( + &client, + &geox_url.geoip, + format!("{}/geoip.dat", &self.mihomo_target_config_root).as_str(), + ) + .await?; + download_file( + &client, + &geox_url.geosite, + format!("{}/geosite.dat", &self.mihomo_target_config_root).as_str(), + ) + .await?; + } else { + download_file( + &client, + &geox_url.mmdb, + format!("{}/country.mmdb", &self.mihomo_target_config_root).as_str(), + ) + .await?; } + + println!("{} Downloaded and updated geodata", self.prefix.green()); + } else { + println!( + "{} `geox_url` undefined, refer to {}", + self.prefix.yellow(), + "'https://wiki.metacubex.one/config/general/#geo_3'" + .bold() + .underline() + ); } Ok(()) } From 8aae8d70e7c486c754ce6caa8a055657a7e679db Mon Sep 17 00:00:00 2001 From: spencerwooo Date: Tue, 16 Jan 2024 11:40:19 +0800 Subject: [PATCH 3/3] fix: enable config override for new fields --- src/config.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/config.rs b/src/config.rs index 25334aa..2ca02ac 100644 --- a/src/config.rs +++ b/src/config.rs @@ -196,6 +196,21 @@ pub struct MihomoYamlConfig { #[serde(skip_serializing_if = "Option::is_none")] secret: Option, + #[serde(rename = "geodata-mode", skip_serializing_if = "Option::is_none")] + geodata_mode: Option, + + #[serde(rename = "geo-auto-update", skip_serializing_if = "Option::is_none")] + geo_auto_update: Option, + + #[serde( + rename = "geo-update-interval", + skip_serializing_if = "Option::is_none" + )] + geo_update_interval: Option, + + #[serde(rename = "geox-url", skip_serializing_if = "Option::is_none")] + geox_url: Option, + #[serde(flatten)] extra: HashMap, } @@ -223,6 +238,10 @@ pub fn apply_mihomo_override(path: &str, override_config: &MihomoConfig) -> Resu mihomo_yaml.external_controller = override_config.external_controller.clone(); mihomo_yaml.external_ui = override_config.external_ui.clone(); mihomo_yaml.secret = override_config.secret.clone(); + mihomo_yaml.geodata_mode = override_config.geodata_mode; + mihomo_yaml.geo_auto_update = override_config.geo_auto_update; + mihomo_yaml.geo_update_interval = override_config.geo_update_interval; + mihomo_yaml.geox_url = override_config.geox_url.clone(); // Write to file let serialized_mihomo_yaml = serde_yaml::to_string(&mihomo_yaml)?;