mirror of
https://github.com/pompurin404/mihomo-party.git
synced 2024-11-16 11:42:19 +08:00
connections and rules
This commit is contained in:
parent
85e1c27274
commit
caa7c11537
|
@ -29,6 +29,7 @@
|
|||
"react-icons": "^5.2.1",
|
||||
"react-router-dom": "^6.25.1",
|
||||
"swr": "^2.2.5",
|
||||
"ws": "^8.18.0",
|
||||
"yaml": "^2.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -38,6 +39,7 @@
|
|||
"@types/node": "^22.0.0",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/ws": "^8.5.12",
|
||||
"@vitejs/plugin-react": "^4.3.1",
|
||||
"adm-zip": "^0.5.14",
|
||||
"autoprefixer": "^10.4.19",
|
||||
|
|
|
@ -38,6 +38,9 @@ importers:
|
|||
swr:
|
||||
specifier: ^2.2.5
|
||||
version: 2.2.5(react@18.3.1)
|
||||
ws:
|
||||
specifier: ^8.18.0
|
||||
version: 8.18.0
|
||||
yaml:
|
||||
specifier: ^2.5.0
|
||||
version: 2.5.0
|
||||
|
@ -60,6 +63,9 @@ importers:
|
|||
'@types/react-dom':
|
||||
specifier: ^18.3.0
|
||||
version: 18.3.0
|
||||
'@types/ws':
|
||||
specifier: ^8.5.12
|
||||
version: 8.5.12
|
||||
'@vitejs/plugin-react':
|
||||
specifier: ^4.3.1
|
||||
version: 4.3.1(vite@5.3.5(@types/node@22.0.0))
|
||||
|
@ -1746,6 +1752,9 @@ packages:
|
|||
'@types/verror@1.10.10':
|
||||
resolution: {integrity: sha512-l4MM0Jppn18hb9xmM6wwD1uTdShpf9Pn80aXTStnK1C94gtPvJcV2FrDmbOQUAQfJ1cKZHktkQUDwEqaAKXMMg==}
|
||||
|
||||
'@types/ws@8.5.12':
|
||||
resolution: {integrity: sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==}
|
||||
|
||||
'@types/yauzl@2.10.3':
|
||||
resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==}
|
||||
|
||||
|
@ -4170,6 +4179,18 @@ packages:
|
|||
wrappy@1.0.2:
|
||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||
|
||||
ws@8.18.0:
|
||||
resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
peerDependencies:
|
||||
bufferutil: ^4.0.1
|
||||
utf-8-validate: '>=5.0.2'
|
||||
peerDependenciesMeta:
|
||||
bufferutil:
|
||||
optional: true
|
||||
utf-8-validate:
|
||||
optional: true
|
||||
|
||||
xmlbuilder@15.1.1:
|
||||
resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==}
|
||||
engines: {node: '>=8.0'}
|
||||
|
@ -6740,6 +6761,10 @@ snapshots:
|
|||
'@types/verror@1.10.10':
|
||||
optional: true
|
||||
|
||||
'@types/ws@8.5.12':
|
||||
dependencies:
|
||||
'@types/node': 22.0.0
|
||||
|
||||
'@types/yauzl@2.10.3':
|
||||
dependencies:
|
||||
'@types/node': 22.0.0
|
||||
|
@ -9561,6 +9586,8 @@ snapshots:
|
|||
|
||||
wrappy@1.0.2: {}
|
||||
|
||||
ws@8.18.0: {}
|
||||
|
||||
xmlbuilder@15.1.1: {}
|
||||
|
||||
y18n@5.0.8: {}
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
import { ipcMain } from 'electron'
|
||||
import { mihomoConfig, mihomoVersion, patchMihomoConfig } from './mihomo-api'
|
||||
import {
|
||||
mihomoConfig,
|
||||
mihomoConnections,
|
||||
mihomoRules,
|
||||
mihomoVersion,
|
||||
patchMihomoConfig
|
||||
} from './mihomo-api'
|
||||
import { checkAutoRun, disableAutoRun, enableAutoRun } from './autoRun'
|
||||
import {
|
||||
getAppConfig,
|
||||
|
@ -13,6 +19,8 @@ import { restartCore } from './manager'
|
|||
export function registerIpcMainHandlers(): void {
|
||||
ipcMain.handle('mihomoVersion', mihomoVersion)
|
||||
ipcMain.handle('mihomoConfig', mihomoConfig)
|
||||
ipcMain.handle('mihomoConnections', mihomoConnections)
|
||||
ipcMain.handle('mihomeRules', mihomoRules)
|
||||
ipcMain.handle('patchMihomoConfig', async (_e, patch) => await patchMihomoConfig(patch))
|
||||
ipcMain.handle('checkAutoRun', checkAutoRun)
|
||||
ipcMain.handle('enableAutoRun', enableAutoRun)
|
||||
|
|
|
@ -7,9 +7,9 @@ import { registerIpcMainHandlers } from './cmds'
|
|||
import { initConfig, appConfig, controledMihomoConfig, setControledMihomoConfig } from './config'
|
||||
import { stopCore, startCore } from './manager'
|
||||
import { initDirs } from './dirs'
|
||||
import { patchMihomoConfig } from './mihomo-api'
|
||||
import { mihomoTraffic, patchMihomoConfig } from './mihomo-api'
|
||||
|
||||
let window: BrowserWindow | null = null
|
||||
export let window: BrowserWindow | null = null
|
||||
let tray: Tray | null = null
|
||||
let trayContextMenu: Menu | null = null
|
||||
|
||||
|
@ -57,7 +57,7 @@ if (!gotTheLock) {
|
|||
registerIpcMainHandlers()
|
||||
createWindow()
|
||||
createTray()
|
||||
|
||||
mihomoTraffic()
|
||||
app.on('activate', function () {
|
||||
// On macOS it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import axios, { AxiosInstance } from 'axios'
|
||||
import { controledMihomoConfig } from './config'
|
||||
import WebSocket from 'ws'
|
||||
import { window } from '.'
|
||||
|
||||
let axiosIns: AxiosInstance = null!
|
||||
let mihomoTrafficWs: WebSocket = null!
|
||||
|
||||
/// initialize some information
|
||||
/// enable force update axiosIns
|
||||
export const getAxios = async (force: boolean = false): Promise<AxiosInstance> => {
|
||||
if (axiosIns && !force) return axiosIns
|
||||
|
||||
|
@ -32,8 +33,34 @@ export const mihomoConfig = async (): Promise<IMihomoConfig> => {
|
|||
return instance.get('/configs') as Promise<IMihomoConfig>
|
||||
}
|
||||
|
||||
/// Update current configs
|
||||
export const patchMihomoConfig = async (patch: Partial<IMihomoConfig>): Promise<void> => {
|
||||
const instance = await getAxios()
|
||||
return instance.patch('/configs', patch)
|
||||
}
|
||||
|
||||
export const mihomoConnections = async (): Promise<IMihomoConnectionsInfo> => {
|
||||
const instance = await getAxios()
|
||||
return instance.get('/connections') as Promise<IMihomoConnectionsInfo>
|
||||
}
|
||||
|
||||
export const mihomoRules = async (): Promise<IMihomoRulesInfo> => {
|
||||
const instance = await getAxios()
|
||||
return instance.get('/rules') as Promise<IMihomoRulesInfo>
|
||||
}
|
||||
|
||||
export const mihomoTraffic = (): void => {
|
||||
let server = controledMihomoConfig['external-controller']
|
||||
const secret = controledMihomoConfig.secret ?? ''
|
||||
if (server?.startsWith(':')) server = `127.0.0.1${server}`
|
||||
|
||||
mihomoTrafficWs = new WebSocket(`ws://${server}/traffic?secret=${secret}`)
|
||||
|
||||
mihomoTrafficWs.onmessage = (e: { data: string }): void => {
|
||||
window?.webContents.send('mihomoTraffic', JSON.parse(e.data) as IMihomoTrafficInfo)
|
||||
}
|
||||
|
||||
mihomoTrafficWs.onerror = (): void => {
|
||||
console.error('Traffic ws error')
|
||||
mihomoConfig()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,27 @@
|
|||
import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
|
||||
import { IoLink } from 'react-icons/io5'
|
||||
import { Button, Card, CardBody, CardFooter, Chip } from '@nextui-org/react'
|
||||
import { useLocation, useNavigate } from 'react-router-dom'
|
||||
import { IoLink } from 'react-icons/io5'
|
||||
import { useEffect } from 'react'
|
||||
import useSWR from 'swr'
|
||||
import { mihomoConnections } from '@renderer/utils/ipc'
|
||||
|
||||
const ConnCard: React.FC = () => {
|
||||
const navigate = useNavigate()
|
||||
const location = useLocation()
|
||||
|
||||
const { data: connections } = useSWR<IMihomoConnectionsInfo>('/connections', mihomoConnections, {
|
||||
refreshInterval: 5000
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
window.electron.ipcRenderer.on('mihomoTraffic', (_e, info: IMihomoTrafficInfo) => {
|
||||
console.log(info)
|
||||
})
|
||||
return (): void => {
|
||||
window.electron.ipcRenderer.removeAllListeners('mihomoTraffic')
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Card
|
||||
className={`w-[50%] mr-1 mb-2 ${location.pathname.includes('/connections') ? 'bg-primary' : ''}`}
|
||||
|
@ -22,6 +38,9 @@ const ConnCard: React.FC = () => {
|
|||
>
|
||||
<IoLink color="default" className="text-[20px]" />
|
||||
</Button>
|
||||
<Chip size="sm" color="secondary" variant="bordered" className="mr-3 mt-2">
|
||||
{connections?.connections?.length ?? 0}
|
||||
</Chip>
|
||||
</div>
|
||||
</CardBody>
|
||||
<CardFooter className="pt-1">
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
import { Button, Card, CardBody, CardFooter, Chip } from '@nextui-org/react'
|
||||
import { mihomoRules } from '@renderer/utils/ipc'
|
||||
import { IoGitNetwork } from 'react-icons/io5'
|
||||
import { useLocation, useNavigate } from 'react-router-dom'
|
||||
import useSWR from 'swr'
|
||||
|
||||
const RuleCard: React.FC = () => {
|
||||
const navigate = useNavigate()
|
||||
const location = useLocation()
|
||||
|
||||
const { data: rules } = useSWR<IMihomoRulesInfo>('/connections', mihomoRules, {
|
||||
refreshInterval: 5000
|
||||
})
|
||||
|
||||
return (
|
||||
<Card
|
||||
className={`w-[50%] mr-1 mb-2 ${location.pathname.includes('/rules') ? 'bg-primary' : ''}`}
|
||||
|
@ -23,7 +29,7 @@ const RuleCard: React.FC = () => {
|
|||
<IoGitNetwork color="default" className="text-[20px]" />
|
||||
</Button>
|
||||
<Chip size="sm" color="secondary" variant="bordered" className="mr-3 mt-2">
|
||||
1103
|
||||
{rules?.rules?.length ?? 0}
|
||||
</Chip>
|
||||
</div>
|
||||
</CardBody>
|
||||
|
|
6
src/renderer/src/utils/calc.ts
Normal file
6
src/renderer/src/utils/calc.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
export function calcTraffic(bit: number): string {
|
||||
if (bit < 1024) return `${bit} B`
|
||||
if (bit < 1024 * 1024) return `${(bit / 1024).toFixed(2)} KB`
|
||||
if (bit < 1024 * 1024 * 1024) return `${(bit / 1024 / 1024).toFixed(2)} MB`
|
||||
return `${(bit / 1024 / 1024 / 1024).toFixed(2)} GB`
|
||||
}
|
|
@ -6,6 +6,14 @@ export async function mihomoConfig(): Promise<IMihomoConfig> {
|
|||
return await window.electron.ipcRenderer.invoke('mihomoConfig')
|
||||
}
|
||||
|
||||
export async function mihomoConnections(): Promise<IMihomoConnectionsInfo> {
|
||||
return await window.electron.ipcRenderer.invoke('mihomoConnections')
|
||||
}
|
||||
|
||||
export async function mihomoRules(): Promise<IMihomoRulesInfo> {
|
||||
return await window.electron.ipcRenderer.invoke('mihomoRules')
|
||||
}
|
||||
|
||||
export async function patchMihomoConfig(patch: Partial<IMihomoConfig>): Promise<void> {
|
||||
await window.electron.ipcRenderer.invoke('patchMihomoConfig', patch)
|
||||
}
|
||||
|
|
57
src/shared/types.d.ts
vendored
57
src/shared/types.d.ts
vendored
|
@ -6,6 +6,63 @@ interface IMihomoVersion {
|
|||
meta: boolean
|
||||
}
|
||||
|
||||
interface IMihomoTrafficInfo {
|
||||
up: number
|
||||
down: number
|
||||
}
|
||||
|
||||
interface IMihomoRulesInfo {
|
||||
rules: IMihomoRulesDetail[]
|
||||
}
|
||||
|
||||
interface IMihomoRulesDetail {
|
||||
type: string
|
||||
payload: string
|
||||
proxy: string
|
||||
size: number
|
||||
}
|
||||
|
||||
interface IMihomoConnectionsInfo {
|
||||
downloadTotal: number
|
||||
uploadTotal: number
|
||||
connections?: IMihomoConnectionDetail[]
|
||||
memory: number
|
||||
}
|
||||
|
||||
interface IMihomoConnectionDetail {
|
||||
id: string
|
||||
metadata: {
|
||||
network: 'tcp' | 'udp'
|
||||
type: string
|
||||
sourceIP: string
|
||||
destinationIP: string
|
||||
destinationGeoIP: string
|
||||
destinationIPASN: string
|
||||
sourcePort: string
|
||||
destinationPort: string
|
||||
inboundIP: string
|
||||
inboundPort: string
|
||||
inboundName: string
|
||||
inboundUser: string
|
||||
host: string
|
||||
dnsMode: string
|
||||
uid: number
|
||||
process: string
|
||||
processPath: string
|
||||
specialProxy: string
|
||||
specialRules: string
|
||||
remoteDestination: string
|
||||
dscp: number
|
||||
sniffHost: string
|
||||
}
|
||||
upload: number
|
||||
download: number
|
||||
start: string
|
||||
chains: string[]
|
||||
rule: string
|
||||
rulePayload: string
|
||||
}
|
||||
|
||||
interface IAppConfig {
|
||||
core: 'mihomo' | 'mihomo-alpha'
|
||||
silentStart: boolean
|
||||
|
|
Loading…
Reference in New Issue
Block a user