mihomo-cli 2.3.1 → 2.4.0
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 +16 -0
- package/README.md +2 -0
- package/dist/index.js +59 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.4.0] - 2026-05-02
|
|
4
|
+
|
|
5
|
+
### 新功能
|
|
6
|
+
|
|
7
|
+
- **sub best** - `sub best <id>` 一键添加聚合订阅(每小时自动更新、去重、测活)
|
|
8
|
+
- `best 1` 精选 29 组(仅测速源:FreeSubsCheck, shaoyouvip, dalazhi, getnode)
|
|
9
|
+
- `best 2` ACL4SSR 29 组(全部 7 个源)
|
|
10
|
+
- `best 3` freeSub 24 组
|
|
11
|
+
- **新增免费源** - yahr601, Auto-Sync, ssrsub, dalazhi, getnode
|
|
12
|
+
|
|
13
|
+
### 修复
|
|
14
|
+
|
|
15
|
+
- `setDefaultSubscription` 移到下载成功后再设置,避免下载失败留下无效默认订阅
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
3
19
|
## [2.3.1] - 2026-05-02
|
|
4
20
|
|
|
5
21
|
### 新功能
|
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
- 🧹 **节点测速清理** - `sub test` 测试连通性,`sub clean` 自动清理失败节点,启动时自动清理
|
|
11
11
|
- 📊 **免费订阅基准测试** - `bench` 命令一键测试 20 个内置免费订阅源质量排名
|
|
12
12
|
- 🆓 **快速添加免费订阅** - `sub free <id>` 一键添加内置免费订阅源
|
|
13
|
+
- 🏆 **聚合订阅** - `sub best <id>` 一键添加自动更新的聚合订阅(每小时更新、去重、测活)
|
|
13
14
|
- 📝 **覆写配置** - 在订阅基础上进行自定义覆写,支持强制覆盖、数组合并
|
|
14
15
|
- 🔄 **智能重启** - `sub use` 切换订阅、`ow on/off` 切换覆写后自动重启
|
|
15
16
|
- 🚀 **进程管理** - 启动/停止/切换模式,自动清理残留进程
|
|
@@ -100,6 +101,7 @@ mihomo ui yacd # YACD
|
|
|
100
101
|
| `mihomo sub use <name>` | 切换当前订阅(支持模糊匹配,自动重启) |
|
|
101
102
|
| `mihomo sub add <url> [name]` | 添加订阅并自动切换(支持逗号分隔多 URL 合并) |
|
|
102
103
|
| `mihomo sub free <id>` | 添加内置免费订阅(`0`=合并 #1+#2,`sub free` 列出可用源)|
|
|
104
|
+
| `mihomo sub best <id>` | 添加聚合订阅(`sub best` 列出可用源)|
|
|
103
105
|
| `mihomo sub update` | 更新所有订阅 |
|
|
104
106
|
| `mihomo sub update <name>` | 更新指定订阅(支持模糊匹配) |
|
|
105
107
|
| `mihomo sub remove <name>` | 删除订阅(支持模糊匹配) |
|
package/dist/index.js
CHANGED
|
@@ -2652,9 +2652,16 @@ var TUN_CONFIG = {
|
|
|
2652
2652
|
};
|
|
2653
2653
|
function getFreeSubscriptionSources() {
|
|
2654
2654
|
return [
|
|
2655
|
-
// 完整配置(
|
|
2655
|
+
// 完整配置(ACL4SSR 29 组)
|
|
2656
2656
|
{ name: "FreeSubsCheck", url: "https://gh-proxy.org/raw.githubusercontent.com/kooker/FreeSubsCheck/main/mihomo.yaml" },
|
|
2657
|
+
{ name: "yahr601", url: "https://gh-proxy.org/raw.githubusercontent.com/yahr601-prog/1/main/clash.yaml" },
|
|
2658
|
+
{ name: "Auto-Sync", url: "https://gh-proxy.org/raw.githubusercontent.com/walke2019/Auto-Sync/main/clash/GG/clash.yaml" },
|
|
2659
|
+
{ name: "ssrsub", url: "https://gh-proxy.org/raw.githubusercontent.com/ssrsub/ssr/master/clash.yaml" },
|
|
2660
|
+
// OpenAi → Ai平台
|
|
2657
2661
|
{ name: "shaoyouvip", url: "https://gh-proxy.org/raw.githubusercontent.com/shaoyouvip/free/main/mihomo.yaml" },
|
|
2662
|
+
{ name: "dalazhi", url: "https://gh-proxy.org/raw.githubusercontent.com/dalazhi/v2ray/main/data/mihomo.yaml" },
|
|
2663
|
+
{ name: "getnode", url: "https://gh-proxy.org/raw.githubusercontent.com/limitless-d/getnode/main/clash.yaml" },
|
|
2664
|
+
// 完整配置(24 组)
|
|
2658
2665
|
{ name: "freeSub", url: "https://gh-proxy.org/raw.githubusercontent.com/Ruk1ng001/freeSub/main/clash.yaml" },
|
|
2659
2666
|
// 完整配置(13 组)
|
|
2660
2667
|
{ name: "PuddinCat", url: "https://gh-proxy.org/raw.githubusercontent.com/PuddinCat/BestClash/refs/heads/main/proxies.yaml" },
|
|
@@ -2680,6 +2687,14 @@ function getFreeSubscriptionSources() {
|
|
|
2680
2687
|
{ name: "NoMoreWalls", url: "https://gh-proxy.org/raw.githubusercontent.com/peasoft/NoMoreWalls/master/list.meta.yml" }
|
|
2681
2688
|
];
|
|
2682
2689
|
}
|
|
2690
|
+
var GH_SUB = "https://gh-proxy.org/raw.githubusercontent.com/imaex/mihomo-free-sub/sub";
|
|
2691
|
+
function getBestSubscriptionSources() {
|
|
2692
|
+
return [
|
|
2693
|
+
{ name: "curated", url: `${GH_SUB}/curated.yaml`, description: "\u7CBE\u9009 29 \u7EC4\uFF08\u4EC5\u6D4B\u901F\u6E90\uFF09" },
|
|
2694
|
+
{ name: "acl4ssr", url: `${GH_SUB}/acl4ssr.yaml`, description: "ACL4SSR 29 \u7EC4\uFF08\u5168\u90E8\u6E90\uFF09" },
|
|
2695
|
+
{ name: "freesub", url: `${GH_SUB}/freesub.yaml`, description: "freeSub 24 \u7EC4" }
|
|
2696
|
+
];
|
|
2697
|
+
}
|
|
2683
2698
|
var BENCH_CONFIG = {
|
|
2684
2699
|
"allow-lan": false,
|
|
2685
2700
|
"external-controller": "127.0.0.1:19090",
|
|
@@ -4861,8 +4876,8 @@ async function addFreeSubscription(freeId) {
|
|
|
4861
4876
|
console.log(`\u6DFB\u52A0\u5408\u5E76\u514D\u8D39\u8BA2\u9605: ${name2} (${sources.map((s) => s.name).join(" + ")})`);
|
|
4862
4877
|
try {
|
|
4863
4878
|
addSubscription(mergedUrl, name2);
|
|
4864
|
-
setDefaultSubscription(name2);
|
|
4865
4879
|
const info = await downloadMergedSubscription(urls, name2);
|
|
4880
|
+
setDefaultSubscription(name2);
|
|
4866
4881
|
const repoUrls = sources.map((s) => githubRepoUrl(s.url)).filter(Boolean);
|
|
4867
4882
|
if (repoUrls.length > 0) saveSubscriptionCache(name2, { web_page_url: repoUrls.join(", ") });
|
|
4868
4883
|
console.log(`\u5DF2\u6DFB\u52A0\u5E76\u5207\u6362\u5230 "${name2}" (${formatProxySummary(info)}, \u5408\u5E76 ${sources.length} \u6E90)`);
|
|
@@ -4885,8 +4900,8 @@ async function addFreeSubscription(freeId) {
|
|
|
4885
4900
|
console.log(`\u6DFB\u52A0\u514D\u8D39\u8BA2\u9605: ${name}`);
|
|
4886
4901
|
try {
|
|
4887
4902
|
addSubscription(source.url, name);
|
|
4888
|
-
setDefaultSubscription(name);
|
|
4889
4903
|
const info = await downloadSubscription(source.url, name);
|
|
4904
|
+
setDefaultSubscription(name);
|
|
4890
4905
|
const repoUrl = githubRepoUrl(source.url);
|
|
4891
4906
|
if (repoUrl) saveSubscriptionCache(name, { web_page_url: repoUrl });
|
|
4892
4907
|
console.log(`\u5DF2\u6DFB\u52A0\u5E76\u5207\u6362\u5230 "${name}" (${formatProxySummary(info)})`);
|
|
@@ -4897,6 +4912,36 @@ async function addFreeSubscription(freeId) {
|
|
|
4897
4912
|
console.log("");
|
|
4898
4913
|
await printSubscriptionList();
|
|
4899
4914
|
}
|
|
4915
|
+
function printBestSourceList() {
|
|
4916
|
+
const bestSources = getBestSubscriptionSources();
|
|
4917
|
+
for (let i = 0; i < bestSources.length; i++) {
|
|
4918
|
+
console.log(` ${i + 1} ${bestSources[i].name} \u2014 ${bestSources[i].description}`);
|
|
4919
|
+
}
|
|
4920
|
+
}
|
|
4921
|
+
async function addBestSubscription(bestId) {
|
|
4922
|
+
const bestSources = getBestSubscriptionSources();
|
|
4923
|
+
if (bestId < 1 || bestId > bestSources.length) {
|
|
4924
|
+
console.error(`\u9519\u8BEF: best \u8BA2\u9605 ID \u8303\u56F4 1-${bestSources.length}`);
|
|
4925
|
+
console.log("\n\u53EF\u7528\u6E90:");
|
|
4926
|
+
printBestSourceList();
|
|
4927
|
+
process.exit(1);
|
|
4928
|
+
}
|
|
4929
|
+
const source = bestSources[bestId - 1];
|
|
4930
|
+
const name = `best${bestId}`;
|
|
4931
|
+
console.log(`\u6DFB\u52A0 best \u8BA2\u9605: ${name} (${source.description})`);
|
|
4932
|
+
try {
|
|
4933
|
+
addSubscription(source.url, name);
|
|
4934
|
+
const info = await downloadSubscription(source.url, name);
|
|
4935
|
+
setDefaultSubscription(name);
|
|
4936
|
+
saveSubscriptionCache(name, { web_page_url: "https://github.com/imaex/mihomo-free-sub" });
|
|
4937
|
+
console.log(`\u5DF2\u6DFB\u52A0\u5E76\u5207\u6362\u5230 "${name}" (${formatProxySummary(info)})`);
|
|
4938
|
+
} catch (e) {
|
|
4939
|
+
console.error(`\u6DFB\u52A0\u5931\u8D25: ${e.message}`);
|
|
4940
|
+
process.exit(1);
|
|
4941
|
+
}
|
|
4942
|
+
console.log("");
|
|
4943
|
+
await printSubscriptionList();
|
|
4944
|
+
}
|
|
4900
4945
|
async function cmdSubscription(args) {
|
|
4901
4946
|
const action = args[1];
|
|
4902
4947
|
if (!action || action === "list") {
|
|
@@ -4914,6 +4959,17 @@ async function cmdSubscription(args) {
|
|
|
4914
4959
|
await addFreeSubscription(id);
|
|
4915
4960
|
return;
|
|
4916
4961
|
}
|
|
4962
|
+
if (action === "best") {
|
|
4963
|
+
const id = parseInt(args[2], 10);
|
|
4964
|
+
if (Number.isNaN(id)) {
|
|
4965
|
+
console.log("\u7528\u6CD5: mihomo sub best <id>\n");
|
|
4966
|
+
console.log("\u53EF\u7528\u6E90:");
|
|
4967
|
+
printBestSourceList();
|
|
4968
|
+
process.exit(1);
|
|
4969
|
+
}
|
|
4970
|
+
await addBestSubscription(id);
|
|
4971
|
+
return;
|
|
4972
|
+
}
|
|
4917
4973
|
if (action === "add") {
|
|
4918
4974
|
const freeId = parseIntArg(args, "--free", "--free", -1);
|
|
4919
4975
|
if (freeId > 0) {
|