Skip to content

Commit

Permalink
refactor: ruleset & rule-provider
Browse files Browse the repository at this point in the history
  • Loading branch information
Ayideyia committed Sep 22, 2024
1 parent 3eaa681 commit 900a275
Show file tree
Hide file tree
Showing 7 changed files with 230 additions and 57 deletions.
88 changes: 66 additions & 22 deletions frontend/src/constant/profile.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import i18n from '@/lang'
import { sampleID } from '@/utils'
import { ProxyGroup } from '@/constant'
import { ProxyGroup, RulesetBehavior, RulesetFormat } from '@/constant'
import type { ProfileType } from '@/stores'

const { t } = i18n.global
Expand Down Expand Up @@ -34,7 +34,7 @@ export const AdvancedConfigDefaults = (): ProfileType['advancedConfig'] => ({
'private-key': ''
},
'global-client-fingerprint': 'chrome',
'geodata-mode': true,
'geodata-mode': false,
'geo-auto-update': false,
'geo-update-interval': 24,
'geodata-loader': 'standard',
Expand Down Expand Up @@ -209,56 +209,100 @@ export const RulesConfigDefaults = (ids: string[]): ProfileType['rulesConfig'] =
type: 'LOGIC',
payload: 'AND,((DST-PORT,443),(NETWORK,udp))',
proxy: ids[3],
'no-resolve': false
'no-resolve': false,
'ruleset-name': '',
'ruleset-type': 'file',
'ruleset-behavior': RulesetBehavior.Domain,
'ruleset-format': RulesetFormat.Mrs,
'ruleset-proxy': ids[2]
},
{
id: sampleID(),
type: 'GEOSITE',
payload: 'category-ads-all',
type: 'RULE-SET',
payload:
'https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@meta/geo/geosite/category-ads-all.mrs',
proxy: ids[3],
'no-resolve': false
'no-resolve': false,
'ruleset-name': 'category-ads-all',
'ruleset-type': 'http',
'ruleset-behavior': RulesetBehavior.Domain,
'ruleset-format': RulesetFormat.Mrs,
'ruleset-proxy': ids[2]
},
{
id: sampleID(),
type: 'GEOIP',
payload: 'private',
type: 'RULE-SET',
payload:
'https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@meta/geo/geoip/private.mrs',
proxy: ids[2],
'no-resolve': true
'no-resolve': true,
'ruleset-name': 'GEOIP-Private',
'ruleset-type': 'http',
'ruleset-behavior': RulesetBehavior.Ipcidr,
'ruleset-format': RulesetFormat.Mrs,
'ruleset-proxy': ids[2]
},
{
id: sampleID(),
type: 'GEOIP',
payload: 'CN',
type: 'RULE-SET',
payload: 'https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@meta/geo/geoip/cn.mrs',
proxy: ids[2],
'no-resolve': true
'no-resolve': true,
'ruleset-name': 'GEOIP-CN',
'ruleset-type': 'http',
'ruleset-behavior': RulesetBehavior.Ipcidr,
'ruleset-format': RulesetFormat.Mrs,
'ruleset-proxy': ids[2]
},
{
id: sampleID(),
type: 'GEOSITE',
payload: 'private',
type: 'RULE-SET',
payload:
'https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@meta/geo/geosite/private.mrs',
proxy: ids[2],
'no-resolve': false
'no-resolve': false,
'ruleset-name': 'GEOSITE-Private',
'ruleset-type': 'http',
'ruleset-behavior': RulesetBehavior.Domain,
'ruleset-format': RulesetFormat.Mrs,
'ruleset-proxy': ids[2]
},
{
id: sampleID(),
type: 'GEOSITE',
payload: 'CN',
type: 'RULE-SET',
payload: 'https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@meta/geo/geosite/cn.mrs',
proxy: ids[2],
'no-resolve': false
'no-resolve': false,
'ruleset-name': 'GEOSITE-CN',
'ruleset-type': 'http',
'ruleset-behavior': RulesetBehavior.Domain,
'ruleset-format': RulesetFormat.Mrs,
'ruleset-proxy': ids[2]
},
{
id: sampleID(),
type: 'GEOSITE',
payload: 'geolocation-!cn',
type: 'RULE-SET',
payload:
'https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@meta/geo/geosite/geolocation-!cn.mrs',
proxy: ids[0],
'no-resolve': false
'no-resolve': false,
'ruleset-name': 'geolocation-!cn',
'ruleset-type': 'http',
'ruleset-behavior': RulesetBehavior.Domain,
'ruleset-format': RulesetFormat.Mrs,
'ruleset-proxy': ids[2]
},
{
id: sampleID(),
type: 'MATCH',
payload: '',
proxy: ids[4],
'no-resolve': false
'no-resolve': false,
'ruleset-name': '',
'ruleset-type': 'file',
'ruleset-behavior': RulesetBehavior.Domain,
'ruleset-format': RulesetFormat.Mrs,
'ruleset-proxy': ids[2]
}
]

