import { exec, execFile, spawn } from 'child_process' import { app, dialog, nativeTheme, shell } from 'electron' import { readFile } from 'fs/promises' import path from 'path' import { promisify } from 'util' import { dataDir, exePath, mihomoCorePath, overridePath, profilePath, resourcesDir } from '../utils/dirs' export function getFilePath(ext: string[]): string[] | undefined { return dialog.showOpenDialogSync({ title: '选择订阅文件', filters: [{ name: `${ext} file`, extensions: ext }], properties: ['openFile'] }) } export async function readTextFile(filePath: string): Promise { return await readFile(filePath, 'utf8') } export function openFile(type: 'profile' | 'override', id: string, ext?: 'yaml' | 'js'): void { if (type === 'profile') { shell.openPath(profilePath(id)) } if (type === 'override') { shell.openPath(overridePath(id, ext || 'js')) } } export async function openUWPTool(): Promise { const execPromise = promisify(exec) const execFilePromise = promisify(execFile) const uwpToolPath = path.join(resourcesDir(), 'files', 'enableLoopback.exe') const { checkAdminPrivileges } = await import('../core/manager') const isAdmin = await checkAdminPrivileges() if (!isAdmin) { const escapedPath = uwpToolPath.replace(/'/g, "''") const command = `powershell -NoProfile -Command "Start-Process -FilePath '${escapedPath}' -Verb RunAs -Wait"` await execPromise(command, { windowsHide: true }) return } await execFilePromise(uwpToolPath) } export async function setupFirewall(): Promise { const execPromise = promisify(exec) const removeCommand = ` $rules = @("mihomo", "mihomo-alpha", "Mihomo Party") foreach ($rule in $rules) { if (Get-NetFirewallRule -DisplayName $rule -ErrorAction SilentlyContinue) { Remove-NetFirewallRule -DisplayName $rule -ErrorAction SilentlyContinue } } ` const createCommand = ` New-NetFirewallRule -DisplayName "mihomo" -Direction Inbound -Action Allow -Program "${mihomoCorePath('mihomo')}" -Enabled True -Profile Any -ErrorAction SilentlyContinue New-NetFirewallRule -DisplayName "mihomo-alpha" -Direction Inbound -Action Allow -Program "${mihomoCorePath('mihomo-alpha')}" -Enabled True -Profile Any -ErrorAction SilentlyContinue New-NetFirewallRule -DisplayName "Mihomo Party" -Direction Inbound -Action Allow -Program "${exePath()}" -Enabled True -Profile Any -ErrorAction SilentlyContinue ` if (process.platform === 'win32') { await execPromise(removeCommand, { shell: 'powershell' }) await execPromise(createCommand, { shell: 'powershell' }) } } export function setNativeTheme(theme: 'system' | 'light' | 'dark'): void { nativeTheme.themeSource = theme } export function resetAppConfig(): void { if (process.platform === 'win32') { spawn( 'cmd', [ '/C', `"timeout /t 2 /nobreak >nul && rmdir /s /q "${dataDir()}" && start "" "${exePath()}""` ], { shell: true, detached: true } ).unref() } else { const script = `while kill -0 ${process.pid} 2>/dev/null; do sleep 0.1 done rm -rf '${dataDir()}' ${process.argv.join(' ')} & disown exit ` spawn('sh', ['-c', `"${script}"`], { shell: true, detached: true, stdio: 'ignore' }) } app.quit() }