Files
clash-verge-rev/src/services/cmds.ts
T

553 lines
14 KiB
TypeScript

import { invoke } from "@tauri-apps/api/core";
import dayjs from "dayjs";
import { getProxies, getProxyProviders } from "tauri-plugin-mihomo-api";
import { showNotice } from "@/services/noticeService";
import { debugLog } from "@/utils/debug";
export async function copyClashEnv() {
return invoke<void>("copy_clash_env");
}
export async function getProfiles() {
return invoke<IProfilesConfig>("get_profiles");
}
export async function enhanceProfiles() {
return invoke<void>("enhance_profiles");
}
export async function patchProfilesConfig(profiles: IProfilesConfig) {
return invoke<void>("patch_profiles_config", { profiles });
}
export async function createProfile(
item: Partial<IProfileItem>,
fileData?: string | null,
) {
return invoke<void>("create_profile", { item, fileData });
}
export async function viewProfile(index: string) {
return invoke<void>("view_profile", { index });
}
export async function readProfileFile(index: string) {
return invoke<string>("read_profile_file", { index });
}
export async function saveProfileFile(index: string, fileData: string) {
return invoke<void>("save_profile_file", { index, fileData });
}
export async function importProfile(url: string, option?: IProfileOption) {
return invoke<void>("import_profile", {
url,
option: option || { with_proxy: true },
});
}
export async function reorderProfile(activeId: string, overId: string) {
return invoke<void>("reorder_profile", {
activeId,
overId,
});
}
export async function updateProfile(index: string, option?: IProfileOption) {
return invoke<void>("update_profile", { index, option });
}
export async function deleteProfile(index: string) {
return invoke<void>("delete_profile", { index });
}
export async function patchProfile(
index: string,
profile: Partial<IProfileItem>,
) {
return invoke<void>("patch_profile", { index, profile });
}
export async function getClashInfo() {
return invoke<IClashInfo | null>("get_clash_info");
}
// Get runtime config which controlled by verge
export async function getRuntimeConfig() {
return invoke<IConfigData | null>("get_runtime_config");
}
export async function getRuntimeYaml() {
return invoke<string | null>("get_runtime_yaml");
}
export async function getRuntimeExists() {
return invoke<string[]>("get_runtime_exists");
}
export async function getRuntimeLogs() {
return invoke<Record<string, [string, string][]>>("get_runtime_logs");
}
export async function getRuntimeProxyChainConfig(proxyChainExitNode: string) {
return invoke<string>("get_runtime_proxy_chain_config", {
proxyChainExitNode,
});
}
export async function updateProxyChainConfigInRuntime(proxyChainConfig: any) {
return invoke<void>("update_proxy_chain_config_in_runtime", {
proxyChainConfig,
});
}
export async function patchClashConfig(payload: Partial<IConfigData>) {
return invoke<void>("patch_clash_config", { payload });
}
export async function patchClashMode(payload: string) {
return invoke<void>("patch_clash_mode", { payload });
}
export async function syncTrayProxySelection() {
return invoke<void>("sync_tray_proxy_selection");
}
export async function calcuProxies(): Promise<{
global: IProxyGroupItem;
direct: IProxyItem;
groups: IProxyGroupItem[];
records: Record<string, IProxyItem>;
proxies: IProxyItem[];
}> {
const [proxyResponse, providerResponse] = await Promise.all([
getProxies(),
calcuProxyProviders(),
]);
const proxyRecord = proxyResponse.proxies;
const providerRecord = providerResponse;
// provider name map
const providerMap = Object.fromEntries(
Object.entries(providerRecord).flatMap(([provider, item]) =>
item!.proxies.map((p) => [p.name, { ...p, provider }]),
),
);
// compatible with proxy-providers
const generateItem = (name: string) => {
if (proxyRecord[name]) return proxyRecord[name];
if (providerMap[name]) return providerMap[name];
return {
name,
type: "unknown",
udp: false,
xudp: false,
tfo: false,
mptcp: false,
smux: false,
history: [],
};
};
const { GLOBAL: global, DIRECT: direct, REJECT: reject } = proxyRecord;
let groups: IProxyGroupItem[] = Object.values(proxyRecord).reduce<
IProxyGroupItem[]
>((acc, each) => {
if (each?.name !== "GLOBAL" && each?.all) {
acc.push({
...each,
all: each.all!.map((item) => generateItem(item)),
});
}
return acc;
}, []);
if (global?.all) {
const globalGroups: IProxyGroupItem[] = global.all.reduce<
IProxyGroupItem[]
>((acc, name) => {
if (proxyRecord[name]?.all) {
acc.push({
...proxyRecord[name],
all: proxyRecord[name].all!.map((item) => generateItem(item)),
});
}
return acc;
}, []);
const globalNames = new Set(globalGroups.map((each) => each.name));
groups = groups
.filter((group) => {
return !globalNames.has(group.name);
})
.concat(globalGroups);
}
const proxies = [direct, reject].concat(
Object.values(proxyRecord).filter(
(p) => !p?.all?.length && p?.name !== "DIRECT" && p?.name !== "REJECT",
),
);
const _global = {
...global,
all: global?.all?.map((item) => generateItem(item)) || [],
};
return {
global: _global as IProxyGroupItem,
direct: direct as IProxyItem,
groups,
records: proxyRecord as Record<string, IProxyItem>,
proxies: (proxies as IProxyItem[]) ?? [],
};
}
export async function calcuProxyProviders() {
const providers = await getProxyProviders();
return Object.fromEntries(
Object.entries(providers.providers)
.sort()
.filter(
([_, item]) =>
item?.vehicleType === "HTTP" || item?.vehicleType === "File",
),
);
}
export async function getClashLogs() {
const regex = /time="(.+?)"\s+level=(.+?)\s+msg="(.+?)"/;
const newRegex = /(.+?)\s+(.+?)\s+(.+)/;
const logs = await invoke<string[]>("get_clash_logs");
return logs.reduce<ILogItem[]>((acc, log) => {
const result = log.match(regex);
if (result) {
const [_, _time, type, payload] = result;
const time = dayjs(_time).format("MM-DD HH:mm:ss");
acc.push({ time, type, payload });
return acc;
}
const result2 = log.match(newRegex);
if (result2) {
const [_, time, type, payload] = result2;
acc.push({ time, type, payload });
}
return acc;
}, []);
}
export async function clearLogs() {
return invoke<void>("clear_logs");
}
export async function getVergeConfig() {
return invoke<IVergeConfig>("get_verge_config");
}
export async function patchVergeConfig(payload: IVergeConfig) {
return invoke<void>("patch_verge_config", { payload });
}
export async function getSystemProxy() {
return invoke<{
enable: boolean;
server: string;
bypass: string;
}>("get_sys_proxy");
}
export async function getAutotemProxy() {
try {
debugLog("[API] 开始调用 get_auto_proxy");
const result = await invoke<{
enable: boolean;
url: string;
}>("get_auto_proxy");
debugLog("[API] get_auto_proxy 调用成功:", result);
return result;
} catch (error) {
console.error("[API] get_auto_proxy 调用失败:", error);
return {
enable: false,
url: "",
};
}
}
export async function getAutoLaunchStatus() {
try {
return await invoke<boolean>("get_auto_launch_status");
} catch (error) {
console.error("获取自启动状态失败:", error);
return false;
}
}
export async function changeClashCore(clashCore: string) {
return invoke<string | null>("change_clash_core", { clashCore });
}
export async function startCore() {
return invoke<void>("start_core");
}
export async function stopCore() {
return invoke<void>("stop_core");
}
export async function restartCore() {
return invoke<void>("restart_core");
}
export async function restartApp() {
return invoke<void>("restart_app");
}
export async function getAppDir() {
return invoke<string>("get_app_dir");
}
export async function openAppDir() {
return invoke<void>("open_app_dir").catch((err) => showNotice.error(err));
}
export async function openCoreDir() {
return invoke<void>("open_core_dir").catch((err) => showNotice.error(err));
}
export async function openLogsDir() {
return invoke<void>("open_logs_dir").catch((err) => showNotice.error(err));
}
export const openWebUrl = async (url: string) => {
try {
await invoke("open_web_url", { url });
} catch (err: any) {
showNotice.error(err);
}
};
export async function cmdGetProxyDelay(
name: string,
timeout: number,
url?: string,
) {
// 确保URL不为空
const testUrl = url || "https://cp.cloudflare.com/generate_204";
try {
// 不再在前端编码代理名称,由后端统一处理编码
const result = await invoke<{ delay: number }>(
"clash_api_get_proxy_delay",
{
name,
url: testUrl, // 传递经过验证的URL
timeout,
},
);
// 验证返回结果中是否有delay字段,并且值是一个有效的数字
if (result && typeof result.delay === "number") {
return result;
} else {
// 返回一个有效的结果对象,但标记为超时
return { delay: 1e6 };
}
} catch {
// 返回一个有效的结果对象,但标记为错误
return { delay: 1e6 };
}
}
export async function cmdTestDelay(url: string) {
return invoke<number>("test_delay", { url });
}
export async function invoke_uwp_tool() {
return invoke<void>("invoke_uwp_tool").catch((err) =>
showNotice.error(err, 1500),
);
}
export async function getPortableFlag() {
return invoke<boolean>("get_portable_flag");
}
export async function openDevTools() {
return invoke("open_devtools");
}
export async function exitApp() {
return invoke("exit_app");
}
export async function exportDiagnosticInfo() {
return invoke("export_diagnostic_info");
}
export async function getSystemInfo() {
return invoke<string>("get_system_info");
}
export async function copyIconFile(
path: string,
name: "common" | "sysproxy" | "tun",
) {
const key = `icon_${name}_update_time`;
const previousTime = localStorage.getItem(key) || "";
const currentTime = String(Date.now());
localStorage.setItem(key, currentTime);
const iconInfo = {
name,
previous_t: previousTime,
current_t: currentTime,
};
return invoke<void>("copy_icon_file", { path, iconInfo });
}
export async function downloadIconCache(url: string, name: string) {
return invoke<string>("download_icon_cache", { url, name });
}
export async function getNetworkInterfaces() {
return invoke<string[]>("get_network_interfaces");
}
export async function getSystemHostname() {
return invoke<string>("get_system_hostname");
}
export async function getNetworkInterfacesInfo() {
return invoke<INetworkInterface[]>("get_network_interfaces_info");
}
export async function createWebdavBackup() {
return invoke<void>("create_webdav_backup");
}
export async function createLocalBackup() {
return invoke<void>("create_local_backup");
}
export async function deleteWebdavBackup(filename: string) {
return invoke<void>("delete_webdav_backup", { filename });
}
export async function deleteLocalBackup(filename: string) {
return invoke<void>("delete_local_backup", { filename });
}
export async function restoreWebDavBackup(filename: string) {
return invoke<void>("restore_webdav_backup", { filename });
}
export async function restoreLocalBackup(filename: string) {
return invoke<void>("restore_local_backup", { filename });
}
export async function exportLocalBackup(filename: string, destination: string) {
return invoke<void>("export_local_backup", { filename, destination });
}
export async function saveWebdavConfig(
url: string,
username: string,
password: string,
) {
return invoke<void>("save_webdav_config", {
url,
username,
password,
});
}
export async function listWebDavBackup() {
const list: IWebDavFile[] = await invoke<IWebDavFile[]>("list_webdav_backup");
list.map((item) => {
item.filename = item.href.split("/").pop() as string;
});
return list;
}
export async function listLocalBackup() {
return invoke<ILocalBackupFile[]>("list_local_backup");
}
export async function scriptValidateNotice(status: string, msg: string) {
return invoke<void>("script_validate_notice", { status, msg });
}
export async function validateScriptFile(filePath: string) {
return invoke<boolean>("validate_script_file", { filePath });
}
// 获取当前运行模式
export const getRunningMode = async () => {
return invoke<string>("get_running_mode");
};
// 获取应用运行时间
export const getAppUptime = async () => {
return invoke<number>("get_app_uptime");
};
// 安装系统服务
export const installService = async () => {
return invoke<void>("install_service");
};
// 卸载系统服务
export const uninstallService = async () => {
return invoke<void>("uninstall_service");
};
// 重装系统服务
export const reinstallService = async () => {
return invoke<void>("reinstall_service");
};
// 修复系统服务
export const repairService = async () => {
return invoke<void>("repair_service");
};
// 系统服务是否可用
export const isServiceAvailable = async () => {
try {
return await invoke<boolean>("is_service_available");
} catch (error) {
console.error("Service check failed:", error);
return false;
}
};
export const entry_lightweight_mode = async () => {
return invoke<void>("entry_lightweight_mode");
};
export const exit_lightweight_mode = async () => {
return invoke<void>("exit_lightweight_mode");
};
export const isAdmin = async () => {
try {
return await invoke<boolean>("app_is_admin");
} catch (error) {
console.error("检查管理员权限失败:", error);
return false;
}
};
export async function getNextUpdateTime(uid: string) {
return invoke<number | null>("get_next_update_time", { uid });
}