mirror of
https://github.com/pompurin404/mihomo-party.git
synced 2024-11-16 11:42:19 +08:00
geo data config
This commit is contained in:
parent
afaeea2aac
commit
db6804e25a
|
@ -238,8 +238,8 @@ async function downloadFile(url, path) {
|
|||
|
||||
const resolveMmdb = () =>
|
||||
resolveResource({
|
||||
file: 'Country.mmdb',
|
||||
downloadURL: `https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/country.mmdb`
|
||||
file: 'country.mmdb',
|
||||
downloadURL: `https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/country-lite.mmdb`
|
||||
})
|
||||
const resolveGeosite = () =>
|
||||
resolveResource({
|
||||
|
@ -249,7 +249,12 @@ const resolveGeosite = () =>
|
|||
const resolveGeoIP = () =>
|
||||
resolveResource({
|
||||
file: 'geoip.dat',
|
||||
downloadURL: `https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.dat`
|
||||
downloadURL: `https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip-lite.dat`
|
||||
})
|
||||
const resolveASN = () =>
|
||||
resolveResource({
|
||||
file: 'ASN.mmdb',
|
||||
downloadURL: `https://github.com/xishang0128/geoip/releases/download/latest/GeoLite2-ASN.mmdb`
|
||||
})
|
||||
const resolveEnableLoopback = () =>
|
||||
resolveResource({
|
||||
|
@ -285,6 +290,7 @@ const tasks = [
|
|||
{ name: 'mmdb', func: resolveMmdb, retry: 5 },
|
||||
{ name: 'geosite', func: resolveGeosite, retry: 5 },
|
||||
{ name: 'geoip', func: resolveGeoIP, retry: 5 },
|
||||
{ name: 'asn', func: resolveASN, retry: 5 },
|
||||
{
|
||||
name: 'font',
|
||||
func: resolveFont,
|
||||
|
|
|
@ -85,6 +85,13 @@ export const mihomoChangeProxy = async (group: string, proxy: string): Promise<I
|
|||
})) as IMihomoProxy
|
||||
}
|
||||
|
||||
export const mihomoUpgradeGeo = async (): Promise<void> => {
|
||||
const instance = await getAxios()
|
||||
return instance.post('/configs/geo').catch((e) => {
|
||||
return e.response.data
|
||||
})
|
||||
}
|
||||
|
||||
export const mihomoProxyDelay = async (proxy: string, url?: string): Promise<IMihomoDelay> => {
|
||||
const appConfig = getAppConfig()
|
||||
const { delayTestUrl, delayTestTimeout } = appConfig
|
||||
|
|
|
@ -58,7 +58,7 @@ function initConfig(): void {
|
|||
}
|
||||
|
||||
function initFiles(): void {
|
||||
const fileList = ['Country.mmdb', 'geoip.dat', 'geosite.dat']
|
||||
const fileList = ['country.mmdb', 'geoip.dat', 'geosite.dat', 'ASN.mmdb']
|
||||
for (const file of fileList) {
|
||||
const targetPath = path.join(mihomoWorkDir(), file)
|
||||
const testTargrtPath = path.join(mihomoTestDir(), file)
|
||||
|
|
|
@ -6,6 +6,7 @@ import {
|
|||
mihomoProxies,
|
||||
mihomoProxyDelay,
|
||||
mihomoRules,
|
||||
mihomoUpgradeGeo,
|
||||
mihomoVersion,
|
||||
patchMihomoConfig,
|
||||
startMihomoConnections,
|
||||
|
@ -34,6 +35,7 @@ import { triggerSysProxy } from '../resolve/sysproxy'
|
|||
import { checkUpdate } from '../resolve/autoUpdater'
|
||||
import { exePath, mihomoCorePath, mihomoWorkConfigPath } from './dirs'
|
||||
import { execSync } from 'child_process'
|
||||
import yaml from 'yaml'
|
||||
import fs from 'fs'
|
||||
|
||||
export function registerIpcMainHandlers(): void {
|
||||
|
@ -43,6 +45,7 @@ export function registerIpcMainHandlers(): void {
|
|||
ipcMain.handle('mihomoRules', mihomoRules)
|
||||
ipcMain.handle('mihomoProxies', mihomoProxies)
|
||||
ipcMain.handle('mihomoChangeProxy', (_e, group, proxy) => mihomoChangeProxy(group, proxy))
|
||||
ipcMain.handle('mihomoUpgradeGeo', mihomoUpgradeGeo)
|
||||
ipcMain.handle('mihomoProxyDelay', (_e, proxy, url) => mihomoProxyDelay(proxy, url))
|
||||
ipcMain.handle('startMihomoLogs', startMihomoLogs)
|
||||
ipcMain.handle('stopMihomoLogs', stopMihomoLogs)
|
||||
|
@ -71,6 +74,7 @@ export function registerIpcMainHandlers(): void {
|
|||
ipcMain.handle('encryptString', (_e, str) => safeStorage.encryptString(str))
|
||||
ipcMain.handle('getFilePath', getFilePath)
|
||||
ipcMain.handle('readTextFile', (_e, filePath) => readTextFile(filePath))
|
||||
ipcMain.handle('getRuntimeConfigStr', getRuntimeConfigStr)
|
||||
ipcMain.handle('getRuntimeConfig', getRuntimeConfig)
|
||||
ipcMain.handle('checkUpdate', () => checkUpdate())
|
||||
ipcMain.handle('getVersion', () => app.getVersion())
|
||||
|
@ -91,10 +95,14 @@ function readTextFile(filePath: string): string {
|
|||
return fs.readFileSync(filePath, 'utf8')
|
||||
}
|
||||
|
||||
function getRuntimeConfig(): string {
|
||||
function getRuntimeConfigStr(): string {
|
||||
return fs.readFileSync(mihomoWorkConfigPath(), 'utf8')
|
||||
}
|
||||
|
||||
function getRuntimeConfig(): Record<string, unknown> {
|
||||
return yaml.parse(getRuntimeConfigStr())
|
||||
}
|
||||
|
||||
async function setupFirewall(): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const removeCommand = `
|
||||
|
|
|
@ -58,6 +58,15 @@ export const defaultControledMihomoConfig: Partial<IMihomoConfig> = {
|
|||
}
|
||||
},
|
||||
'skip-domain': ['+.push.apple.com']
|
||||
},
|
||||
'geo-auto-update': false,
|
||||
'geo-update-interval': 24,
|
||||
'geodata-mode': false,
|
||||
'geox-url': {
|
||||
geoip: 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip-lite.dat',
|
||||
geosite: 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat',
|
||||
mmdb: 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/country-lite.mmdb',
|
||||
asn: 'https://github.com/xishang0128/geoip/releases/download/latest/GeoLite2-ASN.mmdb'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,9 +15,9 @@ import SniffCard from '@renderer/components/sider/sniff-card'
|
|||
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'
|
||||
import UpdaterButton from './components/updater/updater-button.js'
|
||||
import MihomoCoreCard from '@renderer/components/sider/mihomo-core-card'
|
||||
import ResourceCard from '@renderer/components/sider/resource-card'
|
||||
import UpdaterButton from '@renderer/components/updater/updater-button'
|
||||
|
||||
const App: React.FC = () => {
|
||||
const { setTheme } = useTheme()
|
||||
|
@ -63,9 +63,24 @@ const App: React.FC = () => {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="m-2">
|
||||
<OutboundModeSwitcher />
|
||||
</div>
|
||||
{/* <div className="grid">
|
||||
<SysproxySwitcher />
|
||||
<TunSwitcher />
|
||||
<ProfileCard />
|
||||
<ProxyCard />
|
||||
<MihomoCoreCard />
|
||||
<ConnCard />
|
||||
<DNSCard />
|
||||
<SniffCard />
|
||||
<LogCard />
|
||||
<RuleCard />
|
||||
<TestCard />
|
||||
<OverrideCard />
|
||||
</div> */}
|
||||
<div className="flex justify-between mx-2 mb-2">
|
||||
<SysproxySwitcher />
|
||||
<TunSwitcher />
|
||||
|
@ -86,7 +101,7 @@ const App: React.FC = () => {
|
|||
<RuleCard />
|
||||
</div>
|
||||
<div className="flex justify-between mx-2">
|
||||
<TestCard />
|
||||
<ResourceCard />
|
||||
<OverrideCard />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Button } from
|
|||
import React, { useEffect, useState } from 'react'
|
||||
import MonacoEditor, { monaco } from 'react-monaco-editor'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { getRuntimeConfig } from '@renderer/utils/ipc'
|
||||
import { getRuntimeConfigStr } from '@renderer/utils/ipc'
|
||||
interface Props {
|
||||
onClose: () => void
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ const ConfigViewer: React.FC<Props> = (props) => {
|
|||
}
|
||||
|
||||
const getContent = async (): Promise<void> => {
|
||||
setCurrData(await getRuntimeConfig())
|
||||
setCurrData(await getRuntimeConfigStr())
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -46,7 +46,7 @@ const ProfileCard: React.FC = () => {
|
|||
>
|
||||
{info?.name}
|
||||
</h3>
|
||||
<div>
|
||||
<div className="flex">
|
||||
<Button
|
||||
isIconOnly
|
||||
size="sm"
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
|
||||
import React from 'react'
|
||||
import { TbWorldCheck } from 'react-icons/tb'
|
||||
import { FaLayerGroup } from 'react-icons/fa6'
|
||||
import { useLocation, useNavigate } from 'react-router-dom'
|
||||
|
||||
const TestCard: React.FC = () => {
|
||||
const ResourceCard: React.FC = () => {
|
||||
const navigate = useNavigate()
|
||||
const location = useLocation()
|
||||
const match = location.pathname.includes('/tests')
|
||||
const match = location.pathname.includes('/resources')
|
||||
|
||||
return (
|
||||
<Card
|
||||
className={`w-[50%] mr-1 mb-2 ${match ? 'bg-primary' : ''}`}
|
||||
isPressable
|
||||
onPress={() => navigate('/tests')}
|
||||
onPress={() => navigate('/resources')}
|
||||
>
|
||||
<CardBody className="pb-1 pt-0 px-0">
|
||||
<div className="flex justify-between">
|
||||
|
@ -22,7 +22,7 @@ const TestCard: React.FC = () => {
|
|||
variant="flat"
|
||||
color="default"
|
||||
>
|
||||
<TbWorldCheck
|
||||
<FaLayerGroup
|
||||
color="default"
|
||||
className={`${match ? 'text-white' : 'text-foreground'} text-[24px] font-bold`}
|
||||
/>
|
||||
|
@ -31,11 +31,11 @@ const TestCard: React.FC = () => {
|
|||
</CardBody>
|
||||
<CardFooter className="pt-1">
|
||||
<h3 className={`select-none text-md font-bold ${match ? 'text-white' : 'text-foreground'}`}>
|
||||
测试
|
||||
外部资源
|
||||
</h3>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default TestCard
|
||||
export default ResourceCard
|
163
src/renderer/src/pages/resources.tsx
Normal file
163
src/renderer/src/pages/resources.tsx
Normal file
|
@ -0,0 +1,163 @@
|
|||
import { Button, Input, Switch, Tab, Tabs } from '@nextui-org/react'
|
||||
import BasePage from '@renderer/components/base/base-page'
|
||||
import SettingCard from '@renderer/components/base/base-setting-card'
|
||||
import SettingItem from '@renderer/components/base/base-setting-item'
|
||||
import { useControledMihomoConfig } from '@renderer/hooks/use-controled-mihomo-config'
|
||||
import { mihomoUpgradeGeo } from '@renderer/utils/ipc'
|
||||
import { useState } from 'react'
|
||||
import { IoMdRefresh } from 'react-icons/io'
|
||||
|
||||
const Resources: React.FC = () => {
|
||||
const { controledMihomoConfig, patchControledMihomoConfig } = useControledMihomoConfig()
|
||||
const {
|
||||
'geox-url': geoxUrl = {
|
||||
geoip: 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip-lite.dat',
|
||||
geosite: 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat',
|
||||
mmdb: 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/country-lite.mmdb',
|
||||
asn: 'https://github.com/xishang0128/geoip/releases/download/latest/GeoLite2-ASN.mmdb'
|
||||
},
|
||||
'geodata-mode': geoMode = false,
|
||||
'geo-auto-update': geoAutoUpdate = false,
|
||||
'geo-update-interval': geoUpdateInterval = 24
|
||||
} = controledMihomoConfig || {}
|
||||
const [geoipInput, setGeoIpInput] = useState(geoxUrl.geoip)
|
||||
const [geositeInput, setGeositeInput] = useState(geoxUrl.geosite)
|
||||
const [mmdbInput, setMmdbInput] = useState(geoxUrl.mmdb)
|
||||
const [asnInput, setAsnInput] = useState(geoxUrl.asn)
|
||||
const [updating, setUpdating] = useState(false)
|
||||
|
||||
return (
|
||||
<BasePage title="外部资源">
|
||||
<SettingCard>
|
||||
<SettingItem title="GeoIP 数据库" divider>
|
||||
<div className="flex">
|
||||
{geoipInput !== geoxUrl.geoip && (
|
||||
<Button
|
||||
size="sm"
|
||||
color="primary"
|
||||
className="mr-2"
|
||||
onPress={() => {
|
||||
patchControledMihomoConfig({ 'geox-url': { ...geoxUrl, geoip: geoipInput } })
|
||||
}}
|
||||
>
|
||||
确认
|
||||
</Button>
|
||||
)}
|
||||
<Input size="sm" value={geoipInput} onValueChange={setGeoIpInput} />
|
||||
</div>
|
||||
</SettingItem>
|
||||
<SettingItem title="GeoSite 数据库" divider>
|
||||
<div className="flex">
|
||||
{geositeInput !== geoxUrl.geosite && (
|
||||
<Button
|
||||
size="sm"
|
||||
color="primary"
|
||||
className="mr-2"
|
||||
onPress={() => {
|
||||
patchControledMihomoConfig({ 'geox-url': { ...geoxUrl, geosite: geositeInput } })
|
||||
}}
|
||||
>
|
||||
确认
|
||||
</Button>
|
||||
)}
|
||||
<Input size="sm" value={geositeInput} onValueChange={setGeositeInput} />
|
||||
</div>
|
||||
</SettingItem>
|
||||
<SettingItem title="MMDB 数据库" divider>
|
||||
<div className="flex">
|
||||
{mmdbInput !== geoxUrl.mmdb && (
|
||||
<Button
|
||||
size="sm"
|
||||
color="primary"
|
||||
className="mr-2"
|
||||
onPress={() => {
|
||||
patchControledMihomoConfig({ 'geox-url': { ...geoxUrl, mmdb: mmdbInput } })
|
||||
}}
|
||||
>
|
||||
确认
|
||||
</Button>
|
||||
)}
|
||||
<Input size="sm" value={mmdbInput} onValueChange={setMmdbInput} />
|
||||
</div>
|
||||
</SettingItem>
|
||||
<SettingItem title="ASN 数据库" divider>
|
||||
<div className="flex">
|
||||
{asnInput !== geoxUrl.asn && (
|
||||
<Button
|
||||
size="sm"
|
||||
color="primary"
|
||||
className="mr-2"
|
||||
onPress={() => {
|
||||
patchControledMihomoConfig({ 'geox-url': { ...geoxUrl, asn: asnInput } })
|
||||
}}
|
||||
>
|
||||
确认
|
||||
</Button>
|
||||
)}
|
||||
<Input size="sm" value={asnInput} onValueChange={setAsnInput} />
|
||||
</div>
|
||||
</SettingItem>
|
||||
<SettingItem title="GeoIP 数据模式" divider>
|
||||
<Tabs
|
||||
size="sm"
|
||||
color="primary"
|
||||
selectedKey={geoMode ? 'dat' : 'db'}
|
||||
onSelectionChange={(key) => {
|
||||
patchControledMihomoConfig({ 'geodata-mode': key === 'dat' })
|
||||
}}
|
||||
>
|
||||
<Tab key="db" title="db" />
|
||||
<Tab key="dat" title="dat" />
|
||||
</Tabs>
|
||||
</SettingItem>
|
||||
<SettingItem
|
||||
title="自动更新 Geo 数据库"
|
||||
actions={
|
||||
<Button
|
||||
size="sm"
|
||||
isIconOnly
|
||||
variant="light"
|
||||
onPress={() => {
|
||||
setUpdating(true)
|
||||
mihomoUpgradeGeo()
|
||||
.catch((e) => {
|
||||
new Notification('更新失败', { body: e.message })
|
||||
})
|
||||
.finally(() => {
|
||||
new Notification('Geo 数据库更新成功')
|
||||
setUpdating(false)
|
||||
})
|
||||
}}
|
||||
>
|
||||
<IoMdRefresh className={`text-lg ${updating ? 'animate-spin' : ''}`} />
|
||||
</Button>
|
||||
}
|
||||
divider={geoAutoUpdate}
|
||||
>
|
||||
<Switch
|
||||
size="sm"
|
||||
isSelected={geoAutoUpdate}
|
||||
onValueChange={(v) => {
|
||||
patchControledMihomoConfig({ 'geo-auto-update': v })
|
||||
}}
|
||||
/>
|
||||
</SettingItem>
|
||||
{geoAutoUpdate && (
|
||||
<SettingItem title="更新间隔(小时)">
|
||||
<Input
|
||||
size="sm"
|
||||
type="number"
|
||||
className="w-[100px]"
|
||||
value={geoUpdateInterval.toString()}
|
||||
onValueChange={(v) => {
|
||||
patchControledMihomoConfig({ 'geo-update-interval': parseInt(v) })
|
||||
}}
|
||||
/>
|
||||
</SettingItem>
|
||||
)}
|
||||
</SettingCard>
|
||||
</BasePage>
|
||||
)
|
||||
}
|
||||
|
||||
export default Resources
|
|
@ -1,7 +0,0 @@
|
|||
import BasePage from '@renderer/components/base/base-page'
|
||||
|
||||
const Tests: React.FC = () => {
|
||||
return <BasePage title="测试"></BasePage>
|
||||
}
|
||||
|
||||
export default Tests
|
|
@ -9,7 +9,7 @@ import Connections from '@renderer/pages/connections'
|
|||
import Mihomo from '@renderer/pages/mihomo'
|
||||
import Sysproxy from '@renderer/pages/syspeoxy'
|
||||
import Tun from '@renderer/pages/tun'
|
||||
import Tests from '@renderer/pages/tests'
|
||||
import Resources from '@renderer/pages/resources'
|
||||
import DNS from '@renderer/pages/dns'
|
||||
import Sniffer from '@renderer/pages/sniffer'
|
||||
|
||||
|
@ -35,8 +35,8 @@ const routes = [
|
|||
element: <Rules />
|
||||
},
|
||||
{
|
||||
path: '/tests',
|
||||
element: <Tests />
|
||||
path: '/resources',
|
||||
element: <Resources />
|
||||
},
|
||||
{
|
||||
path: '/dns',
|
||||
|
|
|
@ -22,6 +22,10 @@ export async function mihomoChangeProxy(group: string, proxy: string): Promise<I
|
|||
return await window.electron.ipcRenderer.invoke('mihomoChangeProxy', group, proxy)
|
||||
}
|
||||
|
||||
export async function mihomoUpgradeGeo(): Promise<void> {
|
||||
return await window.electron.ipcRenderer.invoke('mihomoUpgradeGeo')
|
||||
}
|
||||
|
||||
export async function mihomoProxyDelay(proxy: string, url?: string): Promise<IMihomoDelay> {
|
||||
const res = await window.electron.ipcRenderer.invoke('mihomoProxyDelay', proxy, url)
|
||||
return res
|
||||
|
@ -135,7 +139,11 @@ export async function readTextFile(filePath: string): Promise<string> {
|
|||
return await window.electron.ipcRenderer.invoke('readTextFile', filePath)
|
||||
}
|
||||
|
||||
export async function getRuntimeConfig(): Promise<string> {
|
||||
export async function getRuntimeConfigStr(): Promise<string> {
|
||||
return await window.electron.ipcRenderer.invoke('getRuntimeConfigStr')
|
||||
}
|
||||
|
||||
export async function getRuntimeConfig(): Promise<IMihomoConfig> {
|
||||
return await window.electron.ipcRenderer.invoke('getRuntimeConfig')
|
||||
}
|
||||
|
||||
|
|
9
src/shared/types.d.ts
vendored
9
src/shared/types.d.ts
vendored
|
@ -246,6 +246,15 @@ interface IMihomoConfig {
|
|||
'proxy-groups'?: []
|
||||
rules?: []
|
||||
hosts?: { [key: string]: string | string[] }
|
||||
'geodata-mode'?: boolean
|
||||
'geo-auto-update'?: boolean
|
||||
'geo-update-interval'?: number
|
||||
'geox-url'?: {
|
||||
geoip?: string
|
||||
geosite?: string
|
||||
mmdb?: string
|
||||
asn?: string
|
||||
}
|
||||
tun: IMihomoTunConfig
|
||||
dns: IMihomoDNSConfig
|
||||
sniffer: IMihomoSnifferConfig
|
||||
|
|
Loading…
Reference in New Issue
Block a user