/** * Sub-Store 节点名称属性注入脚本 (全自动配置驱动版) * 核心架构:动态按长度排序编译正则 + 智能边界识别 + O(1) 映射提取 * 维护说明:仅需修改 featureMap 字典即可,底部逻辑永远无需改动。 */ function operator(proxies) { // ================= 唯一配置区 ================= // 在这里新增或修改关键词。格式:"节点关键词": "想要注入的标签" // 支持大小写混合,支持包含空格或特殊符号。 const featureMap = { "GTM 0.5x": "三网", "GTM": "三网", "S1": "广移", "S2": "广电", "S3": "广移", "S4": "广联", "BGP": "cn2|5x", "Anytls": "直连" // 日后如果要加 IEPL,只需在这里写 "IEPL": "专线" }; // ============================================== // ================= 核心逻辑区 (无需修改) ================= // 1. 初始化预处理:生成稳定的查找字典 (全大写+去空格) // 目的:无论节点名叫 "gtm 0.5x" 还是 "GTM0.5X",都能稳定映射 const normalizedMap = {}; const originalKeys = Object.keys(featureMap); for (const key of originalKeys) { const safeKey = key.toUpperCase().replace(/\s+/g, ''); normalizedMap[safeKey] = featureMap[key]; } // 2. 动态构建复合正则表达式 (核心引擎) // 按字符串长度降序排序,彻底解决 "短路匹配" (Short-Circuit) 问题 const sortedKeys = originalKeys.sort((a, b) => b.length - a.length); const regexParts = sortedKeys.map(key => { // 自动转义正则特殊字符 (防注入报错) const escapedKey = key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // 智能边界处理:如果关键词仅由字母和数字组成 (如 S1, BGP),追加 \b 边界 // 这样能防止配置的 "S1" 错误匹配到 "US1" 或 "TLS1.3" if (/^[A-Za-z0-9]+$/.test(key)) { return `\\b${escapedKey}\\b`; } return escapedKey; }); // 动态拼接出类似: /(GTM\ 0\.5x|\bAnytls\b|\bBGP\b|...)/i const featureRegex = new RegExp(`(${regexParts.join('|')})`, 'i'); // 缓存后缀匹配正则,避免循环内重复创建 const suffixRegex = /(\s*-\s*SNTP.*)$/i; // 3. 执行节点遍历与注入 return proxies.map(p => { const name = p.name; // A. 单次复合正则扫描提取 const match = name.match(featureRegex); if (!match) return p; // 未命中配置库,直接放行 // B. 清洗提取到的特征词,并去 O(1) 字典中取值 const mapKey = match[1].toUpperCase().replace(/\s+/g, ''); const injectPayload = normalizedMap[mapKey]; if (!injectPayload) return p; // 兜底安全校验 // C. 格式化组装与幂等校验 (防重复注入 Bug) const formatStr = ` [${injectPayload}]`; if (name.includes(formatStr)) { return p; } // D. 实施中缀注入 (Infix Injection) if (suffixRegex.test(name)) { p.name = name.replace(suffixRegex, `${formatStr}$1`); } else { // 纯净节点无后缀时,直接挂载在末尾 p.name = name + formatStr; } return p; }); }