From 43115d1da4b0d57c26ea09860e473c6ec2546d96 Mon Sep 17 00:00:00 2001 From: pompurin404 Date: Sat, 12 Oct 2024 20:06:33 +0800 Subject: [PATCH] specify work directory for each profile --- changelog.md | 6 ++---- src/main/config/profile.ts | 20 ++++++++++++++++++-- src/main/core/factory.ts | 30 ++++++++++++++++++++++++++---- src/main/core/manager.ts | 18 +++++++++++++----- src/main/utils/dirs.ts | 8 ++++++-- 5 files changed, 65 insertions(+), 17 deletions(-) diff --git a/changelog.md b/changelog.md index 102d774..7ae2053 100644 --- a/changelog.md +++ b/changelog.md @@ -1,9 +1,7 @@ ### New Features -- 支持自定义 WebDAV 备份目录名称 +- 支持多个订阅切换分别保存选择的节点 ### Bug Fixes -- 修复 macOS 自动更新失败的问题 -- 修复订阅点击无法切换的问题 -- 修复某些 Windows 管理员权限依然无法启动的问题 +- 修复订阅显示样式错误 diff --git a/src/main/config/profile.ts b/src/main/config/profile.ts index 7e90c83..45b64a8 100644 --- a/src/main/config/profile.ts +++ b/src/main/config/profile.ts @@ -1,12 +1,13 @@ import { getControledMihomoConfig } from './controledMihomo' -import { profileConfigPath, profilePath } from '../utils/dirs' +import { mihomoProfileWorkDir, profileConfigPath, profilePath } from '../utils/dirs' import { addProfileUpdater } from '../core/profileUpdater' -import { readFile, rm, writeFile } from 'fs/promises' +import { readFile, rm, unlink, writeFile } from 'fs/promises' import { restartCore } from '../core/manager' import { getAppConfig } from './app' import { existsSync } from 'fs' import axios, { AxiosResponse } from 'axios' import yaml from 'yaml' +import path from 'path' import { defaultProfile } from '../utils/template' import { subStorePort } from '../resolve/server' @@ -92,6 +93,21 @@ export async function removeProfileItem(id: string): Promise { if (shouldRestart) { await restartCore() } + if (existsSync(mihomoProfileWorkDir(id))) { + const unln = async (file: string): Promise => { + const targetPath = path.join(mihomoProfileWorkDir(id), file) + if (existsSync(targetPath)) { + await unlink(targetPath) + } + } + await Promise.all([ + unln('country.mmdb'), + unln('geoip.dat'), + unln('geosite.dat'), + unln('ASN.mmdb') + ]) + await rm(mihomoProfileWorkDir(id), { recursive: true }) + } } export async function getCurrentProfileItem(): Promise { diff --git a/src/main/core/factory.ts b/src/main/core/factory.ts index a95fd61..587e5d3 100644 --- a/src/main/core/factory.ts +++ b/src/main/core/factory.ts @@ -7,12 +7,18 @@ import { getOverrideItem, getOverrideConfig } from '../config' -import { mihomoWorkConfigPath, overridePath } from '../utils/dirs' +import { + mihomoProfileWorkDir, + mihomoWorkConfigPath, + overridePath, + resourcesFilesDir +} from '../utils/dirs' import yaml from 'yaml' -import { writeFile } from 'fs/promises' +import { link, mkdir, writeFile } from 'fs/promises' import { deepMerge } from '../utils/merge' import vm from 'vm' -import { writeFileSync } from 'fs' +import { existsSync, writeFileSync } from 'fs' +import path from 'path' let runtimeConfigStr: string let runtimeConfig: IMihomoConfig @@ -26,7 +32,23 @@ export async function generateProfile(): Promise { profile['log-level'] = 'info' runtimeConfig = profile runtimeConfigStr = yaml.stringify(profile) - await writeFile(mihomoWorkConfigPath(), runtimeConfigStr) + await prepareProfileWorkDir(current) + await writeFile(mihomoWorkConfigPath(current), runtimeConfigStr) +} + +async function prepareProfileWorkDir(current: string | undefined): Promise { + if (!existsSync(mihomoProfileWorkDir(current))) { + await mkdir(mihomoProfileWorkDir(current), { recursive: true }) + } + const ln = async (file: string): Promise => { + const targetPath = path.join(mihomoProfileWorkDir(current), file) + + const sourcePath = path.join(resourcesFilesDir(), file) + if (!existsSync(targetPath) && existsSync(sourcePath)) { + await link(sourcePath, targetPath) + } + } + await Promise.all([ln('country.mmdb'), ln('geoip.dat'), ln('geosite.dat'), ln('ASN.mmdb')]) } async function overrideProfile( diff --git a/src/main/core/manager.ts b/src/main/core/manager.ts index ba3e8d1..4a3d5a1 100644 --- a/src/main/core/manager.ts +++ b/src/main/core/manager.ts @@ -4,14 +4,15 @@ import { logPath, mihomoCoreDir, mihomoCorePath, + mihomoProfileWorkDir, mihomoTestDir, - mihomoWorkConfigPath, - mihomoWorkDir + mihomoWorkConfigPath } from '../utils/dirs' import { generateProfile } from './factory' import { getAppConfig, getControledMihomoConfig, + getProfileConfig, patchAppConfig, patchControledMihomoConfig } from '../config' @@ -75,7 +76,7 @@ export async function startCore(detached = false): Promise[]> { await rm(path.join(dataDir(), 'core.pid')) } } - + const { current } = await getProfileConfig() const { tun } = await getControledMihomoConfig() const corePath = mihomoCorePath(core) await autoGrantCorePermition(corePath) @@ -92,7 +93,7 @@ export async function startCore(detached = false): Promise[]> { } } - child = spawn(corePath, ['-d', mihomoWorkDir(), ctlParam, mihomoIpcPath], { + child = spawn(corePath, ['-d', mihomoProfileWorkDir(current), ctlParam, mihomoIpcPath], { detached: detached, stdio: detached ? 'ignore' : undefined }) @@ -205,10 +206,17 @@ export async function quitWithoutCore(): Promise { async function checkProfile(): Promise { const { core = 'mihomo' } = await getAppConfig() + const { current } = await getProfileConfig() const corePath = mihomoCorePath(core) const execFilePromise = promisify(execFile) try { - await execFilePromise(corePath, ['-t', '-f', mihomoWorkConfigPath(), '-d', mihomoTestDir()]) + await execFilePromise(corePath, [ + '-t', + '-f', + mihomoWorkConfigPath(current), + '-d', + mihomoTestDir() + ]) } catch (error) { if (error instanceof Error && 'stdout' in error) { const { stdout } = error as { stdout: string } diff --git a/src/main/utils/dirs.ts b/src/main/utils/dirs.ts index 8af31db..ea066ae 100644 --- a/src/main/utils/dirs.ts +++ b/src/main/utils/dirs.ts @@ -102,12 +102,16 @@ export function mihomoWorkDir(): string { return path.join(dataDir(), 'work') } +export function mihomoProfileWorkDir(id: string | undefined): string { + return path.join(mihomoWorkDir(), id || 'default') +} + export function mihomoTestDir(): string { return path.join(dataDir(), 'test') } -export function mihomoWorkConfigPath(): string { - return path.join(mihomoWorkDir(), 'config.yaml') +export function mihomoWorkConfigPath(id: string | undefined): string { + return path.join(mihomoProfileWorkDir(id), 'config.yaml') } export function logDir(): string {