From 354521d161b1c2fcaca207fb5cae33ae8853e5b6 Mon Sep 17 00:00:00 2001 From: Orion Date: Wed, 3 Jun 2026 15:47:30 +0800 Subject: [PATCH] fix(substore): normalize mojibake flag prefixes --- substore/README.md | 2 +- substore/alphaair-rename.js | 2 +- substore/common.js | 46 +++++++++++++++++++++++++++++-------- substore/liangxin-rename.js | 2 +- substore/peiqian-rename.js | 2 +- substore/rename.js | 6 ++++- substore/sntp-rename.js | 2 +- substore/yuetong-rename.js | 2 +- 8 files changed, 47 insertions(+), 17 deletions(-) diff --git a/substore/README.md b/substore/README.md index e6e3ac4..cd74603 100644 --- a/substore/README.md +++ b/substore/README.md @@ -5,7 +5,7 @@ `common.js` 是公共工具库,各处理脚本会按下面的 raw 地址自动加载: ```text -https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-3 +https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-4 ``` ## 推荐使用顺序 diff --git a/substore/alphaair-rename.js b/substore/alphaair-rename.js index 0158c29..73ccc51 100644 --- a/substore/alphaair-rename.js +++ b/substore/alphaair-rename.js @@ -6,7 +6,7 @@ * - 不追加订阅后缀,整合订阅最后仍交给 rename.js 处理 */ // noinspection JSUnusedGlobalSymbols -const COMMON_SCRIPT_URL = 'https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-3'; +const COMMON_SCRIPT_URL = 'https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-4'; async function loadRenameUtils() { if (typeof globalThis !== 'undefined' && globalThis.SubStoreRenameUtils) { diff --git a/substore/common.js b/substore/common.js index 45ca34f..23ec6e7 100644 --- a/substore/common.js +++ b/substore/common.js @@ -2,12 +2,13 @@ * Sub-Store 节点命名公共工具 * * 远程引用地址: - * https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-3 + * https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-4 */ (function (root) { const regexSpecialChars = new Set(['.', '*', '+', '?', '^', '$', '{', '}', '(', ')', '|', '[', ']', '\\']); const leadingFlagRegex = /^([\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 escapeRegex = value => [...String(value)] .map(char => regexSpecialChars.has(char) ? `\\${char}` : char) @@ -17,7 +18,29 @@ .replace(/\s{2,}/g, ' ') .trim(); - const normalizeLeadingFlagSpacing = value => String(value) + const decodeMojibakeUtf8 = value => { + try { + const encoded = [...String(value)] + .map(char => `%${char.charCodeAt(0).toString(16).padStart(2, '0')}`) + .join(''); + return decodeURIComponent(encoded); + } catch (error) { + return ''; + } + }; + + const normalizeLeadingMojibakeFlag = value => String(value) + .replace(leadingMojibakeFlagRegex, (match, mojibakeFlag) => { + const decodedFlag = decodeMojibakeUtf8(mojibakeFlag); + return leadingFlagRegex.test(decodedFlag) ? `${decodedFlag} ` : ''; + }) + .trim(); + + const stripLeadingMojibakeFlag = value => String(value) + .replace(leadingMojibakeFlagRegex, '') + .trim(); + + const normalizeLeadingFlagSpacing = value => normalizeLeadingMojibakeFlag(value) .replace(leadingFlagRegex, '$1 ') .replace(/\s{2,}/g, ' ') .trim(); @@ -51,17 +74,18 @@ }; const splitLeadingFlag = name => { - const leadingFlagMatch = String(name).match(leadingFlagRegex); - if (!leadingFlagMatch) return { flag: '', text: String(name).trim() }; + const cleanName = normalizeLeadingMojibakeFlag(name); + const leadingFlagMatch = cleanName.match(leadingFlagRegex); + if (!leadingFlagMatch) return { flag: '', text: cleanName.trim() }; return { flag: leadingFlagMatch[1], - text: String(name).slice(leadingFlagMatch[0].length).trim() + text: cleanName.slice(leadingFlagMatch[0].length).trim() }; }; const splitLeadingOrInlineFlag = name => { - const cleanName = String(name); + const cleanName = normalizeLeadingMojibakeFlag(name); const leadingFlagMatch = cleanName.match(leadingFlagRegex); if (leadingFlagMatch) { return { @@ -89,7 +113,7 @@ const sortedAliases = sortRegionAliases(aliases); const regionCodeOf = name => { - const cleanName = String(name); + const cleanName = normalizeLeadingMojibakeFlag(name); const leadingFlagMatch = cleanName.match(leadingFlagRegex); if (leadingFlagMatch) return flagToRegionCode(leadingFlagMatch[1]); @@ -108,7 +132,7 @@ }; const aliasRegionPrefixOf = name => { - const cleanNameLower = String(name).toLowerCase(); + const cleanNameLower = stripLeadingMojibakeFlag(name).toLowerCase(); for (const [, replacement, aliasLower] of sortedAliases) { if (cleanNameLower.includes(aliasLower)) return replacement; } @@ -117,7 +141,7 @@ }; const normalizeLeadingRegion = name => { - const cleanName = String(name).trim(); + const cleanName = stripLeadingMojibakeFlag(name); const cleanNameLower = cleanName.toLowerCase(); for (const [alias, replacement, aliasLower] of sortedAliases) { @@ -254,7 +278,7 @@ const embeddedDescriptorRegex = new RegExp(`\\s*(?:${descriptorPattern})(?=\\s|\\d|$)`, 'gi'); const bracketDescriptorRegex = new RegExp(`\\s*\\[(?:${descriptorPattern})(?:\\s+(?:${descriptorPattern}))*]\\s*`, 'gi'); - const [head, ...segments] = String(name).split('|'); + const [head, ...segments] = stripLeadingMojibakeFlag(name).split('|'); const keptSegments = segments .map(segment => segment.trim()) .filter(segment => segment && !descriptorOnlyRegex.test(segment)); @@ -282,11 +306,13 @@ moveMultiplierToEnd, normalizeHyphenatedRegionFeatures, normalizeLeadingFlagSpacing, + normalizeLeadingMojibakeFlag, normalizeMultiplierText, normalizeRegionSequence, normalizeWhitespace, regionCodeToFlag, sortRegionAliases, + stripLeadingMojibakeFlag, splitLeadingFlag, splitLeadingOrInlineFlag, stripLineDescriptors diff --git a/substore/liangxin-rename.js b/substore/liangxin-rename.js index 371158b..a975f9f 100644 --- a/substore/liangxin-rename.js +++ b/substore/liangxin-rename.js @@ -3,7 +3,7 @@ * 负责去掉高速、BGP、CMCU 等 LiangXin 线路描述,保留地区、序号和倍率。 */ // noinspection JSUnusedGlobalSymbols -const COMMON_SCRIPT_URL = 'https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-3'; +const COMMON_SCRIPT_URL = 'https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-4'; async function loadRenameUtils() { if (typeof globalThis !== 'undefined' && globalThis.SubStoreRenameUtils) { diff --git a/substore/peiqian-rename.js b/substore/peiqian-rename.js index 7a9a4ad..bf40542 100644 --- a/substore/peiqian-rename.js +++ b/substore/peiqian-rename.js @@ -3,7 +3,7 @@ * 负责清理推荐、用途、hy2、倍率、线路特征和提供商等 PeiQian 节点文案。 */ // noinspection JSUnusedGlobalSymbols -const COMMON_SCRIPT_URL = 'https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-3'; +const COMMON_SCRIPT_URL = 'https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-4'; async function loadRenameUtils() { if (typeof globalThis !== 'undefined' && globalThis.SubStoreRenameUtils) { diff --git a/substore/rename.js b/substore/rename.js index 84192eb..9f9434c 100644 --- a/substore/rename.js +++ b/substore/rename.js @@ -5,7 +5,7 @@ * - 基于归一化后的完整名称做精准去重 */ // noinspection JSUnusedGlobalSymbols -const COMMON_SCRIPT_URL = 'https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-3'; +const COMMON_SCRIPT_URL = 'https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-4'; async function loadRenameUtils() { if (typeof globalThis !== 'undefined' && globalThis.SubStoreRenameUtils) { @@ -581,6 +581,9 @@ async function operator(proxies) { const escapeRegex = utils.escapeRegex; const leadingFlagRegex = /^([\u{1F1E6}-\u{1F1FF}]{2}|🏴‍☠️)\s*/u; const inlineFlagRegex = /^(.{1,24}?)([\u{1F1E6}-\u{1F1FF}]{2}|🏴‍☠️)\s*(.*)$/u; + const normalizeLeadingMojibakeFlag = utils.normalizeLeadingMojibakeFlag + || utils.stripLeadingMojibakeFlag + || (name => String(name).trim()); const flagToRegionCode = flag => utils.flagToRegionCode(flag, flagCodeOverrides); @@ -726,6 +729,7 @@ async function operator(proxies) { }; const normalizeCoreName = name => { + name = normalizeLeadingMojibakeFlag(name); const leadingFlagMatch = name.match(leadingFlagRegex); const inlineFlagMatch = leadingFlagMatch ? null diff --git a/substore/sntp-rename.js b/substore/sntp-rename.js index a264b80..98b3e52 100644 --- a/substore/sntp-rename.js +++ b/substore/sntp-rename.js @@ -4,7 +4,7 @@ * 维护说明:仅需修改 featureMap 字典即可,底部逻辑永远无需改动。 */ // noinspection JSUnusedGlobalSymbols -const COMMON_SCRIPT_URL = 'https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-3'; +const COMMON_SCRIPT_URL = 'https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-4'; async function loadRenameUtils() { if (typeof globalThis !== 'undefined' && globalThis.SubStoreRenameUtils) { diff --git a/substore/yuetong-rename.js b/substore/yuetong-rename.js index df67c36..641b1cb 100644 --- a/substore/yuetong-rename.js +++ b/substore/yuetong-rename.js @@ -4,7 +4,7 @@ * 按地区稳定归并后重新连续编号,避免专属/普通节点撞号。 */ // noinspection JSUnusedGlobalSymbols -const COMMON_SCRIPT_URL = 'https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-3'; +const COMMON_SCRIPT_URL = 'https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-4'; async function loadRenameUtils() { if (typeof globalThis !== 'undefined' && globalThis.SubStoreRenameUtils) {