From 6a5d9c15f24aaf886bc6a579c1fc087af821655a Mon Sep 17 00:00:00 2001 From: pompurin404 Date: Sun, 22 Sep 2024 16:05:35 +0800 Subject: [PATCH] support direct connection under specific WiFi SSID --- changelog.md | 4 + src/main/core/manager.ts | 2 +- src/main/sys/ssid.ts | 77 +++++++++++++++++++ src/main/utils/init.ts | 2 + .../src/components/settings/mihomo-config.tsx | 52 ++++++++++++- src/shared/types.d.ts | 3 +- 6 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 src/main/sys/ssid.ts diff --git a/changelog.md b/changelog.md index ba0c1f0a..09dfe887 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,7 @@ +### Features + +- 支持在特定WiFi SSID下直连 + ### Bug Fixes - 修复某些mac无法开启开机启动的问题 diff --git a/src/main/core/manager.ts b/src/main/core/manager.ts index e7e08d7f..bedfc1f4 100644 --- a/src/main/core/manager.ts +++ b/src/main/core/manager.ts @@ -262,7 +262,7 @@ export function isEncryptionAvailable(): boolean { return safeStorage.isEncryptionAvailable() } -async function getDefaultService(password?: string): Promise { +export async function getDefaultService(password?: string): Promise { const execPromise = promisify(exec) let sudo = '' if (password) sudo = `echo "${password}" | sudo -S ` diff --git a/src/main/sys/ssid.ts b/src/main/sys/ssid.ts new file mode 100644 index 00000000..a3a796a9 --- /dev/null +++ b/src/main/sys/ssid.ts @@ -0,0 +1,77 @@ +import { exec } from 'child_process' +import { promisify } from 'util' +import { getAppConfig, patchControledMihomoConfig } from '../config' +import { patchMihomoConfig } from '../core/mihomoApi' +import { mainWindow } from '..' +import { ipcMain } from 'electron' +import { getDefaultService } from '../core/manager' + +export async function getCurrentSSID(): Promise { + const execPromise = promisify(exec) + try { + if (process.platform === 'win32') { + const { stdout } = await execPromise('netsh wlan show interfaces') + for (const line of stdout.split('\n')) { + if (line.trim().startsWith('SSID')) { + return line.split(': ')[1].trim() + } + } + } + if (process.platform === 'linux') { + const { stdout } = await execPromise( + `iwconfig 2>/dev/null | grep 'ESSID' | awk -F'"' '{print $2}'` + ) + if (stdout.trim() !== '') { + return stdout.trim() + } + } + if (process.platform === 'darwin') { + try { + const { stdout } = await execPromise( + '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I' + ) + for (const line of stdout.split('\n')) { + if (line.trim().startsWith('SSID')) { + return line.split(': ')[1].trim() + } + } + } catch { + const service = await getDefaultService() + const { stdout } = await execPromise(`networksetup -getairportnetwork ${service}`) + if (stdout.split(': ').length > 1) { + return stdout.split(': ')[1].trim() + } + } + } + } catch { + // ignore + } + return undefined +} + +export async function checkSSID(): Promise { + try { + const { pauseSSID = [] } = await getAppConfig() + if (pauseSSID.length === 0) return + const currentSSID = await getCurrentSSID() + + if (currentSSID && pauseSSID.includes(currentSSID)) { + await patchControledMihomoConfig({ mode: 'direct' }) + await patchMihomoConfig({ mode: 'direct' }) + mainWindow?.webContents.send('controledMihomoConfigUpdated') + ipcMain.emit('updateTrayMenu') + } else { + await patchControledMihomoConfig({ mode: 'rule' }) + await patchMihomoConfig({ mode: 'rule' }) + mainWindow?.webContents.send('controledMihomoConfigUpdated') + ipcMain.emit('updateTrayMenu') + } + } catch { + // ignore + } +} + +export async function startSSIDCheck(): Promise { + await checkSSID() + setInterval(checkSSID, 30000) +} diff --git a/src/main/utils/init.ts b/src/main/utils/init.ts index 89158a9e..e128a618 100644 --- a/src/main/utils/init.ts +++ b/src/main/utils/init.ts @@ -34,6 +34,7 @@ import { patchControledMihomoConfig } from '../config' import { app } from 'electron' +import { startSSIDCheck } from '../sys/ssid' async function initDirs(): Promise { if (!existsSync(dataDir())) { @@ -212,6 +213,7 @@ export async function init(): Promise { await startSubStoreServer() const { sysProxy } = await getAppConfig() await triggerSysProxy(sysProxy.enable) + await startSSIDCheck() initDeeplink() } diff --git a/src/renderer/src/components/settings/mihomo-config.tsx b/src/renderer/src/components/settings/mihomo-config.tsx index 1421491a..1532a57c 100644 --- a/src/renderer/src/components/settings/mihomo-config.tsx +++ b/src/renderer/src/components/settings/mihomo-config.tsx @@ -1,10 +1,11 @@ import React, { useState } from 'react' import SettingCard from '../base/base-setting-card' import SettingItem from '../base/base-setting-item' -import { Input, Select, SelectItem, Switch } from '@nextui-org/react' +import { Button, Input, Select, SelectItem, Switch } from '@nextui-org/react' import { useAppConfig } from '@renderer/hooks/use-app-config' import debounce from '@renderer/utils/debounce' import { patchControledMihomoConfig, restartCore } from '@renderer/utils/ipc' +import { MdDeleteForever } from 'react-icons/md' const MihomoConfig: React.FC = () => { const { appConfig, patchAppConfig } = useAppConfig() @@ -13,11 +14,13 @@ const MihomoConfig: React.FC = () => { controlSniff = true, delayTestTimeout, autoCloseConnection = true, + pauseSSID = [], delayTestUrl, userAgent, proxyCols = 'auto' } = appConfig || {} const [url, setUrl] = useState(delayTestUrl) + const [pauseSSIDInput, setPauseSSIDInput] = useState(pauseSSID) const setUrlDebounce = debounce((v: string) => { patchAppConfig({ delayTestUrl: v }) }, 500) @@ -109,7 +112,7 @@ const MihomoConfig: React.FC = () => { }} /> - + { }} /> + + {pauseSSIDInput.join('') !== pauseSSID.join('') && ( + + )} + +
+ {[...pauseSSIDInput, ''].map((ssid, index) => { + return ( +
+ { + if (index === pauseSSIDInput.length) { + setPauseSSIDInput([...pauseSSIDInput, v]) + } else { + setPauseSSIDInput(pauseSSIDInput.map((a, i) => (i === index ? v : a))) + } + }} + /> + {index < pauseSSIDInput.length && ( + + )} +
+ ) + })} +
) } diff --git a/src/shared/types.d.ts b/src/shared/types.d.ts index 4d966f96..b1b22ca8 100644 --- a/src/shared/types.d.ts +++ b/src/shared/types.d.ts @@ -213,6 +213,7 @@ interface IAppConfig { connectionCardStatus?: CardStatus dnsCardStatus?: CardStatus logCardStatus?: CardStatus + pauseSSID?: string[] mihomoCoreCardStatus?: CardStatus overrideCardStatus?: CardStatus profileCardStatus?: CardStatus @@ -237,7 +238,7 @@ interface IAppConfig { proxyInTray: boolean siderOrder: string[] appTheme: AppTheme - customTheme: string + customTheme?: string autoCheckUpdate: boolean silentStart: boolean autoCloseConnection: boolean