c6f9588738
本次变更引入了一套完整的节点自动化重命名方案,旨在提升 Sub-Store 订阅管理的标准化程度: 1. 新增三个机场专属处理脚本:peiqian-rename.js、yuetong-rename.js 及整合版 rename.js,用于精简节点名称和统一格式。 2. 优化 sntp-rename.js:增加了 CT(CF) 和 D(直连) 等线路特征识别。 3. 更新 README.md:详细说明了脚本的链式调用顺序与各自职责。 4. 核心逻辑改进:支持国家/城市短码转换、国旗位置归位及防重复注入机制。
94 lines
4.1 KiB
JavaScript
94 lines
4.1 KiB
JavaScript
/**
|
|
* Sub-Store 节点名称属性注入脚本 (全自动配置驱动版)
|
|
* 核心架构:动态按长度排序编译正则 + 智能边界识别 + O(1) 映射提取
|
|
* 维护说明:仅需修改 featureMap 字典即可,底部逻辑永远无需改动。
|
|
*/
|
|
function operator(proxies) {
|
|
// ================= 唯一配置区 =================
|
|
// 在这里新增或修改关键词。格式:"节点关键词": "想要注入的标签"
|
|
// 支持大小写混合,支持包含空格或特殊符号。
|
|
const featureMap = {
|
|
"GTM 0.5x": "三网",
|
|
"GTM": "三网",
|
|
"CT": "CF",
|
|
"S1": "广移",
|
|
"S2": "广电",
|
|
"S3": "广移",
|
|
"S4": "广联",
|
|
"BGP": "cn2",
|
|
"D": "直连",
|
|
"Anytls": "直连" // 日后如果要加 IEPL,只需在这里写 "IEPL": "专线"
|
|
};
|
|
// ==============================================
|
|
|
|
|
|
// ================= 核心逻辑区 (无需修改) =================
|
|
|
|
// 1. 初始化预处理:生成稳定的查找字典 (全大写+去空格)
|
|
// 目的:无论节点名叫 "gtm 0.5x" 还是 "GTM0.5X",都能稳定映射
|
|
const normalizedFeatureMap = {};
|
|
const featureKeywords = Object.keys(featureMap);
|
|
const normalizeFeatureKeyword = keyword => keyword.toUpperCase().replace(/\s+/g, '');
|
|
const escapeRegexKeyword = keyword => keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
for (const featureKeyword of featureKeywords) {
|
|
normalizedFeatureMap[normalizeFeatureKeyword(featureKeyword)] = featureMap[featureKeyword];
|
|
}
|
|
|
|
// 2. 动态构建复合正则表达式 (核心引擎)
|
|
// 按字符串长度降序排序,彻底解决 "短路匹配" (Short-Circuit) 问题
|
|
const sortedFeatureKeywords = [...featureKeywords].sort(
|
|
(firstFeatureKeyword, secondFeatureKeyword) => secondFeatureKeyword.length - firstFeatureKeyword.length
|
|
);
|
|
|
|
const featureRegexParts = sortedFeatureKeywords.map(featureKeyword => {
|
|
// 自动转义正则特殊字符 (防注入报错)
|
|
const escapedKeywordPattern = featureKeyword.trim().split(/\s+/).filter(Boolean).map(escapeRegexKeyword).join('\\s*');
|
|
|
|
// 智能边界处理:如果关键词首尾都是字母或数字,就追加 \b 边界
|
|
// 这样能防止配置的 "S1" 错误匹配到 "US1" 或 "TLS1.3"
|
|
const trimmedFeatureKeyword = featureKeyword.trim();
|
|
if (/^[A-Za-z0-9]/.test(trimmedFeatureKeyword) && /[A-Za-z0-9]$/.test(trimmedFeatureKeyword)) {
|
|
return `\\b${escapedKeywordPattern}\\b`;
|
|
}
|
|
return escapedKeywordPattern;
|
|
});
|
|
|
|
// 动态拼接出类似: /(GTM\s*0\.5x|\bAnytls\b|\bBGP\b|...)/i
|
|
const featureRegex = new RegExp(`(${featureRegexParts.join('|')})`, 'i');
|
|
|
|
// 缓存后缀匹配正则,避免循环内重复创建
|
|
const suffixRegex = /(\s*-\s*SNTP.*)$/i;
|
|
|
|
// 3. 执行节点遍历与注入
|
|
return proxies.map(proxy => {
|
|
const proxyName = proxy.name;
|
|
if (typeof proxyName !== 'string') return proxy;
|
|
|
|
// 单次复合正则扫描提取
|
|
const featureMatch = proxyName.match(featureRegex);
|
|
if (!featureMatch) return proxy; // 未命中配置库,直接放行
|
|
|
|
// 清洗提取到的特征词,并去 O(1) 字典中取值
|
|
const normalizedMatchedKeyword = normalizeFeatureKeyword(featureMatch[1]);
|
|
const injectedFeatureLabel = normalizedFeatureMap[normalizedMatchedKeyword];
|
|
|
|
if (!injectedFeatureLabel) return proxy; // 兜底安全校验
|
|
|
|
// 格式化组装与幂等校验 (防重复注入 Bug)
|
|
const formattedFeatureLabel = ` [${injectedFeatureLabel}]`;
|
|
if (proxyName.includes(formattedFeatureLabel)) {
|
|
return proxy;
|
|
}
|
|
|
|
// 实施中缀注入 (Infix Injection)
|
|
if (suffixRegex.test(proxyName)) {
|
|
proxy.name = proxyName.replace(suffixRegex, `${formattedFeatureLabel}$1`);
|
|
} else {
|
|
// 纯净节点无后缀时,直接挂载在末尾
|
|
proxy.name = proxyName + formattedFeatureLabel;
|
|
}
|
|
|
|
return proxy;
|
|
});
|
|
}
|