🧹 修复(substore): 归一化自建节点提供商命名
This commit is contained in:
+77
-2
@@ -584,6 +584,11 @@ async function operator(proxies) {
|
|||||||
regionAliases.map(([, replacement]) => replacement.split(/\s+/)[0])
|
regionAliases.map(([, replacement]) => replacement.split(/\s+/)[0])
|
||||||
);
|
);
|
||||||
Object.values(flagCodeOverrides).forEach(code => knownRegionCodes.add(code));
|
Object.values(flagCodeOverrides).forEach(code => knownRegionCodes.add(code));
|
||||||
|
const knownCityCodes = new Set(
|
||||||
|
regionAliases
|
||||||
|
.map(([, replacement]) => replacement.split(/\s+/)[1])
|
||||||
|
.filter(code => /^[A-Z]{3}$/.test(code || ''))
|
||||||
|
);
|
||||||
|
|
||||||
const escapeRegex = utils.escapeRegex;
|
const escapeRegex = utils.escapeRegex;
|
||||||
const leadingFlagRegex = /^([\u{1F1E6}-\u{1F1FF}]{2}|🏴☠️)\s*/u;
|
const leadingFlagRegex = /^([\u{1F1E6}-\u{1F1FF}]{2}|🏴☠️)\s*/u;
|
||||||
@@ -594,6 +599,16 @@ async function operator(proxies) {
|
|||||||
|
|
||||||
const flagToRegionCode = flag => utils.flagToRegionCode(flag, flagCodeOverrides);
|
const flagToRegionCode = flag => utils.flagToRegionCode(flag, flagCodeOverrides);
|
||||||
|
|
||||||
|
const providerAliases = [
|
||||||
|
['搬瓦工', 'BWH'],
|
||||||
|
['Bandwagon', 'BWH'],
|
||||||
|
['BWG', 'BWH'],
|
||||||
|
['BWH', 'BWH'],
|
||||||
|
['SkyStroll', 'SkyStroll'],
|
||||||
|
['ISIF', 'ISIF'],
|
||||||
|
['RFC', 'RFC']
|
||||||
|
];
|
||||||
|
|
||||||
const stripExistingSuffix = (name, subName) => {
|
const stripExistingSuffix = (name, subName) => {
|
||||||
if (!subName) return name.trim();
|
if (!subName) return name.trim();
|
||||||
const suffixRegex = suffixRegexCache[subName] || (
|
const suffixRegex = suffixRegexCache[subName] || (
|
||||||
@@ -653,6 +668,59 @@ async function operator(proxies) {
|
|||||||
return rest ? `${regionCode} Pro-${rest}` : regionCode;
|
return rest ? `${regionCode} Pro-${rest}` : regionCode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const providerOf = name => {
|
||||||
|
const cleanName = String(name);
|
||||||
|
for (const [alias, provider] of providerAliases) {
|
||||||
|
const aliasRegex = /^[A-Za-z0-9.]+$/.test(alias)
|
||||||
|
? new RegExp(`(^|[^A-Za-z0-9])${escapeRegex(alias)}([^A-Za-z0-9]|$)`, 'i')
|
||||||
|
: new RegExp(escapeRegex(alias), 'i');
|
||||||
|
if (aliasRegex.test(cleanName)) return provider;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const embeddedRegionPrefixOf = (name, fallbackRegionCode) => {
|
||||||
|
const cleanName = String(name);
|
||||||
|
const candidates = [];
|
||||||
|
if (fallbackRegionCode) {
|
||||||
|
candidates.push({ index: -1, region: fallbackRegionCode });
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [alias, replacement, aliasLower] of sortedRegionAliases) {
|
||||||
|
const aliasRegex = /^[A-Za-z0-9 ]+$/.test(alias)
|
||||||
|
? new RegExp(`(^|[^A-Za-z])${escapeRegex(alias)}(?=$|[^A-Za-z])`, 'i')
|
||||||
|
: new RegExp(escapeRegex(alias), 'i');
|
||||||
|
const match = cleanName.match(aliasRegex);
|
||||||
|
if (!match) continue;
|
||||||
|
|
||||||
|
const matchIndex = match.index + (match[1] ? match[1].length : 0);
|
||||||
|
candidates.push({ index: matchIndex, region: replacement });
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const match of cleanName.matchAll(/(^|[^A-Za-z])([A-Z]{2})(?:\d{1,2})?(?=$|[^A-Za-z])/g)) {
|
||||||
|
const regionCode = match[2].toUpperCase();
|
||||||
|
if (!knownRegionCodes.has(regionCode)) continue;
|
||||||
|
|
||||||
|
candidates.push({
|
||||||
|
index: match.index + (match[1] ? match[1].length : 0),
|
||||||
|
region: regionCode
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
candidates.sort((firstCandidate, secondCandidate) => firstCandidate.index - secondCandidate.index);
|
||||||
|
return candidates.length ? candidates[0].region : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const normalizeProviderRegionName = (name, fallbackRegionCode) => {
|
||||||
|
if (/^[A-Z]{2}(?:\s+[A-Z]{3})?\s+\d{2}(?=$|\s)/.test(name)) return name;
|
||||||
|
|
||||||
|
const provider = providerOf(name);
|
||||||
|
if (!provider) return name;
|
||||||
|
|
||||||
|
const regionPrefix = embeddedRegionPrefixOf(name, fallbackRegionCode);
|
||||||
|
return regionPrefix ? `${regionPrefix} ${provider}` : name;
|
||||||
|
};
|
||||||
|
|
||||||
const simplifyCoreName = name => {
|
const simplifyCoreName = name => {
|
||||||
return name
|
return name
|
||||||
.replace(/[\u{1F300}-\u{1FAFF}\u{2600}-\u{27BF}\uFE0F]/gu, '')
|
.replace(/[\u{1F300}-\u{1FAFF}\u{2600}-\u{27BF}\uFE0F]/gu, '')
|
||||||
@@ -686,9 +754,14 @@ async function operator(proxies) {
|
|||||||
if (!sequenceMatch) return null;
|
if (!sequenceMatch) return null;
|
||||||
|
|
||||||
const prefix = sequenceMatch[1] || '';
|
const prefix = sequenceMatch[1] || '';
|
||||||
const regionCode = sequenceMatch[2];
|
let regionCode = sequenceMatch[2];
|
||||||
const sequenceNumber = sequenceMatch[3] || '';
|
const sequenceNumber = sequenceMatch[3] || '';
|
||||||
const rest = sequenceMatch[4] || '';
|
let rest = sequenceMatch[4] || '';
|
||||||
|
const cityCodeMatch = regionCode.match(/^([A-Z]{2})\s+([A-Z]{3})$/);
|
||||||
|
if (cityCodeMatch && !knownCityCodes.has(cityCodeMatch[2])) {
|
||||||
|
regionCode = cityCodeMatch[1];
|
||||||
|
rest = ` ${cityCodeMatch[2]}${rest}`;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
prefix,
|
prefix,
|
||||||
@@ -777,6 +850,8 @@ async function operator(proxies) {
|
|||||||
.trim();
|
.trim();
|
||||||
|
|
||||||
const flagRegionCode = flagToRegionCode(flag);
|
const flagRegionCode = flagToRegionCode(flag);
|
||||||
|
core = normalizeProviderRegionName(core, flagRegionCode);
|
||||||
|
|
||||||
core = moveProRegionToFront(core, flagRegionCode);
|
core = moveProRegionToFront(core, flagRegionCode);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|||||||
Reference in New Issue
Block a user