Expand Down
3 changes: 3 additions & 0 deletions frontend/src/lang/locale/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ export default {
'no-resolve': 'No Resolve',
ruleset: 'RuleSet',
rulesets: 'RuleSets',
'rule-set-type': 'RuleSet Type',
'ruleset-name': 'Name',
'ruleset-proxy': 'Proxy',
needGeodataMode: 'Please enable the "geodata-mode" option in the advanced settings',
notFound: 'proxy group does not exist',
empty: 'Ruleset list is empty',
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/lang/locale/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ export default {
'no-resolve': '跳过DNS解析',
ruleset: '规则集',
rulesets: '规则集列表',
'rule-set-type': '规则集类型',
'ruleset-name': '名称',
'ruleset-proxy': '下载方式',
needGeodataMode: '请在高级设置中打开"GEO数据模式"',
notFound: '策略组不存在',
empty: '规则集列表为空',
Expand Down
23 changes: 17 additions & 6 deletions frontend/src/stores/profiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import {
ProfilesFilePath,
ProxyGroup,
MixinConfigDefaults,
ScriptConfigDefaults
ScriptConfigDefaults,
RulesetBehavior,
RulesetFormat
} from '@/constant'

export type ProfileType = {
Expand Down Expand Up @@ -126,6 +128,11 @@ export type ProfileType = {
payload: string
proxy: string
'no-resolve': boolean
'ruleset-type': 'file' | 'http'
'ruleset-name': string
'ruleset-behavior': RulesetBehavior
'ruleset-format': RulesetFormat
'ruleset-proxy': string
}[]
mixinConfig: {
priority: 'mixin' | 'gui'
Expand All @@ -144,11 +151,15 @@ export const useProfilesStore = defineStore('profiles', () => {
data && (profiles.value = parse(data))
// compatibility code
profiles.value.forEach((profile) => {
profile.dnsConfig.hosts = profile.dnsConfig.hosts ?? {}
profile.tunConfig['route-address'] =
profile.tunConfig['route-address'] ?? TunConfigDefaults()['route-address']
profile.mixinConfig = profile.mixinConfig ?? MixinConfigDefaults()
profile.scriptConfig = profile.scriptConfig ?? ScriptConfigDefaults()
profile.rulesConfig.forEach((rule) => {
if (!rule['ruleset-type']) {
rule['ruleset-type'] = 'file'
rule['ruleset-name'] = ''
rule['ruleset-behavior'] = RulesetBehavior.Domain
rule['ruleset-format'] = RulesetFormat.Yaml
rule['ruleset-proxy'] = ''
}
})
})
}

Expand Down
72 changes: 51 additions & 21 deletions frontend/src/utils/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,26 @@ export const generateRule = (
rule: ProfileType['rulesConfig'][0],
proxyGruoups?: ProfileType['proxyGroupsConfig']
) => {
const { type, payload, proxy, 'no-resolve': noResolve } = rule
const {
type,
payload,
proxy,
'no-resolve': noResolve,
'ruleset-type': rulesetType,
'ruleset-name': rulesetName
} = rule
let ruleStr = type
let proxyStr = proxy
if (type !== 'MATCH') {
if (type === 'RULE-SET') {
const rulesetsStore = useRulesetsStore()
const ruleset = rulesetsStore.getRulesetById(payload)
if (ruleset) {
ruleStr += ',' + ruleset.name
if (rulesetType === 'file') {
const rulesetsStore = useRulesetsStore()
const ruleset = rulesetsStore.getRulesetById(payload)
if (ruleset) {
ruleStr += ',' + ruleset.name
}
} else if (rulesetType === 'http') {
ruleStr += ',' + rulesetName
}
} else if (type === 'LOGIC') {
ruleStr = payload
Expand Down Expand Up @@ -202,24 +213,14 @@ export const generateProxyProviders = async (groups: ProfileType['proxyGroupsCon

const generateRuleProviders = async (
dns: ProfileType['dnsConfig'],
rules: ProfileType['rulesConfig']
rules: ProfileType['rulesConfig'],
proxyGruoups: ProfileType['proxyGroupsConfig']
) => {
const rulesetsStore = useRulesetsStore()
const providers: Record<string, any> = {}
const rulesetList: string[] = []

rulesetList.push(...rules.flatMap((rule) => (rule.type === 'RULE-SET' ? rule.payload : [])))
rulesetList.push(
...dns['fake-ip-filter'].filter((v) => v.startsWith('rule-set:')).map((v) => v.substring(9))
)
rulesetList.push(
...Object.keys(dns['nameserver-policy']).flatMap((key) =>
key.startsWith('rule-set:') ? key.substring(9).split(',') : []
)
)

rulesetList.forEach((rule) => {
const ruleset = rulesetsStore.getRulesetById(rule) || rulesetsStore.getRulesetByName(rule)
function appendLocalProvider(name: string) {
const ruleset = rulesetsStore.getRulesetById(name) || rulesetsStore.getRulesetByName(name)
if (ruleset) {
providers[ruleset.name] = {
type: 'file',
Expand All @@ -228,7 +229,32 @@ const generateRuleProviders = async (
format: ruleset.format
}
}
})
}

rules
.filter((rule) => rule.type === 'RULE-SET')
.forEach((rule) => {
if (rule['ruleset-type'] === 'file') {
appendLocalProvider(rule.payload)
} else {
const group = proxyGruoups.find((v) => v.id === rule['ruleset-proxy'])
providers[rule['ruleset-name']] = {
type: 'http',
url: rule.payload,
behavior: rule['ruleset-behavior'],
format: rule['ruleset-format'],
proxy: group?.name || 'DIRECT'
}
}
})

const l1 = dns['fake-ip-filter'].flatMap((v) => (v.startsWith('rule-set:') ? v.substring(9) : []))
const l2 = Object.keys(dns['nameserver-policy']).flatMap((key) =>
key.startsWith('rule-set:') ? key.substring(9).split(',') : []
)

l1.concat(l2).forEach((name) => appendLocalProvider(name))

return providers
}

Expand Down Expand Up @@ -285,7 +311,11 @@ export const generateConfig = async (originalProfile: ProfileType) => {

config['proxy-providers'] = await generateProxyProviders(profile.proxyGroupsConfig)

config['rule-providers'] = await generateRuleProviders(profile.dnsConfig, profile.rulesConfig)
config['rule-providers'] = await generateRuleProviders(
profile.dnsConfig,
profile.rulesConfig,
profile.proxyGroupsConfig
)

config['proxies'] = await generateProxies(profile.proxyGroupsConfig)

Expand Down
37 changes: 34 additions & 3 deletions frontend/src/utils/restorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import {
GeneralConfigDefaults,
TunConfigDefaults,
MixinConfigDefaults,
ScriptConfigDefaults
ScriptConfigDefaults,
RulesetBehavior,
RulesetFormat
} from '@/constant'

export const restoreProfile = (
Expand All @@ -32,6 +34,9 @@ export const restoreProfile = (
const GroupNameIdMap: Record<string, string> = {}
const GroupIdNameMap: Record<string, string> = {}

config['proxy-groups'] = config['proxy-groups'] || []
config['rule-providers'] = config['rule-providers'] || {}

config['proxy-groups'].forEach((group: any) => {
const id = sampleID()
GroupNameIdMap[group.name] = id
Expand All @@ -43,7 +48,7 @@ export const restoreProfile = (
}

config['proxy-groups'].forEach((group: any) => {
const _group = {
const _group: ProfileType['proxyGroupsConfig'][number] = {
id: GroupNameIdMap[group.name],
name: group.name,
type: group.type,
Expand Down Expand Up @@ -109,12 +114,38 @@ export const restoreProfile = (
return
}

if (type === 'RULE-SET') {
const provider = config['rule-providers'][payload]
// Skip invalid rules:rule-provider missing
if (!provider) {
return
}
profile.rulesConfig.push({
id: index.toString(),
type: type,
payload: provider.url,
proxy: _proxy,
'no-resolve': !!noResolve,
'ruleset-behavior': provider.behavior,
'ruleset-format': provider.format || RulesetFormat.Yaml,
'ruleset-type': 'http',
'ruleset-name': payload,
'ruleset-proxy': 'DIRECT'
})
return
}

profile.rulesConfig.push({
id: index.toString(),
type: type,
payload: type === 'MATCH' ? '' : payload,
proxy: _proxy,
'no-resolve': !!noResolve
'no-resolve': !!noResolve,
'ruleset-behavior': RulesetBehavior.Domain,
'ruleset-format': RulesetFormat.Mrs,
'ruleset-type': 'http',
'ruleset-name': '',
'ruleset-proxy': ''
})
})
}
Expand Down
Loading

0 comments on commit 900a275

Please sign in to comment.