Skip to content
This repository has been archived by the owner on Feb 5, 2025. It is now read-only.

Commit

Permalink
support direct connection under specific WiFi SSID
Browse files Browse the repository at this point in the history
  • Loading branch information
pompurin404 committed Sep 22, 2024
1 parent bdf53c6 commit 6a5d9c1
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 4 deletions.
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
### Features

- 支持在特定WiFi SSID下直连

### Bug Fixes

- 修复某些mac无法开启开机启动的问题
2 changes: 1 addition & 1 deletion src/main/core/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ export function isEncryptionAvailable(): boolean {
return safeStorage.isEncryptionAvailable()
}

async function getDefaultService(password?: string): Promise<string> {
export async function getDefaultService(password?: string): Promise<string> {
const execPromise = promisify(exec)
let sudo = ''
if (password) sudo = `echo "${password}" | sudo -S `
Expand Down
77 changes: 77 additions & 0 deletions src/main/sys/ssid.ts
Original file line number Diff line number Diff line change
@@ -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<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
}

export async function checkSSID(): Promise<void> {
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<void> {
await checkSSID()
setInterval(checkSSID, 30000)
}
2 changes: 2 additions & 0 deletions src/main/utils/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
patchControledMihomoConfig
} from '../config'
import { app } from 'electron'
import { startSSIDCheck } from '../sys/ssid'

async function initDirs(): Promise<void> {
if (!existsSync(dataDir())) {
Expand Down Expand Up @@ -212,6 +213,7 @@ export async function init(): Promise<void> {
await startSubStoreServer()
const { sysProxy } = await getAppConfig()
await triggerSysProxy(sysProxy.enable)
await startSSIDCheck()

initDeeplink()
}
52 changes: 50 additions & 2 deletions src/renderer/src/components/settings/mihomo-config.tsx
Original file line number Diff line number Diff line change
@@ -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()
Expand All @@ -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)
Expand Down Expand Up @@ -109,7 +112,7 @@ const MihomoConfig: React.FC = () => {
}}
/>
</SettingItem>
<SettingItem title="自动断开连接">
<SettingItem title="自动断开连接" divider>
<Switch
size="sm"
isSelected={autoCloseConnection}
Expand All @@ -118,6 +121,51 @@ const MihomoConfig: React.FC = () => {
}}
/>
</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>
)
}
Expand Down
3 changes: 2 additions & 1 deletion src/shared/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ interface IAppConfig {
connectionCardStatus?: CardStatus
dnsCardStatus?: CardStatus
logCardStatus?: CardStatus
pauseSSID?: string[]
mihomoCoreCardStatus?: CardStatus
overrideCardStatus?: CardStatus
profileCardStatus?: CardStatus
Expand All @@ -237,7 +238,7 @@ interface IAppConfig {
proxyInTray: boolean
siderOrder: string[]
appTheme: AppTheme
customTheme: string
customTheme?: string
autoCheckUpdate: boolean
silentStart: boolean
autoCloseConnection: boolean
Expand Down

0 comments on commit 6a5d9c1

Please sign in to comment.