feat: добавлены функции для работы с пользовательскими rule-sets
Добавлены новые API-методы для получения и сохранения пользовательских rule-sets. Обновлены компоненты для работы с этими данными, включая интерфейс для добавления и удаления rule-sets. Refs: None
This commit is contained in:
@@ -33,25 +33,50 @@ function findOutbound(subscriptionConfig, selectedTag) {
|
||||
);
|
||||
}
|
||||
|
||||
function ruleSets() {
|
||||
if (!settings.routingRuDirect) return [];
|
||||
function readCustomRuleSets() {
|
||||
try {
|
||||
if (!fs.existsSync(settings.customRuleSetsPath)) return [];
|
||||
const data = JSON.parse(fs.readFileSync(settings.customRuleSetsPath, "utf8"));
|
||||
return Array.isArray(data) ? data : [];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
function ruleSets(customRuleSets = []) {
|
||||
const builtIn = settings.routingRuDirect
|
||||
? [
|
||||
{
|
||||
type: "remote",
|
||||
tag: "geoip-ru",
|
||||
format: "binary",
|
||||
url: "https://cdn.jsdelivr.net/gh/SagerNet/sing-geoip@rule-set/geoip-ru.srs",
|
||||
download_detour: "direct",
|
||||
},
|
||||
{
|
||||
type: "remote",
|
||||
tag: "geosite-category-ru",
|
||||
format: "binary",
|
||||
url: "https://cdn.jsdelivr.net/gh/SagerNet/sing-geosite@rule-set/geosite-category-ru.srs",
|
||||
download_detour: "direct",
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
const custom = (Array.isArray(customRuleSets) ? customRuleSets : [])
|
||||
.filter((rs) => rs.tag && rs.url)
|
||||
.map((rs) => ({
|
||||
type: "remote",
|
||||
tag: "geoip-ru",
|
||||
format: "binary",
|
||||
url: "https://cdn.jsdelivr.net/gh/SagerNet/sing-geoip@rule-set/geoip-ru.srs",
|
||||
tag: String(rs.tag).trim(),
|
||||
format: rs.format || "binary",
|
||||
url: String(rs.url).trim(),
|
||||
download_detour: "direct",
|
||||
},
|
||||
{
|
||||
type: "remote",
|
||||
tag: "geosite-category-ru",
|
||||
format: "binary",
|
||||
url: "https://cdn.jsdelivr.net/gh/SagerNet/sing-geosite@rule-set/geosite-category-ru.srs",
|
||||
download_detour: "direct",
|
||||
},
|
||||
];
|
||||
}));
|
||||
|
||||
// Пользовательские rule-sets не должны дублировать встроенные
|
||||
const builtInTags = new Set(builtIn.map((rs) => rs.tag));
|
||||
const merged = [...builtIn, ...custom.filter((rs) => !builtInTags.has(rs.tag))];
|
||||
return merged;
|
||||
}
|
||||
|
||||
function uniqueClean(values) {
|
||||
@@ -91,13 +116,17 @@ function toSingboxRule(customRule, vpnTag) {
|
||||
if (ports.length) rule.port = ports;
|
||||
if (networks.length) rule.network = networks;
|
||||
|
||||
const ruleSetsRef = uniqueClean(customRule.ruleSets);
|
||||
if (ruleSetsRef.length) rule.rule_set = ruleSetsRef;
|
||||
|
||||
if (
|
||||
!rule.domain &&
|
||||
!rule.domain_suffix &&
|
||||
!rule.domain_keyword &&
|
||||
!rule.ip_cidr &&
|
||||
!rule.port &&
|
||||
!rule.network
|
||||
!rule.network &&
|
||||
!rule.rule_set
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
@@ -144,6 +173,8 @@ export function buildGatewayConfig(subscriptionConfig, selectedTag) {
|
||||
vpnOutbound.packet_encoding = "xudp";
|
||||
}
|
||||
|
||||
const customRuleSets = readCustomRuleSets();
|
||||
|
||||
return {
|
||||
log: {
|
||||
level: settings.logLevel,
|
||||
@@ -182,7 +213,7 @@ export function buildGatewayConfig(subscriptionConfig, selectedTag) {
|
||||
{ type: "block", tag: "block" },
|
||||
],
|
||||
route: {
|
||||
rule_set: ruleSets(),
|
||||
rule_set: ruleSets(customRuleSets),
|
||||
rules: routeRules(subscriptionConfig.customRules, vpnOutbound.tag),
|
||||
final: vpnOutbound.tag,
|
||||
auto_detect_interface: true,
|
||||
|
||||
Reference in New Issue
Block a user