rename.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /**
  2. * 更新日期:2024-04-05 15:30:15
  3. * 修改: 添加协议前缀功能 (H2/VL/VS/TR 等)
  4. * 用法:Sub-Store 脚本操作添加
  5. * rename.js 以下是此脚本支持的参数,必须以 # 为开头多个参数使用"&"连接,参考上述地址为例使用参数。 禁用缓存url#noCache
  6. *
  7. *** 主要参数
  8. * [in=] 自动判断机场节点名类型 优先级 zh(中文) -> flag(国旗) -> quan(英文全称) -> en(英文简写)
  9. * 如果不准的情况, 可以加参数指定:
  10. *
  11. * [nm] 保留没有匹配到的节点
  12. * [in=zh] 或in=cn识别中文
  13. * [in=en] 或in=us 识别英文缩写
  14. * [in=flag] 或in=gq 识别国旗 如果加参数 in=flag 则识别国旗 脚本操作前面不要添加国旗操作 否则移除国旗后面脚本识别不到
  15. * [in=quan] 识别英文全称
  16. *
  17. * [out=] 输出节点名可选参数: (cn或zh ,us或en ,gq或flag ,quan) 对应:(中文,英文缩写 ,国旗 ,英文全称) 默认中文 例如 [out=en] 或 out=us 输出英文缩写
  18. *** 分隔符参数
  19. *
  20. * [fgf=] 节点名前缀或国旗分隔符,默认为空格;
  21. * [sn=] 设置国家与序号之间的分隔符,默认为空格;
  22. * 序号参数
  23. * [one] 清理只有一个节点的地区的01
  24. * [flag] 给节点前面加国旗
  25. *
  26. *** 前缀参数
  27. * [name=] 节点添加机场名称前缀;
  28. * [nf] 把 name= 的前缀值放在最前面
  29. *** 保留参数
  30. * [blkey=iplc+gpt+NF+IPLC] 用+号添加多个关键词 保留节点名的自定义字段 需要区分大小写!
  31. * 如果需要修改 保留的关键词 替换成别的 可以用 > 分割 例如 [#blkey=GPT>新名字+其他关键词] 这将把【GPT】替换成【新名字】
  32. * 例如 https://raw.githubusercontent.com/Keywos/rule/main/rename.js#flag&blkey=GPT>新名字+NF
  33. * [blgd] 保留: 家宽 IPLC ˣ² 等
  34. * [bl] 正则匹配保留 [0.1x, x0.2, 6x ,3倍]等标识
  35. * [nx] 保留1倍率与不显示倍率的
  36. * [blnx] 只保留高倍率
  37. * [clear] 清理乱名
  38. * [blpx] 如果用了上面的bl参数,对保留标识后的名称分组排序,如果没用上面的bl参数单独使用blpx则不起任何作用
  39. * [blockquic] blockquic=on 阻止; blockquic=off 不阻止
  40. *
  41. *** 协议前缀 (新增)
  42. * [proto] proto=true 开启协议前缀功能 (如 VS, VL, H2 等),默认为 false 不开启
  43. * vmess→VS vless→VL trojan→TR ss→SS ssr→SSR
  44. * hysteria→HY hysteria2→H2 tuic→TU wireguard→WG
  45. * snell→SN http→HTTP https→HTTPS socks5→S5
  46. * ssh→SSH anytls→AT
  47. */
  48. // ──────────────────────────────────────────────
  49. // 协议缩写映射 (新增)
  50. // ──────────────────────────────────────────────
  51. const PROTOCOL_MAP = {
  52. vmess: "VS",
  53. vless: "VL",
  54. trojan: "TR",
  55. ss: "SS",
  56. ssr: "SSR",
  57. hysteria: "HY",
  58. hysteria2: "H2",
  59. tuic: "TU",
  60. wireguard: "WG",
  61. snell: "SN",
  62. http: "HTTP",
  63. https: "HTTPS",
  64. socks5: "S5",
  65. ssh: "SSH",
  66. anytls: "AT",
  67. };
  68. function getProtocolLabel(type) {
  69. if (!type) return "";
  70. const label = PROTOCOL_MAP[String(type).toLowerCase()];
  71. return label || String(type).toUpperCase();
  72. }
  73. // ──────────────────────────────────────────────
  74. // 原始 Keywos rename.js
  75. // ──────────────────────────────────────────────
  76. // const inArg = {'blkey':'iplc+GPT>GPTnewName+NF+IPLC', 'flag':true };
  77. const inArg = $arguments; // console.log(inArg)
  78. const nx = inArg.nx || false,
  79. bl = inArg.bl || false,
  80. nf = inArg.nf || false,
  81. key = inArg.key || false,
  82. blgd = inArg.blgd || false,
  83. blpx = inArg.blpx || false,
  84. blnx = inArg.blnx || false,
  85. numone = inArg.one || false,
  86. debug = inArg.debug || false,
  87. clear = inArg.clear || false,
  88. addflag = inArg.flag || false,
  89. nm = inArg.nm || false,
  90. addproto = inArg.proto || false; // 是否开启协议缩写前缀功能 (如 VS, VL, H2 等,默认为 false 不开启)
  91. const FGF = inArg.fgf == undefined ? " " : decodeURI(inArg.fgf),
  92. XHFGF = inArg.sn == undefined ? " " : decodeURI(inArg.sn),
  93. FNAME = inArg.name == undefined ? "" : decodeURI(inArg.name),
  94. BLKEY = inArg.blkey == undefined ? "" : decodeURI(inArg.blkey),
  95. blockquic = inArg.blockquic == undefined ? "" : decodeURI(inArg.blockquic),
  96. nameMap = {
  97. cn: "cn",
  98. zh: "cn",
  99. us: "us",
  100. en: "us",
  101. quan: "quan",
  102. gq: "gq",
  103. flag: "gq",
  104. },
  105. inname = nameMap[inArg.in] || "",
  106. outputName = nameMap[inArg.out] || "";
  107. // prettier-ignore
  108. const FG = ['🇭🇰','🇲🇴','🇹🇼','🇯🇵','🇰🇷','🇸🇬','🇺🇸','🇬🇧','🇫🇷','🇩🇪','🇦🇺','🇦🇪','🇦🇫','🇦🇱','🇩🇿','🇦🇴','🇦🇷','🇦🇲','🇦🇹','🇦🇿','🇧🇭','🇧🇩','🇧🇾','🇧🇪','🇧🇿','🇧🇯','🇧🇹','🇧🇴','🇧🇦','🇧🇼','🇧🇷','🇻🇬','🇧🇳','🇧🇬','🇧🇫','🇧🇮','🇰🇭','🇨🇲','🇨🇦','🇨🇻','🇰🇾','🇨🇫','🇹🇩','🇨🇱','🇨🇴','🇰🇲','🇨🇬','🇨🇩','🇨🇷','🇭🇷','🇨🇾','🇨🇿','🇩🇰','🇩🇯','🇩🇴','🇪🇨','🇪🇬','🇸🇻','🇬🇶','🇪🇷','🇪🇪','🇪🇹','🇫🇯','🇫🇮','🇬🇦','🇬🇲','🇬🇪','🇬🇭','🇬🇷','🇬🇱','🇬🇹','🇬🇳','🇬🇾','🇭🇹','🇭🇳','🇭🇺','🇮🇸','🇮🇳','🇮🇩','🇮🇷','🇮🇶','🇮🇪','🇮🇲','🇮🇱','🇮🇹','🇨🇮','🇯🇲','🇯🇴','🇰🇿','🇰🇪','🇰🇼','🇰🇬','🇱🇦','🇱🇻','🇱🇧','🇱🇸','🇱🇷','🇱🇾','🇱🇹','🇱🇺','🇲🇰','🇲🇬','🇲🇼','🇲🇾','🇲🇻','🇲🇱','🇲🇹','🇲🇷','🇲🇺','🇲🇽','🇲🇩','🇲🇨','🇲🇳','🇲🇪','🇲🇦','🇲🇿','🇲🇲','🇳🇦','🇳🇵','🇳🇱','🇳🇿','🇳🇮','🇳🇪','🇳🇬','🇰🇵','🇳🇴','🇴🇲','🇵🇰','🇵🇦','🇵🇾','🇵🇪','🇵🇭','🇵🇹','🇵🇷','🇶🇦','🇷🇴','🇷🇺','🇷🇼','🇸🇲','🇸🇦','🇸🇳','🇷🇸','🇸🇱','🇸🇰','🇸🇮','🇸🇴','🇿🇦','🇪🇸','🇱🇰','🇸🇩','🇸🇷','🇸🇿','🇸🇪','🇨🇭','🇸🇾','🇹🇯','🇹🇿','🇹🇭','🇹🇬','🇹🇴','🇹🇹','🇹🇳','🇹🇷','🇹🇲','🇻🇮','🇺🇬','🇺🇦','🇺🇾','🇺🇿','🇻🇪','🇻🇳','🇾🇪','🇿🇲','🇿🇼','🇦🇩','🇷🇪','🇵🇱','🇬🇺','🇻🇦','🇱🇮','🇨🇼','🇸🇨','🇦🇶','🇬🇮','🇨🇺','🇫🇴','🇦🇽','🇧🇲','🇹🇱']
  109. // prettier-ignore
  110. const EN = ['HK','MO','TW','JP','KR','SG','US','GB','FR','DE','AU','AE','AF','AL','DZ','AO','AR','AM','AT','AZ','BH','BD','BY','BE','BZ','BJ','BT','BO','BA','BW','BR','VG','BN','BG','BF','BI','KH','CM','CA','CV','KY','CF','TD','CL','CO','KM','CG','CD','CR','HR','CY','CZ','DK','DJ','DO','EC','EG','SV','GQ','ER','EE','ET','FJ','FI','GA','GM','GE','GH','GR','GL','GT','GN','GY','HT','HN','HU','IS','IN','ID','IR','IQ','IE','IM','IL','IT','CI','JM','JO','KZ','KE','KW','KG','LA','LV','LB','LS','LR','LY','LT','LU','MK','MG','MW','MY','MV','ML','MT','MR','MU','MX','MD','MC','MN','ME','MA','MZ','MM','NA','NP','NL','NZ','NI','NE','NG','KP','NO','OM','PK','PA','PY','PE','PH','PT','PR','QA','RO','RU','RW','SM','SA','SN','RS','SL','SK','SI','SO','ZA','ES','LK','SD','SR','SZ','SE','CH','SY','TJ','TZ','TH','TG','TO','TT','TN','TR','TM','VI','UG','UA','UY','UZ','VE','VN','YE','ZM','ZW','AD','RE','PL','GU','VA','LI','CW','SC','AQ','GI','CU','FO','AX','BM','TL'];
  111. // prettier-ignore
  112. const ZH = ['香港','澳门','台湾','日本','韩国','新加坡','美国','英国','法国','德国','澳大利亚','阿联酋','阿富汗','阿尔巴尼亚','阿尔及利亚','安哥拉','阿根廷','亚美尼亚','奥地利','阿塞拜疆','巴林','孟加拉国','白俄罗斯','比利时','伯利兹','贝宁','不丹','玻利维亚','波斯尼亚和黑塞哥维那','博茨瓦纳','巴西','英属维京群岛','文莱','保加利亚','布基纳法索','布隆迪','柬埔寨','喀麦隆','加拿大','佛得角','开曼群岛','中非共和国','乍得','智利','哥伦比亚','科摩罗','刚果(布)','刚果(金)','哥斯达黎加','克罗地亚','塞浦路斯','捷克','丹麦','吉布提','多米尼加共和国','厄瓜多尔','埃及','萨尔瓦多','赤道几内亚','厄立特里亚','爱沙尼亚','埃塞俄比亚','斐济','芬兰','加蓬','冈比亚','格鲁吉亚','加纳','希腊','格陵兰','危地马拉','几内亚','圭亚那','海地','洪都拉斯','匈牙利','冰岛','印度','印尼','伊朗','伊拉克','爱尔兰','马恩岛','以色列','意大利','科特迪瓦','牙买加','约旦','哈萨克斯坦','肯尼亚','科威特','吉尔吉斯斯坦','老挝','拉脱维亚','黎巴嫩','莱索托','利比里亚','利比亚','立陶宛','卢森堡','马其顿','马达加斯加','马拉维','马来','马尔代夫','马里','马耳他','毛利塔尼亚','毛里求斯','墨西哥','摩尔多瓦','摩纳哥','蒙古','黑山共和国','摩洛哥','莫桑比克','缅甸','纳米比亚','尼泊尔','荷兰','新西兰','尼加拉瓜','尼日尔','尼日利亚','朝鲜','挪威','阿曼','巴基斯坦','巴拿马','巴拉圭','秘鲁','菲律宾','葡萄牙','波多黎各','卡塔尔','罗马尼亚','俄罗斯','卢旺达','圣马力诺','沙特阿拉伯','塞内加尔','塞尔维亚','塞拉利昂','斯洛伐克','斯洛文尼亚','索马里','南非','西班牙','斯里兰卡','苏丹','苏里南','斯威士兰','瑞典','瑞士','叙利亚','塔吉克斯坦','坦桑尼亚','泰国','多哥','汤加','特立尼达和多巴哥','突尼斯','土耳其','土库曼斯坦','美属维尔京群岛','乌干达','乌克兰','乌拉圭','乌兹别克斯坦','委内瑞拉','越南','也门','赞比亚','津巴布韦','安道尔','留尼汪','波兰','关岛','梵蒂冈','列支敦士登','库拉索','塞舌尔','南极','直布罗陀','古巴','法罗群岛','奥兰群岛','百慕达','东帝汶'];
  113. // prettier-ignore
  114. const QC = ['Hong Kong','Macao','Taiwan','Japan','Korea','Singapore','United States','United Kingdom','France','Germany','Australia','Dubai','Afghanistan','Albania','Algeria','Angola','Argentina','Armenia','Austria','Azerbaijan','Bahrain','Bangladesh','Belarus','Belgium','Belize','Benin','Bhutan','Bolivia','Bosnia and Herzegovina','Botswana','Brazil','British Virgin Islands','Brunei','Bulgaria','Burkina-faso','Burundi','Cambodia','Cameroon','Canada','CapeVerde','CaymanIslands','Central African Republic','Chad','Chile','Colombia','Comoros','Congo-Brazzaville','Congo-Kinshasa','CostaRica','Croatia','Cyprus','Czech Republic','Denmark','Djibouti','Dominican Republic','Ecuador','Egypt','EISalvador','Equatorial Guinea','Eritrea','Estonia','Ethiopia','Fiji','Finland','Gabon','Gambia','Georgia','Ghana','Greece','Greenland','Guatemala','Guinea','Guyana','Haiti','Honduras','Hungary','Iceland','India','Indonesia','Iran','Iraq','Ireland','Isle of Man','Israel','Italy','Ivory Coast','Jamaica','Jordan','Kazakstan','Kenya','Kuwait','Kyrgyzstan','Laos','Latvia','Lebanon','Lesotho','Liberia','Libya','Lithuania','Luxembourg','Macedonia','Madagascar','Malawi','Malaysia','Maldives','Mali','Malta','Mauritania','Mauritius','Mexico','Moldova','Monaco','Mongolia','Montenegro','Morocco','Mozambique','Myanmar(Burma)','Namibia','Nepal','Netherlands','New Zealand','Nicaragua','Niger','Nigeria','NorthKorea','Norway','Oman','Pakistan','Panama','Paraguay','Peru','Philippines','Portugal','PuertoRico','Qatar','Romania','Russia','Rwanda','SanMarino','SaudiArabia','Senegal','Serbia','SierraLeone','Slovakia','Slovenia','Somalia','SouthAfrica','Spain','SriLanka','Sudan','Suriname','Swaziland','Sweden','Switzerland','Syria','Tajikstan','Tanzania','Thailand','Togo','Tonga','TrinidadandTobago','Tunisia','Turkey','Turkmenistan','U.S.Virgin Islands','Uganda','Ukraine','Uruguay','Uzbekistan','Venezuela','Vietnam','Yemen','Zambia','Zimbabwe','Andorra','Reunion','Poland','Guam','Vatican','Liechtensteins','Curacao','Seychelles','Antarctica','Gibraltar','Cuba','Faroe Islands','Ahvenanmaa','Bermuda','Timor-Leste'];
  115. const specialRegex = [
  116. /(\d\.)?\d+×/,
  117. /IPLC|IEPL|Kern|Edge|Pro|Std|Exp|Biz|Fam|Game|Buy|Zx|LB|Game/,
  118. ];
  119. const nameclear =
  120. /(套餐|到期|有效|剩余|版本|已用|过期|失联|测试|官方|网址|备用|群|TEST|客服|网站|获取|订阅|流量|机场|下次|官址|联系|邮箱|工单|学术|USE|USED|TOTAL|EXPIRE|EMAIL)/i;
  121. // prettier-ignore
  122. const regexArray=[/ˣ²/, /ˣ³/, /ˣ⁴/, /ˣ⁵/, /ˣ⁶/, /ˣ⁷/, /ˣ⁸/, /ˣ⁹/, /ˣ¹⁰/, /ˣ²⁰/, /ˣ³⁰/, /ˣ⁴⁰/, /ˣ⁵⁰/, /IPLC/i, /IEPL/i, /核心/, /边缘/, /高级/, /标准/, /实验/, /商宽/, /家宽/, /游戏|game/i, /购物/, /专线/, /LB/, /cloudflare/i, /\budp\b/i, /\bgpt\b/i,/udpn\b/];
  123. // prettier-ignore
  124. const valueArray= [ "2×","3×","4×","5×","6×","7×","8×","9×","10×","20×","30×","40×","50×","IPLC","IEPL","Kern","Edge","Pro","Std","Exp","Biz","Fam","Game","Buy","Zx","LB","CF","UDP","GPT","UDPN"];
  125. const nameblnx = /(高倍|(?!1)2+(x|倍)|ˣ²|ˣ³|ˣ⁴|ˣ⁵|ˣ¹⁰)/i;
  126. const namenx = /(高倍|(?!1)(0\.|\d)+(x|倍)|ˣ²|ˣ³|ˣ⁴|ˣ⁵|ˣ¹⁰)/i;
  127. const keya =
  128. /港|Hong|HK|新加坡|SG|Singapore|日本|Japan|JP|美国|United States|US|韩|土耳其|TR|Turkey|Korea|KR|🇸🇬|🇭🇰|🇯🇵|🇺🇸|🇰🇷|🇹🇷/i;
  129. const keyb =
  130. /(((1|2|3|4)\d)|(香港|Hong|HK) 0[5-9]|((新加坡|SG|Singapore|日本|Japan|JP|美国|United States|US|韩|土耳其|TR|Turkey|Korea|KR) 0[3-9]))/i;
  131. const rurekey = {
  132. GB: /UK/g,
  133. "B-G-P": /BGP/g,
  134. "Russia Moscow": /Moscow/g,
  135. "Korea Chuncheon": /Chuncheon|Seoul/g,
  136. "Hong Kong": /Hongkong|HONG KONG/gi,
  137. "United Kingdom London": /London|Great Britain/g,
  138. "Dubai United Arab Emirates": /United Arab Emirates/g,
  139. "Taiwan TW 台湾 🇹🇼": /(台|Tai\s?wan|TW).*?🇨🇳|🇨🇳.*?(台|Tai\s?wan|TW)/g,
  140. "United States": /USA|Los Angeles|San Jose|Silicon Valley|Michigan/g,
  141. 澳大利亚: /澳洲|墨尔本|悉尼|土澳|(深|沪|呼|京|广|杭)澳/g,
  142. 德国: /(深|沪|呼|京|广|杭)德(?!.*(I|线))|法兰克福|滬德/g,
  143. 香港: /(深|沪|呼|京|广|杭)港(?!.*(I|线))/g,
  144. 日本: /(深|沪|呼|京|广|杭|中|辽)日(?!.*(I|线))|东京|大坂/g,
  145. 新加坡: /狮城|(深|沪|呼|京|广|杭)新/g,
  146. 美国: /(深|沪|呼|京|广|杭)美|波特兰|芝加哥|哥伦布|纽约|硅谷|俄勒冈|西雅图|芝加哥/g,
  147. 波斯尼亚和黑塞哥维那: /波黑共和国/g,
  148. 印尼: /印度尼西亚|雅加达/g,
  149. 印度: /孟买/g,
  150. 阿联酋: /迪拜|阿拉伯联合酋长国/g,
  151. 孟加拉国: /孟加拉/g,
  152. 捷克: /捷克共和国/g,
  153. 台湾: /新台|新北|台(?!.*线)/g,
  154. Taiwan: /Taipei/g,
  155. 韩国: /春川|韩|首尔/g,
  156. Japan: /Tokyo|Osaka/g,
  157. 英国: /伦敦/g,
  158. India: /Mumbai/g,
  159. Germany: /Frankfurt/g,
  160. Switzerland: /Zurich/g,
  161. 俄罗斯: /莫斯科/g,
  162. 土耳其: /伊斯坦布尔/g,
  163. 泰国: /泰國|曼谷/g,
  164. 法国: /巴黎/g,
  165. G: /\d\s?GB/gi,
  166. Esnc: /esnc/gi,
  167. };
  168. let GetK = false, AMK = []
  169. function ObjKA(i) {
  170. GetK = true
  171. AMK = Object.entries(i)
  172. }
  173. function operator(pro) {
  174. const Allmap = {};
  175. const outList = getList(outputName);
  176. let inputList,
  177. retainKey = "";
  178. if (inname !== "") {
  179. inputList = [getList(inname)];
  180. } else {
  181. inputList = [ZH, FG, QC, EN];
  182. }
  183. inputList.forEach((arr) => {
  184. arr.forEach((value, valueIndex) => {
  185. Allmap[value] = outList[valueIndex];
  186. });
  187. });
  188. if (clear || nx || blnx || key) {
  189. pro = pro.filter((res) => {
  190. const resname = res.name;
  191. const shouldKeep =
  192. !(clear && nameclear.test(resname)) &&
  193. !(nx && namenx.test(resname)) &&
  194. !(blnx && !nameblnx.test(resname)) &&
  195. !(key && !(keya.test(resname) && /2|4|6|7/i.test(resname)));
  196. return shouldKeep;
  197. });
  198. }
  199. const BLKEYS = BLKEY ? BLKEY.split("+") : "";
  200. pro.forEach((e) => {
  201. let bktf = false, ens = e.name
  202. // 获取协议前缀 (新增)
  203. const protoLabel = addproto ? getProtocolLabel(e.type) : "";
  204. // 预处理 防止预判或遗漏
  205. Object.keys(rurekey).forEach((ikey) => {
  206. if (rurekey[ikey].test(e.name)) {
  207. e.name = e.name.replace(rurekey[ikey], ikey);
  208. if (BLKEY) {
  209. bktf = true
  210. let BLKEY_REPLACE = "",
  211. re = false;
  212. BLKEYS.forEach((i) => {
  213. if (i.includes(">") && ens.includes(i.split(">")[0])) {
  214. if (rurekey[ikey].test(i.split(">")[0])) {
  215. e.name += " " + i.split(">")[0]
  216. }
  217. if (i.split(">")[1]) {
  218. BLKEY_REPLACE = i.split(">")[1];
  219. re = true;
  220. }
  221. } else {
  222. if (ens.includes(i)) {
  223. e.name += " " + i
  224. }
  225. }
  226. retainKey = re
  227. ? BLKEY_REPLACE
  228. : BLKEYS.filter((items) => e.name.includes(items));
  229. });}
  230. }
  231. });
  232. if (blockquic == "on") {
  233. e["block-quic"] = "on";
  234. } else if (blockquic == "off") {
  235. e["block-quic"] = "off";
  236. } else {
  237. delete e["block-quic"];
  238. }
  239. // 自定义
  240. if (!bktf && BLKEY) {
  241. let BLKEY_REPLACE = "",
  242. re = false;
  243. BLKEYS.forEach((i) => {
  244. if (i.includes(">") && e.name.includes(i.split(">")[0])) {
  245. if (i.split(">")[1]) {
  246. BLKEY_REPLACE = i.split(">")[1];
  247. re = true;
  248. }
  249. }
  250. });
  251. retainKey = re
  252. ? BLKEY_REPLACE
  253. : BLKEYS.filter((items) => e.name.includes(items));
  254. }
  255. let ikey = "",
  256. ikeys = "";
  257. // 保留固定格式 倍率
  258. if (blgd) {
  259. regexArray.forEach((regex, index) => {
  260. if (regex.test(e.name)) {
  261. ikeys = valueArray[index];
  262. }
  263. });
  264. }
  265. // 正则 匹配倍率
  266. if (bl) {
  267. const match = e.name.match(
  268. /((倍率|X|x|×)\D?((\d{1,3}\.)?d+)\D?)|((\d{1,3}\.)?d+)(倍|X|x|×)/
  269. );
  270. if (match) {
  271. const rev = match[0].match(/(\d[\d.]*)/)[0];
  272. if (rev !== "1") {
  273. const newValue = rev + "×";
  274. ikey = newValue;
  275. }
  276. }
  277. }
  278. !GetK && ObjKA(Allmap)
  279. // 匹配 Allkey 地区
  280. const findKey = AMK.find(([key]) =>
  281. e.name.includes(key)
  282. )
  283. let firstName = "",
  284. nNames = "";
  285. if (nf) {
  286. firstName = FNAME;
  287. } else {
  288. nNames = FNAME;
  289. }
  290. if (findKey?.[1]) {
  291. const findKeyValue = findKey[1];
  292. let keyover = [],
  293. usflag = "";
  294. if (addflag) {
  295. const index = outList.indexOf(findKeyValue);
  296. if (index !== -1) {
  297. usflag = FG[index];
  298. usflag = usflag === "🇹🇼" ? "🇨🇳" : usflag;
  299. }
  300. }
  301. // 插入协议前缀 protoLabel (新增: 在 nNames/firstName 之后、地区名之前)
  302. keyover = keyover
  303. .concat(firstName, usflag, nNames, protoLabel, findKeyValue, retainKey, ikey, ikeys)
  304. .filter((k) => k !== "");
  305. e.name = keyover.join(FGF);
  306. } else {
  307. if (nm) {
  308. // 未匹配节点也加协议前缀 (新增)
  309. e.name = [FNAME, protoLabel, e.name].filter(k => k !== "").join(FGF);
  310. } else {
  311. e.name = null;
  312. }
  313. }
  314. });
  315. pro = pro.filter((e) => e.name !== null);
  316. jxh(pro);
  317. numone && oneP(pro);
  318. blpx && (pro = fampx(pro));
  319. key && (pro = pro.filter((e) => !keyb.test(e.name)));
  320. return pro;
  321. }
  322. // prettier-ignore
  323. function getList(arg) { switch (arg) { case 'us': return EN; case 'gq': return FG; case 'quan': return QC; default: return ZH; }}
  324. // prettier-ignore
  325. function jxh(e) { const n = e.reduce((e, n) => { const t = e.find((e) => e.name === n.name); if (t) { t.count++; t.items.push({ ...n, name: `${n.name}${XHFGF}${t.count.toString().padStart(2, "0")}`, }); } else { e.push({ name: n.name, count: 1, items: [{ ...n, name: `${n.name}${XHFGF}01` }], }); } return e; }, []);const t=(typeof Array.prototype.flatMap==='function'?n.flatMap((e) => e.items):n.reduce((acc, e) => acc.concat(e.items),[])); e.splice(0, e.length, ...t); return e;}
  326. // prettier-ignore
  327. function oneP(e) { const t = e.reduce((e, t) => { const n = t.name.replace(/[^A-Za-z0-9\u00C0-\u017F\u4E00-\u9FFF]+\d+$/, ""); if (!e[n]) { e[n] = []; } e[n].push(t); return e; }, {}); for (const e in t) { if (t[e].length === 1 && t[e][0].name.endsWith("01")) {/* const n = t[e][0]; n.name = e;*/ t[e][0].name= t[e][0].name.replace(/[^.]01/, "") } } return e; }
  328. // prettier-ignore
  329. function fampx(pro) { const wis = []; const wnout = []; for (const proxy of pro) { const fan = specialRegex.some((regex) => regex.test(proxy.name)); if (fan) { wis.push(proxy); } else { wnout.push(proxy); } } const sps = wis.map((proxy) => specialRegex.findIndex((regex) => regex.test(proxy.name)) ); wis.sort( (a, b) => sps[wis.indexOf(a)] - sps[wis.indexOf(b)] || a.name.localeCompare(b.name) ); wnout.sort((a, b) => pro.indexOf(a) - pro.indexOf(b)); return wnout.concat(wis);}