♻️ refactor(substore): 重构节点重命名脚本以支持更稳定的线路标识过滤与地区归并
This commit is contained in:
+20
-1
@@ -716,6 +716,25 @@ function operator(proxies) {
|
|||||||
.trim();
|
.trim();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const withInferredRegionSequence = sequenceInfo => {
|
||||||
|
const featureSequenceMatch = sequenceInfo.rest.match(/^\s+(专属|家宽|AI|高速|专线)\s+(\d{1,2})(?!\d)(?!\s*(?:[xX倍]|\.\d))(.*)$/i);
|
||||||
|
if (!featureSequenceMatch) return withRegionSequence(sequenceInfo, '01');
|
||||||
|
|
||||||
|
const featureName = featureSequenceMatch[1].toUpperCase() === 'AI'
|
||||||
|
? 'AI'
|
||||||
|
: featureSequenceMatch[1];
|
||||||
|
const inferredSequence = featureSequenceMatch[2].padStart(2, '0');
|
||||||
|
const remainingRest = featureSequenceMatch[3] || '';
|
||||||
|
|
||||||
|
return withRegionSequence(
|
||||||
|
{
|
||||||
|
...sequenceInfo,
|
||||||
|
rest: ` ${featureName}${remainingRest}`
|
||||||
|
},
|
||||||
|
inferredSequence
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const normalizeBilingualName = name => {
|
const normalizeBilingualName = name => {
|
||||||
const bilingualMatch = name.match(/^(.+?)\s*|\s*(.+)$/);
|
const bilingualMatch = name.match(/^(.+?)\s*|\s*(.+)$/);
|
||||||
if (!bilingualMatch) return name;
|
if (!bilingualMatch) return name;
|
||||||
@@ -802,7 +821,7 @@ function operator(proxies) {
|
|||||||
const sequenceInfo = sequenceInfos[proxyIndex];
|
const sequenceInfo = sequenceInfos[proxyIndex];
|
||||||
const needsLeadingSequence = sequenceInfo && !sequenceInfo.sequenceNumber;
|
const needsLeadingSequence = sequenceInfo && !sequenceInfo.sequenceNumber;
|
||||||
const coreName = needsLeadingSequence
|
const coreName = needsLeadingSequence
|
||||||
? withRegionSequence(sequenceInfo, '01')
|
? withInferredRegionSequence(sequenceInfo)
|
||||||
: normalizedCoreName;
|
: normalizedCoreName;
|
||||||
const baseName = subName ? `${coreName} - ${subName}` : coreName;
|
const baseName = subName ? `${coreName} - ${subName}` : coreName;
|
||||||
|
|
||||||
|
|||||||
+114
-4
@@ -1,21 +1,131 @@
|
|||||||
/**
|
/**
|
||||||
* YueTong 专用节点清理脚本
|
* YueTong 专用节点清理脚本
|
||||||
* 负责去掉“悦·”品牌前缀、钻石等装饰,以及压短 AI 解锁文案。
|
* 负责去掉“悦·”品牌前缀、钻石、专属/家宽等线路标识,以及压短 AI 解锁文案。
|
||||||
|
* 保留线路标识后面的序号,并按地区稳定归并。
|
||||||
*/
|
*/
|
||||||
// noinspection JSUnusedGlobalSymbols
|
// noinspection JSUnusedGlobalSymbols
|
||||||
function operator(proxies) {
|
function operator(proxies) {
|
||||||
return proxies.map(proxy => {
|
const regionAliases = [
|
||||||
|
['Hong Kong', 'HK'],
|
||||||
|
['香港', 'HK'],
|
||||||
|
['HK', 'HK'],
|
||||||
|
['Japan', 'JP'],
|
||||||
|
['日本', 'JP'],
|
||||||
|
['JP', 'JP'],
|
||||||
|
['Singapore', 'SG'],
|
||||||
|
['新加坡', 'SG'],
|
||||||
|
['狮城', 'SG'],
|
||||||
|
['SG', 'SG'],
|
||||||
|
['Taiwan', 'TW'],
|
||||||
|
['台湾', 'TW'],
|
||||||
|
['台灣', 'TW'],
|
||||||
|
['TW', 'TW'],
|
||||||
|
['United States', 'US'],
|
||||||
|
['America', 'US'],
|
||||||
|
['USA', 'US'],
|
||||||
|
['美国', 'US'],
|
||||||
|
['美國', 'US'],
|
||||||
|
['美西', 'US'],
|
||||||
|
['美东', 'US'],
|
||||||
|
['美東', 'US'],
|
||||||
|
['US', 'US'],
|
||||||
|
['Korea', 'KR'],
|
||||||
|
['韩国', 'KR'],
|
||||||
|
['韓國', 'KR'],
|
||||||
|
['KR', 'KR'],
|
||||||
|
['United Kingdom', 'UK'],
|
||||||
|
['Britain', 'UK'],
|
||||||
|
['英国', 'UK'],
|
||||||
|
['英國', 'UK'],
|
||||||
|
['UK', 'UK'],
|
||||||
|
['Germany', 'DE'],
|
||||||
|
['德国', 'DE'],
|
||||||
|
['德國', 'DE'],
|
||||||
|
['DE', 'DE'],
|
||||||
|
['Netherlands', 'NL'],
|
||||||
|
['荷兰', 'NL'],
|
||||||
|
['荷蘭', 'NL'],
|
||||||
|
['NL', 'NL']
|
||||||
|
];
|
||||||
|
const sortedRegionAliases = regionAliases
|
||||||
|
.map(([alias, replacement]) => [alias, replacement, alias.toLowerCase()])
|
||||||
|
.sort((firstAlias, secondAlias) => secondAlias[0].length - firstAlias[0].length);
|
||||||
|
const leadingFlagRegex = /^([\u{1F1E6}-\u{1F1FF}]{2})\s*/u;
|
||||||
|
|
||||||
|
const flagToRegionCode = flag => {
|
||||||
|
if (!flag) return '';
|
||||||
|
const codePoints = [...flag].map(char => char.codePointAt(0));
|
||||||
|
if (
|
||||||
|
codePoints.length !== 2 ||
|
||||||
|
codePoints.some(codePoint => codePoint < 0x1F1E6 || codePoint > 0x1F1FF)
|
||||||
|
) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const regionCode = codePoints
|
||||||
|
.map(codePoint => String.fromCharCode(codePoint - 0x1F1E6 + 65))
|
||||||
|
.join('');
|
||||||
|
return regionCode === 'GB' ? 'UK' : regionCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
const regionCodeOf = name => {
|
||||||
|
const leadingFlagMatch = name.match(leadingFlagRegex);
|
||||||
|
if (leadingFlagMatch) return flagToRegionCode(leadingFlagMatch[1]);
|
||||||
|
|
||||||
|
const nameLower = name.toLowerCase();
|
||||||
|
for (const [alias, replacement, aliasLower] of sortedRegionAliases) {
|
||||||
|
if (/^[A-Z]{2}$/.test(alias)) {
|
||||||
|
const codeMatch = name.match(new RegExp(`(^|[^A-Za-z])${alias}([^A-Za-z]|$)`, 'i'));
|
||||||
|
if (codeMatch) return replacement;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nameLower.includes(aliasLower)) return replacement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const normalizedItems = proxies.map((proxy, originalIndex) => {
|
||||||
if (typeof proxy.name !== 'string') {
|
if (typeof proxy.name !== 'string') {
|
||||||
return proxy;
|
return {
|
||||||
|
proxy,
|
||||||
|
originalIndex,
|
||||||
|
regionCode: ''
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy.name = proxy.name
|
proxy.name = proxy.name
|
||||||
.replace(/悦[·・]\s*/g, '')
|
.replace(/悦[·・]\s*/g, '')
|
||||||
.replace(/AI解锁/g, 'AI')
|
.replace(/AI解锁/g, 'AI')
|
||||||
|
.replace(/\s*(?:专属|家宽|高速|专线)(?:\s*(\d+)(?!\s*(?:[xX倍]|\.\d)))?/g, '$1')
|
||||||
.replace(/💎/gu, '')
|
.replace(/💎/gu, '')
|
||||||
|
.replace(/([\u4e00-\u9fff])AI\b/g, '$1 AI')
|
||||||
.replace(/\s{2,}/g, ' ')
|
.replace(/\s{2,}/g, ' ')
|
||||||
.trim();
|
.trim();
|
||||||
|
|
||||||
return proxy;
|
return {
|
||||||
|
proxy,
|
||||||
|
originalIndex,
|
||||||
|
regionCode: regionCodeOf(proxy.name)
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const regionOrder = Object.create(null);
|
||||||
|
const groupOrder = normalizedItems.map(item => {
|
||||||
|
if (!item.regionCode) return item.originalIndex;
|
||||||
|
if (regionOrder[item.regionCode] === undefined) {
|
||||||
|
regionOrder[item.regionCode] = item.originalIndex;
|
||||||
|
}
|
||||||
|
return regionOrder[item.regionCode];
|
||||||
|
});
|
||||||
|
|
||||||
|
normalizedItems.sort((firstItem, secondItem) => {
|
||||||
|
const firstGroupOrder = groupOrder[firstItem.originalIndex];
|
||||||
|
const secondGroupOrder = groupOrder[secondItem.originalIndex];
|
||||||
|
if (firstGroupOrder !== secondGroupOrder) return firstGroupOrder - secondGroupOrder;
|
||||||
|
return firstItem.originalIndex - secondItem.originalIndex;
|
||||||
|
});
|
||||||
|
|
||||||
|
return normalizedItems.map(item => item.proxy);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user