mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2025-12-27 13:10:30 +08:00
102 lines
2.9 KiB
TypeScript
102 lines
2.9 KiB
TypeScript
import {
|
|
getControledMihomoConfig,
|
|
getProfileConfig,
|
|
getProfile,
|
|
getProfileItem,
|
|
getOverride,
|
|
getOverrideItem
|
|
} from '../config'
|
|
import { mihomoWorkConfigPath, overridePath } from '../utils/dirs'
|
|
import yaml from 'yaml'
|
|
import { readFile, writeFile } from 'fs/promises'
|
|
import { deepMerge } from '../utils/merge'
|
|
import vm from 'vm'
|
|
import { writeFileSync } from 'fs'
|
|
|
|
export async function generateProfile(): Promise<void> {
|
|
const { current } = await getProfileConfig()
|
|
const currentProfile = await overrideProfile(current, await getProfile(current))
|
|
const controledMihomoConfig = await getControledMihomoConfig()
|
|
const profile = deepMerge(currentProfile, controledMihomoConfig)
|
|
await writeFile(mihomoWorkConfigPath(), yaml.stringify(profile))
|
|
}
|
|
|
|
async function overrideProfile(
|
|
current: string | undefined,
|
|
profile: IMihomoConfig
|
|
): Promise<IMihomoConfig> {
|
|
const { override = [] } = (await getProfileItem(current)) || {}
|
|
for (const ov of override) {
|
|
const item = await getOverrideItem(ov)
|
|
const content = await getOverride(ov, item?.ext || 'js')
|
|
switch (item?.ext) {
|
|
case 'js':
|
|
profile = runOverrideScript(profile, content, item)
|
|
break
|
|
case 'yaml': {
|
|
const patch = yaml.parse(content)
|
|
if (patch.rules) {
|
|
patch.rules = [...patch.rules, ...(profile.rules || [])]
|
|
}
|
|
if (patch.proxies) {
|
|
patch.proxies = [...patch.proxies, ...(profile.proxies || [])]
|
|
}
|
|
profile = deepMerge(profile, patch)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return profile
|
|
}
|
|
|
|
function runOverrideScript(
|
|
profile: IMihomoConfig,
|
|
script: string,
|
|
item: IOverrideItem
|
|
): IMihomoConfig {
|
|
const log = (type: string, data: string, flag = 'a'): void => {
|
|
writeFileSync(overridePath(item.id, 'log'), `[${type}] ${data}\n`, {
|
|
encoding: 'utf-8',
|
|
flag
|
|
})
|
|
}
|
|
try {
|
|
const ctx = {
|
|
console: Object.freeze({
|
|
log(data: never) {
|
|
log('log', JSON.stringify(data))
|
|
},
|
|
info(data: never) {
|
|
log('info', JSON.stringify(data))
|
|
},
|
|
error(data: never) {
|
|
log('error', JSON.stringify(data))
|
|
},
|
|
debug(data: never) {
|
|
log('debug', JSON.stringify(data))
|
|
}
|
|
})
|
|
}
|
|
vm.createContext(ctx)
|
|
const code = `${script} main(${JSON.stringify(profile)})`
|
|
log('info', '开始执行脚本', 'w')
|
|
const newProfile = vm.runInContext(code, ctx)
|
|
if (typeof newProfile !== 'object') {
|
|
throw new Error('脚本返回值必须是对象')
|
|
}
|
|
log('info', '脚本执行成功')
|
|
return newProfile
|
|
} catch (e) {
|
|
log('exception', `脚本执行失败: ${e}`)
|
|
return profile
|
|
}
|
|
}
|
|
|
|
export async function getRuntimeConfigStr(): Promise<string> {
|
|
return await readFile(mihomoWorkConfigPath(), 'utf8')
|
|
}
|
|
|
|
export async function getRuntimeConfig(): Promise<IMihomoConfig> {
|
|
return yaml.parse(await getRuntimeConfigStr())
|
|
}
|