1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use std::path::PathBuf;
use std::time::Duration;
use clashctl_core::Clash;
use home::home_dir;
use log::debug;
use url::Url;
use crate::{Config, Error, Result};
const DEFAULT_TEST_URL: &str = "http://www.gstatic.com/generate_204";
#[derive(Clone, Debug, clap::Parser)]
pub struct Flags {
#[clap(short, long, parse(from_occurrences))]
pub verbose: u8,
#[clap(short, long, default_value = "2000")]
pub timeout: u64,
#[clap(long, conflicts_with = "config-path")]
pub config_dir: Option<PathBuf>,
#[clap(short, long, conflicts_with = "config-dir")]
pub config_path: Option<PathBuf>,
#[clap(
long,
default_value = DEFAULT_TEST_URL,
)
]
pub test_url: Url,
}
impl Default for Flags {
fn default() -> Self {
Self {
verbose: 0,
timeout: 2000,
config_dir: None,
config_path: None,
test_url: Url::parse(DEFAULT_TEST_URL).unwrap(),
}
}
}
impl Flags {
pub fn get_config(&self) -> Result<Config> {
if let Some(ref dir) = self.config_path {
return Config::from_dir(dir);
}
let conf_dir = self
.config_dir
.to_owned()
.or_else(|| home_dir().map(|dir| dir.join(".config/clashctl/")))
.ok_or(Error::ConfigFileOpenError)?;
if !conf_dir.exists() {
debug!("Config directory does not exist, creating.");
std::fs::create_dir_all(&conf_dir).map_err(Error::ConfigFileIoError)?;
}
if !conf_dir.is_dir() {
Err(Error::ConfigFileTypeError(conf_dir))
} else {
debug!("Path to config: {}", conf_dir.display());
Config::from_dir(conf_dir.join("config.ron"))
}
}
pub fn connect_server_from_config(&self) -> Result<Clash> {
let config = self.get_config()?;
let server = config
.using_server()
.ok_or(Error::ServerNotFound)?
.to_owned();
server.into_clash_with_timeout(Some(Duration::from_millis(self.timeout)))
}
}