mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2025-12-27 21:20:29 +08:00
support direct connection under specific WiFi SSID
This commit is contained in:
parent
43f2b2e701
commit
80f22e719a
@ -1,3 +1,7 @@
|
|||||||
|
### Features
|
||||||
|
|
||||||
|
- 支持在特定WiFi SSID下直连
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
- 修复某些mac无法开启开机启动的问题
|
- 修复某些mac无法开启开机启动的问题
|
||||||
|
|||||||
@ -262,7 +262,7 @@ export function isEncryptionAvailable(): boolean {
|
|||||||
return safeStorage.isEncryptionAvailable()
|
return safeStorage.isEncryptionAvailable()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getDefaultService(password?: string): Promise<string> {
|
export async function getDefaultService(password?: string): Promise<string> {
|
||||||
const execPromise = promisify(exec)
|
const execPromise = promisify(exec)
|
||||||
let sudo = ''
|
let sudo = ''
|
||||||
if (password) sudo = `echo "${password}" | sudo -S `
|
if (password) sudo = `echo "${password}" | sudo -S `
|
||||||
|
|||||||
79
src/main/sys/ssid.ts
Normal file
79
src/main/sys/ssid.ts
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
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<string | undefined> {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
let lastSSID: string | undefined
|
||||||
|
export async function checkSSID(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const { pauseSSID = [] } = await getAppConfig()
|
||||||
|
if (pauseSSID.length === 0) return
|
||||||
|
const currentSSID = await getCurrentSSID()
|
||||||
|
if (currentSSID === lastSSID) return
|
||||||
|
lastSSID = currentSSID
|
||||||
|
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<void> {
|
||||||
|
await checkSSID()
|
||||||
|
setInterval(checkSSID, 30000)
|
||||||
|
}
|
||||||
@ -34,6 +34,7 @@ import {
|
|||||||
patchControledMihomoConfig
|
patchControledMihomoConfig
|
||||||
} from '../config'
|
} from '../config'
|
||||||
import { app } from 'electron'
|
import { app } from 'electron'
|
||||||
|
import { startSSIDCheck } from '../sys/ssid'
|
||||||
|
|
||||||
async function initDirs(): Promise<void> {
|
async function initDirs(): Promise<void> {
|
||||||
if (!existsSync(dataDir())) {
|
if (!existsSync(dataDir())) {
|
||||||
@ -212,6 +213,7 @@ export async function init(): Promise<void> {
|
|||||||
await startSubStoreServer()
|
await startSubStoreServer()
|
||||||
const { sysProxy } = await getAppConfig()
|
const { sysProxy } = await getAppConfig()
|
||||||
await triggerSysProxy(sysProxy.enable)
|
await triggerSysProxy(sysProxy.enable)
|
||||||
|
await startSSIDCheck()
|
||||||
|
|
||||||
initDeeplink()
|
initDeeplink()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import SettingCard from '../base/base-setting-card'
|
import SettingCard from '../base/base-setting-card'
|
||||||
import SettingItem from '../base/base-setting-item'
|
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 { useAppConfig } from '@renderer/hooks/use-app-config'
|
||||||
import debounce from '@renderer/utils/debounce'
|
import debounce from '@renderer/utils/debounce'
|
||||||
import { patchControledMihomoConfig, restartCore } from '@renderer/utils/ipc'
|
import { patchControledMihomoConfig, restartCore } from '@renderer/utils/ipc'
|
||||||
|
import { MdDeleteForever } from 'react-icons/md'
|
||||||
|
|
||||||
const MihomoConfig: React.FC = () => {
|
const MihomoConfig: React.FC = () => {
|
||||||
const { appConfig, patchAppConfig } = useAppConfig()
|
const { appConfig, patchAppConfig } = useAppConfig()
|
||||||
@ -13,11 +14,13 @@ const MihomoConfig: React.FC = () => {
|
|||||||
controlSniff = true,
|
controlSniff = true,
|
||||||
delayTestTimeout,
|
delayTestTimeout,
|
||||||
autoCloseConnection = true,
|
autoCloseConnection = true,
|
||||||
|
pauseSSID = [],
|
||||||
delayTestUrl,
|
delayTestUrl,
|
||||||
userAgent,
|
userAgent,
|
||||||
proxyCols = 'auto'
|
proxyCols = 'auto'
|
||||||
} = appConfig || {}
|
} = appConfig || {}
|
||||||
const [url, setUrl] = useState(delayTestUrl)
|
const [url, setUrl] = useState(delayTestUrl)
|
||||||
|
const [pauseSSIDInput, setPauseSSIDInput] = useState(pauseSSID)
|
||||||
const setUrlDebounce = debounce((v: string) => {
|
const setUrlDebounce = debounce((v: string) => {
|
||||||
patchAppConfig({ delayTestUrl: v })
|
patchAppConfig({ delayTestUrl: v })
|
||||||
}, 500)
|
}, 500)
|
||||||
@ -109,7 +112,7 @@ const MihomoConfig: React.FC = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
<SettingItem title="自动断开连接">
|
<SettingItem title="自动断开连接" divider>
|
||||||
<Switch
|
<Switch
|
||||||
size="sm"
|
size="sm"
|
||||||
isSelected={autoCloseConnection}
|
isSelected={autoCloseConnection}
|
||||||
@ -118,6 +121,51 @@ const MihomoConfig: React.FC = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
|
<SettingItem title="在特定的 WiFi SSID 下直连">
|
||||||
|
{pauseSSIDInput.join('') !== pauseSSID.join('') && (
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
color="primary"
|
||||||
|
onPress={() => {
|
||||||
|
patchAppConfig({ pauseSSID: pauseSSIDInput })
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
确认
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</SettingItem>
|
||||||
|
<div className="flex flex-col items-stretch mt-2">
|
||||||
|
{[...pauseSSIDInput, ''].map((ssid, index) => {
|
||||||
|
return (
|
||||||
|
<div key={index} className="flex mb-2">
|
||||||
|
<Input
|
||||||
|
size="sm"
|
||||||
|
fullWidth
|
||||||
|
placeholder="SSID"
|
||||||
|
value={ssid || ''}
|
||||||
|
onValueChange={(v) => {
|
||||||
|
if (index === pauseSSIDInput.length) {
|
||||||
|
setPauseSSIDInput([...pauseSSIDInput, v])
|
||||||
|
} else {
|
||||||
|
setPauseSSIDInput(pauseSSIDInput.map((a, i) => (i === index ? v : a)))
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{index < pauseSSIDInput.length && (
|
||||||
|
<Button
|
||||||
|
className="ml-2"
|
||||||
|
size="sm"
|
||||||
|
variant="flat"
|
||||||
|
color="warning"
|
||||||
|
onClick={() => setPauseSSIDInput(pauseSSIDInput.filter((_, i) => i !== index))}
|
||||||
|
>
|
||||||
|
<MdDeleteForever className="text-lg" />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
</SettingCard>
|
</SettingCard>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
3
src/shared/types.d.ts
vendored
3
src/shared/types.d.ts
vendored
@ -213,6 +213,7 @@ interface IAppConfig {
|
|||||||
connectionCardStatus?: CardStatus
|
connectionCardStatus?: CardStatus
|
||||||
dnsCardStatus?: CardStatus
|
dnsCardStatus?: CardStatus
|
||||||
logCardStatus?: CardStatus
|
logCardStatus?: CardStatus
|
||||||
|
pauseSSID?: string[]
|
||||||
mihomoCoreCardStatus?: CardStatus
|
mihomoCoreCardStatus?: CardStatus
|
||||||
overrideCardStatus?: CardStatus
|
overrideCardStatus?: CardStatus
|
||||||
profileCardStatus?: CardStatus
|
profileCardStatus?: CardStatus
|
||||||
@ -237,7 +238,7 @@ interface IAppConfig {
|
|||||||
proxyInTray: boolean
|
proxyInTray: boolean
|
||||||
siderOrder: string[]
|
siderOrder: string[]
|
||||||
appTheme: AppTheme
|
appTheme: AppTheme
|
||||||
customTheme: string
|
customTheme?: string
|
||||||
autoCheckUpdate: boolean
|
autoCheckUpdate: boolean
|
||||||
silentStart: boolean
|
silentStart: boolean
|
||||||
autoCloseConnection: boolean
|
autoCloseConnection: boolean
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user