From ca3413a1eea8081fe21cee7a27058bff01140085 Mon Sep 17 00:00:00 2001 From: Orion Date: Wed, 3 Jun 2026 14:51:53 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(substore):=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E8=A7=84=E8=8C=83=E5=8C=96=E5=B8=A6=E8=BF=9E=E5=AD=97?= =?UTF-8?q?=E7=AC=A6=E7=9A=84=E8=8A=82=E7=82=B9=E5=8C=BA=E5=9F=9F=E7=89=B9?= =?UTF-8?q?=E5=BE=81=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- substore/README.md | 4 ++++ substore/common.js | 39 +++++++++++++++++++++++++++++++++++++++ substore/rename.js | 2 +- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/substore/README.md b/substore/README.md index 393d98b..a8437ff 100644 --- a/substore/README.md +++ b/substore/README.md @@ -143,6 +143,7 @@ https://git.orionc.me/orion/script/raw/branch/main/substore/common.js - 常见城市转短码,例如 `Los Angeles` -> `LAX`、`San Jose` -> `SJC`、`Seattle` -> `SEA`、`东京` -> `TYO`。 - 国家/地区别名表覆盖常见英文、中文国家名;城市尽量使用三字 IATA/城市码,避免 `LA` 这类两字码被旗帜操作误识别为国家。 - 支持国旗在中间的节点名,例如 `Pro-🇭🇰 Sharon|守夜人` -> `🇭🇰 HK Pro-Sharon|守夜人`。 +- 支持保留连字符命名里的入口/落地特征,例如 `HK-Go-05-HostHatch` -> `HK 05 GO-HostHatch`。 - 将倍率移动到节点核心末尾、订阅后缀之前,例如 `US 2X 02 - Alpha Air` -> `US 02 2X - Alpha Air`。 - 清理 `[DIP China-Hongkong]` 为 `[DIP]`。 - 清理 Alpha Flower 这类 `IEPL 专线 3`、`标准 1`、`高级 1` 的冗余线路尾号。 @@ -160,6 +161,9 @@ https://git.orionc.me/orion/script/raw/branch/main/substore/common.js Pro-🇭🇰 Sharon|守夜人 - Alpha 8K Snell => 🇭🇰 HK Pro-Sharon|守夜人 - Alpha 8K Snell + +🇭🇰 HK-Go-05-HostHatch - VK +=> 🇭🇰 HK 05 GO-HostHatch - VK ``` ## 注意事项 diff --git a/substore/common.js b/substore/common.js index b4c7e84..7e6cecd 100644 --- a/substore/common.js +++ b/substore/common.js @@ -191,6 +191,44 @@ .trim(); }; + const normalizeHyphenatedRegionFeatures = name => { + const hyphenatedMatch = String(name).match(/^([A-Z]{2})(?:\s+([A-Z]{3}))?-(.+)$/); + if (!hyphenatedMatch) return name; + + const countryCode = hyphenatedMatch[1]; + let regionCode = hyphenatedMatch[2] + ? `${countryCode} ${hyphenatedMatch[2]}` + : countryCode; + const tokens = hyphenatedMatch[3].split('-').map(token => token.trim()).filter(Boolean); + + if ( + !hyphenatedMatch[2] && + tokens.length >= 2 && + /^[A-Z]{3}$/.test(tokens[0]) && + /^\d{1,2}$/.test(tokens[1]) + ) { + regionCode = `${countryCode} ${tokens.shift()}`; + } + + const sequenceIndex = tokens.findIndex(token => /^\d{1,2}$/.test(token)); + if (sequenceIndex === -1) return name; + + const sequenceNumber = tokens[sequenceIndex].padStart(2, '0'); + const ingressTokens = tokens + .slice(0, sequenceIndex) + .map(token => token.toUpperCase()); + const egressTokens = tokens.slice(sequenceIndex + 1); + const featureText = ingressTokens.length && egressTokens.length + ? `${ingressTokens.join('-')}-${egressTokens.join('-')}` + : [...ingressTokens, ...egressTokens].join('-'); + + return [regionCode, sequenceNumber, featureText] + .filter(Boolean) + .join(' ') + .replace(/\s{2,}/g, ' ') + .trim(); + }; + const stripLineDescriptors = (name, descriptorKeywords) => { const descriptorPattern = descriptorKeywords.map(escapeRegex).join('|'); const descriptorOnlyRegex = new RegExp(`^(?:${descriptorPattern})+$`, 'i'); @@ -223,6 +261,7 @@ flagToRegionCode, joinAlias, moveMultiplierToEnd, + normalizeHyphenatedRegionFeatures, normalizeLeadingFlagSpacing, normalizeMultiplierText, normalizeRegionSequence, diff --git a/substore/rename.js b/substore/rename.js index 25fa158..fb4601c 100644 --- a/substore/rename.js +++ b/substore/rename.js @@ -770,7 +770,7 @@ async function operator(proxies) { core = joinAlias(flagRegionCode, core); } - core = normalizeRegionSequence(moveMultiplierToEnd(simplifyCoreName(core))) + core = normalizeRegionSequence(utils.normalizeHyphenatedRegionFeatures(moveMultiplierToEnd(simplifyCoreName(core)))) .replace(/^([A-Z]{2}(?:\s+[A-Z]{3})?\s+\d{2}\s+(?:标准|高级))\s+1(?=$|\s)/i, '$1'); return flag ? `${flag} ${core}` : core;