Skip to content

Commit

Permalink
trafficInfo
Browse files Browse the repository at this point in the history
  • Loading branch information
Pompurin404 committed Aug 2, 2024
1 parent 7c00ddc commit e11a98b
Show file tree
Hide file tree
Showing 22 changed files with 195 additions and 122 deletions.
10 changes: 2 additions & 8 deletions src/main/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
export { appConfig, getAppConfig, setAppConfig } from './app'
export { getAppConfig, setAppConfig } from './app'
export { getControledMihomoConfig, setControledMihomoConfig } from './controledMihomo'
export {
controledMihomoConfig,
getControledMihomoConfig,
setControledMihomoConfig
} from './controledMihomo'
export {
profileConfig,
currentProfile,
getCurrentProfile,
getCurrentProfileItem,
getProfileItem,
Expand Down
78 changes: 55 additions & 23 deletions src/main/config/profile.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { controledMihomoConfig } from './controledMihomo'
import { getControledMihomoConfig } from './controledMihomo'
import { profileConfigPath, profilePath } from '../utils/dirs'
import { app } from 'electron'
import { restartCore } from '../core/manager'
import { getAppConfig } from './app'
import { window } from '..'
import axios from 'axios'
import yaml from 'yaml'
import fs from 'fs'

export let profileConfig: IProfileConfig // profile.yaml
export let currentProfile: Partial<IMihomoConfig> // profiles/xxx.yaml
let profileConfig: IProfileConfig // profile.yaml
let currentProfile: Partial<IMihomoConfig> // profiles/xxx.yaml

export function getProfileConfig(force = false): IProfileConfig {
if (force || !profileConfig) {
Expand All @@ -16,19 +18,25 @@ export function getProfileConfig(force = false): IProfileConfig {
}

export function getProfileItem(id: string | undefined): IProfileItem {
const items = profileConfig.items
const items = getProfileConfig().items
return items?.find((item) => item.id === id) || { id: 'default', type: 'local', name: '空白订阅' }
}

export async function addProfileItem(item: Partial<IProfileItem>): Promise<void> {
const newItem = await createProfile(item)
profileConfig.items = getProfileConfig().items.filter((item) => item.id !== newItem.id)
profileConfig.items.push(newItem)
console.log(!profileConfig.current)
if (!profileConfig.current) {
let changeProfile = false
if (!getProfileConfig().current) {
profileConfig.current = newItem.id
changeProfile = true
}
console.log(profileConfig.current)
fs.writeFileSync(profileConfigPath(), yaml.stringify(profileConfig))
window?.webContents.send('profileConfigUpdated')
if (changeProfile) {
getCurrentProfile(true)
restartCore()
}
}

export function removeProfileItem(id: string): void {
Expand All @@ -37,10 +45,33 @@ export function removeProfileItem(id: string): void {
profileConfig.current = profileConfig.items[0]?.id
}
fs.writeFileSync(profileConfigPath(), yaml.stringify(profileConfig))
window?.webContents.send('profileConfigUpdated')
}

export function getCurrentProfileItem(): IProfileItem {
return getProfileItem(profileConfig.current)
return getProfileItem(getProfileConfig().current)
}

// attachment;filename=xxx.yaml; filename*=UTF-8''%xx%xx%xx
function parseFilename(str: string): string {
if (str.includes("filename*=UTF-8''")) {
const filename = decodeURIComponent(str.split("filename*=UTF-8''")[1])
return filename
} else {
const filename = str.split('filename=')[1]
return filename
}
}

// subscription-userinfo: upload=1234; download=2234; total=1024000; expire=2218532293
function parseSubinfo(str: string): ISubscriptionUserInfo {
const parts = str.split('; ')
const obj = {} as ISubscriptionUserInfo
parts.forEach((part) => {
const [key, value] = part.split('=')
obj[key] = parseInt(value)
})
return obj
}

export async function createProfile(item: Partial<IProfileItem>): Promise<IProfileItem> {
Expand All @@ -50,6 +81,7 @@ export async function createProfile(item: Partial<IProfileItem>): Promise<IProfi
name: item.name || 'Local File',
type: item.type || 'local',
url: item.url,
interval: item.interval || 0,
updated: new Date().getTime()
} as IProfileItem
switch (newItem.type) {
Expand All @@ -58,32 +90,31 @@ export async function createProfile(item: Partial<IProfileItem>): Promise<IProfi
throw new Error('URL is required for remote profile')
}
try {
const ua = getAppConfig().userAgent || 'clash-meta'
const res = await axios.get(item.url, {
proxy: {
protocol: 'http',
host: '127.0.0.1',
port: controledMihomoConfig['mixed-port'] || 7890
port: getControledMihomoConfig()['mixed-port'] || 7890
},
headers: {
'User-Agent': `Mihomo.Party.${app.getVersion()}`
'User-Agent': ua
},
responseType: 'text'
})
const data = res.data
const headers = res.headers
if (headers['content-disposition']) {
newItem.name = headers['content-disposition'].split('filename=')[1]
newItem.name = parseFilename(headers['content-disposition'])
}
if (headers['profile-web-page-url']) {
newItem.home = headers['profile-web-page-url']
}
if (headers['profile-update-interval']) {
newItem.interval = parseInt(headers['profile-update-interval']) * 60
}
if (headers['subscription-userinfo']) {
const extra = headers['subscription-userinfo']
.split(';')
.map((item: string) => item.split('=')[1].trim())
newItem.extra = {
upload: parseInt(extra[0]),
download: parseInt(extra[1]),
total: parseInt(extra[2]),
expire: parseInt(extra[3])
}
newItem.extra = parseSubinfo(headers['subscription-userinfo'])
}
fs.writeFileSync(profilePath(id), data, 'utf-8')
} catch (e) {
Expand All @@ -106,8 +137,9 @@ export async function createProfile(item: Partial<IProfileItem>): Promise<IProfi

export function getCurrentProfile(force = false): Partial<IMihomoConfig> {
if (force || !currentProfile) {
if (profileConfig.current) {
currentProfile = yaml.parse(fs.readFileSync(profilePath(profileConfig.current), 'utf-8'))
const current = getProfileConfig().current
if (current) {
currentProfile = yaml.parse(fs.readFileSync(profilePath(current), 'utf-8'))
} else {
currentProfile = yaml.parse(fs.readFileSync(profilePath('default'), 'utf-8'))
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/core/manager.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { ChildProcess, execSync, spawn } from 'child_process'
import { logPath, mihomoCorePath, mihomoWorkDir } from '../utils/dirs'
import { generateProfile } from '../resolve/factory'
import { appConfig } from '../config'
import { getAppConfig } from '../config'
import fs from 'fs'
let child: ChildProcess

export async function startCore(): Promise<void> {
const corePath = mihomoCorePath(appConfig.core ?? 'mihomo')
const corePath = mihomoCorePath(getAppConfig().core ?? 'mihomo')
generateProfile()
stopCore()
if (process.platform !== 'win32') {
Expand Down
10 changes: 5 additions & 5 deletions src/main/core/mihomoApi.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import axios, { AxiosInstance } from 'axios'
import { controledMihomoConfig } from '../config'
import { getControledMihomoConfig } from '../config'
import WebSocket from 'ws'
import { window } from '..'

Expand All @@ -9,8 +9,8 @@ let mihomoTrafficWs: WebSocket = null!
export const getAxios = async (force: boolean = false): Promise<AxiosInstance> => {
if (axiosIns && !force) return axiosIns

let server = controledMihomoConfig['external-controller']
const secret = controledMihomoConfig.secret ?? ''
let server = getControledMihomoConfig()['external-controller']
const secret = getControledMihomoConfig().secret ?? ''
if (server?.startsWith(':')) server = `127.0.0.1${server}`

axiosIns = axios.create({
Expand Down Expand Up @@ -49,8 +49,8 @@ export const mihomoRules = async (): Promise<IMihomoRulesInfo> => {
}

export const mihomoTraffic = (): void => {
let server = controledMihomoConfig['external-controller']
const secret = controledMihomoConfig.secret ?? ''
let server = getControledMihomoConfig()['external-controller']
const secret = getControledMihomoConfig().secret ?? ''
if (server?.startsWith(':')) server = `127.0.0.1${server}`

mihomoTrafficWs = new WebSocket(`ws://${server}/traffic?secret=${secret}`)
Expand Down
17 changes: 11 additions & 6 deletions src/main/core/tray.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { appConfig, controledMihomoConfig, setAppConfig, setControledMihomoConfig } from '../config'
import {
getAppConfig,
getControledMihomoConfig,
setAppConfig,
setControledMihomoConfig
} from '../config'
import icoIcon from '../../../resources/icon.ico?asset'
import pngIcon from '../../../resources/icon.png?asset'
import { patchMihomoConfig } from './mihomoApi'
Expand All @@ -24,7 +29,7 @@ const buildContextMenu = (): Menu => {
id: 'rule',
label: '规则模式',
type: 'radio',
checked: controledMihomoConfig.mode === 'rule',
checked: getControledMihomoConfig().mode === 'rule',
click: (): void => {
setControledMihomoConfig({ mode: 'rule' })
patchMihomoConfig({ mode: 'rule' })
Expand All @@ -36,7 +41,7 @@ const buildContextMenu = (): Menu => {
id: 'global',
label: '全局模式',
type: 'radio',
checked: controledMihomoConfig.mode === 'global',
checked: getControledMihomoConfig().mode === 'global',
click: (): void => {
setControledMihomoConfig({ mode: 'global' })
patchMihomoConfig({ mode: 'global' })
Expand All @@ -48,7 +53,7 @@ const buildContextMenu = (): Menu => {
id: 'direct',
label: '直连模式',
type: 'radio',
checked: controledMihomoConfig.mode === 'direct',
checked: getControledMihomoConfig().mode === 'direct',
click: (): void => {
setControledMihomoConfig({ mode: 'direct' })
patchMihomoConfig({ mode: 'direct' })
Expand All @@ -60,7 +65,7 @@ const buildContextMenu = (): Menu => {
{
type: 'checkbox',
label: '系统代理',
checked: appConfig.sysProxy?.enable ?? false,
checked: getAppConfig().sysProxy?.enable ?? false,
click: (item): void => {
const enable = item.checked
setAppConfig({ sysProxy: { enable } })
Expand All @@ -72,7 +77,7 @@ const buildContextMenu = (): Menu => {
{
type: 'checkbox',
label: '虚拟网卡',
checked: controledMihomoConfig.tun?.enable ?? false,
checked: getControledMihomoConfig().tun?.enable ?? false,
click: (item): void => {
const enable = item.checked
setControledMihomoConfig({ tun: { enable } })
Expand Down
4 changes: 2 additions & 2 deletions src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import icon from '../../resources/icon.png?asset'
import { mihomoTraffic } from './core/mihomoApi'
import { createTray } from './core/tray'
import { init } from './resolve/init'
import { appConfig } from './config'
import { getAppConfig } from './config'
import { join } from 'path'

export let window: BrowserWindow | null = null
Expand Down Expand Up @@ -80,7 +80,7 @@ function createWindow(): void {
})

window.on('ready-to-show', () => {
if (!appConfig.silentStart) {
if (!getAppConfig().silentStart) {
window?.show()
window?.focusOnWebView()
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/resolve/factory.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { controledMihomoConfig, currentProfile } from '../config'
import { getControledMihomoConfig, getCurrentProfile } from '../config'
import { mihomoWorkConfigPath } from '../utils/dirs'
import yaml from 'yaml'
import fs from 'fs'

export function generateProfile(): void {
const profile = Object.assign(currentProfile, controledMihomoConfig)
const profile = Object.assign(getCurrentProfile(), getControledMihomoConfig())
fs.writeFileSync(mihomoWorkConfigPath(), yaml.stringify(profile))
}
12 changes: 1 addition & 11 deletions src/main/resolve/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,6 @@ import {
profilesDir,
resourcesFilesDir
} from '../utils/dirs'
import {
getAppConfig,
getControledMihomoConfig,
getCurrentProfile,
getProfileConfig
} from '../config'
import {
defaultConfig,
defaultControledMihomoConfig,
Expand Down Expand Up @@ -53,16 +47,12 @@ function initConfig(): void {
if (!fs.existsSync(controledMihomoConfigPath())) {
fs.writeFileSync(controledMihomoConfigPath(), yaml.stringify(defaultControledMihomoConfig))
}
getAppConfig(true)
getControledMihomoConfig(true)
getProfileConfig(true)
getCurrentProfile(true)
}

function initFiles(): void {
const fileList = ['Country.mmdb', 'geoip.dat', 'geosite.dat']
for (const file of fileList) {
const targetPath = path.join(profilesDir(), file)
const targetPath = path.join(mihomoWorkDir(), file)
const sourcePath = path.join(resourcesFilesDir(), file)
if (!fs.existsSync(targetPath) && fs.existsSync(sourcePath)) {
fs.copyFileSync(sourcePath, targetPath)
Expand Down
4 changes: 2 additions & 2 deletions src/main/resolve/sysproxy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { controledMihomoConfig } from '../config'
import { getControledMihomoConfig } from '../config'

export function triggerSysProxy(enable: boolean): void {
if (enable) {
Expand All @@ -9,7 +9,7 @@ export function triggerSysProxy(enable: boolean): void {
}

export function enableSysProxy(): void {
console.log('enableSysProxy', controledMihomoConfig['mixed-port'])
console.log('enableSysProxy', getControledMihomoConfig()['mixed-port'])
}

export function disableSysProxy(): void {
Expand Down
2 changes: 1 addition & 1 deletion src/main/utils/cmds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export function registerIpcMainHandlers(): void {
ipcMain.handle('mihomoVersion', mihomoVersion)
ipcMain.handle('mihomoConfig', mihomoConfig)
ipcMain.handle('mihomoConnections', mihomoConnections)
ipcMain.handle('mihomeRules', mihomoRules)
ipcMain.handle('mihomoRules', mihomoRules)
ipcMain.handle('patchMihomoConfig', async (_e, patch) => await patchMihomoConfig(patch))
ipcMain.handle('checkAutoRun', checkAutoRun)
ipcMain.handle('enableAutoRun', enableAutoRun)
Expand Down
6 changes: 4 additions & 2 deletions src/renderer/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import OverrideCard from '@renderer/components/sider/override-card'
import ConnCard from '@renderer/components/sider/conn-card'
import LogCard from '@renderer/components/sider/log-card'
import MihomoCoreCard from './components/sider/mihomo-core-card.tsx'
import TestCard from './components/sider/test-card.js'

const App: React.FC = () => {
const { setTheme } = useTheme()
Expand Down Expand Up @@ -74,14 +75,15 @@ const App: React.FC = () => {
<ProfileCard />
<ProxyCard />
<MihomoCoreCard />
<ConnCard />
</div>

<div className="flex justify-between mx-2">
<ConnCard />
<LogCard />
<RuleCard />
</div>
<div className="flex justify-between mx-2">
<RuleCard />
<TestCard />
<OverrideCard />
</div>
{/* </div> */}
Expand Down
Loading

0 comments on commit e11a98b

Please sign in to comment.