mihomo-cli 2.7.1 → 2.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/README.md +2 -2
- package/dist/index.js +15 -7
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.7.3] - 2026-05-04
|
|
4
|
+
|
|
5
|
+
### 改进
|
|
6
|
+
|
|
7
|
+
- **代码清理** - 提取 `DEFAULT_CLEAN_ROUNDS` 常量,消除重复魔数;简化进度条内部状态
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## [2.7.2] - 2026-05-04
|
|
12
|
+
|
|
13
|
+
### 修复
|
|
14
|
+
|
|
15
|
+
- **进度条轮次标题** - 多轮测试时第 1 轮标题正确显示在进度条之前,单轮不显示轮次标题
|
|
16
|
+
|
|
17
|
+
### 改进
|
|
18
|
+
|
|
19
|
+
- **自定义轮数** - clean 命令支持 `-r N` / `--rounds N` 指定测试轮数(默认 3)
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
3
23
|
## [2.7.1] - 2026-05-04
|
|
4
24
|
|
|
5
25
|
### 修复
|
package/README.md
CHANGED
|
@@ -102,9 +102,9 @@ mihomo ui yacd # YACD
|
|
|
102
102
|
| `mihomo sub remove <name>` | 删除订阅(支持模糊匹配) |
|
|
103
103
|
| `mihomo sub web [name]` | 打开订阅页面(无参打开默认) |
|
|
104
104
|
| `mihomo sub test [name]` | 测试节点连通性(`-t` 超时,`-j` 并发) |
|
|
105
|
-
| `mihomo sub clean [name]` |
|
|
105
|
+
| `mihomo sub clean [name]` | 测速并清理失败节点(`-r` 轮数,默认3)|
|
|
106
106
|
| `mihomo test` | 快速测试当前节点连通性(`-t` 超时,`-j` 并发) |
|
|
107
|
-
| `mihomo clean` | 清理失败节点并自动重启(`-t` 超时,`-j`
|
|
107
|
+
| `mihomo clean` | 清理失败节点并自动重启(`-t` 超时,`-j` 并发,`-r` 轮数) |
|
|
108
108
|
|
|
109
109
|
### 覆写配置
|
|
110
110
|
|
package/dist/index.js
CHANGED
|
@@ -4031,7 +4031,7 @@ ${colors.cyan("\u8BA2\u9605:")}
|
|
|
4031
4031
|
${colors.bold("subscription")} test [name] \u6D4B\u8BD5\u8282\u70B9\u8FDE\u901A\u6027
|
|
4032
4032
|
${colors.bold("subscription")} clean [name] \u6D4B\u901F\u5E76\u6E05\u7406\u5931\u8D25\u8282\u70B9
|
|
4033
4033
|
${colors.bold("test")} [-t ms] [-j N] \u5FEB\u901F\u6D4B\u8BD5\u5F53\u524D\u8282\u70B9\u8FDE\u901A\u6027
|
|
4034
|
-
${colors.bold("clean")} [-t ms] [-j N]
|
|
4034
|
+
${colors.bold("clean")} [-t ms] [-j N] [-r N] \u6E05\u7406\u5931\u8D25\u8282\u70B9\u5E76\u81EA\u52A8\u91CD\u542F
|
|
4035
4035
|
|
|
4036
4036
|
${colors.cyan("\u914D\u7F6E:")}
|
|
4037
4037
|
${colors.bold("overwrite")} \u67E5\u770B\u8986\u5199\u72B6\u6001\uFF08\u522B\u540D ow\uFF09
|
|
@@ -4433,6 +4433,7 @@ import path6 from "path";
|
|
|
4433
4433
|
|
|
4434
4434
|
// src/subscription.ts
|
|
4435
4435
|
var DEFAULT_UPDATE_INTERVAL_HOURS = 4;
|
|
4436
|
+
var DEFAULT_CLEAN_ROUNDS = 3;
|
|
4436
4437
|
var YAML_DUMP_OPTS = { indent: 2, lineWidth: -1, noCompatMode: true };
|
|
4437
4438
|
var HTTP_CLIENT2 = createHttpClient({ timeout: 6e4 });
|
|
4438
4439
|
function isMultiUrl(url) {
|
|
@@ -4812,7 +4813,7 @@ function cleanDeadProxies(parsed, deadNames) {
|
|
|
4812
4813
|
}
|
|
4813
4814
|
async function autoCleanSubscription(subName, options = {}) {
|
|
4814
4815
|
const parsed = loadSubscriptionConfig(subName);
|
|
4815
|
-
const { onResult, onRetryRound, ...testOptions } = options;
|
|
4816
|
+
const { onResult, onRetryRound, rounds = DEFAULT_CLEAN_ROUNDS, ...testOptions } = options;
|
|
4816
4817
|
const wrapOnResult = (round) => onResult ? (r, i, t) => onResult(r, i, t, round) : void 0;
|
|
4817
4818
|
const summary = await testSubscriptionProxies(subName, {
|
|
4818
4819
|
...testOptions,
|
|
@@ -4829,7 +4830,7 @@ async function autoCleanSubscription(subName, options = {}) {
|
|
|
4829
4830
|
} else {
|
|
4830
4831
|
const deadNames = new Set(summary.results.filter((r) => r.delay === null).map((r) => r.name));
|
|
4831
4832
|
const deadProxies = parsed.proxies.filter((p) => deadNames.has(p.name));
|
|
4832
|
-
for (let retry = 0; retry <
|
|
4833
|
+
for (let retry = 0; retry < rounds - 1; retry++) {
|
|
4833
4834
|
const round = retry + 2;
|
|
4834
4835
|
const retryTargets = deadProxies.filter((p) => deadNames.has(p.name));
|
|
4835
4836
|
if (retryTargets.length === 0) break;
|
|
@@ -5042,7 +5043,7 @@ async function withTestInstance(subName, fn) {
|
|
|
5042
5043
|
// src/commands/subscription.ts
|
|
5043
5044
|
var IS_TTY = process.stdout.isTTY === true;
|
|
5044
5045
|
var BAR_WIDTH = 20;
|
|
5045
|
-
function createProgressPrinter() {
|
|
5046
|
+
function createProgressPrinter(totalRounds = 1) {
|
|
5046
5047
|
let alive = 0;
|
|
5047
5048
|
let dead = 0;
|
|
5048
5049
|
const resultMap = /* @__PURE__ */ new Map();
|
|
@@ -5055,6 +5056,9 @@ function createProgressPrinter() {
|
|
|
5055
5056
|
}
|
|
5056
5057
|
return {
|
|
5057
5058
|
onResult(result, index, total, round = 1) {
|
|
5059
|
+
if (resultMap.size === 0 && totalRounds > 1) {
|
|
5060
|
+
console.log(`--- \u7B2C 1 \u8F6E\u6D4B\u8BD5 (${total} \u4E2A\u8282\u70B9) ---`);
|
|
5061
|
+
}
|
|
5058
5062
|
if (result.delay !== null) alive++;
|
|
5059
5063
|
else dead++;
|
|
5060
5064
|
resultMap.set(result.name, { result, round });
|
|
@@ -5382,14 +5386,16 @@ async function cmdSubscription(args) {
|
|
|
5382
5386
|
}
|
|
5383
5387
|
if (action === "clean") {
|
|
5384
5388
|
const { target, timeout, concurrency } = resolveTestTarget(args);
|
|
5389
|
+
const rounds = parseIntArg(args, "-r", "--rounds", DEFAULT_CLEAN_ROUNDS);
|
|
5385
5390
|
console.log(`\u6E05\u7406\u8BA2\u9605 "${target.name}"...`);
|
|
5386
5391
|
console.log(`\u8D85\u65F6: ${timeout}ms \u5E76\u53D1: ${concurrency}`);
|
|
5387
5392
|
console.log("");
|
|
5388
|
-
const progress = createProgressPrinter();
|
|
5393
|
+
const progress = createProgressPrinter(rounds);
|
|
5389
5394
|
const result = await withTestInstance(target.name, async (apiBase) => {
|
|
5390
5395
|
return autoCleanSubscription(target.name, {
|
|
5391
5396
|
timeout,
|
|
5392
5397
|
concurrency,
|
|
5398
|
+
rounds,
|
|
5393
5399
|
apiBase,
|
|
5394
5400
|
onResult: progress.onResult,
|
|
5395
5401
|
onRetryRound: progress.onRetryRound
|
|
@@ -5491,7 +5497,7 @@ async function cmdStart(args) {
|
|
|
5491
5497
|
console.log(`\u8282\u70B9\u6570 ${configInfo.proxies} \u8D85\u8FC7 ${AUTO_CLEAN_THRESHOLD}\uFF0C\u81EA\u52A8\u6E05\u7406...`);
|
|
5492
5498
|
console.log("");
|
|
5493
5499
|
await sleep(1e3);
|
|
5494
|
-
const progress = createProgressPrinter();
|
|
5500
|
+
const progress = createProgressPrinter(DEFAULT_CLEAN_ROUNDS);
|
|
5495
5501
|
const cleanResult = await autoCleanSubscription(sub.name, {
|
|
5496
5502
|
onResult: progress.onResult,
|
|
5497
5503
|
onRetryRound: progress.onRetryRound
|
|
@@ -5803,13 +5809,15 @@ async function cmdClean(args) {
|
|
|
5803
5809
|
const activeSub = requireActiveSub();
|
|
5804
5810
|
const timeout = parseIntArg(args, "-t", "--timeout", 1500);
|
|
5805
5811
|
const concurrency = parseIntArg(args, "-j", "--concurrency", 100);
|
|
5812
|
+
const rounds = parseIntArg(args, "-r", "--rounds", DEFAULT_CLEAN_ROUNDS);
|
|
5806
5813
|
console.log(`\u6E05\u7406 "${activeSub.name}" \u5931\u8D25\u8282\u70B9...`);
|
|
5807
5814
|
console.log(`\u8D85\u65F6: ${timeout}ms \u5E76\u53D1: ${concurrency}`);
|
|
5808
5815
|
console.log("");
|
|
5809
|
-
const progress = createProgressPrinter();
|
|
5816
|
+
const progress = createProgressPrinter(rounds);
|
|
5810
5817
|
const result = await autoCleanSubscription(activeSub.name, {
|
|
5811
5818
|
timeout,
|
|
5812
5819
|
concurrency,
|
|
5820
|
+
rounds,
|
|
5813
5821
|
onResult: progress.onResult,
|
|
5814
5822
|
onRetryRound: progress.onRetryRound
|
|
5815
5823
|
});
|