verge.rs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. use crate::utils::{dirs, help};
  2. use anyhow::Result;
  3. use log::LevelFilter;
  4. use serde::{Deserialize, Serialize};
  5. /// ### `verge.yaml` schema
  6. #[derive(Default, Debug, Clone, Deserialize, Serialize)]
  7. pub struct IVerge {
  8. /// app listening port for app singleton
  9. pub app_singleton_port: Option<u16>,
  10. /// app log level
  11. /// silent | error | warn | info | debug | trace
  12. pub app_log_level: Option<String>,
  13. // i18n
  14. pub language: Option<String>,
  15. /// `light` or `dark` or `system`
  16. pub theme_mode: Option<String>,
  17. /// enable blur mode
  18. /// maybe be able to set the alpha
  19. pub theme_blur: Option<bool>,
  20. /// tray click event
  21. pub tray_event: Option<String>,
  22. /// copy env type
  23. pub env_type: Option<String>,
  24. /// enable traffic graph default is true
  25. pub traffic_graph: Option<bool>,
  26. /// show memory info (only for Clash Meta)
  27. pub enable_memory_usage: Option<bool>,
  28. /// clash tun mode
  29. pub enable_tun_mode: Option<bool>,
  30. /// windows service mode
  31. #[serde(skip_serializing_if = "Option::is_none")]
  32. pub enable_service_mode: Option<bool>,
  33. /// can the app auto startup
  34. pub enable_auto_launch: Option<bool>,
  35. /// not show the window on launch
  36. pub enable_silent_start: Option<bool>,
  37. /// set system proxy
  38. pub enable_system_proxy: Option<bool>,
  39. /// enable proxy guard
  40. pub enable_proxy_guard: Option<bool>,
  41. /// set system proxy bypass
  42. pub system_proxy_bypass: Option<String>,
  43. /// proxy guard duration
  44. pub proxy_guard_duration: Option<u64>,
  45. /// theme setting
  46. pub theme_setting: Option<IVergeTheme>,
  47. /// web ui list
  48. pub web_ui_list: Option<Vec<String>>,
  49. /// clash core path
  50. #[serde(skip_serializing_if = "Option::is_none")]
  51. pub clash_core: Option<String>,
  52. /// hotkey map
  53. /// format: {func},{key}
  54. pub hotkeys: Option<Vec<String>>,
  55. /// 切换代理时自动关闭连接
  56. pub auto_close_connection: Option<bool>,
  57. /// 默认的延迟测试连接
  58. pub default_latency_test: Option<String>,
  59. /// 支持关闭字段过滤,避免meta的新字段都被过滤掉,默认为关闭
  60. pub enable_clash_fields: Option<bool>,
  61. /// 是否使用内部的脚本支持,默认为真
  62. pub enable_builtin_enhanced: Option<bool>,
  63. /// proxy 页面布局 列数
  64. pub proxy_layout_column: Option<i32>,
  65. /// 日志清理
  66. /// 0: 不清理; 1: 7天; 2: 30天; 3: 90天
  67. pub auto_log_clean: Option<i32>,
  68. /// window size and position
  69. #[serde(skip_serializing_if = "Option::is_none")]
  70. pub window_size_position: Option<Vec<f64>>,
  71. /// 是否启用随机端口
  72. pub enable_random_port: Option<bool>,
  73. /// verge mixed port 用于覆盖 clash 的 mixed port
  74. pub verge_mixed_port: Option<u16>,
  75. }
  76. #[derive(Default, Debug, Clone, Deserialize, Serialize)]
  77. pub struct IVergeTheme {
  78. pub primary_color: Option<String>,
  79. pub secondary_color: Option<String>,
  80. pub primary_text: Option<String>,
  81. pub secondary_text: Option<String>,
  82. pub info_color: Option<String>,
  83. pub error_color: Option<String>,
  84. pub warning_color: Option<String>,
  85. pub success_color: Option<String>,
  86. pub font_family: Option<String>,
  87. pub css_injection: Option<String>,
  88. }
  89. impl IVerge {
  90. pub fn new() -> Self {
  91. match dirs::verge_path().and_then(|path| help::read_yaml::<IVerge>(&path)) {
  92. Ok(config) => config,
  93. Err(err) => {
  94. log::error!(target: "app", "{err}");
  95. Self::template()
  96. }
  97. }
  98. }
  99. pub fn template() -> Self {
  100. Self {
  101. clash_core: Some("clash-meta".into()),
  102. language: Some("zh".into()),
  103. theme_mode: Some("system".into()),
  104. #[cfg(not(target_os = "windows"))]
  105. env_type: Some("bash".into()),
  106. #[cfg(target_os = "windows")]
  107. env_type: Some("powershell".into()),
  108. theme_blur: Some(false),
  109. traffic_graph: Some(true),
  110. enable_memory_usage: Some(true),
  111. enable_auto_launch: Some(false),
  112. enable_silent_start: Some(false),
  113. enable_system_proxy: Some(false),
  114. enable_random_port: Some(false),
  115. verge_mixed_port: Some(7897),
  116. enable_proxy_guard: Some(false),
  117. proxy_guard_duration: Some(30),
  118. auto_close_connection: Some(true),
  119. enable_builtin_enhanced: Some(true),
  120. enable_clash_fields: Some(false),
  121. auto_log_clean: Some(3),
  122. ..Self::default()
  123. }
  124. }
  125. /// Save IVerge App Config
  126. pub fn save_file(&self) -> Result<()> {
  127. help::save_yaml(&dirs::verge_path()?, &self, Some("# Clash Verge Config"))
  128. }
  129. /// patch verge config
  130. /// only save to file
  131. pub fn patch_config(&mut self, patch: IVerge) {
  132. macro_rules! patch {
  133. ($key: tt) => {
  134. if patch.$key.is_some() {
  135. self.$key = patch.$key;
  136. }
  137. };
  138. }
  139. patch!(app_log_level);
  140. patch!(language);
  141. patch!(theme_mode);
  142. patch!(theme_blur);
  143. patch!(tray_event);
  144. patch!(env_type);
  145. patch!(traffic_graph);
  146. patch!(enable_memory_usage);
  147. patch!(enable_tun_mode);
  148. patch!(enable_service_mode);
  149. patch!(enable_auto_launch);
  150. patch!(enable_silent_start);
  151. patch!(enable_random_port);
  152. patch!(verge_mixed_port);
  153. patch!(enable_system_proxy);
  154. patch!(enable_proxy_guard);
  155. patch!(system_proxy_bypass);
  156. patch!(proxy_guard_duration);
  157. patch!(theme_setting);
  158. patch!(web_ui_list);
  159. patch!(clash_core);
  160. patch!(hotkeys);
  161. patch!(auto_close_connection);
  162. patch!(default_latency_test);
  163. patch!(enable_builtin_enhanced);
  164. patch!(proxy_layout_column);
  165. patch!(enable_clash_fields);
  166. patch!(auto_log_clean);
  167. patch!(window_size_position);
  168. }
  169. /// 在初始化前尝试拿到单例端口的值
  170. pub fn get_singleton_port() -> u16 {
  171. #[cfg(not(feature = "verge-dev"))]
  172. const SERVER_PORT: u16 = 33331;
  173. #[cfg(feature = "verge-dev")]
  174. const SERVER_PORT: u16 = 11233;
  175. match dirs::verge_path().and_then(|path| help::read_yaml::<IVerge>(&path)) {
  176. Ok(config) => config.app_singleton_port.unwrap_or(SERVER_PORT),
  177. Err(_) => SERVER_PORT, // 这里就不log错误了
  178. }
  179. }
  180. /// 获取日志等级
  181. pub fn get_log_level(&self) -> LevelFilter {
  182. if let Some(level) = self.app_log_level.as_ref() {
  183. match level.to_lowercase().as_str() {
  184. "silent" => LevelFilter::Off,
  185. "error" => LevelFilter::Error,
  186. "warn" => LevelFilter::Warn,
  187. "info" => LevelFilter::Info,
  188. "debug" => LevelFilter::Debug,
  189. "trace" => LevelFilter::Trace,
  190. _ => LevelFilter::Info,
  191. }
  192. } else {
  193. LevelFilter::Info
  194. }
  195. }
  196. }