Files

91 lines
3.7 KiB
JavaScript

/**
* Sub-Store 整合订阅后缀脚本
* - 保留节点原名,只追加当前订阅的 `_subName`
* - 重复执行不会叠加相同的订阅后缀
* - 同名节点追加两位编号,避免节点名重复
*/
// noinspection JSUnusedGlobalSymbols
const COMMON_SCRIPT_VERSION = '20260702-1';
const COMMON_SCRIPT_URL = `https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=${COMMON_SCRIPT_VERSION}`;
const hasCurrentRenameUtils = utils => Boolean(
utils && utils.version === COMMON_SCRIPT_VERSION
);
async function loadRenameUtils() {
if (typeof globalThis !== 'undefined' && hasCurrentRenameUtils(globalThis.SubStoreRenameUtils)) {
return globalThis.SubStoreRenameUtils;
}
const cache = typeof scriptResourceCache !== 'undefined' ? scriptResourceCache : null;
let script = cache && cache.get(COMMON_SCRIPT_URL);
if (!script) {
const response = await $substore.http.get({ url: COMMON_SCRIPT_URL });
script = response && (response.body || response.data || response);
if (cache) cache.set(COMMON_SCRIPT_URL, script);
}
new Function(String(script))();
if (!hasCurrentRenameUtils(globalThis.SubStoreRenameUtils)) {
throw new Error('Loaded common.js is missing current rename utilities');
}
return globalThis.SubStoreRenameUtils;
}
async function operator(proxies) {
const utils = await loadRenameUtils();
const stripSubscriptionSuffix = utils.stripSubscriptionSuffix || ((name, subName) => {
const cleanSubName = String(subName || '').trim();
if (!cleanSubName) return String(name);
const escapeRegex = utils.escapeRegex || (value => String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
return String(name)
.replace(new RegExp(`\\s+-\\s*${escapeRegex(cleanSubName)}(?:\\s+\\d{2})?\\s*$`, 'i'), '')
.trim();
});
const nameCounts = Object.create(null);
const currentCounts = Object.create(null);
const baseNames = new Array(proxies.length);
const coreNames = new Array(proxies.length);
const subNames = new Array(proxies.length);
proxies.forEach((proxy, proxyIndex) => {
// 非对象或非字符串名称不参与处理,避免改动无效节点数据。
if (!proxy || typeof proxy !== 'object' || typeof proxy.name !== 'string') {
baseNames[proxyIndex] = null;
return;
}
const proxyName = proxy.name;
const subName = proxy && typeof proxy._subName === 'string'
? proxy._subName.trim()
: '';
// 没有订阅名时完全保留原字符串;公共工具的兼容实现会顺手 trim。
const coreName = subName ? stripSubscriptionSuffix(proxyName, subName) : proxyName;
const baseName = subName
? (coreName ? `${coreName} - ${subName}` : subName)
: coreName;
baseNames[proxyIndex] = baseName;
coreNames[proxyIndex] = coreName;
subNames[proxyIndex] = subName;
nameCounts[baseName] = (nameCounts[baseName] || 0) + 1;
});
return proxies.map((proxy, proxyIndex) => {
const baseName = baseNames[proxyIndex];
if (baseName === null || !proxy || typeof proxy !== 'object') return proxy;
if (nameCounts[baseName] > 1) {
currentCounts[baseName] = (currentCounts[baseName] || 0) + 1;
const duplicateNumber = String(currentCounts[baseName]).padStart(2, '0');
proxy.name = subNames[proxyIndex]
? `${coreNames[proxyIndex]} ${duplicateNumber} - ${subNames[proxyIndex]}`
: `${baseName} ${duplicateNumber}`;
} else {
proxy.name = baseName;
}
return proxy;
});
}