mirror of
https://git.mirrors.martin98.com/https://github.com/sub-store-org/Sub-Store.git
synced 2025-08-11 03:29:03 +08:00
添加一些内置分流
This commit is contained in:
parent
117a920faf
commit
99514f521b
@ -110,7 +110,10 @@ function service() {
|
|||||||
async function downloadSubscription(req, res) {
|
async function downloadSubscription(req, res) {
|
||||||
const {name} = req.params;
|
const {name} = req.params;
|
||||||
const {cache} = req.query;
|
const {cache} = req.query;
|
||||||
const platform = req.query.target || getPlatformFromHeaders(req.headers);
|
const platform = req.query.target || getPlatformFromHeaders(req.headers) || "JSON";
|
||||||
|
|
||||||
|
$.info(`正在下载订阅:${name}`);
|
||||||
|
|
||||||
const allSubs = $.read(SUBS_KEY);
|
const allSubs = $.read(SUBS_KEY);
|
||||||
const sub = allSubs[name];
|
const sub = allSubs[name];
|
||||||
if (sub) {
|
if (sub) {
|
||||||
@ -263,7 +266,7 @@ function service() {
|
|||||||
async function downloadCollection(req, res) {
|
async function downloadCollection(req, res) {
|
||||||
const {name} = req.params;
|
const {name} = req.params;
|
||||||
const {cache} = req.query || "false";
|
const {cache} = req.query || "false";
|
||||||
const platform = req.query.target || getPlatformFromHeaders(req.headers);
|
const platform = req.query.target || getPlatformFromHeaders(req.headers) || "JSON";
|
||||||
|
|
||||||
const allCollections = $.read(COLLECTIONS_KEY);
|
const allCollections = $.read(COLLECTIONS_KEY);
|
||||||
const allSubs = $.read(SUBS_KEY);
|
const allSubs = $.read(SUBS_KEY);
|
||||||
@ -424,7 +427,7 @@ function service() {
|
|||||||
async function downloadRule(req, res) {
|
async function downloadRule(req, res) {
|
||||||
const {name} = req.params;
|
const {name} = req.params;
|
||||||
const {builtin} = req.query;
|
const {builtin} = req.query;
|
||||||
const platform = req.query.target || getPlatformFromHeaders(req.headers);
|
const platform = req.query.target || getPlatformFromHeaders(req.headers) || "Surge";
|
||||||
|
|
||||||
$.info(`正在下载${builtin ? "内置" : ""}分流订阅:${name}...`);
|
$.info(`正在下载${builtin ? "内置" : ""}分流订阅:${name}...`);
|
||||||
|
|
||||||
@ -446,9 +449,10 @@ function service() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// remove duplicates
|
// remove duplicates
|
||||||
rules = await RuleUtils.process(rules, [{type: "Remove Duplicate"}]);
|
rules = await RuleUtils.process(rules, [{type: "Remove Duplicate Filter"}]);
|
||||||
// produce output
|
// produce output
|
||||||
const output = RuleUtils.produce(rules, platform);
|
const output = RuleUtils.produce(rules, platform);
|
||||||
|
$.info(`分流订阅${name}下载成功,共包含${rules.length}条分流规则。`);
|
||||||
res.send(output);
|
res.send(output);
|
||||||
} else {
|
} else {
|
||||||
// rule not found
|
// rule not found
|
||||||
@ -575,8 +579,7 @@ function service() {
|
|||||||
} else if (UA.indexOf("Decar") !== -1 || UA.indexOf("Loon") !== -1) {
|
} else if (UA.indexOf("Decar") !== -1 || UA.indexOf("Loon") !== -1) {
|
||||||
return "Loon";
|
return "Loon";
|
||||||
} else {
|
} else {
|
||||||
// browser
|
return null;
|
||||||
return "JSON";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1616,7 +1619,7 @@ var ProxyUtils = (function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rename by regex
|
// rename by regex
|
||||||
// keywords: [{expr: "string format regex", now: "now"}]
|
// keywords: [{expr: "string format regex", now: "now"}]
|
||||||
function RegexRenameOperator(regex) {
|
function RegexRenameOperator(regex) {
|
||||||
return {
|
return {
|
||||||
name: "Regex Rename Operator",
|
name: "Regex Rename Operator",
|
||||||
@ -1632,7 +1635,7 @@ var ProxyUtils = (function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// delete keywords operator
|
// delete keywords operator
|
||||||
// keywords: ['a', 'b', 'c']
|
// keywords: ['a', 'b', 'c']
|
||||||
function KeywordDeleteOperator(keywords) {
|
function KeywordDeleteOperator(keywords) {
|
||||||
const keywords_ = keywords.map((k) => {
|
const keywords_ = keywords.map((k) => {
|
||||||
return {
|
return {
|
||||||
@ -1647,7 +1650,7 @@ var ProxyUtils = (function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// delete regex operator
|
// delete regex operator
|
||||||
// regex: ['a', 'b', 'c']
|
// regex: ['a', 'b', 'c']
|
||||||
function RegexDeleteOperator(regex) {
|
function RegexDeleteOperator(regex) {
|
||||||
const regex_ = regex.map((r) => {
|
const regex_ = regex.map((r) => {
|
||||||
return {
|
return {
|
||||||
@ -1781,7 +1784,8 @@ var ProxyUtils = (function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// use base64 encoded script to filter proxies
|
// use base64 encoded script to filter proxies
|
||||||
/** Script Example
|
/**
|
||||||
|
Script Example
|
||||||
function func(proxies) {
|
function func(proxies) {
|
||||||
const selected = FULL(proxies.length, true);
|
const selected = FULL(proxies.length, true);
|
||||||
// do something
|
// do something
|
||||||
@ -2016,60 +2020,6 @@ var ProxyUtils = (function () {
|
|||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
// some logical functions for proxy filters
|
|
||||||
function AND(...args) {
|
|
||||||
return args.reduce((a, b) => a.map((c, i) => b[i] && c));
|
|
||||||
}
|
|
||||||
|
|
||||||
function OR(...args) {
|
|
||||||
return args.reduce((a, b) => a.map((c, i) => b[i] || c));
|
|
||||||
}
|
|
||||||
|
|
||||||
function NOT(array) {
|
|
||||||
return array.map((c) => !c);
|
|
||||||
}
|
|
||||||
|
|
||||||
function FULL(length, bool) {
|
|
||||||
return [...Array(length).keys()].map(() => bool);
|
|
||||||
}
|
|
||||||
|
|
||||||
function clone(object) {
|
|
||||||
return JSON.parse(JSON.stringify(object));
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply filter to proxies
|
|
||||||
function ApplyFilter(filter, proxies) {
|
|
||||||
// select proxies
|
|
||||||
let selected = FULL(proxies.length, true);
|
|
||||||
try {
|
|
||||||
selected = AND(selected, filter.func(proxies));
|
|
||||||
} catch (err) {
|
|
||||||
console.log(`Cannot apply filter ${filter.name}\n Reason: ${err}`);
|
|
||||||
}
|
|
||||||
return proxies.filter((_, i) => selected[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply operator to proxies
|
|
||||||
function ApplyOperator(operator, proxies) {
|
|
||||||
let output = clone(proxies);
|
|
||||||
try {
|
|
||||||
const output_ = operator.func(output);
|
|
||||||
if (output_) output = output_;
|
|
||||||
} catch (err) {
|
|
||||||
// print log and skip this operator
|
|
||||||
console.log(`Cannot apply operator ${op.name}! Reason: ${err}`);
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Apply(process, proxies) {
|
|
||||||
if (process.name.indexOf("Filter") !== -1) {
|
|
||||||
return ApplyFilter(process, proxies);
|
|
||||||
} else if (process.name.indexOf("Operator") !== -1) {
|
|
||||||
return ApplyOperator(process, proxies);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"Keyword Filter": KeywordFilter,
|
"Keyword Filter": KeywordFilter,
|
||||||
"Useless Filter": UselessFilter,
|
"Useless Filter": UselessFilter,
|
||||||
@ -2087,8 +2037,6 @@ var ProxyUtils = (function () {
|
|||||||
"Regex Rename Operator": RegexRenameOperator,
|
"Regex Rename Operator": RegexRenameOperator,
|
||||||
"Regex Delete Operator": RegexDeleteOperator,
|
"Regex Delete Operator": RegexDeleteOperator,
|
||||||
"Script Operator": ScriptOperator,
|
"Script Operator": ScriptOperator,
|
||||||
|
|
||||||
"Apply": Apply,
|
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
const PROXY_PRODUCERS = (function () {
|
const PROXY_PRODUCERS = (function () {
|
||||||
@ -2528,26 +2476,23 @@ var ProxyUtils = (function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const op = PROXY_PROCESSORS[item.type];
|
if (!PROXY_PROCESSORS[item.type]) {
|
||||||
if (!op) {
|
|
||||||
$.error(`Unknown operator: "${item.type}"`);
|
$.error(`Unknown operator: "${item.type}"`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
$.log(
|
$.log(
|
||||||
`Applying "${item.type}" with arguments:\n >>> ${
|
`Applying "${item.type}" with arguments:\n >>> ${
|
||||||
JSON.stringify(item.args, null, 2) || "None"
|
JSON.stringify(item.args, null, 2) || "None"
|
||||||
}`
|
}`
|
||||||
);
|
);
|
||||||
|
let processor;
|
||||||
if (item.type.indexOf('Script') !== -1) {
|
if (item.type.indexOf('Script') !== -1) {
|
||||||
proxies = PROXY_PROCESSORS.Apply(op(script), proxies);
|
processor = PROXY_PROCESSORS[item.type](script);
|
||||||
} else {
|
} else {
|
||||||
proxies = PROXY_PROCESSORS.Apply(op(item.args), proxies);
|
processor = PROXY_PROCESSORS[item.type](item.args);
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
$.error(`Failed to apply "${item.type}"!\n REASON: ${err}`);
|
|
||||||
}
|
}
|
||||||
|
proxies = ApplyProcessor(processor, proxies);
|
||||||
}
|
}
|
||||||
return proxies;
|
return proxies;
|
||||||
}
|
}
|
||||||
@ -2664,10 +2609,17 @@ var RuleUtils = (function () {
|
|||||||
const conf = YAML.eval(raw);
|
const conf = YAML.eval(raw);
|
||||||
const payload = conf["payload"]
|
const payload = conf["payload"]
|
||||||
.map(
|
.map(
|
||||||
rule => rule.replace("DST-PORT", "DEST-PORT")
|
rule => {
|
||||||
.replace("SRC-IP-CIDR", "SRC-IP")
|
if (typeof rule === "string") {
|
||||||
.replace("SRC-PORT", "IN-PORT")
|
return rule.replace(/DST-PORT/i, "DEST-PORT")
|
||||||
|
.replace(/SRC-IP-CIDR/i, "SRC-IP")
|
||||||
|
.replace(/SRC-PORT/i, "IN-PORT")
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
.filter(line => line.length > 0)
|
||||||
.join("\n");
|
.join("\n");
|
||||||
return SurgeRuleSet().parse(payload);
|
return SurgeRuleSet().parse(payload);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -2707,8 +2659,33 @@ var RuleUtils = (function () {
|
|||||||
return [SurgeRuleSet(), QX(), ClashRuleProvider()];
|
return [SurgeRuleSet(), QX(), ClashRuleProvider()];
|
||||||
})();
|
})();
|
||||||
const RULE_PROCESSORS = (function () {
|
const RULE_PROCESSORS = (function () {
|
||||||
function RemoveDuplicate() {
|
function RegexFilter({regex = [], keep = true}) {
|
||||||
return {
|
return {
|
||||||
|
name: "Regex Filter",
|
||||||
|
func: (rules) => {
|
||||||
|
return rules.map((rule) => {
|
||||||
|
const selected = regex.some((r) => {
|
||||||
|
r = new RegExp(r);
|
||||||
|
return r.test(rule);
|
||||||
|
});
|
||||||
|
return keep ? selected : !selected;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function TypeFilter(types) {
|
||||||
|
return {
|
||||||
|
name: "Type Filter",
|
||||||
|
func: (rules) => {
|
||||||
|
return rules.map((rule) => types.some((t) => rule.type === t));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function RemoveDuplicateFilter() {
|
||||||
|
return {
|
||||||
|
name: "Remove Duplicate Filter",
|
||||||
func: rules => {
|
func: rules => {
|
||||||
const seen = new Set();
|
const seen = new Set();
|
||||||
const result = [];
|
const result = [];
|
||||||
@ -2726,8 +2703,27 @@ var RuleUtils = (function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// regex: [{expr: "string format regex", now: "now"}]
|
||||||
|
function RegexReplaceOperator(regex) {
|
||||||
return {
|
return {
|
||||||
"Remove Duplicate": RemoveDuplicate
|
name: "Regex Rename Operator",
|
||||||
|
func: (rules) => {
|
||||||
|
return rules.map((rule) => {
|
||||||
|
for (const {expr, now} of regex) {
|
||||||
|
rule.content = rule.content.replace(new RegExp(expr, "g"), now).trim();
|
||||||
|
}
|
||||||
|
return rule;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"Regex Filter": RegexFilter,
|
||||||
|
"Remove Duplicate Filter": RemoveDuplicateFilter,
|
||||||
|
"Type Filter": TypeFilter,
|
||||||
|
|
||||||
|
"Regex Replace Operator": RegexReplaceOperator
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
const RULE_PRODUCERS = (function () {
|
const RULE_PRODUCERS = (function () {
|
||||||
@ -2833,17 +2829,13 @@ var RuleUtils = (function () {
|
|||||||
console.error(`Unknown operator: ${item.type}!`);
|
console.error(`Unknown operator: ${item.type}!`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const op = RULE_PROCESSORS[item.type](item.args);
|
const processor = RULE_PROCESSORS[item.type](item.args);
|
||||||
try {
|
|
||||||
console.log(
|
console.log(
|
||||||
`Applying operator "${item.type}" with arguments: \n >>> ${
|
`Applying "${item.type}" with arguments: \n >>> ${
|
||||||
JSON.stringify(item.args) || "None"
|
JSON.stringify(item.args) || "None"
|
||||||
}`
|
}`
|
||||||
);
|
);
|
||||||
rules = op.func(rules);
|
rules = ApplyProcessor(processor, rules);
|
||||||
} catch (err) {
|
|
||||||
console.error(`Failed to apply operator "${item.type}"!\n REASON: ${err}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return rules;
|
return rules;
|
||||||
}
|
}
|
||||||
@ -2886,11 +2878,84 @@ function getBuiltInRules() {
|
|||||||
"https://raw.githubusercontent.com/privacy-protection-tools/anti-AD/master/anti-ad-surge.txt",
|
"https://raw.githubusercontent.com/privacy-protection-tools/anti-AD/master/anti-ad-surge.txt",
|
||||||
"https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/Providers/BanAD.yaml"
|
"https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/Providers/BanAD.yaml"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"Global": {
|
||||||
|
"name": "Global",
|
||||||
|
"description": "",
|
||||||
|
"urls": [
|
||||||
|
"https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/Providers/ProxyGFWlist.yaml",
|
||||||
|
"https://raw.githubusercontent.com/DivineEngine/Profiles/master/Quantumult/Filter/Global.list"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"CN": {
|
||||||
|
"name": "CN",
|
||||||
|
"description": "",
|
||||||
|
"urls": [
|
||||||
|
"https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/Providers/ChinaDomain.yaml",
|
||||||
|
"https://raw.githubusercontent.com/DivineEngine/Profiles/master/Quantumult/Filter/China.list"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************** Supporting Functions **********************************************************/
|
/****************************************** Supporting Functions **********************************************************/
|
||||||
|
function ApplyProcessor(process, objs) {
|
||||||
|
function ApplyFilter(filter, objs) {
|
||||||
|
// select proxies
|
||||||
|
let selected = FULL(objs.length, true);
|
||||||
|
try {
|
||||||
|
selected = AND(selected, filter.func(objs));
|
||||||
|
} catch (err) {
|
||||||
|
// print log and skip this filter
|
||||||
|
console.log(`Cannot apply filter ${filter.name}\n Reason: ${err}`);
|
||||||
|
}
|
||||||
|
return objs.filter((_, i) => selected[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ApplyOperator(operator, objs) {
|
||||||
|
let output = clone(objs);
|
||||||
|
try {
|
||||||
|
const output_ = operator.func(output);
|
||||||
|
if (output_) output = output_;
|
||||||
|
} catch (err) {
|
||||||
|
// print log and skip this operator
|
||||||
|
console.log(`Cannot apply operator ${operator.name}! Reason: ${err}`);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.name.indexOf("Filter") !== -1) {
|
||||||
|
return ApplyFilter(process, objs);
|
||||||
|
} else if (process.name.indexOf("Operator") !== -1) {
|
||||||
|
return ApplyOperator(process, objs);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// some logical functions
|
||||||
|
function AND(...args) {
|
||||||
|
return args.reduce((a, b) => a.map((c, i) => b[i] && c));
|
||||||
|
}
|
||||||
|
|
||||||
|
function OR(...args) {
|
||||||
|
return args.reduce((a, b) => a.map((c, i) => b[i] || c));
|
||||||
|
}
|
||||||
|
|
||||||
|
function NOT(array) {
|
||||||
|
return array.map((c) => !c);
|
||||||
|
}
|
||||||
|
|
||||||
|
function FULL(length, bool) {
|
||||||
|
return [...Array(length).keys()].map(() => bool);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clone(object) {
|
||||||
|
return JSON.parse(JSON.stringify(object));
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************** Own Libraries **********************************************************/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OpenAPI
|
* OpenAPI
|
||||||
* https://github.com/Peng-YM/QuanX/blob/master/Tools/OpenAPI/README.md
|
* https://github.com/Peng-YM/QuanX/blob/master/Tools/OpenAPI/README.md
|
||||||
|
4
backend/sub-store.min.js
vendored
4
backend/sub-store.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user