♻️ refactor(substore): 重构 regex 缓存机制并升级公共脚本版本
This commit is contained in:
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
`common.js` 是公共工具库,各处理脚本会按下面的 raw 地址自动加载:
|
`common.js` 是公共工具库,各处理脚本会按下面的 raw 地址自动加载:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-7
|
https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260608-1
|
||||||
```
|
```
|
||||||
|
|
||||||
## 推荐使用顺序
|
## 推荐使用顺序
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* - 不追加订阅后缀,整合订阅最后仍交给 rename.js 处理
|
* - 不追加订阅后缀,整合订阅最后仍交给 rename.js 处理
|
||||||
*/
|
*/
|
||||||
// noinspection JSUnusedGlobalSymbols
|
// noinspection JSUnusedGlobalSymbols
|
||||||
const COMMON_SCRIPT_VERSION = '20260603-7';
|
const COMMON_SCRIPT_VERSION = '20260608-1';
|
||||||
const COMMON_SCRIPT_URL = `https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=${COMMON_SCRIPT_VERSION}`;
|
const COMMON_SCRIPT_URL = `https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=${COMMON_SCRIPT_VERSION}`;
|
||||||
const hasCurrentRenameUtils = utils => Boolean(
|
const hasCurrentRenameUtils = utils => Boolean(
|
||||||
utils && utils.version === COMMON_SCRIPT_VERSION
|
utils && utils.version === COMMON_SCRIPT_VERSION
|
||||||
@@ -132,13 +132,14 @@ async function operator(proxies) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const countryOrder = Object.create(null);
|
const countryOrder = Object.create(null);
|
||||||
|
let countryOrderCount = 0;
|
||||||
const normalizedItems = proxies.map((proxy, proxyIndex) => {
|
const normalizedItems = proxies.map((proxy, proxyIndex) => {
|
||||||
const normalizedItem = normalizeProxy(proxy, proxyIndex);
|
const normalizedItem = normalizeProxy(proxy, proxyIndex);
|
||||||
if (
|
if (
|
||||||
normalizedItem.countryCode &&
|
normalizedItem.countryCode &&
|
||||||
countryOrder[normalizedItem.countryCode] === undefined
|
countryOrder[normalizedItem.countryCode] === undefined
|
||||||
) {
|
) {
|
||||||
countryOrder[normalizedItem.countryCode] = Object.keys(countryOrder).length;
|
countryOrder[normalizedItem.countryCode] = countryOrderCount++;
|
||||||
}
|
}
|
||||||
return normalizedItem;
|
return normalizedItem;
|
||||||
});
|
});
|
||||||
|
|||||||
+46
-19
@@ -2,14 +2,16 @@
|
|||||||
* Sub-Store 节点命名公共工具
|
* Sub-Store 节点命名公共工具
|
||||||
*
|
*
|
||||||
* 远程引用地址:
|
* 远程引用地址:
|
||||||
* https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-7
|
* https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260608-1
|
||||||
*/
|
*/
|
||||||
(function (root) {
|
(function (root) {
|
||||||
const VERSION = '20260603-7';
|
const VERSION = '20260608-1';
|
||||||
const regexSpecialChars = new Set(['.', '*', '+', '?', '^', '$', '{', '}', '(', ')', '|', '[', ']', '\\']);
|
const regexSpecialChars = new Set(['.', '*', '+', '?', '^', '$', '{', '}', '(', ')', '|', '[', ']', '\\']);
|
||||||
const leadingFlagRegex = /^([\u{1F1E6}-\u{1F1FF}]{2}|🏴☠️)\s*/u;
|
const leadingFlagRegex = /^([\u{1F1E6}-\u{1F1FF}]{2}|🏴☠️)\s*/u;
|
||||||
const inlineFlagRegex = /^(.{1,24}?)([\u{1F1E6}-\u{1F1FF}]{2}|🏴☠️)\s*(.*)$/u;
|
const inlineFlagRegex = /^(.{1,24}?)([\u{1F1E6}-\u{1F1FF}]{2}|🏴☠️)\s*(.*)$/u;
|
||||||
const leadingMojibakeFlagRegex = /^((?:ð[\u0080-\u00BF]{3}){2})\s*/;
|
const leadingMojibakeFlagRegex = /^((?:ð[\u0080-\u00BF]{3}){2})\s*/;
|
||||||
|
const regionSequenceRegexCache = Object.create(null);
|
||||||
|
const lineDescriptorRegexCache = Object.create(null);
|
||||||
|
|
||||||
const escapeRegex = value => [...String(value)]
|
const escapeRegex = value => [...String(value)]
|
||||||
.map(char => regexSpecialChars.has(char) ? `\\${char}` : char)
|
.map(char => regexSpecialChars.has(char) ? `\\${char}` : char)
|
||||||
@@ -112,6 +114,14 @@
|
|||||||
|
|
||||||
const createRegionResolver = aliases => {
|
const createRegionResolver = aliases => {
|
||||||
const sortedAliases = sortRegionAliases(aliases);
|
const sortedAliases = sortRegionAliases(aliases);
|
||||||
|
const compiledAliases = sortedAliases.map(([alias, replacement, aliasLower]) => [
|
||||||
|
alias,
|
||||||
|
replacement,
|
||||||
|
aliasLower,
|
||||||
|
/^[A-Z]{2}$/.test(alias)
|
||||||
|
? new RegExp(`(^|[^A-Za-z])${escapeRegex(alias)}([^A-Za-z]|$)`, 'i')
|
||||||
|
: null
|
||||||
|
]);
|
||||||
|
|
||||||
const regionCodeOf = name => {
|
const regionCodeOf = name => {
|
||||||
const cleanName = normalizeLeadingMojibakeFlag(name);
|
const cleanName = normalizeLeadingMojibakeFlag(name);
|
||||||
@@ -119,9 +129,9 @@
|
|||||||
if (leadingFlagMatch) return flagToRegionCode(leadingFlagMatch[1]);
|
if (leadingFlagMatch) return flagToRegionCode(leadingFlagMatch[1]);
|
||||||
|
|
||||||
const cleanNameLower = cleanName.toLowerCase();
|
const cleanNameLower = cleanName.toLowerCase();
|
||||||
for (const [alias, replacement, aliasLower] of sortedAliases) {
|
for (const [alias, replacement, aliasLower, codeRegex] of compiledAliases) {
|
||||||
if (/^[A-Z]{2}$/.test(alias)) {
|
if (codeRegex) {
|
||||||
const codeMatch = cleanName.match(new RegExp(`(^|[^A-Za-z])${escapeRegex(alias)}([^A-Za-z]|$)`, 'i'));
|
const codeMatch = cleanName.match(codeRegex);
|
||||||
if (codeMatch) return replacement;
|
if (codeMatch) return replacement;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -134,7 +144,7 @@
|
|||||||
|
|
||||||
const aliasRegionPrefixOf = name => {
|
const aliasRegionPrefixOf = name => {
|
||||||
const cleanNameLower = stripLeadingMojibakeFlag(name).toLowerCase();
|
const cleanNameLower = stripLeadingMojibakeFlag(name).toLowerCase();
|
||||||
for (const [, replacement, aliasLower] of sortedAliases) {
|
for (const [, replacement, aliasLower] of compiledAliases) {
|
||||||
if (cleanNameLower.includes(aliasLower)) return replacement;
|
if (cleanNameLower.includes(aliasLower)) return replacement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +155,7 @@
|
|||||||
const cleanName = stripLeadingMojibakeFlag(name);
|
const cleanName = stripLeadingMojibakeFlag(name);
|
||||||
const cleanNameLower = cleanName.toLowerCase();
|
const cleanNameLower = cleanName.toLowerCase();
|
||||||
|
|
||||||
for (const [alias, replacement, aliasLower] of sortedAliases) {
|
for (const [alias, replacement, aliasLower] of compiledAliases) {
|
||||||
if (!cleanNameLower.startsWith(aliasLower)) continue;
|
if (!cleanNameLower.startsWith(aliasLower)) continue;
|
||||||
|
|
||||||
const rest = cleanName.slice(alias.length);
|
const rest = cleanName.slice(alias.length);
|
||||||
@@ -198,12 +208,22 @@
|
|||||||
|
|
||||||
const normalizeRegionSequence = (name, options) => {
|
const normalizeRegionSequence = (name, options) => {
|
||||||
const allowCityCode = Boolean(options && options.allowCityCode);
|
const allowCityCode = Boolean(options && options.allowCityCode);
|
||||||
const regionPattern = allowCityCode
|
const cacheKey = allowCityCode ? 'city' : 'country';
|
||||||
? '[A-Z]{2}(?:\\s+[A-Z]{3})?'
|
const cachedRegexes = regionSequenceRegexCache[cacheKey] || (
|
||||||
: '[A-Z]{2}';
|
regionSequenceRegexCache[cacheKey] = (() => {
|
||||||
|
const regionPattern = allowCityCode
|
||||||
|
? '[A-Z]{2}(?:\\s+[A-Z]{3})?'
|
||||||
|
: '[A-Z]{2}';
|
||||||
|
|
||||||
|
return {
|
||||||
|
sequenceRegex: new RegExp(`(^|\\s)(${regionPattern})[\\s|\\-]*(\\d{1,2})(?=$|[\\s|\\-[\\]])`, 'g'),
|
||||||
|
multiplierHyphenRegex: new RegExp(`(\\b${regionPattern} \\d{2})-\\s*(?=\\d+(?:\\.\\d+)?X\\b)`, 'g')
|
||||||
|
};
|
||||||
|
})()
|
||||||
|
);
|
||||||
|
|
||||||
return String(name)
|
return String(name)
|
||||||
.replace(new RegExp(`(^|\\s)(${regionPattern})[\\s|\\-]*(\\d{1,2})(?=$|[\\s|\\-[\\]])`, 'g'), (
|
.replace(cachedRegexes.sequenceRegex, (
|
||||||
match,
|
match,
|
||||||
prefix,
|
prefix,
|
||||||
regionCode,
|
regionCode,
|
||||||
@@ -221,7 +241,7 @@
|
|||||||
|
|
||||||
return `${prefix}${regionCode} ${sequenceNumber.padStart(2, '0')}`;
|
return `${prefix}${regionCode} ${sequenceNumber.padStart(2, '0')}`;
|
||||||
})
|
})
|
||||||
.replace(new RegExp(`(\\b${regionPattern} \\d{2})-\\s*(?=\\d+(?:\\.\\d+)?X\\b)`, 'g'), '$1 ')
|
.replace(cachedRegexes.multiplierHyphenRegex, '$1 ')
|
||||||
.replace(/\s{2,}/g, ' ')
|
.replace(/\s{2,}/g, ' ')
|
||||||
.trim();
|
.trim();
|
||||||
};
|
};
|
||||||
@@ -284,19 +304,26 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const stripLineDescriptors = (name, descriptorKeywords) => {
|
const stripLineDescriptors = (name, descriptorKeywords) => {
|
||||||
const descriptorPattern = descriptorKeywords.map(escapeRegex).join('|');
|
const descriptorCacheKey = descriptorKeywords.join('\u0000');
|
||||||
const descriptorOnlyRegex = new RegExp(`^(?:${descriptorPattern})+$`, 'i');
|
const descriptorRegexes = lineDescriptorRegexCache[descriptorCacheKey] || (
|
||||||
const embeddedDescriptorRegex = new RegExp(`\\s*(?:${descriptorPattern})(?=\\s|\\d|$)`, 'gi');
|
lineDescriptorRegexCache[descriptorCacheKey] = (() => {
|
||||||
const bracketDescriptorRegex = new RegExp(`\\s*\\[(?:${descriptorPattern})(?:\\s+(?:${descriptorPattern}))*]\\s*`, 'gi');
|
const descriptorPattern = descriptorKeywords.map(escapeRegex).join('|');
|
||||||
|
return {
|
||||||
|
descriptorOnlyRegex: new RegExp(`^(?:${descriptorPattern})+$`, 'i'),
|
||||||
|
embeddedDescriptorRegex: new RegExp(`\\s*(?:${descriptorPattern})(?=\\s|\\d|$)`, 'gi'),
|
||||||
|
bracketDescriptorRegex: new RegExp(`\\s*\\[(?:${descriptorPattern})(?:\\s+(?:${descriptorPattern}))*]\\s*`, 'gi')
|
||||||
|
};
|
||||||
|
})()
|
||||||
|
);
|
||||||
|
|
||||||
const [head, ...segments] = stripLeadingMojibakeFlag(name).split('|');
|
const [head, ...segments] = stripLeadingMojibakeFlag(name).split('|');
|
||||||
const keptSegments = segments
|
const keptSegments = segments
|
||||||
.map(segment => segment.trim())
|
.map(segment => segment.trim())
|
||||||
.filter(segment => segment && !descriptorOnlyRegex.test(segment));
|
.filter(segment => segment && !descriptorRegexes.descriptorOnlyRegex.test(segment));
|
||||||
|
|
||||||
const cleanHead = head
|
const cleanHead = head
|
||||||
.replace(bracketDescriptorRegex, ' ')
|
.replace(descriptorRegexes.bracketDescriptorRegex, ' ')
|
||||||
.replace(embeddedDescriptorRegex, '')
|
.replace(descriptorRegexes.embeddedDescriptorRegex, '')
|
||||||
.replace(leadingFlagRegex, '$1 ')
|
.replace(leadingFlagRegex, '$1 ')
|
||||||
.replace(/\s{2,}/g, ' ')
|
.replace(/\s{2,}/g, ' ')
|
||||||
.trim();
|
.trim();
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* 负责去掉高速、BGP、CMCU 等 LiangXin 线路描述,保留地区、序号和倍率。
|
* 负责去掉高速、BGP、CMCU 等 LiangXin 线路描述,保留地区、序号和倍率。
|
||||||
*/
|
*/
|
||||||
// noinspection JSUnusedGlobalSymbols
|
// noinspection JSUnusedGlobalSymbols
|
||||||
const COMMON_SCRIPT_VERSION = '20260603-7';
|
const COMMON_SCRIPT_VERSION = '20260608-1';
|
||||||
const COMMON_SCRIPT_URL = `https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=${COMMON_SCRIPT_VERSION}`;
|
const COMMON_SCRIPT_URL = `https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=${COMMON_SCRIPT_VERSION}`;
|
||||||
const hasCurrentRenameUtils = utils => Boolean(
|
const hasCurrentRenameUtils = utils => Boolean(
|
||||||
utils && utils.version === COMMON_SCRIPT_VERSION
|
utils && utils.version === COMMON_SCRIPT_VERSION
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* 负责清理推荐、用途、hy2、倍率、线路特征和提供商等 PeiQian 节点文案。
|
* 负责清理推荐、用途、hy2、倍率、线路特征和提供商等 PeiQian 节点文案。
|
||||||
*/
|
*/
|
||||||
// noinspection JSUnusedGlobalSymbols
|
// noinspection JSUnusedGlobalSymbols
|
||||||
const COMMON_SCRIPT_VERSION = '20260603-7';
|
const COMMON_SCRIPT_VERSION = '20260608-1';
|
||||||
const COMMON_SCRIPT_URL = `https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=${COMMON_SCRIPT_VERSION}`;
|
const COMMON_SCRIPT_URL = `https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=${COMMON_SCRIPT_VERSION}`;
|
||||||
const hasCurrentRenameUtils = utils => Boolean(
|
const hasCurrentRenameUtils = utils => Boolean(
|
||||||
utils && utils.version === COMMON_SCRIPT_VERSION
|
utils && utils.version === COMMON_SCRIPT_VERSION
|
||||||
|
|||||||
+30
-21
@@ -5,7 +5,7 @@
|
|||||||
* - 基于归一化后的完整名称做精准去重
|
* - 基于归一化后的完整名称做精准去重
|
||||||
*/
|
*/
|
||||||
// noinspection JSUnusedGlobalSymbols
|
// noinspection JSUnusedGlobalSymbols
|
||||||
const COMMON_SCRIPT_VERSION = '20260603-7';
|
const COMMON_SCRIPT_VERSION = '20260608-1';
|
||||||
const COMMON_SCRIPT_URL = `https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=${COMMON_SCRIPT_VERSION}`;
|
const COMMON_SCRIPT_URL = `https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=${COMMON_SCRIPT_VERSION}`;
|
||||||
const hasCurrentRenameUtils = utils => Boolean(
|
const hasCurrentRenameUtils = utils => Boolean(
|
||||||
utils && utils.version === COMMON_SCRIPT_VERSION
|
utils && utils.version === COMMON_SCRIPT_VERSION
|
||||||
@@ -608,6 +608,18 @@ async function operator(proxies) {
|
|||||||
['ISIF', 'ISIF'],
|
['ISIF', 'ISIF'],
|
||||||
['RFC', 'RFC']
|
['RFC', 'RFC']
|
||||||
];
|
];
|
||||||
|
const providerAliasMatchers = providerAliases.map(([alias, provider]) => [
|
||||||
|
provider,
|
||||||
|
/^[A-Za-z0-9.]+$/.test(alias)
|
||||||
|
? new RegExp(`(^|[^A-Za-z0-9])${escapeRegex(alias)}([^A-Za-z0-9]|$)`, 'i')
|
||||||
|
: new RegExp(escapeRegex(alias), 'i')
|
||||||
|
]);
|
||||||
|
const embeddedRegionAliasMatchers = sortedRegionAliases.map(([alias, replacement]) => [
|
||||||
|
replacement,
|
||||||
|
/^[A-Za-z0-9 ]+$/.test(alias)
|
||||||
|
? new RegExp(`(^|[^A-Za-z])${escapeRegex(alias)}(?=$|[^A-Za-z])`, 'i')
|
||||||
|
: new RegExp(escapeRegex(alias), 'i')
|
||||||
|
]);
|
||||||
|
|
||||||
const stripExistingSuffix = (name, subName) => {
|
const stripExistingSuffix = (name, subName) => {
|
||||||
if (!subName) return name.trim();
|
if (!subName) return name.trim();
|
||||||
@@ -670,45 +682,42 @@ async function operator(proxies) {
|
|||||||
|
|
||||||
const providerOf = name => {
|
const providerOf = name => {
|
||||||
const cleanName = String(name);
|
const cleanName = String(name);
|
||||||
for (const [alias, provider] of providerAliases) {
|
for (const [provider, aliasRegex] of providerAliasMatchers) {
|
||||||
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;
|
if (aliasRegex.test(cleanName)) return provider;
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
};
|
};
|
||||||
|
|
||||||
const embeddedRegionPrefixOf = (name, fallbackRegionCode) => {
|
const embeddedRegionPrefixOf = (name, fallbackRegionCode) => {
|
||||||
const cleanName = String(name);
|
if (fallbackRegionCode) return fallbackRegionCode;
|
||||||
const candidates = [];
|
|
||||||
if (fallbackRegionCode) {
|
|
||||||
candidates.push({ index: -1, region: fallbackRegionCode });
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [alias, replacement, aliasLower] of sortedRegionAliases) {
|
const cleanName = String(name);
|
||||||
const aliasRegex = /^[A-Za-z0-9 ]+$/.test(alias)
|
let bestIndex = Number.POSITIVE_INFINITY;
|
||||||
? new RegExp(`(^|[^A-Za-z])${escapeRegex(alias)}(?=$|[^A-Za-z])`, 'i')
|
let bestRegion = '';
|
||||||
: new RegExp(escapeRegex(alias), 'i');
|
|
||||||
|
for (const [replacement, aliasRegex] of embeddedRegionAliasMatchers) {
|
||||||
const match = cleanName.match(aliasRegex);
|
const match = cleanName.match(aliasRegex);
|
||||||
if (!match) continue;
|
if (!match) continue;
|
||||||
|
|
||||||
const matchIndex = match.index + (match[1] ? match[1].length : 0);
|
const matchIndex = match.index + (match[1] ? match[1].length : 0);
|
||||||
candidates.push({ index: matchIndex, region: replacement });
|
if (matchIndex < bestIndex) {
|
||||||
|
bestIndex = matchIndex;
|
||||||
|
bestRegion = replacement;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const match of cleanName.matchAll(/(^|[^A-Za-z])([A-Z]{2})(?:\d{1,2})?(?=$|[^A-Za-z])/g)) {
|
for (const match of cleanName.matchAll(/(^|[^A-Za-z])([A-Z]{2})(?:\d{1,2})?(?=$|[^A-Za-z])/g)) {
|
||||||
const regionCode = match[2].toUpperCase();
|
const regionCode = match[2].toUpperCase();
|
||||||
if (!knownRegionCodes.has(regionCode)) continue;
|
if (!knownRegionCodes.has(regionCode)) continue;
|
||||||
|
|
||||||
candidates.push({
|
const matchIndex = match.index + (match[1] ? match[1].length : 0);
|
||||||
index: match.index + (match[1] ? match[1].length : 0),
|
if (matchIndex < bestIndex) {
|
||||||
region: regionCode
|
bestIndex = matchIndex;
|
||||||
});
|
bestRegion = regionCode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
candidates.sort((firstCandidate, secondCandidate) => firstCandidate.index - secondCandidate.index);
|
return bestRegion;
|
||||||
return candidates.length ? candidates[0].region : '';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const normalizeProviderRegionName = (name, fallbackRegionCode) => {
|
const normalizeProviderRegionName = (name, fallbackRegionCode) => {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* 维护说明:仅需修改 featureMap 字典即可,底部逻辑永远无需改动。
|
* 维护说明:仅需修改 featureMap 字典即可,底部逻辑永远无需改动。
|
||||||
*/
|
*/
|
||||||
// noinspection JSUnusedGlobalSymbols
|
// noinspection JSUnusedGlobalSymbols
|
||||||
const COMMON_SCRIPT_VERSION = '20260603-7';
|
const COMMON_SCRIPT_VERSION = '20260608-1';
|
||||||
const COMMON_SCRIPT_URL = `https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=${COMMON_SCRIPT_VERSION}`;
|
const COMMON_SCRIPT_URL = `https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=${COMMON_SCRIPT_VERSION}`;
|
||||||
const hasCurrentRenameUtils = utils => Boolean(
|
const hasCurrentRenameUtils = utils => Boolean(
|
||||||
utils && utils.version === COMMON_SCRIPT_VERSION
|
utils && utils.version === COMMON_SCRIPT_VERSION
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* 按地区稳定归并后重新连续编号,避免专属/普通节点撞号。
|
* 按地区稳定归并后重新连续编号,避免专属/普通节点撞号。
|
||||||
*/
|
*/
|
||||||
// noinspection JSUnusedGlobalSymbols
|
// noinspection JSUnusedGlobalSymbols
|
||||||
const COMMON_SCRIPT_VERSION = '20260603-7';
|
const COMMON_SCRIPT_VERSION = '20260608-1';
|
||||||
const COMMON_SCRIPT_URL = `https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=${COMMON_SCRIPT_VERSION}`;
|
const COMMON_SCRIPT_URL = `https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=${COMMON_SCRIPT_VERSION}`;
|
||||||
const hasCurrentRenameUtils = utils => Boolean(
|
const hasCurrentRenameUtils = utils => Boolean(
|
||||||
utils && utils.version === COMMON_SCRIPT_VERSION
|
utils && utils.version === COMMON_SCRIPT_VERSION
|
||||||
|
|||||||
Reference in New Issue
Block a user