feat: enhanced mode supports more fields
This commit is contained in:
parent
6ea567742b
commit
c9649ac501
@ -1,48 +1,80 @@
|
|||||||
import { emit, listen } from "@tauri-apps/api/event";
|
import { emit, listen } from "@tauri-apps/api/event";
|
||||||
import { CmdType } from "./types";
|
import { CmdType } from "./types";
|
||||||
|
import ignoreCase from "../utils/ignore-case";
|
||||||
|
|
||||||
|
const DEFAULT_FIELDS = [
|
||||||
|
"rules",
|
||||||
|
"proxies",
|
||||||
|
"proxy-groups",
|
||||||
|
"proxy-providers",
|
||||||
|
"rule-providers",
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
const USE_FLAG_FIELDS = [
|
||||||
|
"tun",
|
||||||
|
"dns",
|
||||||
|
"hosts",
|
||||||
|
"script",
|
||||||
|
"profile",
|
||||||
|
"payload",
|
||||||
|
"interface-name",
|
||||||
|
"routing-mark",
|
||||||
|
] as const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* process the merge mode
|
* process the merge mode
|
||||||
*/
|
*/
|
||||||
function toMerge(
|
function toMerge(merge: CmdType.ProfileMerge, data: CmdType.ProfileData) {
|
||||||
merge: CmdType.ProfileMerge,
|
if (!merge) return { data, use: [] };
|
||||||
data: CmdType.ProfileData
|
|
||||||
): CmdType.ProfileData {
|
|
||||||
if (!merge) return data;
|
|
||||||
|
|
||||||
const newData = { ...data };
|
const {
|
||||||
|
use,
|
||||||
|
"prepend-rules": preRules,
|
||||||
|
"append-rules": postRules,
|
||||||
|
"prepend-proxies": preProxies,
|
||||||
|
"append-proxies": postProxies,
|
||||||
|
"prepend-proxy-groups": preProxyGroups,
|
||||||
|
"append-proxy-groups": postProxyGroups,
|
||||||
|
...mergeConfig
|
||||||
|
} = merge;
|
||||||
|
|
||||||
|
[...DEFAULT_FIELDS, ...USE_FLAG_FIELDS].forEach((key) => {
|
||||||
|
// the value should not be null
|
||||||
|
if (mergeConfig[key] != null) {
|
||||||
|
data[key] = mergeConfig[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// init
|
||||||
|
if (!data.rules) data.rules = [];
|
||||||
|
if (!data.proxies) data.proxies = [];
|
||||||
|
if (!data["proxy-groups"]) data["proxy-groups"] = [];
|
||||||
|
|
||||||
// rules
|
// rules
|
||||||
if (Array.isArray(merge["prepend-rules"])) {
|
if (Array.isArray(preRules)) {
|
||||||
if (!newData.rules) newData.rules = [];
|
data.rules.unshift(...preRules);
|
||||||
newData.rules.unshift(...merge["prepend-rules"]);
|
|
||||||
}
|
}
|
||||||
if (Array.isArray(merge["append-rules"])) {
|
if (Array.isArray(postRules)) {
|
||||||
if (!newData.rules) newData.rules = [];
|
data.rules.push(...postRules);
|
||||||
newData.rules.push(...merge["append-rules"]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// proxies
|
// proxies
|
||||||
if (Array.isArray(merge["prepend-proxies"])) {
|
if (Array.isArray(preProxies)) {
|
||||||
if (!newData.proxies) newData.proxies = [];
|
data.proxies.unshift(...preProxies);
|
||||||
newData.proxies.unshift(...merge["prepend-proxies"]);
|
|
||||||
}
|
}
|
||||||
if (Array.isArray(merge["append-proxies"])) {
|
if (Array.isArray(postProxies)) {
|
||||||
if (!newData.proxies) newData.proxies = [];
|
data.proxies.push(...postProxies);
|
||||||
newData.proxies.push(...merge["append-proxies"]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// proxy-groups
|
// proxy-groups
|
||||||
if (Array.isArray(merge["prepend-proxy-groups"])) {
|
if (Array.isArray(preProxyGroups)) {
|
||||||
if (!newData["proxy-groups"]) newData["proxy-groups"] = [];
|
data["proxy-groups"].unshift(...preProxyGroups);
|
||||||
newData["proxy-groups"].unshift(...merge["prepend-proxy-groups"]);
|
|
||||||
}
|
}
|
||||||
if (Array.isArray(merge["append-proxy-groups"])) {
|
if (Array.isArray(postProxyGroups)) {
|
||||||
if (!newData["proxy-groups"]) newData["proxy-groups"] = [];
|
data["proxy-groups"].push(...postProxyGroups);
|
||||||
newData["proxy-groups"].push(...merge["append-proxy-groups"]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return newData;
|
return { data, use: Array.isArray(use) ? use : [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -99,24 +131,41 @@ class Enhance {
|
|||||||
|
|
||||||
listen("script-handler", async (event) => {
|
listen("script-handler", async (event) => {
|
||||||
const payload = event.payload as CmdType.EnhancedPayload;
|
const payload = event.payload as CmdType.EnhancedPayload;
|
||||||
|
|
||||||
|
const result = await this.runner(payload).catch((err: any) => ({
|
||||||
|
data: null,
|
||||||
|
status: "error",
|
||||||
|
error: err.message,
|
||||||
|
}));
|
||||||
|
|
||||||
|
emit(payload.callback, JSON.stringify(result)).catch(console.error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// enhanced mode runner
|
||||||
|
private async runner(payload: CmdType.EnhancedPayload) {
|
||||||
|
const chain = payload.chain || [];
|
||||||
|
|
||||||
|
if (!Array.isArray(chain)) throw new Error("unhandle error");
|
||||||
|
|
||||||
let pdata = payload.current || {};
|
let pdata = payload.current || {};
|
||||||
|
let useList = [] as string[];
|
||||||
|
|
||||||
let hasScript = false;
|
for (const each of chain) {
|
||||||
|
|
||||||
for (const each of payload.chain) {
|
|
||||||
const { uid, type = "" } = each.item;
|
const { uid, type = "" } = each.item;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// process script
|
// process script
|
||||||
if (type === "script") {
|
if (type === "script") {
|
||||||
// support async main function
|
// support async main function
|
||||||
pdata = await toScript(each.script!, { ...pdata });
|
pdata = await toScript(each.script!, ignoreCase(pdata));
|
||||||
hasScript = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// process merge
|
// process merge
|
||||||
else if (type === "merge") {
|
else if (type === "merge") {
|
||||||
pdata = toMerge(each.merge!, { ...pdata });
|
const temp = toMerge(each.merge!, ignoreCase(pdata));
|
||||||
|
pdata = temp.data;
|
||||||
|
useList = useList.concat(temp.use || []);
|
||||||
}
|
}
|
||||||
|
|
||||||
// invalid type
|
// invalid type
|
||||||
@ -126,41 +175,29 @@ class Enhance {
|
|||||||
|
|
||||||
this.exec(uid, { status: "ok" });
|
this.exec(uid, { status: "ok" });
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
|
console.error(err);
|
||||||
|
|
||||||
this.exec(uid, {
|
this.exec(uid, {
|
||||||
status: "error",
|
status: "error",
|
||||||
message: err.message || err.toString(),
|
message: err.message || err.toString(),
|
||||||
});
|
});
|
||||||
|
|
||||||
console.error(err);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If script is never used
|
pdata = ignoreCase(pdata);
|
||||||
// filter other fields
|
|
||||||
if (!hasScript) {
|
|
||||||
const validKeys = [
|
|
||||||
"proxies",
|
|
||||||
"proxy-providers",
|
|
||||||
"proxy-groups",
|
|
||||||
"rule-providers",
|
|
||||||
"rules",
|
|
||||||
];
|
|
||||||
|
|
||||||
// to lowercase
|
// filter the data
|
||||||
const newData: any = {};
|
const filterData: typeof pdata = {};
|
||||||
Object.keys(pdata).forEach((key) => {
|
Object.keys(pdata).forEach((key: any) => {
|
||||||
const newKey = key.toLowerCase();
|
if (
|
||||||
if (validKeys.includes(newKey)) {
|
DEFAULT_FIELDS.includes(key) ||
|
||||||
newData[newKey] = (pdata as any)[key];
|
(USE_FLAG_FIELDS.includes(key) && useList.includes(key))
|
||||||
|
) {
|
||||||
|
filterData[key] = pdata[key];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
pdata = newData;
|
return { data: filterData, status: "ok" };
|
||||||
}
|
|
||||||
|
|
||||||
const result = { data: pdata, status: "ok" };
|
|
||||||
emit(payload.callback, JSON.stringify(result)).catch(console.error);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// exec the listener
|
// exec the listener
|
||||||
|
@ -132,7 +132,33 @@ export namespace CmdType {
|
|||||||
system_proxy_bypass?: string;
|
system_proxy_bypass?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ProfileMerge = Record<string, any>;
|
type ClashConfigValue = any;
|
||||||
|
|
||||||
|
export interface ProfileMerge {
|
||||||
|
// clash config fields (default supports)
|
||||||
|
rules?: ClashConfigValue;
|
||||||
|
proxies?: ClashConfigValue;
|
||||||
|
"proxy-groups"?: ClashConfigValue;
|
||||||
|
"proxy-providers"?: ClashConfigValue;
|
||||||
|
"rule-providers"?: ClashConfigValue;
|
||||||
|
// clash config fields (use flag)
|
||||||
|
tun?: ClashConfigValue;
|
||||||
|
dns?: ClashConfigValue;
|
||||||
|
hosts?: ClashConfigValue;
|
||||||
|
script?: ClashConfigValue;
|
||||||
|
profile?: ClashConfigValue;
|
||||||
|
payload?: ClashConfigValue;
|
||||||
|
"interface-name"?: ClashConfigValue;
|
||||||
|
"routing-mark"?: ClashConfigValue;
|
||||||
|
// functional fields
|
||||||
|
use?: string[];
|
||||||
|
"prepend-rules"?: any[];
|
||||||
|
"append-rules"?: any[];
|
||||||
|
"prepend-proxies"?: any[];
|
||||||
|
"append-proxies"?: any[];
|
||||||
|
"prepend-proxy-groups"?: any[];
|
||||||
|
"append-proxy-groups"?: any[];
|
||||||
|
}
|
||||||
|
|
||||||
// partial of the clash config
|
// partial of the clash config
|
||||||
export type ProfileData = Partial<{
|
export type ProfileData = Partial<{
|
||||||
@ -141,6 +167,8 @@ export namespace CmdType {
|
|||||||
"proxy-groups": any[];
|
"proxy-groups": any[];
|
||||||
"proxy-providers": any[];
|
"proxy-providers": any[];
|
||||||
"rule-providers": any[];
|
"rule-providers": any[];
|
||||||
|
|
||||||
|
[k: string]: any;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export interface ChainItem {
|
export interface ChainItem {
|
||||||
|
14
src/utils/ignore-case.ts
Normal file
14
src/utils/ignore-case.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Shallow copy and change all keys to lowercase
|
||||||
|
type TData = Record<string, any>;
|
||||||
|
|
||||||
|
export default function ignoreCase(data: TData): TData {
|
||||||
|
if (!data) return data;
|
||||||
|
|
||||||
|
const newData = {} as TData;
|
||||||
|
|
||||||
|
Object.keys(data).forEach((key) => {
|
||||||
|
newData[key.toLowerCase()] = data[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
return newData;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user