refactor: Remove clash field filter

This commit is contained in:
MystiPanda 2024-02-05 16:47:40 +08:00
parent 45f863a72a
commit e990530ada
14 changed files with 182 additions and 352 deletions

View File

@ -25,6 +25,8 @@ impl IClashTemp {
let mut map = Mapping::new();
map.insert("mixed-port".into(), 7897.into());
map.insert("socks-port".into(), 7898.into());
map.insert("port".into(), 7899.into());
map.insert("log-level".into(), "info".into());
map.insert("allow-lan".into(), false.into());
map.insert("mode".into(), "rule".into());
@ -35,10 +37,14 @@ impl IClashTemp {
}
fn guard(mut config: Mapping) -> Mapping {
let port = Self::guard_mixed_port(&config);
let mixed_port = Self::guard_mixed_port(&config);
let socks_port = Self::guard_socks_port(&config);
let port = Self::guard_port(&config);
let ctrl = Self::guard_server_ctrl(&config);
config.insert("mixed-port".into(), port.into());
config.insert("mixed-port".into(), mixed_port.into());
config.insert("socks-port".into(), socks_port.into());
config.insert("port".into(), port.into());
config.insert("external-controller".into(), ctrl.into());
config
}
@ -61,11 +67,23 @@ impl IClashTemp {
Self::guard_mixed_port(&self.0)
}
#[allow(unused)]
pub fn get_socks_port(&self) -> u16 {
Self::guard_socks_port(&self.0)
}
#[allow(unused)]
pub fn get_port(&self) -> u16 {
Self::guard_port(&self.0)
}
pub fn get_client_info(&self) -> ClashInfo {
let config = &self.0;
ClashInfo {
port: Self::guard_mixed_port(config),
mixed_port: Self::guard_mixed_port(config),
socks_port: Self::guard_socks_port(config),
port: Self::guard_port(config),
server: Self::guard_client_ctrl(config),
secret: config.get("secret").and_then(|value| match value {
Value::String(val_str) => Some(val_str.clone()),
@ -91,6 +109,36 @@ impl IClashTemp {
port
}
pub fn guard_socks_port(config: &Mapping) -> u16 {
let mut port = config
.get("socks-port")
.and_then(|value| match value {
Value::String(val_str) => val_str.parse().ok(),
Value::Number(val_num) => val_num.as_u64().map(|u| u as u16),
_ => None,
})
.unwrap_or(7898);
if port == 0 {
port = 7898;
}
port
}
pub fn guard_port(config: &Mapping) -> u16 {
let mut port = config
.get("port")
.and_then(|value| match value {
Value::String(val_str) => val_str.parse().ok(),
Value::Number(val_num) => val_num.as_u64().map(|u| u as u16),
_ => None,
})
.unwrap_or(7899);
if port == 0 {
port = 7899;
}
port
}
pub fn guard_server_ctrl(config: &Mapping) -> String {
config
.get("external-controller")
@ -129,6 +177,8 @@ impl IClashTemp {
#[derive(Default, Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
pub struct ClashInfo {
/// clash core port
pub mixed_port: u16,
pub socks_port: u16,
pub port: u16,
/// same as `external-controller`
pub server: String,
@ -148,7 +198,9 @@ fn test_clash_info() {
fn get_result<S: Into<String>>(port: u16, server: S) -> ClashInfo {
ClashInfo {
port,
mixed_port: port,
socks_port: 7898,
port: 7899,
server: server.into(),
secret: None,
}

View File

@ -14,9 +14,6 @@ pub struct IProfiles {
/// same as PrfConfig.chain
pub chain: Option<Vec<String>>,
/// record valid fields for clash
pub valid: Option<Vec<String>>,
/// profile list
pub items: Option<Vec<PrfItem>>,
}
@ -55,13 +52,6 @@ impl IProfiles {
pub fn template() -> Self {
Self {
valid: Some(vec![
"dns".into(),
"sub-rules".into(),
"unified-delay".into(),
"tcp-concurrent".into(),
"global-client-fingerprint".into(),
]),
items: Some(vec![]),
..Self::default()
}
@ -94,10 +84,6 @@ impl IProfiles {
self.chain = Some(chain);
}
if let Some(valid) = patch.valid {
self.valid = Some(valid);
}
Ok(())
}

View File

@ -81,9 +81,6 @@ pub struct IVerge {
/// 默认的延迟测试连接
pub default_latency_test: Option<String>,
/// 支持关闭字段过滤避免meta的新字段都被过滤掉默认为关闭
pub enable_clash_fields: Option<bool>,
/// 是否使用内部的脚本支持,默认为真
pub enable_builtin_enhanced: Option<bool>,
@ -106,6 +103,10 @@ pub struct IVerge {
/// verge mixed port 用于覆盖 clash 的 mixed port
pub verge_mixed_port: Option<u16>,
pub verge_socks_port: Option<u16>,
pub verge_port: Option<u16>,
}
#[derive(Default, Debug, Clone, Deserialize, Serialize)]
@ -160,11 +161,12 @@ impl IVerge {
enable_system_proxy: Some(false),
enable_random_port: Some(false),
verge_mixed_port: Some(7897),
verge_socks_port: Some(7898),
verge_port: Some(7899),
enable_proxy_guard: Some(false),
proxy_guard_duration: Some(30),
auto_close_connection: Some(true),
enable_builtin_enhanced: Some(true),
enable_clash_fields: Some(true),
auto_log_clean: Some(3),
..Self::default()
}
@ -202,6 +204,8 @@ impl IVerge {
patch!(enable_silent_start);
patch!(enable_random_port);
patch!(verge_mixed_port);
patch!(verge_socks_port);
patch!(verge_port);
patch!(enable_system_proxy);
patch!(enable_proxy_guard);
patch!(system_proxy_bypass);
@ -217,7 +221,6 @@ impl IVerge {
patch!(enable_builtin_enhanced);
patch!(proxy_layout_column);
patch!(test_list);
patch!(enable_clash_fields);
patch!(auto_log_clean);
patch!(window_size_position);
}

View File

@ -3,9 +3,9 @@ use std::collections::HashSet;
pub const HANDLE_FIELDS: [&str; 9] = [
"mode",
"port",
"socks-port",
"mixed-port",
"socks-port",
"port",
"allow-lan",
"log-level",
"ipv6",
@ -15,71 +15,13 @@ pub const HANDLE_FIELDS: [&str; 9] = [
pub const DEFAULT_FIELDS: [&str; 5] = [
"proxies",
"proxy-groups",
"proxy-providers",
"rules",
"proxy-groups",
"rule-providers",
"rules",
];
pub const OTHERS_FIELDS: [&str; 31] = [
"dns",
"tun",
"ebpf",
"hosts",
"script",
"profile",
"payload",
"tunnels",
"auto-redir",
"experimental",
"interface-name",
"routing-mark",
"redir-port",
"tproxy-port",
"iptables",
"external-ui",
"bind-address",
"authentication",
"tls", // meta
"sniffer", // meta
"geox-url", // meta
"listeners", // meta
"sub-rules", // meta
"geodata-mode", // meta
"unified-delay", // meta
"tcp-concurrent", // meta
"enable-process", // meta
"find-process-mode", // meta
"skip-auth-prefixes", // meta
"external-controller-tls", // meta
"global-client-fingerprint", // meta
];
pub fn use_clash_fields() -> Vec<String> {
DEFAULT_FIELDS
.into_iter()
.chain(HANDLE_FIELDS)
.chain(OTHERS_FIELDS)
.map(|s| s.to_string())
.collect()
}
pub fn use_valid_fields(mut valid: Vec<String>) -> Vec<String> {
let others = Vec::from(OTHERS_FIELDS);
valid.iter_mut().for_each(|s| s.make_ascii_lowercase());
valid
.into_iter()
.filter(|s| others.contains(&s.as_str()))
.chain(DEFAULT_FIELDS.iter().map(|s| s.to_string()))
.collect()
}
pub fn use_filter(config: Mapping, filter: &Vec<String>, enable: bool) -> Mapping {
if !enable {
return config;
}
pub fn use_filter(config: Mapping, filter: &Vec<String>) -> Mapping {
let mut ret = Mapping::new();
for (key, value) in config.into_iter() {
@ -105,40 +47,35 @@ pub fn use_lowercase(config: Mapping) -> Mapping {
ret
}
pub fn use_sort(config: Mapping, enable_filter: bool) -> Mapping {
pub fn use_sort(config: Mapping) -> Mapping {
let mut ret = Mapping::new();
HANDLE_FIELDS.into_iter().for_each(|key| {
let key = Value::from(key);
if let Some(value) = config.get(&key) {
ret.insert(key, value.clone());
}
});
HANDLE_FIELDS
let supported_keys: HashSet<&str> = HANDLE_FIELDS.into_iter().chain(DEFAULT_FIELDS).collect();
let config_keys: HashSet<&str> = config
.keys()
.filter_map(|e| e.as_str())
.into_iter()
.chain(OTHERS_FIELDS)
.chain(DEFAULT_FIELDS)
.for_each(|key| {
let key = Value::from(key);
if let Some(value) = config.get(&key) {
ret.insert(key, value.clone());
}
});
.collect();
if !enable_filter {
let supported_keys: HashSet<&str> = HANDLE_FIELDS
.into_iter()
.chain(OTHERS_FIELDS)
.chain(DEFAULT_FIELDS)
.collect();
let config_keys: HashSet<&str> = config
.keys()
.filter_map(|e| e.as_str())
.into_iter()
.collect();
config_keys.difference(&supported_keys).for_each(|&key| {
let key = Value::from(key);
if let Some(value) = config.get(&key) {
ret.insert(key, value.clone());
}
});
}
config_keys.difference(&supported_keys).for_each(|&key| {
let key = Value::from(key);
if let Some(value) = config.get(&key) {
ret.insert(key, value.clone());
}
});
DEFAULT_FIELDS.into_iter().for_each(|key| {
let key = Value::from(key);
if let Some(value) = config.get(&key) {
ret.insert(key, value.clone());
}
});
ret
}

View File

@ -19,7 +19,7 @@ pub fn use_merge(merge: Mapping, mut config: Mapping) -> Mapping {
});
let merge_list = MERGE_FIELDS.iter().map(|s| s.to_string());
let merge = use_filter(merge, &merge_list.collect(), true);
let merge = use_filter(merge, &merge_list.collect());
["rules", "proxies", "proxy-groups"]
.iter()

View File

@ -22,19 +22,18 @@ pub fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
// config.yaml 的订阅
let clash_config = { Config::clash().latest().0.clone() };
let (clash_core, enable_tun, enable_builtin, enable_filter) = {
let (clash_core, enable_tun, enable_builtin) = {
let verge = Config::verge();
let verge = verge.latest();
(
verge.clash_core.clone(),
verge.enable_tun_mode.unwrap_or(false),
verge.enable_builtin_enhanced.unwrap_or(true),
verge.enable_clash_fields.unwrap_or(true),
)
};
// 从profiles里拿东西
let (mut config, chain, valid) = {
let (mut config, chain) = {
let profiles = Config::profiles();
let profiles = profiles.latest();
@ -49,23 +48,17 @@ pub fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
None => vec![],
};
let valid = profiles.valid.clone().unwrap_or_default();
(current, chain, valid)
(current, chain)
};
let mut result_map = HashMap::new(); // 保存脚本日志
let mut exists_keys = use_keys(&config); // 保存出现过的keys
let valid = use_valid_fields(valid);
config = use_filter(config, &valid, enable_filter);
// 处理用户的profile
chain.into_iter().for_each(|item| match item.data {
ChainType::Merge(merge) => {
exists_keys.extend(use_keys(&merge));
config = use_merge(merge, config.to_owned());
config = use_filter(config.to_owned(), &valid, enable_filter);
}
ChainType::Script(script) => {
let mut logs = vec![];
@ -73,7 +66,6 @@ pub fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
match use_script(script, config.to_owned()) {
Ok((res_config, res_logs)) => {
exists_keys.extend(use_keys(&res_config));
config = use_filter(res_config, &valid, enable_filter);
logs.extend(res_logs);
}
Err(err) => logs.push(("exception".into(), err.to_string())),
@ -88,8 +80,6 @@ pub fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
config.insert(key, value);
}
let clash_fields = use_clash_fields();
// 内建脚本最后跑
if enable_builtin {
ChainItem::builtin()
@ -102,7 +92,7 @@ pub fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
match item.data {
ChainType::Script(script) => match use_script(script, config.to_owned()) {
Ok((res_config, _)) => {
config = use_filter(res_config, &clash_fields, enable_filter);
config = res_config;
}
Err(err) => {
log::error!(target: "app", "builtin script error `{err}`");
@ -113,12 +103,11 @@ pub fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
});
}
config = use_filter(config, &clash_fields, enable_filter);
config = use_tun(config, enable_tun);
config = use_sort(config, enable_filter);
config = use_sort(config);
let mut exists_set = HashSet::new();
exists_set.extend(exists_keys.into_iter().filter(|s| clash_fields.contains(s)));
exists_set.extend(exists_keys.into_iter());
exists_keys = exists_set.into_iter().collect();
(config, exists_keys, result_map)

View File

@ -162,6 +162,8 @@ pub async fn patch_clash(patch: Mapping) -> Result<()> {
match {
let mixed_port = patch.get("mixed-port");
let socks_port = patch.get("socks-port");
let port = patch.get("port");
let enable_random_port = Config::verge().latest().enable_random_port.unwrap_or(false);
if mixed_port.is_some() && !enable_random_port {
let changed = mixed_port.unwrap()
@ -182,6 +184,8 @@ pub async fn patch_clash(patch: Mapping) -> Result<()> {
// 激活订阅
if mixed_port.is_some()
|| socks_port.is_some()
|| port.is_some()
|| patch.get("secret").is_some()
|| patch.get("external-controller").is_some()
{

View File

@ -1,123 +0,0 @@
import useSWR from "swr";
import { forwardRef, useImperativeHandle, useState } from "react";
import { useTranslation } from "react-i18next";
import { Checkbox, Divider, Stack, Tooltip, Typography } from "@mui/material";
import { InfoRounded } from "@mui/icons-material";
import { getRuntimeExists } from "@/services/cmds";
import {
HANDLE_FIELDS,
DEFAULT_FIELDS,
OTHERS_FIELDS,
} from "@/utils/clash-fields";
import { BaseDialog, DialogRef } from "@/components/base";
import { useProfiles } from "@/hooks/use-profiles";
import { Notice } from "@/components/base";
const otherFields = [...OTHERS_FIELDS];
const handleFields = [...HANDLE_FIELDS, ...DEFAULT_FIELDS];
export const ClashFieldViewer = forwardRef<DialogRef>((props, ref) => {
const { t } = useTranslation();
const { profiles = {}, patchProfiles } = useProfiles();
const { data: existsKeys = [], mutate: mutateExists } = useSWR(
"getRuntimeExists",
getRuntimeExists
);
const [open, setOpen] = useState(false);
const [selected, setSelected] = useState<string[]>([]);
useImperativeHandle(ref, () => ({
open: () => {
mutateExists();
setSelected(profiles.valid || []);
setOpen(true);
},
close: () => setOpen(false),
}));
const handleChange = (item: string) => {
if (!item) return;
setSelected((old) =>
old.includes(item) ? old.filter((e) => e !== item) : [...old, item]
);
};
const handleSave = async () => {
setOpen(false);
const oldSet = new Set(profiles.valid || []);
const curSet = new Set(selected);
const joinSet = new Set(selected.concat([...oldSet]));
if (curSet.size === oldSet.size && curSet.size === joinSet.size) return;
try {
await patchProfiles({ valid: [...curSet] });
// Notice.success("Refresh clash config", 1000);
} catch (err: any) {
Notice.error(err?.message || err.toString());
}
};
return (
<BaseDialog
open={open}
title={t("Clash Field")}
contentSx={{
pb: 0,
width: 320,
height: 300,
overflowY: "auto",
userSelect: "text",
}}
okBtn={t("Save")}
cancelBtn={t("Back")}
onClose={() => setOpen(false)}
onCancel={() => setOpen(false)}
onOk={handleSave}
>
{otherFields.map((item) => {
const inSelect = selected.includes(item);
const inConfig = existsKeys.includes(item);
return (
<Stack key={item} mb={0.5} direction="row" alignItems="center">
<Checkbox
checked={inSelect}
size="small"
sx={{ p: 0.5 }}
onChange={() => handleChange(item)}
/>
<Typography width="100%">{item}</Typography>
{!inSelect && inConfig && <WarnIcon />}
</Stack>
);
})}
<Divider sx={{ my: 1 }}>
<Typography color="text.secondary" fontSize={14}>
Clash Verge Control Fields
</Typography>
</Divider>
{handleFields.map((item) => (
<Stack key={item} mb={0.5} direction="row" alignItems="center">
<Checkbox defaultChecked disabled size="small" sx={{ p: 0.5 }} />
<Typography>{item}</Typography>
</Stack>
))}
</BaseDialog>
);
});
function WarnIcon() {
return (
<Tooltip title="The field exists in the config but not enabled.">
<InfoRounded color="warning" sx={{ cursor: "pointer", opacity: 0.5 }} />
</Tooltip>
);
}

View File

@ -13,26 +13,42 @@ export const ClashPortViewer = forwardRef<DialogRef>((props, ref) => {
const { verge, patchVerge } = useVerge();
const [open, setOpen] = useState(false);
const [mixedPort, setMixedPort] = useState(
verge?.verge_mixed_port ?? clashInfo?.mixed_port ?? 7897
);
const [socksPort, setSocksPort] = useState(
verge?.verge_socks_port ?? clashInfo?.socks_port ?? 7898
);
const [port, setPort] = useState(
verge?.verge_mixed_port ?? clashInfo?.port ?? 7897
verge?.verge_port ?? clashInfo?.port ?? 7899
);
useImperativeHandle(ref, () => ({
open: () => {
if (verge?.verge_mixed_port) setPort(verge?.verge_mixed_port);
if (verge?.verge_mixed_port) setMixedPort(verge?.verge_mixed_port);
if (verge?.verge_socks_port) setSocksPort(verge?.verge_socks_port);
if (verge?.verge_port) setPort(verge?.verge_port);
setOpen(true);
},
close: () => setOpen(false),
}));
const onSave = useLockFn(async () => {
if (port === verge?.verge_mixed_port) {
if (
mixedPort === verge?.verge_mixed_port &&
socksPort === verge?.verge_socks_port &&
port === verge?.verge_port
) {
setOpen(false);
return;
}
try {
await patchInfo({ "mixed-port": port });
await patchVerge({ verge_mixed_port: port });
await patchInfo({ "mixed-port": mixedPort });
await patchInfo({ "socks-port": socksPort });
await patchInfo({ port });
await patchVerge({ verge_mixed_port: mixedPort });
await patchVerge({ verge_socks_port: socksPort });
await patchVerge({ verge_port: port });
setOpen(false);
Notice.success("Change Clash port successfully!", 1000);
} catch (err: any) {
@ -54,6 +70,30 @@ export const ClashPortViewer = forwardRef<DialogRef>((props, ref) => {
<List>
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary="Mixed Port" />
<TextField
size="small"
autoComplete="off"
sx={{ width: 135 }}
value={mixedPort}
onChange={(e) =>
setMixedPort(+e.target.value?.replace(/\D+/, "").slice(0, 5))
}
/>
</ListItem>
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary="Socks Port" />
<TextField
size="small"
autoComplete="off"
sx={{ width: 135 }}
value={socksPort}
onChange={(e) =>
setSocksPort(+e.target.value?.replace(/\D+/, "").slice(0, 5))
}
/>
</ListItem>
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary="Http Port" />
<TextField
size="small"
autoComplete="off"

View File

@ -21,7 +21,6 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
const [values, setValues] = useState({
appLogLevel: "info",
autoCloseConnection: true,
enableClashFields: true,
enableBuiltinEnhanced: true,
proxyLayoutColumn: 6,
defaultLatencyTest: "",
@ -34,7 +33,6 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
setValues({
appLogLevel: verge?.app_log_level ?? "info",
autoCloseConnection: verge?.auto_close_connection ?? true,
enableClashFields: verge?.enable_clash_fields ?? true,
enableBuiltinEnhanced: verge?.enable_builtin_enhanced ?? true,
proxyLayoutColumn: verge?.proxy_layout_column || 6,
defaultLatencyTest: verge?.default_latency_test || "",
@ -49,7 +47,6 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
await patchVerge({
app_log_level: values.appLogLevel,
auto_close_connection: values.autoCloseConnection,
enable_clash_fields: values.enableClashFields,
enable_builtin_enhanced: values.enableBuiltinEnhanced,
proxy_layout_column: values.proxyLayoutColumn,
default_latency_test: values.defaultLatencyTest,
@ -105,17 +102,6 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
/>
</ListItem>
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary={t("Enable Clash Fields Filter")} />
<Switch
edge="end"
checked={values.enableClashFields}
onChange={(_, c) =>
setValues((v) => ({ ...v, enableClashFields: c }))
}
/>
</ListItem>
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary={t("Enable Builtin Enhanced")} />
<Switch

View File

@ -15,7 +15,6 @@ import { DialogRef, Notice } from "@/components/base";
import { useClash } from "@/hooks/use-clash";
import { GuardState } from "./mods/guard-state";
import { WebUIViewer } from "./mods/web-ui-viewer";
import { ClashFieldViewer } from "./mods/clash-field-viewer";
import { ClashPortViewer } from "./mods/clash-port-viewer";
import { ControllerViewer } from "./mods/controller-viewer";
import { SettingList, SettingItem } from "./mods/setting-comp";
@ -39,11 +38,7 @@ const SettingClash = ({ onError }: Props) => {
const { ipv6, "allow-lan": allowLan, "log-level": logLevel } = clash ?? {};
const {
enable_random_port = false,
verge_mixed_port,
enable_clash_fields = true,
} = verge ?? {};
const { enable_random_port = false, verge_mixed_port } = verge ?? {};
const webRef = useRef<DialogRef>(null);
const fieldRef = useRef<DialogRef>(null);
@ -70,7 +65,6 @@ const SettingClash = ({ onError }: Props) => {
return (
<SettingList title={t("Clash Setting")}>
<WebUIViewer ref={webRef} />
<ClashFieldViewer ref={fieldRef} />
<ClashPortViewer ref={portRef} />
<ControllerViewer ref={ctrlRef} />
<ClashCoreViewer ref={coreRef} />
@ -176,19 +170,6 @@ const SettingClash = ({ onError }: Props) => {
</IconButton>
</SettingItem>
{enable_clash_fields && (
<SettingItem label={t("Clash Field")}>
<IconButton
color="inherit"
size="small"
sx={{ my: "2px" }}
onClick={() => fieldRef.current?.open()}
>
<ArrowForward />
</IconButton>
</SettingItem>
)}
<SettingItem
label={t("Clash Core")}
extra={

View File

@ -48,11 +48,16 @@ export const useClashInfo = () => {
const patchInfo = async (
patch: Partial<
Pick<IConfigData, "mixed-port" | "external-controller" | "secret">
Pick<
IConfigData,
"port" | "socks-port" | "mixed-port" | "external-controller" | "secret"
>
>
) => {
const hasInfo =
patch["mixed-port"] != null ||
patch["socks-port"] != null ||
patch["port"] != null ||
patch["external-controller"] != null ||
patch.secret != null;
@ -68,6 +73,26 @@ export const useClashInfo = () => {
}
}
if (patch["socks-port"]) {
const port = patch["socks-port"];
if (port < 1000) {
throw new Error("The port should not < 1000");
}
if (port > 65536) {
throw new Error("The port should not > 65536");
}
}
if (patch["port"]) {
const port = patch["port"];
if (port < 1000) {
throw new Error("The port should not < 1000");
}
if (port > 65536) {
throw new Error("The port should not > 65536");
}
}
await patchClashConfig(patch);
mutateInfo();
mutate("getClashConfig");

View File

@ -131,7 +131,9 @@ interface IConnections {
interface IClashInfo {
// status: string;
port?: number; // clash mixed port
mixed_port?: number; // clash mixed port
socks_port?: number; // clash socks port
port?: number; // clash http port
server?: string; // external-controller
secret?: string;
}
@ -196,6 +198,8 @@ interface IVergeConfig {
enable_system_proxy?: boolean;
enable_random_port?: boolean;
verge_mixed_port?: number;
verge_socks_port?: number;
verge_port?: number;
enable_proxy_guard?: boolean;
proxy_guard_duration?: number;
system_proxy_bypass?: string;
@ -215,7 +219,6 @@ interface IVergeConfig {
};
auto_close_connection?: boolean;
default_latency_test?: string;
enable_clash_fields?: boolean;
enable_builtin_enhanced?: boolean;
auto_log_clean?: 0 | 1 | 2 | 3;
proxy_layout_column?: number;

View File

@ -1,53 +0,0 @@
export const HANDLE_FIELDS = [
"mode",
"port",
"socks-port",
"mixed-port",
"allow-lan",
"log-level",
"ipv6",
"secret",
"external-controller",
];
export const DEFAULT_FIELDS = [
"proxies",
"proxy-groups",
"proxy-providers",
"rules",
"rule-providers",
] as const;
export const OTHERS_FIELDS = [
"dns",
"tun",
"ebpf",
"hosts",
"script",
"profile",
"payload",
"tunnels",
"auto-redir",
"experimental",
"interface-name",
"routing-mark",
"redir-port",
"tproxy-port",
"iptables",
"external-ui",
"bind-address",
"authentication",
"tls", // meta
"sniffer", // meta
"geox-url", // meta
"listeners", // meta
"sub-rules", // meta
"geodata-mode", // meta
"unified-delay", // meta
"tcp-concurrent", // meta
"enable-process", // meta
"find-process-mode", // meta
"skip-auth-prefixes", // meta
"external-controller-tls", // meta
"global-client-fingerprint", // meta
] as const;