surgio
Version:
Generating rules for Surge, Clash, Quantumult like a PRO
234 lines • 9.18 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadLocalSnippet = exports.convertNewSurgeScriptRuleToQuantumultXRewriteRule = exports.convertSurgeScriptRuleToQuantumultXRewriteRule = void 0;
exports.getEngine = getEngine;
const path_1 = __importDefault(require("path"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const nunjucks_1 = __importDefault(require("nunjucks"));
const yaml_1 = __importDefault(require("yaml"));
const utils_1 = require("../utils");
const constant_1 = require("../constant");
function getEngine(templateDir, options = {}) {
const engine = nunjucks_1.default.configure(templateDir, {
autoescape: false,
});
const getClashFilter = (clashCore) => {
const supportedRule = (() => {
switch (clashCore) {
case 'stash':
return constant_1.STASH_SUPPORTED_RULE;
case 'clash.meta':
return constant_1.CLASH_META_SUPPORTED_RULE;
default:
return constant_1.CLASH_SUPPORTED_RULE;
}
})();
return (str) => {
// istanbul ignore next
if (!str) {
return '';
}
const array = str.split('\n');
return array
.map((item) => {
const testString = !!item && item.trim() !== '' ? item.toUpperCase() : '';
if (testString.startsWith('#') || testString === '') {
return item;
}
const matched = testString.match(/^([\w-]+),/);
if (matched && supportedRule.some((s) => matched[1] === s)) {
// 过滤出支持的规则类型
return `- ${item}`.replace(/\/\/.*$/, '').trim();
}
return null;
})
.filter((item) => !!item)
.join('\n');
};
};
if (options.clashCore) {
engine.addFilter('clash', getClashFilter(options.clashCore));
}
else {
engine.addFilter('clash', getClashFilter('clash'));
}
engine.addFilter('clashMeta', getClashFilter('clash.meta'));
engine.addFilter('stash', getClashFilter('stash'));
engine.addFilter('quantumultx', (str) => {
// istanbul ignore next
if (!str) {
return '';
}
const array = str.split('\n');
return array
.map((item) => {
const testString = !!item && item.trim() !== '' ? item.toUpperCase() : '';
if (testString.startsWith('#') || testString === '') {
return item;
}
// Surge Script 处理
if (testString.startsWith('HTTP-RESPONSE')) {
return (0, exports.convertSurgeScriptRuleToQuantumultXRewriteRule)(item);
}
if (testString.startsWith('HTTP-REQUEST')) {
return (0, exports.convertSurgeScriptRuleToQuantumultXRewriteRule)(item);
}
if (/type\s?=\s?http-response/.test(item)) {
return (0, exports.convertNewSurgeScriptRuleToQuantumultXRewriteRule)(item);
}
if (/type\s?=\s?http-request/.test(item)) {
return (0, exports.convertNewSurgeScriptRuleToQuantumultXRewriteRule)(item);
}
const matched = testString.match(/^([\w-]+),/);
if (matched &&
constant_1.QUANTUMULT_X_SUPPORTED_RULE.some((s) => matched[1] === s)) {
if (matched[1] === 'IP-CIDR6') {
return item.replace(/IP-CIDR6/i, 'IP6-CIDR');
}
// 过滤出支持的规则类型
return item;
}
return null;
})
.filter((item) => !!item)
.join('\n');
});
engine.addFilter('loon', (str) => {
// istanbul ignore next
if (!str) {
return '';
}
const array = str.split('\n');
return array
.map((item) => {
const testString = !!item && item.trim() !== '' ? item.toUpperCase() : '';
if (testString.startsWith('#') || testString === '') {
return item;
}
const matched = testString.match(/^([\w-]+),/);
if (matched && constant_1.LOON_SUPPORTED_RULE.some((s) => matched[1] === s)) {
// 过滤出支持的规则类型
return `${item}`.replace(/\/\/.*$/, '').trim();
}
return null;
})
.filter((item) => !!item)
.join('\n');
});
engine.addFilter('surfboard', (str) => {
// istanbul ignore next
if (!str) {
return '';
}
const array = str.split('\n');
return array
.map((item) => {
const testString = !!item && item.trim() !== '' ? item.toUpperCase() : '';
if (testString.startsWith('#') || testString === '') {
return item;
}
const matched = testString.match(/^([\w-]+),/);
if (matched && constant_1.SURFBOARD_SUPPORTED_RULE.some((s) => matched[1] === s)) {
// 过滤出支持的规则类型
return item.trim();
}
return null;
})
.filter((item) => !!item)
.join('\n');
});
// yaml
engine.addFilter('yaml', (obj) => yaml_1.default.stringify(obj));
// base64
engine.addFilter('base64', (str) => (0, utils_1.toBase64)(str));
// json
engine.addFilter('json', (obj) => JSON.stringify(obj));
return engine;
}
const convertSurgeScriptRuleToQuantumultXRewriteRule = (str) => {
const parts = str.split(' ');
const result = [];
switch (parts[0]) {
case 'http-response': {
const params = (0, utils_1.decodeStringList)(parts.splice(2).join('').split(','));
const scriptPath = params['script-path'];
const isRequireBody = 'requires-body' in params;
if (isRequireBody) {
// parts[1] => Effective URL Rule
result.push(parts[1], 'url', 'script-response-body', scriptPath);
}
else {
result.push(parts[1], 'url', 'script-response-header', scriptPath);
}
return result.join(' ');
}
case 'http-request': {
const params = (0, utils_1.decodeStringList)(parts.splice(2).join('').split(','));
const scriptPath = params['script-path'];
const isRequireBody = 'requires-body' in params;
if (isRequireBody) {
// parts[1] => Effective URL Rule
result.push(parts[1], 'url', 'script-request-body', scriptPath);
}
else {
result.push(parts[1], 'url', 'script-request-header', scriptPath);
}
return result.join(' ');
}
default:
return '';
}
};
exports.convertSurgeScriptRuleToQuantumultXRewriteRule = convertSurgeScriptRuleToQuantumultXRewriteRule;
const convertNewSurgeScriptRuleToQuantumultXRewriteRule = (str) => {
const matched = str.match(/^(.+?)=(.+?)$/);
const result = [];
if (!matched) {
return '';
}
const params = (0, utils_1.decodeStringList)(matched[2].trim().split(','));
switch (params.type) {
case 'http-response': {
const isRequireBody = 'requires-body' in params;
if (isRequireBody) {
result.push(params.pattern, 'url', 'script-response-body', params['script-path']);
}
else {
result.push(params.pattern, 'url', 'script-response-header', params['script-path']);
}
return result.join(' ');
}
case 'http-request': {
const isRequireBody = 'requires-body' in params;
if (isRequireBody) {
result.push(params.pattern, 'url', 'script-request-body', params['script-path']);
}
else {
result.push(params.pattern, 'url', 'script-request-header', params['script-path']);
}
return result.join(' ');
}
default:
return '';
}
};
exports.convertNewSurgeScriptRuleToQuantumultXRewriteRule = convertNewSurgeScriptRuleToQuantumultXRewriteRule;
const loadLocalSnippet = (cwd, relativeFilePath) => {
// istanbul ignore next
if (!relativeFilePath) {
throw new Error('必须指定一个文件');
}
const absFilePath = path_1.default.join(cwd, relativeFilePath);
const file = fs_extra_1.default.readFileSync(absFilePath, { encoding: 'utf-8' });
return {
url: absFilePath,
name: '',
main: (rule) => (0, utils_1.addProxyToSurgeRuleSet)(file, rule),
text: file,
};
};
exports.loadLocalSnippet = loadLocalSnippet;
//# sourceMappingURL=template.js.map