clash-kit 1.0.3 → 1.0.4
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/README.md +4 -5
- package/lib/subscription.js +61 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# Clash Kit
|
|
2
2
|
|
|
3
|
-
<img width="800" alt="clash-kit" src="https://github.com/user-attachments/assets/dd7dfd29-f59a-418b-8623-6ab08ece9ddb" />
|
|
4
|
-
|
|
5
3
|
一个基于 Node.js 的 Clash 命令行管理工具,旨在简化 Clash 的配置管理、订阅切换和节点测速等操作。
|
|
6
4
|
|
|
5
|
+
## 截图
|
|
6
|
+
|
|
7
|
+
<img width="1920" alt="image" src="https://github.com/user-attachments/assets/1183f778-62b0-4ac7-ab55-b821b66161f0" />
|
|
8
|
+
|
|
7
9
|
## 特性
|
|
8
10
|
|
|
9
11
|
- 🔄 **订阅管理**:支持添加、切换多个订阅源。
|
|
@@ -95,9 +97,6 @@ sudo ck tun on
|
|
|
95
97
|
| `ck sysproxy` (`sys`) | 设置系统代理 (on/off) | `ck sys on` |
|
|
96
98
|
| `ck tun` | 设置 TUN 模式 (on/off) | `sudo ck tun on` |
|
|
97
99
|
|
|
98
|
-
## 截图
|
|
99
|
-
|
|
100
|
-
<img width="2742" height="1994" alt="image" src="https://github.com/user-attachments/assets/1183f778-62b0-4ac7-ab55-b821b66161f0" />
|
|
101
100
|
|
|
102
101
|
## License
|
|
103
102
|
|
package/lib/subscription.js
CHANGED
|
@@ -4,6 +4,7 @@ import axios from 'axios'
|
|
|
4
4
|
import { fileURLToPath } from 'url'
|
|
5
5
|
import ora from 'ora'
|
|
6
6
|
import { reloadConfig, isClashRunning } from './api.js'
|
|
7
|
+
import YAML from 'yaml'
|
|
7
8
|
|
|
8
9
|
const __filename = fileURLToPath(import.meta.url)
|
|
9
10
|
const __dirname = path.dirname(__filename)
|
|
@@ -20,9 +21,46 @@ if (!fs.existsSync(PROFILES_DIR)) {
|
|
|
20
21
|
export async function downloadSubscription(url, name) {
|
|
21
22
|
const spinner = ora(`正在下载订阅 ${name}...`).start()
|
|
22
23
|
try {
|
|
23
|
-
const res = await axios.get(url, {
|
|
24
|
+
const res = await axios.get(url, {
|
|
25
|
+
responseType: 'text',
|
|
26
|
+
headers: {
|
|
27
|
+
'User-Agent': 'Clash/1.0.0', // 伪装成 Clash 客户端,通常能直接获取 YAML 格式
|
|
28
|
+
},
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
let content = res.data
|
|
32
|
+
|
|
33
|
+
// 尝试解析 YAML,如果不是对象或者看起来不像配置,尝试 Base64 解码
|
|
34
|
+
let isConfig = false
|
|
35
|
+
try {
|
|
36
|
+
const parsed = YAML.parse(content)
|
|
37
|
+
if (parsed && typeof parsed === 'object' && (parsed.proxies || parsed.Proxy || parsed.port)) {
|
|
38
|
+
isConfig = true
|
|
39
|
+
}
|
|
40
|
+
} catch (e) {
|
|
41
|
+
console.warn('订阅服务商返回的不是有效 YAML,尝试 Base64 解码...')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!isConfig) {
|
|
45
|
+
try {
|
|
46
|
+
// 尝试 Base64 解码
|
|
47
|
+
const decoded = Buffer.from(content, 'base64').toString('utf-8')
|
|
48
|
+
// 再次检查解码后是否为有效 YAML 配置
|
|
49
|
+
const parsedDecoded = YAML.parse(decoded)
|
|
50
|
+
if (
|
|
51
|
+
parsedDecoded &&
|
|
52
|
+
typeof parsedDecoded === 'object' &&
|
|
53
|
+
(parsedDecoded.proxies || parsedDecoded.Proxy || parsedDecoded.port)
|
|
54
|
+
) {
|
|
55
|
+
content = decoded
|
|
56
|
+
}
|
|
57
|
+
} catch (e) {
|
|
58
|
+
console.warn('Base64 解码失败,保留原始内容')
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
24
62
|
const filePath = path.join(PROFILES_DIR, `${name}.yaml`)
|
|
25
|
-
fs.writeFileSync(filePath,
|
|
63
|
+
fs.writeFileSync(filePath, content)
|
|
26
64
|
spinner.succeed(`订阅 ${name} 下载成功`)
|
|
27
65
|
return filePath
|
|
28
66
|
} catch (err) {
|
|
@@ -51,9 +89,27 @@ export async function useProfile(name) {
|
|
|
51
89
|
|
|
52
90
|
const spinner = ora(`正在切换到配置 ${name}...`).start()
|
|
53
91
|
|
|
54
|
-
//
|
|
55
|
-
fs.
|
|
56
|
-
|
|
92
|
+
// 读取订阅配置
|
|
93
|
+
const subscriptionConfig = YAML.parse(fs.readFileSync(source, 'utf8'))
|
|
94
|
+
|
|
95
|
+
// 读取现有配置(如果存在)
|
|
96
|
+
let existingConfig = {}
|
|
97
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
98
|
+
existingConfig = YAML.parse(fs.readFileSync(CONFIG_PATH, 'utf8'))
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// 合并配置:保留用户自定义字段,更新订阅字段
|
|
102
|
+
const mergedConfig = {
|
|
103
|
+
...subscriptionConfig,
|
|
104
|
+
port: existingConfig['port'],
|
|
105
|
+
'bind-address': existingConfig['bind-address'],
|
|
106
|
+
'socks-port': existingConfig['socks-port'],
|
|
107
|
+
'allow-lan': existingConfig['allow-lan'],
|
|
108
|
+
// 其他需要保留的自定义字段...
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// 写入合并后的配置
|
|
112
|
+
fs.writeFileSync(CONFIG_PATH, YAML.stringify(mergedConfig))
|
|
57
113
|
|
|
58
114
|
// 尝试热重载
|
|
59
115
|
if (await isClashRunning()) {
|