mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2025-12-27 05:00:30 +08:00
use unix socket and namedpipe instead of http api
This commit is contained in:
parent
c516f8d1d9
commit
c420f0397c
@ -1,7 +1,6 @@
|
|||||||
import { controledMihomoConfigPath } from '../utils/dirs'
|
import { controledMihomoConfigPath } from '../utils/dirs'
|
||||||
import { readFile, writeFile } from 'fs/promises'
|
import { readFile, writeFile } from 'fs/promises'
|
||||||
import yaml from 'yaml'
|
import yaml from 'yaml'
|
||||||
import { getAxios } from '../core/mihomoApi'
|
|
||||||
import { generateProfile } from '../core/factory'
|
import { generateProfile } from '../core/factory'
|
||||||
import { getAppConfig } from './app'
|
import { getAppConfig } from './app'
|
||||||
import { defaultControledMihomoConfig } from '../utils/template'
|
import { defaultControledMihomoConfig } from '../utils/template'
|
||||||
@ -52,9 +51,6 @@ export async function patchControledMihomoConfig(patch: Partial<IMihomoConfig>):
|
|||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
delete controledMihomoConfig?.tun?.device
|
delete controledMihomoConfig?.tun?.device
|
||||||
}
|
}
|
||||||
if (patch['external-controller'] || patch.secret) {
|
|
||||||
await getAxios(true)
|
|
||||||
}
|
|
||||||
await generateProfile()
|
await generateProfile()
|
||||||
await writeFile(controledMihomoConfigPath(), yaml.stringify(controledMihomoConfig), 'utf-8')
|
await writeFile(controledMihomoConfigPath(), yaml.stringify(controledMihomoConfig), 'utf-8')
|
||||||
}
|
}
|
||||||
|
|||||||
@ -113,25 +113,19 @@ export async function startCore(detached = false): Promise<Promise<void>[]> {
|
|||||||
})
|
})
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
child.stdout?.on('data', async (data) => {
|
child.stdout?.on('data', async (data) => {
|
||||||
if (data.toString().includes('configure tun interface: operation not permitted')) {
|
const str = data.toString()
|
||||||
|
if (str.includes('configure tun interface: operation not permitted')) {
|
||||||
patchControledMihomoConfig({ tun: { enable: false } })
|
patchControledMihomoConfig({ tun: { enable: false } })
|
||||||
mainWindow?.webContents.send('controledMihomoConfigUpdated')
|
mainWindow?.webContents.send('controledMihomoConfigUpdated')
|
||||||
ipcMain.emit('updateTrayMenu')
|
ipcMain.emit('updateTrayMenu')
|
||||||
reject('虚拟网卡启动失败, 请尝试手动授予内核权限')
|
reject('虚拟网卡启动失败, 请尝试手动授予内核权限')
|
||||||
}
|
}
|
||||||
if (data.toString().includes('External controller listen error')) {
|
|
||||||
if (retry) {
|
if (
|
||||||
retry--
|
(process.platform !== 'win32' && str.includes('RESTful API unix listening at')) ||
|
||||||
try {
|
(process.platform === 'win32' && str.includes('RESTful API pipe listening at'))
|
||||||
resolve(await startCore())
|
) {
|
||||||
} catch (e) {
|
await autoGrantUnixSocket()
|
||||||
reject(e)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reject('内核连接失败, 请尝试修改外部控制端口或重启电脑')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (data.toString().includes('RESTful API listening at')) {
|
|
||||||
resolve([
|
resolve([
|
||||||
new Promise((resolve) => {
|
new Promise((resolve) => {
|
||||||
child.stdout?.on('data', async (data) => {
|
child.stdout?.on('data', async (data) => {
|
||||||
@ -223,6 +217,25 @@ async function checkProfile(): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function autoGrantUnixSocket(): Promise<void> {
|
||||||
|
if (process.platform === 'win32') return
|
||||||
|
const { encryptedPassword } = await getAppConfig()
|
||||||
|
const { 'external-controller-unix': mihomoUnix = 'mihomo-party.sock' } =
|
||||||
|
await getControledMihomoConfig()
|
||||||
|
const execPromise = promisify(exec)
|
||||||
|
if (encryptedPassword && isEncryptionAvailable()) {
|
||||||
|
try {
|
||||||
|
const password = safeStorage.decryptString(Buffer.from(encryptedPassword))
|
||||||
|
await execPromise(
|
||||||
|
`echo "${password}" | sudo -S chmod 777 "${path.join(mihomoWorkDir(), mihomoUnix)}"`
|
||||||
|
)
|
||||||
|
} catch (error) {
|
||||||
|
patchAppConfig({ encryptedPassword: undefined })
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function autoGrantCorePermition(corePath: string): Promise<void> {
|
export async function autoGrantCorePermition(corePath: string): Promise<void> {
|
||||||
if (process.platform === 'win32') return
|
if (process.platform === 'win32') return
|
||||||
const { encryptedPassword } = await getAppConfig()
|
const { encryptedPassword } = await getAppConfig()
|
||||||
|
|||||||
@ -1,77 +1,104 @@
|
|||||||
import axios, { AxiosInstance } from 'axios'
|
import net from 'net'
|
||||||
|
import { getRuntimeConfig } from './factory'
|
||||||
import { getAppConfig, getControledMihomoConfig } from '../config'
|
import { getAppConfig, getControledMihomoConfig } from '../config'
|
||||||
import { mainWindow } from '..'
|
import { mainWindow } from '..'
|
||||||
import WebSocket from 'ws'
|
|
||||||
import { tray } from '../resolve/tray'
|
import { tray } from '../resolve/tray'
|
||||||
import { calcTraffic } from '../utils/calc'
|
import { calcTraffic } from '../utils/calc'
|
||||||
import { getRuntimeConfig } from './factory'
|
import { join } from 'path'
|
||||||
|
import { mihomoWorkDir } from '../utils/dirs'
|
||||||
|
|
||||||
let axiosIns: AxiosInstance = null!
|
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'
|
||||||
let mihomoTrafficWs: WebSocket | null = null
|
|
||||||
|
let mihomoTrafficWs: net.Socket | null = null
|
||||||
let trafficRetry = 10
|
let trafficRetry = 10
|
||||||
let mihomoMemoryWs: WebSocket | null = null
|
let mihomoMemoryWs: net.Socket | null = null
|
||||||
let memoryRetry = 10
|
let memoryRetry = 10
|
||||||
let mihomoLogsWs: WebSocket | null = null
|
let mihomoLogsWs: net.Socket | null = null
|
||||||
let logsRetry = 10
|
let logsRetry = 10
|
||||||
let mihomoConnectionsWs: WebSocket | null = null
|
let mihomoConnectionsWs: net.Socket | null = null
|
||||||
let connectionsRetry = 10
|
let connectionsRetry = 10
|
||||||
|
|
||||||
export const getAxios = async (force: boolean = false): Promise<AxiosInstance> => {
|
function trimJson(data: string): string {
|
||||||
if (axiosIns && !force) return axiosIns
|
if (data.trim().length === 0) return ''
|
||||||
const controledMihomoConfig = await getControledMihomoConfig()
|
const start = data.indexOf('{')
|
||||||
let server = controledMihomoConfig['external-controller']
|
const end = data.lastIndexOf('}')
|
||||||
const secret = controledMihomoConfig.secret ?? ''
|
return data.slice(start, end + 1)
|
||||||
if (server?.startsWith(':')) server = `127.0.0.1${server}`
|
|
||||||
|
|
||||||
axiosIns = axios.create({
|
|
||||||
baseURL: `http://${server}`,
|
|
||||||
proxy: false,
|
|
||||||
headers: secret ? { Authorization: `Bearer ${secret}` } : {},
|
|
||||||
timeout: 15000
|
|
||||||
})
|
|
||||||
|
|
||||||
axiosIns.interceptors.response.use(
|
|
||||||
(response) => {
|
|
||||||
return response.data
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
if (error.response && error.response.data) {
|
|
||||||
return Promise.reject(error.response.data)
|
|
||||||
}
|
|
||||||
return Promise.reject(error)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
return axiosIns
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function mihomoVersion(): Promise<IMihomoVersion> {
|
async function mihomoHttp<T>(method: HttpMethod, path: string, data?: object): Promise<T> {
|
||||||
const instance = await getAxios()
|
const {
|
||||||
return await instance.get('/version')
|
'external-controller-pipe': mihomoPipe = '\\\\.\\pipe\\MihomoParty\\mihomo',
|
||||||
|
'external-controller-unix': mihomoUnix = 'mihomo-party.sock'
|
||||||
|
} = await getControledMihomoConfig()
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const client = net.connect(
|
||||||
|
process.platform === 'win32' ? mihomoPipe : join(mihomoWorkDir(), mihomoUnix)
|
||||||
|
)
|
||||||
|
client.on('data', function (res) {
|
||||||
|
try {
|
||||||
|
const data = trimJson(res.toString().split('\r\n\r\n')[1])
|
||||||
|
if (res.toString().includes('HTTP/1.1 4') || res.toString().includes('HTTP/1.1 5')) {
|
||||||
|
reject(data ? JSON.parse(data) : undefined)
|
||||||
|
} else {
|
||||||
|
resolve(data ? JSON.parse(data) : undefined)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
reject(e)
|
||||||
|
} finally {
|
||||||
|
client.end()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
client.on('error', function (error) {
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
if (data) {
|
||||||
|
const json = JSON.stringify(data)
|
||||||
|
client.write(
|
||||||
|
`${method} ${path} HTTP/1.1\r\nHost: mihomo-party\r\nContent-Type: application/json\r\nContent-Length: ${json.length}\r\n\r\n${json}`
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
client.write(`${method} ${path} HTTP/1.1\r\nHost: mihomo-party\r\n\r\n`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function mihomoWs(path: string): Promise<net.Socket> {
|
||||||
|
const {
|
||||||
|
'external-controller-pipe': mihomoPipe = '\\\\.\\pipe\\MihomoParty\\mihomo',
|
||||||
|
'external-controller-unix': mihomoUnix = 'mihomo-party.sock'
|
||||||
|
} = await getControledMihomoConfig()
|
||||||
|
const client = net.connect(
|
||||||
|
process.platform === 'win32' ? mihomoPipe : join(mihomoWorkDir(), mihomoUnix)
|
||||||
|
)
|
||||||
|
client.write(
|
||||||
|
`GET ${path} HTTP/1.1\r\nHost: mihomo-party\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: xxxxxxxxxxxxxxxxxxxxxxxx\r\n\r\n`
|
||||||
|
)
|
||||||
|
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mihomoVersion = async (): Promise<IMihomoVersion> => {
|
||||||
|
return await mihomoHttp('GET', '/version')
|
||||||
}
|
}
|
||||||
|
|
||||||
export const patchMihomoConfig = async (patch: Partial<IMihomoConfig>): Promise<void> => {
|
export const patchMihomoConfig = async (patch: Partial<IMihomoConfig>): Promise<void> => {
|
||||||
const instance = await getAxios()
|
return await mihomoHttp('PATCH', '/configs', patch)
|
||||||
return await instance.patch('/configs', patch)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mihomoCloseConnection = async (id: string): Promise<void> => {
|
export const mihomoCloseConnection = async (id: string): Promise<void> => {
|
||||||
const instance = await getAxios()
|
return await mihomoHttp('DELETE', `/connection/${id}`)
|
||||||
return await instance.delete(`/connections/${encodeURIComponent(id)}`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mihomoCloseAllConnections = async (): Promise<void> => {
|
export const mihomoCloseAllConnections = async (): Promise<void> => {
|
||||||
const instance = await getAxios()
|
return await mihomoHttp('DELETE', '/connections')
|
||||||
return await instance.delete('/connections')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mihomoRules = async (): Promise<IMihomoRulesInfo> => {
|
export const mihomoRules = async (): Promise<IMihomoRulesInfo> => {
|
||||||
const instance = await getAxios()
|
return await mihomoHttp('GET', '/rules')
|
||||||
return await instance.get('/rules')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mihomoProxies = async (): Promise<IMihomoProxies> => {
|
export const mihomoProxies = async (): Promise<IMihomoProxies> => {
|
||||||
const instance = await getAxios()
|
const proxies = (await mihomoHttp('GET', '/proxies')) as IMihomoProxies
|
||||||
const proxies = (await instance.get('/proxies')) as IMihomoProxies
|
|
||||||
if (!proxies.proxies['GLOBAL']) {
|
if (!proxies.proxies['GLOBAL']) {
|
||||||
throw new Error('GLOBAL proxy not found')
|
throw new Error('GLOBAL proxy not found')
|
||||||
}
|
}
|
||||||
@ -102,265 +129,194 @@ export const mihomoGroups = async (): Promise<IMihomoMixedGroup[]> => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const mihomoProxyProviders = async (): Promise<IMihomoProxyProviders> => {
|
export const mihomoProxyProviders = async (): Promise<IMihomoProxyProviders> => {
|
||||||
const instance = await getAxios()
|
return await mihomoHttp('GET', '/providers/proxies')
|
||||||
return await instance.get('/providers/proxies')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mihomoUpdateProxyProviders = async (name: string): Promise<void> => {
|
export const mihomoUpdateProxyProviders = async (name: string): Promise<void> => {
|
||||||
const instance = await getAxios()
|
return await mihomoHttp('PUT', `/providers/proxies/${encodeURIComponent(name)}`)
|
||||||
return await instance.put(`/providers/proxies/${encodeURIComponent(name)}`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mihomoRuleProviders = async (): Promise<IMihomoRuleProviders> => {
|
export const mihomoRuleProviders = async (): Promise<IMihomoRuleProviders> => {
|
||||||
const instance = await getAxios()
|
return await mihomoHttp('GET', '/providers/rules')
|
||||||
return await instance.get('/providers/rules')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mihomoUpdateRuleProviders = async (name: string): Promise<void> => {
|
export const mihomoUpdateRuleProviders = async (name: string): Promise<void> => {
|
||||||
const instance = await getAxios()
|
return await mihomoHttp('PUT', `/providers/rules/${encodeURIComponent(name)}`)
|
||||||
return await instance.put(`/providers/rules/${encodeURIComponent(name)}`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mihomoChangeProxy = async (group: string, proxy: string): Promise<IMihomoProxy> => {
|
export const mihomoChangeProxy = async (group: string, proxy: string): Promise<IMihomoProxy> => {
|
||||||
const instance = await getAxios()
|
return await mihomoHttp('PUT', `/proxies/${encodeURIComponent(group)}`, { name: proxy })
|
||||||
return await instance.put(`/proxies/${encodeURIComponent(group)}`, { name: proxy })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mihomoUpgradeGeo = async (): Promise<void> => {
|
export const mihomoUpgradeGeo = async (): Promise<void> => {
|
||||||
const instance = await getAxios()
|
return await mihomoHttp('POST', '/configs/geo')
|
||||||
return await instance.post('/configs/geo')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mihomoProxyDelay = async (proxy: string, url?: string): Promise<IMihomoDelay> => {
|
export const mihomoProxyDelay = async (proxy: string, url?: string): Promise<IMihomoDelay> => {
|
||||||
const appConfig = await getAppConfig()
|
const appConfig = await getAppConfig()
|
||||||
const { delayTestUrl, delayTestTimeout } = appConfig
|
const { delayTestUrl, delayTestTimeout } = appConfig
|
||||||
const instance = await getAxios()
|
|
||||||
return await instance.get(`/proxies/${encodeURIComponent(proxy)}/delay`, {
|
return await mihomoHttp(
|
||||||
params: {
|
'GET',
|
||||||
url: url || delayTestUrl || 'https://www.gstatic.com/generate_204',
|
`/proxies/${encodeURIComponent(proxy)}/delay?url=${encodeURIComponent(url || delayTestUrl || 'https://www.gstatic.com/generate_204')}&timeout=${delayTestTimeout || 5000}`
|
||||||
timeout: delayTestTimeout || 5000
|
)
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mihomoGroupDelay = async (group: string, url?: string): Promise<IMihomoGroupDelay> => {
|
export const mihomoGroupDelay = async (group: string, url?: string): Promise<IMihomoGroupDelay> => {
|
||||||
const appConfig = await getAppConfig()
|
const appConfig = await getAppConfig()
|
||||||
const { delayTestUrl, delayTestTimeout } = appConfig
|
const { delayTestUrl, delayTestTimeout } = appConfig
|
||||||
const instance = await getAxios()
|
return await mihomoHttp(
|
||||||
return await instance.get(`/group/${encodeURIComponent(group)}/delay`, {
|
'GET',
|
||||||
params: {
|
`/proxies/${encodeURIComponent(group)}/delay?url=${encodeURIComponent(url || delayTestUrl || 'https://www.gstatic.com/generate_204')}&timeout=${delayTestTimeout || 5000}`
|
||||||
url: url || delayTestUrl || 'https://www.gstatic.com/generate_204',
|
)
|
||||||
timeout: delayTestTimeout || 5000
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mihomoUpgrade = async (): Promise<void> => {
|
export const mihomoUpgrade = async (): Promise<void> => {
|
||||||
const instance = await getAxios()
|
return await mihomoHttp('POST', '/upgrade')
|
||||||
return await instance.post('/upgrade')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const startMihomoTraffic = async (): Promise<void> => {
|
export const startMihomoTraffic = async (): Promise<void> => {
|
||||||
await mihomoTraffic()
|
await mihomoTraffic()
|
||||||
}
|
}
|
||||||
|
|
||||||
export const stopMihomoTraffic = (): void => {
|
export const stopMihomoTraffic = async (): Promise<void> => {
|
||||||
if (mihomoTrafficWs) {
|
if (mihomoTrafficWs) {
|
||||||
mihomoTrafficWs.removeAllListeners()
|
mihomoTrafficWs.end()
|
||||||
if (mihomoTrafficWs.readyState === WebSocket.OPEN) {
|
|
||||||
mihomoTrafficWs.close()
|
|
||||||
}
|
|
||||||
mihomoTrafficWs = null
|
mihomoTrafficWs = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mihomoTraffic = async (): Promise<void> => {
|
const mihomoTraffic = async (): Promise<void> => {
|
||||||
const controledMihomoConfig = await getControledMihomoConfig()
|
|
||||||
let server = controledMihomoConfig['external-controller']
|
|
||||||
const secret = controledMihomoConfig.secret ?? ''
|
|
||||||
if (server?.startsWith(':')) server = `127.0.0.1${server}`
|
|
||||||
stopMihomoTraffic()
|
stopMihomoTraffic()
|
||||||
|
mihomoTrafficWs = await mihomoWs('/traffic')
|
||||||
mihomoTrafficWs = new WebSocket(`ws://${server}/traffic?token=${encodeURIComponent(secret)}`)
|
mihomoTrafficWs.on('data', (data) => {
|
||||||
|
|
||||||
mihomoTrafficWs.onmessage = async (e): Promise<void> => {
|
|
||||||
const data = e.data as string
|
|
||||||
const json = JSON.parse(data) as IMihomoTrafficInfo
|
|
||||||
trafficRetry = 10
|
|
||||||
try {
|
try {
|
||||||
|
const json = JSON.parse(trimJson(data.toString())) as IMihomoTrafficInfo
|
||||||
|
trafficRetry = 10
|
||||||
mainWindow?.webContents.send('mihomoTraffic', json)
|
mainWindow?.webContents.send('mihomoTraffic', json)
|
||||||
if (process.platform !== 'linux') {
|
tray?.setToolTip(
|
||||||
tray?.setToolTip(
|
'↑' +
|
||||||
'↑' +
|
`${calcTraffic(json.up)}/s`.padStart(9) +
|
||||||
`${calcTraffic(json.up)}/s`.padStart(9) +
|
'\n↓' +
|
||||||
'\n↓' +
|
`${calcTraffic(json.down)}/s`.padStart(9)
|
||||||
`${calcTraffic(json.down)}/s`.padStart(9)
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
} catch {
|
} catch {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
mihomoTrafficWs.on('close', () => {
|
||||||
mihomoTrafficWs.onclose = (): void => {
|
|
||||||
if (trafficRetry) {
|
if (trafficRetry) {
|
||||||
trafficRetry--
|
trafficRetry--
|
||||||
mihomoTraffic()
|
mihomoTraffic()
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
mihomoTrafficWs.onerror = (): void => {
|
mihomoTrafficWs.on('error', (): void => {
|
||||||
if (mihomoTrafficWs) {
|
stopMihomoTraffic()
|
||||||
mihomoTrafficWs.close()
|
})
|
||||||
mihomoTrafficWs = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const startMihomoMemory = async (): Promise<void> => {
|
export const startMihomoMemory = async (): Promise<void> => {
|
||||||
await mihomoMemory()
|
await mihomoMemory()
|
||||||
}
|
}
|
||||||
|
|
||||||
export const stopMihomoMemory = (): void => {
|
export const stopMihomoMemory = async (): Promise<void> => {
|
||||||
if (mihomoMemoryWs) {
|
if (mihomoMemoryWs) {
|
||||||
mihomoMemoryWs.removeAllListeners()
|
mihomoMemoryWs.end()
|
||||||
if (mihomoMemoryWs.readyState === WebSocket.OPEN) {
|
|
||||||
mihomoMemoryWs.close()
|
|
||||||
}
|
|
||||||
mihomoMemoryWs = null
|
mihomoMemoryWs = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mihomoMemory = async (): Promise<void> => {
|
const mihomoMemory = async (): Promise<void> => {
|
||||||
const controledMihomoConfig = await getControledMihomoConfig()
|
|
||||||
let server = controledMihomoConfig['external-controller']
|
|
||||||
const secret = controledMihomoConfig.secret ?? ''
|
|
||||||
if (server?.startsWith(':')) server = `127.0.0.1${server}`
|
|
||||||
stopMihomoMemory()
|
stopMihomoMemory()
|
||||||
|
mihomoMemoryWs = await mihomoWs('/memory')
|
||||||
mihomoMemoryWs = new WebSocket(`ws://${server}/memory?token=${encodeURIComponent(secret)}`)
|
mihomoMemoryWs.on('data', (data) => {
|
||||||
|
|
||||||
mihomoMemoryWs.onmessage = (e): void => {
|
|
||||||
const data = e.data as string
|
|
||||||
memoryRetry = 10
|
|
||||||
try {
|
try {
|
||||||
mainWindow?.webContents.send('mihomoMemory', JSON.parse(data) as IMihomoMemoryInfo)
|
const json = JSON.parse(trimJson(data.toString())) as IMihomoMemoryInfo
|
||||||
|
memoryRetry = 10
|
||||||
|
mainWindow?.webContents.send('mihomoMemory', json)
|
||||||
} catch {
|
} catch {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
mihomoMemoryWs.on('close', () => {
|
||||||
mihomoMemoryWs.onclose = (): void => {
|
|
||||||
if (memoryRetry) {
|
if (memoryRetry) {
|
||||||
memoryRetry--
|
memoryRetry--
|
||||||
mihomoMemory()
|
mihomoMemory()
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
mihomoMemoryWs.onerror = (): void => {
|
mihomoMemoryWs.on('error', (): void => {
|
||||||
if (mihomoMemoryWs) {
|
stopMihomoMemory()
|
||||||
mihomoMemoryWs.close()
|
})
|
||||||
mihomoMemoryWs = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const startMihomoLogs = async (): Promise<void> => {
|
export const startMihomoLogs = async (): Promise<void> => {
|
||||||
await mihomoLogs()
|
await mihomoLogs()
|
||||||
}
|
}
|
||||||
|
|
||||||
export const stopMihomoLogs = (): void => {
|
export const stopMihomoLogs = async (): Promise<void> => {
|
||||||
if (mihomoLogsWs) {
|
if (mihomoLogsWs) {
|
||||||
mihomoLogsWs.removeAllListeners()
|
mihomoLogsWs.end()
|
||||||
if (mihomoLogsWs.readyState === WebSocket.OPEN) {
|
|
||||||
mihomoLogsWs.close()
|
|
||||||
}
|
|
||||||
mihomoLogsWs = null
|
mihomoLogsWs = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mihomoLogs = async (): Promise<void> => {
|
const mihomoLogs = async (): Promise<void> => {
|
||||||
const controledMihomoConfig = await getControledMihomoConfig()
|
|
||||||
const { secret = '', 'log-level': level = 'info' } = controledMihomoConfig
|
|
||||||
let { 'external-controller': server } = controledMihomoConfig
|
|
||||||
if (server?.startsWith(':')) server = `127.0.0.1${server}`
|
|
||||||
stopMihomoLogs()
|
stopMihomoLogs()
|
||||||
|
mihomoLogsWs = await mihomoWs('/logs')
|
||||||
mihomoLogsWs = new WebSocket(
|
mihomoLogsWs.on('data', (data) => {
|
||||||
`ws://${server}/logs?token=${encodeURIComponent(secret)}&level=${level}`
|
|
||||||
)
|
|
||||||
|
|
||||||
mihomoLogsWs.onmessage = (e): void => {
|
|
||||||
const data = e.data as string
|
|
||||||
logsRetry = 10
|
|
||||||
try {
|
try {
|
||||||
mainWindow?.webContents.send('mihomoLogs', JSON.parse(data) as IMihomoLogInfo)
|
const json = JSON.parse(trimJson(data.toString())) as IMihomoLogInfo
|
||||||
|
logsRetry = 10
|
||||||
|
mainWindow?.webContents.send('mihomoLogs', json)
|
||||||
} catch {
|
} catch {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
mihomoLogsWs.on('close', () => {
|
||||||
mihomoLogsWs.onclose = (): void => {
|
|
||||||
if (logsRetry) {
|
if (logsRetry) {
|
||||||
logsRetry--
|
logsRetry--
|
||||||
mihomoLogs()
|
mihomoLogs()
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
mihomoLogsWs.onerror = (): void => {
|
mihomoLogsWs.on('error', (): void => {
|
||||||
if (mihomoLogsWs) {
|
stopMihomoLogs()
|
||||||
mihomoLogsWs.close()
|
})
|
||||||
mihomoLogsWs = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const startMihomoConnections = async (): Promise<void> => {
|
export const startMihomoConnections = async (): Promise<void> => {
|
||||||
await mihomoConnections()
|
await mihomoConnections()
|
||||||
}
|
}
|
||||||
|
|
||||||
export const stopMihomoConnections = (): void => {
|
export const stopMihomoConnections = async (): Promise<void> => {
|
||||||
if (mihomoConnectionsWs) {
|
if (mihomoConnectionsWs) {
|
||||||
mihomoConnectionsWs.removeAllListeners()
|
mihomoConnectionsWs.end()
|
||||||
if (mihomoConnectionsWs.readyState === WebSocket.OPEN) {
|
|
||||||
mihomoConnectionsWs.close()
|
|
||||||
}
|
|
||||||
mihomoConnectionsWs = null
|
mihomoConnectionsWs = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mihomoConnections = async (): Promise<void> => {
|
const mihomoConnections = async (): Promise<void> => {
|
||||||
const controledMihomoConfig = await getControledMihomoConfig()
|
|
||||||
let server = controledMihomoConfig['external-controller']
|
|
||||||
const secret = controledMihomoConfig.secret ?? ''
|
|
||||||
if (server?.startsWith(':')) server = `127.0.0.1${server}`
|
|
||||||
stopMihomoConnections()
|
stopMihomoConnections()
|
||||||
|
mihomoConnectionsWs = await mihomoWs('/connections')
|
||||||
mihomoConnectionsWs = new WebSocket(
|
mihomoConnectionsWs.on('data', (data) => {
|
||||||
`ws://${server}/connections?token=${encodeURIComponent(secret)}`
|
|
||||||
)
|
|
||||||
|
|
||||||
mihomoConnectionsWs.onmessage = (e): void => {
|
|
||||||
const data = e.data as string
|
|
||||||
connectionsRetry = 10
|
|
||||||
try {
|
try {
|
||||||
mainWindow?.webContents.send('mihomoConnections', JSON.parse(data) as IMihomoConnectionsInfo)
|
const json = JSON.parse(trimJson(data.toString())) as IMihomoConnectionsInfo
|
||||||
|
connectionsRetry = 10
|
||||||
|
mainWindow?.webContents.send('mihomoConnections', json)
|
||||||
} catch {
|
} catch {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
mihomoConnectionsWs.on('close', () => {
|
||||||
mihomoConnectionsWs.onclose = (): void => {
|
|
||||||
if (connectionsRetry) {
|
if (connectionsRetry) {
|
||||||
connectionsRetry--
|
connectionsRetry--
|
||||||
mihomoConnections()
|
mihomoConnections()
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
mihomoConnectionsWs.onerror = (): void => {
|
mihomoConnectionsWs.on('error', (): void => {
|
||||||
if (mihomoConnectionsWs) {
|
stopMihomoConnections()
|
||||||
mihomoConnectionsWs.close()
|
})
|
||||||
mihomoConnectionsWs = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -151,6 +151,8 @@ async function migration(): Promise<void> {
|
|||||||
useSubStore = true
|
useSubStore = true
|
||||||
} = await getAppConfig()
|
} = await getAppConfig()
|
||||||
const {
|
const {
|
||||||
|
'external-controller-pipe': externalControllerPipe,
|
||||||
|
'external-controller-unix': externalControllerUnix,
|
||||||
'skip-auth-prefixes': skipAuthPrefixes,
|
'skip-auth-prefixes': skipAuthPrefixes,
|
||||||
authentication,
|
authentication,
|
||||||
'bind-address': bindAddress,
|
'bind-address': bindAddress,
|
||||||
@ -189,6 +191,16 @@ async function migration(): Promise<void> {
|
|||||||
if (typeof envType === 'string') {
|
if (typeof envType === 'string') {
|
||||||
await patchAppConfig({ envType: [envType] })
|
await patchAppConfig({ envType: [envType] })
|
||||||
}
|
}
|
||||||
|
// use unix socket
|
||||||
|
if (process.platform !== 'win32' && !externalControllerUnix) {
|
||||||
|
await patchControledMihomoConfig({ 'external-controller-unix': 'mihomo-party.sock' })
|
||||||
|
}
|
||||||
|
// use named pipe
|
||||||
|
if (process.platform === 'win32' && !externalControllerPipe) {
|
||||||
|
await patchControledMihomoConfig({
|
||||||
|
'external-controller-pipe': '\\\\.\\pipe\\MihomoParty\\mihomo'
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function initDeeplink(): void {
|
function initDeeplink(): void {
|
||||||
|
|||||||
@ -36,8 +36,8 @@ export const defaultConfig: IAppConfig = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const defaultControledMihomoConfig: Partial<IMihomoConfig> = {
|
export const defaultControledMihomoConfig: Partial<IMihomoConfig> = {
|
||||||
'external-controller': '127.0.0.1:9090',
|
'external-controller-pipe': '\\\\.pipe\\MihomoParty\\mihomo',
|
||||||
secret: '',
|
'external-controller-unix': 'mihomo-party.sock',
|
||||||
ipv6: true,
|
ipv6: true,
|
||||||
mode: 'rule',
|
mode: 'rule',
|
||||||
'mixed-port': 7890,
|
'mixed-port': 7890,
|
||||||
|
|||||||
2
src/shared/types.d.ts
vendored
2
src/shared/types.d.ts
vendored
@ -343,6 +343,8 @@ interface IMihomoProfileConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface IMihomoConfig {
|
interface IMihomoConfig {
|
||||||
|
'external-controller-pipe': string
|
||||||
|
'external-controller-unix': string
|
||||||
'external-controller': string
|
'external-controller': string
|
||||||
secret?: string
|
secret?: string
|
||||||
ipv6: boolean
|
ipv6: boolean
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user