Files
script/substore/yinyun-rename.js
T
orion 45a1b883a6 feat(substore): 新增 YinYun 订阅重命名脚本
* 新增 yinyun-rename.js 专门处理 YinYun 节点命名
* 实现中文地区名转短码及地区内连续编号逻辑
* 忽略优选、(T)/(R) 线路标记等原始冗余信息
* 更新 README 文档,补充 YinYun 脚本职责与规则说明
* 在文档注意事项中增加对新脚本的使用建议说明
2026-07-02 23:01:28 +08:00

127 lines
4.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* YinYun 专用节点清理脚本
* - 将中文地区名压成国家短码并补齐国旗
* - 忽略 YinYun 原始的 优选、数字编号和 (T)/(R) 线路标记
* - 按地区出现顺序连续编号,方便全局 rename.js 再追加订阅后缀
*/
// noinspection JSUnusedGlobalSymbols
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 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 regionAliases = [
['哈萨克斯坦', 'KZ'],
['印度尼西亚', 'ID'],
['孟加拉国', 'BD'],
['澳大利亚', 'AU'],
['保加利亚', 'BG'],
['格鲁吉亚', 'GE'],
['立陶宛', 'LT'],
['俄罗斯', 'RU'],
['新加坡', 'SG'],
['马来西亚', 'MY'],
['罗马尼亚', 'RO'],
['亚美尼亚', 'AM'],
['葡萄牙', 'PT'],
['拉脱维亚', 'LV'],
['加拿大', 'CA'],
['加拿大 01', 'CA'],
['澳洲', 'AU'],
['捷克', 'CZ'],
['南非', 'ZA'],
['芬兰', 'FI'],
['瑞士', 'CH'],
['墨西哥', 'MX'],
['瑞典', 'SE'],
['比利时', 'BE'],
['阿联酋', 'AE'],
['法国', 'FR'],
['波兰', 'PL'],
['荷兰', 'NL'],
['奥地利', 'AT'],
['巴西', 'BR'],
['土耳其', 'TR'],
['以色列', 'IL'],
['意大利', 'IT'],
['西班牙', 'ES'],
['香港', 'HK'],
['美国', 'US'],
['日本', 'JP'],
['韩国', 'KR'],
['台湾', 'TW']
];
const regionResolver = utils.createRegionResolver(regionAliases);
const stripExistingSuffix = name => String(name)
.replace(/\s+-\s*YinYun(?:\s+\d{2})?\s*$/i, '')
.trim();
const stripLineType = name => String(name)
.replace(/\s*[(]\s*[TR]\s*[)]\s*$/i, '')
.trim();
const leadingRegionPrefixOf = name => {
const match = String(name).match(/^([A-Z]{2})(?:\s+([A-Z]{3}))?(?=\s|$|-|\d|\|)/);
if (!match) return '';
return match[2] ? `${match[1]} ${match[2]}` : match[1];
};
const regionPrefixOf = name => {
if (/魔法节点/i.test(name)) return 'MAGIC';
return regionResolver.aliasRegionPrefixOf(name) || leadingRegionPrefixOf(name);
};
const regionCount = Object.create(null);
return proxies.map(proxy => {
if (typeof proxy.name !== 'string') {
return proxy;
}
const cleanName = stripExistingSuffix(proxy.name);
const { text } = utils.splitLeadingOrInlineFlag(cleanName);
const coreName = stripLineType(text);
const regionPrefix = regionPrefixOf(coreName);
if (!regionPrefix) {
proxy.name = coreName;
return proxy;
}
regionCount[regionPrefix] = (regionCount[regionPrefix] || 0) + 1;
const sequence = String(regionCount[regionPrefix]).padStart(2, '0');
const regionCode = regionPrefix.split(/\s+/)[0];
const flag = regionPrefix === 'MAGIC' ? '' : utils.regionCodeToFlag(regionCode);
proxy.name = [
flag,
regionPrefix,
sequence
].filter(Boolean).join(' ').trim();
return proxy;
});
}