-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstats.mjs
More file actions
124 lines (109 loc) · 3.95 KB
/
Copy pathstats.mjs
File metadata and controls
124 lines (109 loc) · 3.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import fs from "node:fs";
import {
countPayloadEntries,
fetchText,
loadClashVergeConfig,
loadOpenClashConfig,
} from "./lib.mjs";
const README_PATH = "README.md";
const STATS_PATH = "stats.json";
const START = "<!-- STATS:START -->";
const END = "<!-- STATS:END -->";
const { config: clashVerge, source } = loadClashVergeConfig();
const { config: openClash } = loadOpenClashConfig();
const providers = clashVerge["rule-providers"];
const providerStats = {};
for (const [name, provider] of Object.entries(providers)) {
const content = await fetchText(provider.url);
providerStats[name] = {
rules: countPayloadEntries(content),
behavior: provider.behavior,
source: new URL(provider.url).hostname,
};
}
const keywordMatch = source.match(/excluded:\s*\n?\s*"([^"]+)"/);
const filterKeywords = keywordMatch
? keywordMatch[1]
.replace(/^\(\?i\)\(|\)$/g, "")
.split("|")
.filter((item) => item && !item.includes("\\"))
.length
: 0;
const now = new Date();
const openClashRemoteStats = {};
for (const rule of openClash.remoteRules) {
const content = await fetchText(rule.url);
const key = new URL(rule.url).pathname.split("/").pop().replace(/\.yaml$/, "");
openClashRemoteStats[key] = {
rules: countPayloadEntries(content),
behavior: rule.behavior,
source: new URL(rule.url).hostname,
};
}
const openClashFilterKeywords = openClash.exclude
.split("|")
.filter(Boolean).length;
const stats = {
updatedAt: now.toISOString(),
groups: clashVerge["proxy-groups"].length,
routingRules: clashVerge.rules.length,
providers: Object.keys(providers).length,
remoteRules: Object.values(providerStats).reduce(
(total, provider) => total + provider.rules,
0
),
filterKeywords,
providerStats,
configs: {
clashVergeRev: {
groups: clashVerge["proxy-groups"].length,
routingRules: clashVerge.rules.length,
providers: Object.keys(providers).length,
remoteRules: Object.values(providerStats).reduce(
(total, provider) => total + provider.rules,
0
),
filterKeywords,
},
openClash: {
groups: openClash.groups.length,
routingRules: openClash.rules.length,
remoteRulesets: openClash.remoteRules.length,
remoteRules: Object.values(openClashRemoteStats).reduce(
(total, provider) => total + provider.rules,
0
),
filterKeywords: openClashFilterKeywords,
providerStats: openClashRemoteStats,
},
},
};
fs.writeFileSync(STATS_PATH, `${JSON.stringify(stats, null, 2)}\n`);
const table = Object.entries(providerStats)
.map(
([name, provider]) =>
`| \`${name}\` | ${provider.behavior} | ${provider.rules.toLocaleString("en-US")} |`
)
.join("\n");
const block = `${START}
| 配置 | 策略组 | 路由规则 | 远程规则集 | 收录规则 | 过滤关键词 |
| --- | ---: | ---: | ---: | ---: | ---: |
| Clash Verge Rev | ${stats.configs.clashVergeRev.groups} | ${stats.configs.clashVergeRev.routingRules} | ${stats.configs.clashVergeRev.providers} | ${stats.configs.clashVergeRev.remoteRules.toLocaleString("en-US")} | ${stats.configs.clashVergeRev.filterKeywords} |
| OpenClash | ${stats.configs.openClash.groups} | ${stats.configs.openClash.routingRules} | ${stats.configs.openClash.remoteRulesets} | ${stats.configs.openClash.remoteRules.toLocaleString("en-US")} | ${stats.configs.openClash.filterKeywords} |
<details>
<summary>查看 Clash Verge Rev 规则集统计</summary>
| 规则集 | 类型 | 条目数 |
| --- | --- | ---: |
${table}
统计更新时间:${stats.updatedAt.replace("T", " ").replace(/\.\d{3}Z$/, " UTC")}
</details>
${END}`;
const readme = fs.readFileSync(README_PATH, "utf8");
const pattern = new RegExp(`${START}[\\s\\S]*?${END}`);
if (!pattern.test(readme)) {
throw new Error(`Missing stats markers in ${README_PATH}`);
}
fs.writeFileSync(README_PATH, readme.replace(pattern, block));
console.log(
`Updated ${STATS_PATH}: ${stats.remoteRules.toLocaleString("en-US")} remote rules.`
);