updated the shuffling algorithm and added a deduplication detection mechanism (#3521)

This commit is contained in:
Ahao
2025-05-16 12:26:50 +08:00
committed by GitHub
parent ddd85d4d87
commit 7acbb5da4f
3 changed files with 115 additions and 41 deletions

View File

@@ -65,6 +65,8 @@
- Mihomo 内核默认日志等级为 warn - Mihomo 内核默认日志等级为 warn
- Clash Verge Rev 应用默认日志等级为 warn - Clash Verge Rev 应用默认日志等级为 warn
- 重构了原来的 IP 信息请求重试机制,采用轮询检测,解决了 Network Error 和超时问题 - 重构了原来的 IP 信息请求重试机制,采用轮询检测,解决了 Network Error 和超时问题
- 对轮询检测机制进行了优化,引入洗牌算法来增强随机性。
- 对获取系统信息的流程进行了优化,并添加了去重检测机制,确保剔除重复的信息
## v2.2.3 ## v2.2.3

View File

@@ -26,28 +26,34 @@ export const SystemInfoCard = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const { isAdminMode, isSidecarMode, mutateRunningMode } = useSystemState(); const { isAdminMode, isSidecarMode, mutateRunningMode } = useSystemState();
// 系统信息状态 // 系统信息状态
const [systemState, setSystemState] = useState({ const [systemState, setSystemState] = useState({
osInfo: "", osInfo: "",
lastCheckUpdate: "-", lastCheckUpdate: "-",
}); });
// 初始化系统信息 // 初始化系统信息
useEffect(() => { useEffect(() => {
// 获取系统信息 // 获取系统信息
getSystemInfo() getSystemInfo()
.then((info) => { .then((info) => {
const lines = info.split("\n"); const lines = info.split("\n");
if (lines.length > 0) { if (lines.length > 0) {
const sysName = lines[0].split(": ")[1] || ""; const sysName = lines[0].split(": ")[1] || "";
const sysVersion = lines[1].split(": ")[1] || ""; let sysVersion = lines[1].split(": ")[1] || "";
setSystemState((prev) => ({
...prev, // 处理sysVersion前缀与sysName相同的情况
osInfo: `${sysName} ${sysVersion}`, if (sysName && sysVersion.toLowerCase().startsWith(sysName.toLowerCase())) {
})); sysVersion = sysVersion.substring(sysName.length).trim();
} }
})
.catch(console.error); setSystemState((prev) => ({
...prev,
osInfo: `${sysName} ${sysVersion}`,
}));
}
})
.catch(console.error);
// 获取最后检查更新时间 // 获取最后检查更新时间
const lastCheck = localStorage.getItem("last_check_update"); const lastCheck = localStorage.getItem("last_check_update");

View File

@@ -376,31 +376,97 @@ const IP_CHECK_SERVICES: ServiceConfig[] = [
}), }),
}, },
{ {
url: "https://ipinfo.io/json", url: "https://api.ipapi.is/",
mapping: (data) => { mapping: (data) => ({
const [asn, ...orgParts] = (data.org || '').split(' '); ip: data.ip || '',
const asnOrg = orgParts.join(' '); country_code: data.location?.country_code || '',
country: data.location?.country || '',
return { region: data.location?.state || '',
ip: data.ip || '', city: data.location?.city || '',
country_code: data.country || '', organization: data.asn?.org || data.company?.name || '',
country: data.country || '', asn: data.asn?.asn || 0,
region: data.region || '', asn_organization: data.asn?.org || '',
city: data.city || '', longitude: data.location?.longitude || 0,
organization: asnOrg || '', latitude: data.location?.latitude || 0,
asn: asn? parseInt(asn.replace('AS', '')) : 0, timezone: data.location?.timezone || '',
asn_organization: asnOrg || '', }),
longitude: parseFloat(data.loc?.split(',')[1] || '0'), },
latitude: parseFloat(data.loc?.split(',')[0] || '0'), {
timezone: data.timezone || '', url: "https://ipwho.is/",
}; mapping: (data) => ({
}, ip: data.ip || '',
country_code: data.country_code || '',
country: data.country || '',
region: data.region || '',
city: data.city || '',
organization: data.connection?.org || data.connection?.isp || '',
asn: data.connection?.asn || 0,
asn_organization: data.connection?.isp || '',
longitude: data.longitude || 0,
latitude: data.latitude || 0,
timezone: data.timezone?.id || '',
}),
}, },
]; ];
// 随机打乱服务列表顺序 // 随机服务列表洗牌函数
function shuffleServices() { function shuffleServices() {
return [...IP_CHECK_SERVICES].sort(() => Math.random() - 0.5); // 过滤无效服务并确保每个元素符合ServiceConfig接口
const validServices = IP_CHECK_SERVICES.filter(
(service): service is ServiceConfig =>
service !== null &&
service !== undefined &&
typeof service.url === 'string' &&
typeof service.mapping === 'function' // 添加对mapping属性的检查
);
if (validServices.length === 0) {
console.error('No valid services found in IP_CHECK_SERVICES');
return [];
}
// 使用单一Fisher-Yates洗牌算法增强随机性
const shuffled = [...validServices];
const length = shuffled.length;
// 使用多个种子进行多次洗牌
const seeds = [
Math.random(),
Date.now() / 1000,
performance.now() / 1000
];
for (const seed of seeds) {
const prng = createPrng(seed);
// Fisher-Yates洗牌算法
for (let i = length - 1; i > 0; i--) {
const j = Math.floor(prng() * (i + 1));
// 使用临时变量进行交换,避免解构赋值可能的问题
const temp = shuffled[i];
shuffled[i] = shuffled[j];
shuffled[j] = temp;
}
}
return shuffled;
}
// 创建一个简单的随机数生成器
function createPrng(seed: number): () => number {
// 使用xorshift32算法
let state = seed >>> 0;
// 如果种子为0设置一个默认值
if (state === 0) state = 123456789;
return function() {
state ^= state << 13;
state ^= state >>> 17;
state ^= state << 5;
return (state >>> 0) / 4294967296;
};
} }
// 获取当前IP和地理位置信息 // 获取当前IP和地理位置信息