Initialize rule providers and README
This commit is contained in:
@@ -0,0 +1,1612 @@
|
||||
/**
|
||||
* ============================================================
|
||||
* Sub-Store → Mihomo / Clash Meta 配置生成器
|
||||
* ============================================================
|
||||
*
|
||||
* 当前版本:v1.2.0
|
||||
* 更新时间:2026-08-23
|
||||
*
|
||||
* v1.2.0
|
||||
* ────────────────────────────────────────────────────────────
|
||||
* 1. 重构地区节点分类
|
||||
* - 每个节点只进行一次地区分类
|
||||
* - 保持香港 / 台湾 / 日本 / 新加坡 / 美国 / 韩国 / 其他
|
||||
* 的优先级顺序
|
||||
*
|
||||
* 2. 修复 AI 节点兜底逻辑
|
||||
* - 香港永远不会进入人工智能策略
|
||||
* - 无非香港地区节点时,AI 使用 DIRECT
|
||||
* - 不再通过自动选择间接引入香港
|
||||
*
|
||||
* 3. 优化策略组排序
|
||||
* - 🚀 节点选择
|
||||
* - ♻️ 自动选择
|
||||
* - 🔯 故障转移
|
||||
* 放置在最顶部
|
||||
*
|
||||
* 4. 统一策略组创建逻辑
|
||||
* - 减少重复代码
|
||||
* - 统一候选节点去重
|
||||
* - 降低后续维护难度
|
||||
*
|
||||
* 5. 优化空策略组处理
|
||||
* - 没有节点的地区自动隐藏
|
||||
* - 🇨🇳 其他节点为空时自动隐藏
|
||||
*
|
||||
* 6. 保留原有功能
|
||||
* - TUN
|
||||
* - DNS
|
||||
* - Sniffer
|
||||
* - Fake-IP
|
||||
* - Rule Provider
|
||||
* - AI
|
||||
* - 海外服务
|
||||
* - 网络测试
|
||||
* - 广告拦截
|
||||
* - 代理域名
|
||||
* - 全球直连
|
||||
* - 最终兜底
|
||||
*
|
||||
* 7. 保留原测速参数
|
||||
* - URL:https://www.gstatic.com/generate_204
|
||||
* - interval:600
|
||||
* - timeout:3000
|
||||
* - tolerance:80
|
||||
* - lazy:true
|
||||
* - max-failed-times:3
|
||||
*
|
||||
* 版本:v1.1.0
|
||||
* 更新时间:2026-08-22
|
||||
*
|
||||
* v1.1.0
|
||||
* ────────────────────────────────────────────────────────────
|
||||
* 1. 重构“🇨🇳 其他节点”
|
||||
* - 仅作为真正的地区兜底节点组
|
||||
* - 不属于香港 / 台湾 / 日本 / 新加坡 / 美国 / 韩国
|
||||
* 的节点全部进入这里
|
||||
* - 没有其他节点时自动隐藏
|
||||
*
|
||||
* 2. “💬 GPT专用”更名为“🤖 人工智能”
|
||||
* - 不再只针对 GPT
|
||||
* - 香港节点不加入人工智能节点
|
||||
* - 台湾 / 日本 / 新加坡 / 美国 / 韩国 / 其他节点
|
||||
* 均可参与人工智能节点选择
|
||||
*
|
||||
* 3. “🐟 漏网之鱼”更名为“🛟 兜底策略”
|
||||
* - MATCH 最终兜底策略名称同步修改
|
||||
*
|
||||
* 4. 合并重复策略组
|
||||
* - 微软服务
|
||||
* - 苹果服务
|
||||
* - 游戏平台
|
||||
* - 国内 IP
|
||||
* - 直连域名
|
||||
* - 直连软件
|
||||
* - 私有网络
|
||||
* 等不再单独创建重复 Select 组
|
||||
*
|
||||
* 5. 统一直连策略
|
||||
* - 所有确定应该 DIRECT 的规则统一进入:
|
||||
* 🎯 全球直连
|
||||
*
|
||||
* 6. 减少策略组数量
|
||||
* - 保留真正有实际选择意义的策略组
|
||||
* - 降低 Clash Meta Android 界面复杂度
|
||||
*
|
||||
* 7. 优化自动选择
|
||||
* - 地区内部先选择最佳节点
|
||||
* - 自动选择再选择最佳地区
|
||||
* - 避免直接对所有节点重复测速
|
||||
*
|
||||
* 8. 优化人工智能节点
|
||||
* - 使用地区组作为候选
|
||||
* - 避免人工智能策略组重复测速所有具体节点
|
||||
*
|
||||
* 9. 优化 Android 后台运行
|
||||
* - URL-Test:600 秒
|
||||
* - Fallback:600 秒
|
||||
* - tolerance:80ms
|
||||
* - lazy:true
|
||||
*
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 1. 基础配置
|
||||
* ============================================================ */
|
||||
|
||||
const generalConfig = {
|
||||
|
||||
"mode": "rule",
|
||||
|
||||
/*
|
||||
* 关闭 IPv6。
|
||||
*
|
||||
* 移动网络环境下优先保证稳定性。
|
||||
*/
|
||||
"ipv6": false,
|
||||
|
||||
"log-level": "silent",
|
||||
|
||||
"allow-lan": true,
|
||||
|
||||
/*
|
||||
* 统一延迟计算。
|
||||
*/
|
||||
"unified-delay": true,
|
||||
|
||||
/*
|
||||
* TCP 并发连接。
|
||||
*/
|
||||
"tcp-concurrent": true,
|
||||
|
||||
/*
|
||||
* 严格进程匹配。
|
||||
*/
|
||||
"find-process-mode": "strict",
|
||||
|
||||
/*
|
||||
* Chrome TLS 指纹。
|
||||
*/
|
||||
"global-client-fingerprint": "chrome",
|
||||
|
||||
"profile": {
|
||||
"store-selected": true,
|
||||
"store-fake-ip": true
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 2. Sniffer
|
||||
* ============================================================ */
|
||||
|
||||
const snifferConfig = {
|
||||
|
||||
"enable": true,
|
||||
|
||||
"parse-pure-ip": true,
|
||||
|
||||
"sniff": {
|
||||
|
||||
"HTTP": {
|
||||
"ports": [
|
||||
80,
|
||||
"8080-8880"
|
||||
],
|
||||
"override-destination": true
|
||||
},
|
||||
|
||||
"TLS": {
|
||||
"ports": [
|
||||
443,
|
||||
8443
|
||||
]
|
||||
},
|
||||
|
||||
"QUIC": {
|
||||
"ports": [
|
||||
443,
|
||||
8443
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"skip-domain": [
|
||||
"Mijia Cloud"
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 3. TUN
|
||||
* ============================================================ */
|
||||
|
||||
const tunConfig = {
|
||||
|
||||
"enable": true,
|
||||
|
||||
"stack": "system",
|
||||
|
||||
"dns-hijack": [
|
||||
"any:53"
|
||||
],
|
||||
|
||||
"auto-route": true,
|
||||
|
||||
"auto-detect-interface": true,
|
||||
|
||||
"strict-route": true
|
||||
};
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 4. DNS
|
||||
* ============================================================ */
|
||||
|
||||
const dnsConfig = {
|
||||
|
||||
"enable": true,
|
||||
|
||||
"ipv6": false,
|
||||
|
||||
/*
|
||||
* 移动网络环境下优先稳定性。
|
||||
*/
|
||||
"prefer-h3": false,
|
||||
|
||||
"listen": "0.0.0.0:53",
|
||||
|
||||
"fake-ip-range": "198.18.0.1/16",
|
||||
|
||||
"enhanced-mode": "fake-ip",
|
||||
|
||||
/*
|
||||
* 主 DNS。
|
||||
*/
|
||||
"nameserver": [
|
||||
"https://dns.alidns.com/dns-query",
|
||||
"https://doh.pub/dns-query"
|
||||
],
|
||||
|
||||
/*
|
||||
* DNS 备用。
|
||||
*/
|
||||
"fallback": [
|
||||
"223.5.5.5",
|
||||
"119.29.29.29"
|
||||
],
|
||||
|
||||
/*
|
||||
* 启动阶段 DNS。
|
||||
*/
|
||||
"default-nameserver": [
|
||||
"223.5.5.5",
|
||||
"114.114.114.114"
|
||||
],
|
||||
|
||||
/*
|
||||
* DNS 回退过滤。
|
||||
*/
|
||||
"fallback-filter": {
|
||||
|
||||
"geoip": true,
|
||||
|
||||
"geoip-code": "CN",
|
||||
|
||||
"geosite": [
|
||||
"gfw"
|
||||
],
|
||||
|
||||
"ipcidr": [
|
||||
"240.0.0.0/4",
|
||||
"0.0.0.0/32",
|
||||
"127.0.0.1/32"
|
||||
]
|
||||
},
|
||||
|
||||
/*
|
||||
* Fake-IP 排除列表。
|
||||
*/
|
||||
"fake-ip-filter": [
|
||||
|
||||
"*.lan",
|
||||
"*.localdomain",
|
||||
"*.example",
|
||||
"*.invalid",
|
||||
"*.localhost",
|
||||
"*.test",
|
||||
"*.local",
|
||||
"*.home.arpa",
|
||||
|
||||
"*.woozooo.com",
|
||||
"*.kiid.top",
|
||||
"43.142.112.88",
|
||||
|
||||
"time.*.com",
|
||||
"time.*.gov",
|
||||
"time.*.edu.cn",
|
||||
"time.*.apple.com",
|
||||
"time-ios.apple.com",
|
||||
|
||||
"time1.*.com",
|
||||
"time2.*.com",
|
||||
"time3.*.com",
|
||||
"time4.*.com",
|
||||
"time5.*.com",
|
||||
"time6.*.com",
|
||||
"time7.*.com",
|
||||
|
||||
"ntp.*.com",
|
||||
"ntp1.*.com",
|
||||
"ntp2.*.com",
|
||||
"ntp3.*.com",
|
||||
"ntp4.*.com",
|
||||
"ntp5.*.com",
|
||||
"ntp6.*.com",
|
||||
"ntp7.*.com",
|
||||
|
||||
"*.time.edu.cn",
|
||||
"*.ntp.org.cn",
|
||||
"+.pool.ntp.org",
|
||||
"time1.cloud.tencent.com",
|
||||
|
||||
"music.163.com",
|
||||
"*.music.163.com",
|
||||
"*.126.net",
|
||||
|
||||
"musicapi.taihe.com",
|
||||
"music.taihe.com",
|
||||
|
||||
"songsearch.kugou.com",
|
||||
"trackercdn.kugou.com",
|
||||
|
||||
"*.kuwo.cn",
|
||||
"api-jooxtt.sanook.com",
|
||||
"api.joox.com",
|
||||
"joox.com",
|
||||
|
||||
"y.qq.com",
|
||||
"*.y.qq.com",
|
||||
"streamoc.music.tc.qq.com",
|
||||
"mobileoc.music.tc.qq.com",
|
||||
"isure.stream.qqmusic.qq.com",
|
||||
"dl.stream.qq.com",
|
||||
"aqqmusic.tc.qq.com",
|
||||
"amobile.music.tc.qq.com",
|
||||
|
||||
"*.xiami.com",
|
||||
"*.music.migu.cn",
|
||||
"music.migu.cn",
|
||||
|
||||
"+.msftconnecttest.com",
|
||||
"+.msftncsi.com",
|
||||
|
||||
"localhost.ptlogin2.qq.com",
|
||||
"localhost.sec.qq.com",
|
||||
"+.qq.com",
|
||||
"+.tencent.com",
|
||||
|
||||
"+.srv.nintendo.net",
|
||||
"*.n.n.srv.nintendo.net",
|
||||
"+.stun.playstation.net",
|
||||
|
||||
"xbox.*.*.microsoft.com",
|
||||
"*.*.xboxlive.com",
|
||||
"xbox.*.microsoft.com",
|
||||
"xnotify.xboxlive.com",
|
||||
|
||||
"+.battlenet.com.cn",
|
||||
"+.wotgame.cn",
|
||||
"+.wggames.cn",
|
||||
"+.wowsgame.cn",
|
||||
"+.wargaming.net",
|
||||
|
||||
"proxy.golang.org",
|
||||
|
||||
"stun.*.*",
|
||||
"stun.*.*.*",
|
||||
"+.stun.*.*",
|
||||
"+.stun.*.*.*",
|
||||
"+.stun.*.*.*.*",
|
||||
"+.stun.*.*.*.*.*",
|
||||
|
||||
"heartbeat.belkin.com",
|
||||
"*.linksys.com",
|
||||
"*.linksyssmartwifi.com",
|
||||
"*.router.asus.com",
|
||||
|
||||
"mesu.apple.com",
|
||||
"swscan.apple.com",
|
||||
"swquery.apple.com",
|
||||
"swdownload.apple.com",
|
||||
"swdist.apple.com",
|
||||
|
||||
"lens.l.google.com",
|
||||
"stun.l.google.com",
|
||||
"na.b.g-tun.com",
|
||||
|
||||
"+.nflxvideo.net",
|
||||
|
||||
"*.square-enix.com",
|
||||
"*.finalfantasyxiv.com",
|
||||
"*.ffxiv.com",
|
||||
"*.ff14.sdo.com",
|
||||
"ff.dorado.sdo.com",
|
||||
|
||||
"*.mcdn.bilivideo.cn",
|
||||
"+.media.dssott.com",
|
||||
|
||||
"shark007.net",
|
||||
"Mijia Cloud",
|
||||
|
||||
"+.cmbchina.com",
|
||||
"+.cmbimg.com",
|
||||
|
||||
"adguardteam.github.io",
|
||||
"adrules.top",
|
||||
"anti-ad.net",
|
||||
"local.adguard.org",
|
||||
"static.adtidy.org",
|
||||
|
||||
"+.sandai.net",
|
||||
"+.n0808.com",
|
||||
"+.3gppnetwork.org"
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 5. 节点名称过滤
|
||||
* ============================================================ */
|
||||
|
||||
/*
|
||||
* 排除:
|
||||
*
|
||||
* - 回国
|
||||
* - 校园
|
||||
* - 游戏
|
||||
* - 通知
|
||||
* - 流量
|
||||
* - 到期
|
||||
* - 官网
|
||||
* - 客服
|
||||
* - 机场
|
||||
* - 邀请
|
||||
* - 返利
|
||||
* - 循环
|
||||
* - 备用
|
||||
* - 过期
|
||||
* - 已用
|
||||
* - 联系
|
||||
* - 邮箱
|
||||
* - 工单
|
||||
* - 贩卖
|
||||
* - 倒卖
|
||||
* - 防止
|
||||
* - 国内
|
||||
* - 地址
|
||||
* - 频道
|
||||
* - 无法
|
||||
* - 说明
|
||||
* - 使用
|
||||
* - 提示
|
||||
* - 特别
|
||||
* - 访问
|
||||
* - 支持
|
||||
* - 教程
|
||||
* - 关注
|
||||
* - 更新
|
||||
* - 作者
|
||||
* - 加入
|
||||
* - 超时
|
||||
* - 收藏
|
||||
* - 福利
|
||||
* - 失联
|
||||
* 等非实际代理节点。
|
||||
*/
|
||||
|
||||
const nodeNameExcludeReg =
|
||||
/回国|校园|游戏|通知|流量|到期|官网|客服|机场|邀请|返利|循环|备用|过期|已用|联系|邮箱|工单|贩卖|倒卖|防止|国内|地址|频道|无法|说明|使用|提示|特别|访问|支持|教程|关注|更新|作者|加入|超时|收藏|福利|失联|\b(USE|USED|TOTAL|EXPIRE|EMAIL|PANEL|CHANNEL|AUTHOR|TRAFFIC)\b|compatible/i;
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 6. 地区定义
|
||||
* ============================================================ */
|
||||
|
||||
/*
|
||||
* 地区匹配优先级:
|
||||
*
|
||||
* 1. 香港
|
||||
* 2. 台湾
|
||||
* 3. 日本
|
||||
* 4. 新加坡
|
||||
* 5. 美国
|
||||
* 6. 韩国
|
||||
* 7. 其他
|
||||
*
|
||||
* 其他没有 pattern,
|
||||
* 只负责接收没有匹配任何已知地区的节点。
|
||||
*/
|
||||
|
||||
const regionDefinitions = [
|
||||
|
||||
{
|
||||
key: "hongKong",
|
||||
groupName: "🇭🇰 香港节点",
|
||||
pattern: /🇭🇰|香港|\b(HK|HKG|Hong Kong)\b/i
|
||||
},
|
||||
|
||||
{
|
||||
key: "taiwan",
|
||||
groupName: "🇹🇼 台湾节点",
|
||||
pattern: /🇹🇼|台湾|\b(TW|TWN|Taiwan)\b/i
|
||||
},
|
||||
|
||||
{
|
||||
key: "japan",
|
||||
groupName: "🇯🇵 日本节点",
|
||||
pattern: /🇯🇵|日本|\b(JP|JPN|Japan)\b/i
|
||||
},
|
||||
|
||||
{
|
||||
key: "singapore",
|
||||
groupName: "🇸🇬 新加坡节点",
|
||||
pattern: /🇸🇬|新加坡|狮城|\b(SG|SGP|Singapore)\b/i
|
||||
},
|
||||
|
||||
{
|
||||
key: "usa",
|
||||
groupName: "🇺🇸 美国节点",
|
||||
pattern: /🇺🇸|美国|\b(US|USA|United States)\b/i
|
||||
},
|
||||
|
||||
{
|
||||
key: "korea",
|
||||
groupName: "🇰🇷 韩国节点",
|
||||
pattern: /🇰🇷|韩国|首尔|\b(KR|KOR|Korea)\b/i
|
||||
},
|
||||
|
||||
{
|
||||
key: "other",
|
||||
groupName: "🇨🇳 其他节点",
|
||||
pattern: null
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 7. AI 地区
|
||||
* ============================================================ */
|
||||
|
||||
/*
|
||||
* 香港明确排除。
|
||||
*
|
||||
* AI 可以使用:
|
||||
*
|
||||
* 台湾
|
||||
* 日本
|
||||
* 新加坡
|
||||
* 美国
|
||||
* 韩国
|
||||
* 其他
|
||||
*/
|
||||
|
||||
const aiRegionKeys = [
|
||||
|
||||
"taiwan",
|
||||
|
||||
"japan",
|
||||
|
||||
"singapore",
|
||||
|
||||
"usa",
|
||||
|
||||
"korea",
|
||||
|
||||
"other"
|
||||
];
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 8. 测速配置
|
||||
* ============================================================ */
|
||||
|
||||
const speedTestUrl =
|
||||
"https://www.gstatic.com/generate_204";
|
||||
|
||||
|
||||
/*
|
||||
* 所有 URL-Test 统一使用此参数。
|
||||
*/
|
||||
|
||||
const urlTestDefaults = {
|
||||
|
||||
"interval": 600,
|
||||
|
||||
"timeout": 3000,
|
||||
|
||||
"url": speedTestUrl,
|
||||
|
||||
"lazy": true,
|
||||
|
||||
"max-failed-times": 3,
|
||||
|
||||
"tolerance": 80
|
||||
};
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 9. Rule Provider
|
||||
* ============================================================ */
|
||||
|
||||
const mirrorBaseUrl =
|
||||
"https://ghproxy.net/";
|
||||
|
||||
|
||||
const ruleProviders = {
|
||||
|
||||
"ads": {
|
||||
"type": "http",
|
||||
"behavior": "domain",
|
||||
"format": "text",
|
||||
"path": "./rules/adss.list",
|
||||
"url": mirrorBaseUrl +
|
||||
"https://raw.githubusercontent.com/DustinWin/ruleset_geodata/clash-ruleset/ads.list",
|
||||
"interval": 86400
|
||||
},
|
||||
|
||||
"applications": {
|
||||
"type": "http",
|
||||
"behavior": "classical",
|
||||
"format": "text",
|
||||
"path": "./rules/applicationss.list",
|
||||
"url": mirrorBaseUrl +
|
||||
"https://raw.githubusercontent.com/DustinWin/ruleset_geodata/clash-ruleset/applications.list",
|
||||
"interval": 86400
|
||||
},
|
||||
|
||||
"private": {
|
||||
"type": "http",
|
||||
"behavior": "domain",
|
||||
"format": "text",
|
||||
"path": "./rules/privates.list",
|
||||
"url": mirrorBaseUrl +
|
||||
"https://raw.githubusercontent.com/DustinWin/ruleset_geodata/clash-ruleset/private.list",
|
||||
"filter": "^((?!openai).)*$",
|
||||
"interval": 86400
|
||||
},
|
||||
|
||||
"microsoft-cn": {
|
||||
"type": "http",
|
||||
"behavior": "domain",
|
||||
"format": "text",
|
||||
"path": "./rules/microsoft-cns.list",
|
||||
"url": mirrorBaseUrl +
|
||||
"https://raw.githubusercontent.com/DustinWin/ruleset_geodata/clash-ruleset/microsoft-cn.list",
|
||||
"interval": 86400
|
||||
},
|
||||
|
||||
"openai": {
|
||||
"type": "http",
|
||||
"behavior": "domain",
|
||||
"format": "text",
|
||||
"path": "./rules/openais.list",
|
||||
"url": mirrorBaseUrl +
|
||||
"https://raw.githubusercontent.com/DustinWin/ruleset_geodata/mihomo-ruleset/ai.list",
|
||||
"interval": 86400
|
||||
},
|
||||
|
||||
"apple-cn": {
|
||||
"type": "http",
|
||||
"behavior": "domain",
|
||||
"format": "text",
|
||||
"path": "./rules/apple-cns.list",
|
||||
"url": mirrorBaseUrl +
|
||||
"https://raw.githubusercontent.com/DustinWin/ruleset_geodata/clash-ruleset/apple-cn.list",
|
||||
"interval": 86400
|
||||
},
|
||||
|
||||
"google-cn": {
|
||||
"type": "http",
|
||||
"behavior": "domain",
|
||||
"format": "text",
|
||||
"path": "./rules/google-cns.list",
|
||||
"url": mirrorBaseUrl +
|
||||
"https://raw.githubusercontent.com/DustinWin/ruleset_geodata/clash-ruleset/google-cn.list",
|
||||
"interval": 86400
|
||||
},
|
||||
|
||||
"games-cn": {
|
||||
"type": "http",
|
||||
"behavior": "domain",
|
||||
"format": "text",
|
||||
"path": "./rules/games-cns.list",
|
||||
"url": mirrorBaseUrl +
|
||||
"https://raw.githubusercontent.com/DustinWin/ruleset_geodata/clash-ruleset/games-cn.list",
|
||||
"interval": 86400
|
||||
},
|
||||
|
||||
"networktest": {
|
||||
"type": "http",
|
||||
"behavior": "classical",
|
||||
"format": "text",
|
||||
"path": "./rules/networktests.list",
|
||||
"url": mirrorBaseUrl +
|
||||
"https://raw.githubusercontent.com/DustinWin/ruleset_geodata/clash-ruleset/networktest.list",
|
||||
"interval": 86400
|
||||
},
|
||||
|
||||
"proxy": {
|
||||
"type": "http",
|
||||
"behavior": "domain",
|
||||
"format": "text",
|
||||
"path": "./rules/proxys.list",
|
||||
"url": mirrorBaseUrl +
|
||||
"https://raw.githubusercontent.com/y7478729/ruleset_geodata/clash-ruleset/proxy.list",
|
||||
"interval": 86400
|
||||
},
|
||||
|
||||
"cn": {
|
||||
"type": "http",
|
||||
"behavior": "domain",
|
||||
"format": "text",
|
||||
"path": "./rules/cns.list",
|
||||
"url": mirrorBaseUrl +
|
||||
"https://raw.githubusercontent.com/DustinWin/ruleset_geodata/clash-ruleset/cn.list",
|
||||
"interval": 86400
|
||||
},
|
||||
|
||||
"telegramip": {
|
||||
"type": "http",
|
||||
"behavior": "ipcidr",
|
||||
"format": "text",
|
||||
"path": "./rules/telegramips.list",
|
||||
"url": mirrorBaseUrl +
|
||||
"https://raw.githubusercontent.com/DustinWin/ruleset_geodata/clash-ruleset/telegramip.list",
|
||||
"interval": 86400
|
||||
},
|
||||
|
||||
"privateip": {
|
||||
"type": "http",
|
||||
"behavior": "ipcidr",
|
||||
"format": "text",
|
||||
"path": "./rules/privateips.list",
|
||||
"url": mirrorBaseUrl +
|
||||
"https://raw.githubusercontent.com/DustinWin/ruleset_geodata/clash-ruleset/privateip.list",
|
||||
"interval": 86400
|
||||
},
|
||||
|
||||
"cnip": {
|
||||
"type": "http",
|
||||
"behavior": "ipcidr",
|
||||
"format": "text",
|
||||
"path": "./rules/cnips.list",
|
||||
"url": mirrorBaseUrl +
|
||||
"https://raw.githubusercontent.com/DustinWin/ruleset_geodata/clash-ruleset/cnip.list",
|
||||
"interval": 86400
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 10. 分流规则
|
||||
* ============================================================ */
|
||||
|
||||
const rules = [
|
||||
|
||||
/*
|
||||
* AI
|
||||
*/
|
||||
"RULE-SET,openai,🤖 人工智能",
|
||||
|
||||
/*
|
||||
* 广告
|
||||
*/
|
||||
"RULE-SET,ads,🆎 广告拦截",
|
||||
|
||||
/*
|
||||
* 本地应用
|
||||
*/
|
||||
"RULE-SET,applications,🎯 全球直连",
|
||||
|
||||
/*
|
||||
* 私有网络
|
||||
*/
|
||||
"RULE-SET,private,🎯 全球直连",
|
||||
|
||||
/*
|
||||
* 微软
|
||||
*/
|
||||
"RULE-SET,microsoft-cn,🎯 全球直连",
|
||||
|
||||
/*
|
||||
* Apple
|
||||
*/
|
||||
"RULE-SET,apple-cn,🎯 全球直连",
|
||||
|
||||
/*
|
||||
* Google
|
||||
*/
|
||||
"RULE-SET,google-cn,🌐 海外服务",
|
||||
|
||||
/*
|
||||
* 游戏
|
||||
*/
|
||||
"RULE-SET,games-cn,🎯 全球直连",
|
||||
|
||||
/*
|
||||
* 网络测试
|
||||
*/
|
||||
"RULE-SET,networktest,📈 网络测试",
|
||||
|
||||
/*
|
||||
* 已知代理域名
|
||||
*/
|
||||
"RULE-SET,proxy,🪜 代理域名",
|
||||
|
||||
/*
|
||||
* 中国域名
|
||||
*/
|
||||
"RULE-SET,cn,🎯 全球直连",
|
||||
|
||||
/*
|
||||
* Telegram IP
|
||||
*/
|
||||
"RULE-SET,telegramip,🌐 海外服务,no-resolve",
|
||||
|
||||
/*
|
||||
* 私有 IP
|
||||
*/
|
||||
"RULE-SET,privateip,🎯 全球直连,no-resolve",
|
||||
|
||||
/*
|
||||
* 中国 IP
|
||||
*/
|
||||
"RULE-SET,cnip,🎯 全球直连,no-resolve",
|
||||
|
||||
/*
|
||||
* 最终兜底
|
||||
*/
|
||||
"MATCH,🛟 兜底策略"
|
||||
];
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 11. 通用工具函数
|
||||
* ============================================================ */
|
||||
|
||||
|
||||
/*
|
||||
* 数组去重,同时保持原始顺序。
|
||||
*/
|
||||
function unique(items) {
|
||||
|
||||
return [
|
||||
...new Set(
|
||||
items.filter(Boolean)
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 安全读取节点名称。
|
||||
*/
|
||||
function getProxyName(proxy) {
|
||||
|
||||
if (
|
||||
!proxy ||
|
||||
typeof proxy.name !== "string"
|
||||
) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return proxy.name.trim();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 判断是否为有效节点。
|
||||
*/
|
||||
function isValidProxy(proxy) {
|
||||
|
||||
const name =
|
||||
getProxyName(proxy);
|
||||
|
||||
if (!name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !nodeNameExcludeReg.test(
|
||||
name
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 12. 获取原始节点
|
||||
* ============================================================ */
|
||||
|
||||
function getRawProxies(config) {
|
||||
|
||||
/*
|
||||
* 优先使用 Sub-Store 传入的 config.proxies。
|
||||
*/
|
||||
if (
|
||||
config &&
|
||||
Array.isArray(config.proxies)
|
||||
) {
|
||||
return config.proxies;
|
||||
}
|
||||
|
||||
/*
|
||||
* 兼容 Sub-Store $proxies。
|
||||
*/
|
||||
if (
|
||||
typeof $proxies !== "undefined" &&
|
||||
Array.isArray($proxies)
|
||||
) {
|
||||
return $proxies;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 13. 过滤有效节点
|
||||
* ============================================================ */
|
||||
|
||||
function filterValidProxies(proxies) {
|
||||
|
||||
return unique(
|
||||
proxies
|
||||
.filter(isValidProxy)
|
||||
.map(proxy => ({
|
||||
...proxy,
|
||||
name: getProxyName(proxy)
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 14. 节点地区分类
|
||||
* ============================================================ */
|
||||
|
||||
/*
|
||||
* 与旧版本不同:
|
||||
*
|
||||
* 不再:
|
||||
*
|
||||
* 地区 1 → 遍历全部节点
|
||||
* 地区 2 → 遍历全部节点
|
||||
* 地区 3 → 遍历全部节点
|
||||
*
|
||||
* 而是:
|
||||
*
|
||||
* 节点 1 → 找到所属地区
|
||||
* 节点 2 → 找到所属地区
|
||||
* 节点 3 → 找到所属地区
|
||||
*
|
||||
* 每个节点只分类一次。
|
||||
*/
|
||||
|
||||
function classifyProxies(
|
||||
proxies
|
||||
) {
|
||||
|
||||
const regionProxyMap = {};
|
||||
|
||||
/*
|
||||
* 初始化所有地区。
|
||||
*/
|
||||
regionDefinitions.forEach(
|
||||
region => {
|
||||
|
||||
regionProxyMap[
|
||||
region.key
|
||||
] = [];
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
* 每个节点只处理一次。
|
||||
*/
|
||||
proxies.forEach(proxy => {
|
||||
|
||||
const name =
|
||||
getProxyName(proxy);
|
||||
|
||||
/*
|
||||
* 从前往后寻找第一个匹配地区。
|
||||
*
|
||||
* other 没有 pattern,
|
||||
* 因此最终自然成为兜底。
|
||||
*/
|
||||
const matchedRegion =
|
||||
regionDefinitions.find(
|
||||
region => {
|
||||
|
||||
if (!region.pattern) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return region.pattern.test(
|
||||
name
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
* 理论上不会出现,
|
||||
* 因为 other 永远存在。
|
||||
*/
|
||||
if (!matchedRegion) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
regionProxyMap[
|
||||
matchedRegion.key
|
||||
].push(name);
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
* 最终统一去重。
|
||||
*/
|
||||
Object.keys(
|
||||
regionProxyMap
|
||||
).forEach(key => {
|
||||
|
||||
regionProxyMap[key] =
|
||||
unique(
|
||||
regionProxyMap[key]
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
return regionProxyMap;
|
||||
}
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 15. 创建地区测速组
|
||||
* ============================================================ */
|
||||
|
||||
function createRegionUrlTestGroup(
|
||||
region,
|
||||
proxyNames
|
||||
) {
|
||||
|
||||
return {
|
||||
|
||||
...urlTestDefaults,
|
||||
|
||||
"name": region.groupName,
|
||||
|
||||
"type": "url-test",
|
||||
|
||||
"proxies": unique(
|
||||
proxyNames
|
||||
),
|
||||
|
||||
/*
|
||||
* 地区组只允许真实代理节点。
|
||||
*/
|
||||
"exclude-type": "direct"
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 16. 创建 Select 组
|
||||
* ============================================================ */
|
||||
|
||||
function createSelectGroup(
|
||||
name,
|
||||
proxies,
|
||||
options = {}
|
||||
) {
|
||||
|
||||
return {
|
||||
|
||||
"name": name,
|
||||
|
||||
"type": "select",
|
||||
|
||||
"proxies": unique(
|
||||
proxies
|
||||
),
|
||||
|
||||
...options
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 17. 获取地区组名称
|
||||
* ============================================================ */
|
||||
|
||||
function getActiveRegionNames(
|
||||
regionDefinitions,
|
||||
regionProxyMap
|
||||
) {
|
||||
|
||||
return regionDefinitions
|
||||
.filter(region => {
|
||||
|
||||
const nodes =
|
||||
regionProxyMap[
|
||||
region.key
|
||||
];
|
||||
|
||||
return (
|
||||
Array.isArray(nodes) &&
|
||||
nodes.length > 0
|
||||
);
|
||||
})
|
||||
.map(region =>
|
||||
region.groupName
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 18. 获取 AI 候选地区
|
||||
* ============================================================ */
|
||||
|
||||
function getAiCandidates(
|
||||
regionDefinitions,
|
||||
regionProxyMap
|
||||
) {
|
||||
|
||||
const candidates = [];
|
||||
|
||||
|
||||
aiRegionKeys.forEach(
|
||||
regionKey => {
|
||||
|
||||
const region =
|
||||
regionDefinitions.find(
|
||||
item =>
|
||||
item.key === regionKey
|
||||
);
|
||||
|
||||
if (!region) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const nodes =
|
||||
regionProxyMap[
|
||||
regionKey
|
||||
];
|
||||
|
||||
|
||||
if (
|
||||
!Array.isArray(nodes) ||
|
||||
nodes.length === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
candidates.push(
|
||||
region.groupName
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
* 非香港地区全部不存在时:
|
||||
*
|
||||
* 不允许回退到自动选择,
|
||||
* 因为自动选择可能包含香港。
|
||||
*
|
||||
* 使用 DIRECT 保证:
|
||||
*
|
||||
* 1. 策略组始终存在
|
||||
* 2. 配置始终合法
|
||||
* 3. 香港永远不会进入 AI
|
||||
*/
|
||||
return candidates.length > 0
|
||||
? unique(candidates)
|
||||
: ["DIRECT"];
|
||||
}
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 19. 创建自动选择
|
||||
* ============================================================ */
|
||||
|
||||
function createAutoSelectGroup(
|
||||
candidates
|
||||
) {
|
||||
|
||||
return {
|
||||
|
||||
...urlTestDefaults,
|
||||
|
||||
"name": "♻️ 自动选择",
|
||||
|
||||
"type": "url-test",
|
||||
|
||||
"proxies": unique(
|
||||
candidates
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 20. 创建故障转移
|
||||
* ============================================================ */
|
||||
|
||||
function createFallbackGroup(
|
||||
candidates
|
||||
) {
|
||||
|
||||
return {
|
||||
|
||||
"name": "🔯 故障转移",
|
||||
|
||||
"type": "fallback",
|
||||
|
||||
"proxies": unique(
|
||||
candidates
|
||||
),
|
||||
|
||||
"url": speedTestUrl,
|
||||
|
||||
"interval": 600,
|
||||
|
||||
"timeout": 3000,
|
||||
|
||||
"lazy": true
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/* ============================================================
|
||||
* 21. 主函数
|
||||
* ============================================================ */
|
||||
|
||||
function main(config = {}) {
|
||||
|
||||
|
||||
/* ----------------------------------------------------------
|
||||
* 21.1 获取原始节点
|
||||
* ---------------------------------------------------------- */
|
||||
|
||||
const rawProxies =
|
||||
getRawProxies(config);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------
|
||||
* 21.2 过滤有效节点
|
||||
* ---------------------------------------------------------- */
|
||||
|
||||
const filteredProxies =
|
||||
filterValidProxies(
|
||||
rawProxies
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
* 保留过滤后的节点。
|
||||
*/
|
||||
config.proxies =
|
||||
filteredProxies;
|
||||
|
||||
|
||||
/* ----------------------------------------------------------
|
||||
* 21.3 地区分类
|
||||
* ---------------------------------------------------------- */
|
||||
|
||||
const regionProxyMap =
|
||||
classifyProxies(
|
||||
filteredProxies
|
||||
);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------
|
||||
* 21.4 获取实际存在的地区
|
||||
* ---------------------------------------------------------- */
|
||||
|
||||
const activeRegions =
|
||||
getActiveRegionNames(
|
||||
regionDefinitions,
|
||||
regionProxyMap
|
||||
);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------
|
||||
* 21.5 创建地区测速组
|
||||
* ---------------------------------------------------------- */
|
||||
|
||||
const regionUrlTestGroups = [];
|
||||
|
||||
|
||||
regionDefinitions.forEach(
|
||||
region => {
|
||||
|
||||
const proxyNames =
|
||||
regionProxyMap[
|
||||
region.key
|
||||
];
|
||||
|
||||
|
||||
/*
|
||||
* 没有节点则隐藏。
|
||||
*/
|
||||
if (
|
||||
!Array.isArray(proxyNames) ||
|
||||
proxyNames.length === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
regionUrlTestGroups.push(
|
||||
|
||||
createRegionUrlTestGroup(
|
||||
region,
|
||||
proxyNames
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------
|
||||
* 21.6 自动选择候选
|
||||
* ---------------------------------------------------------- */
|
||||
|
||||
const autoSelectCandidates =
|
||||
activeRegions.length > 0
|
||||
? activeRegions
|
||||
: ["DIRECT"];
|
||||
|
||||
|
||||
const autoSelectGroup =
|
||||
createAutoSelectGroup(
|
||||
autoSelectCandidates
|
||||
);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------
|
||||
* 21.7 故障转移
|
||||
* ---------------------------------------------------------- */
|
||||
|
||||
const fallbackGroup =
|
||||
createFallbackGroup(
|
||||
autoSelectCandidates
|
||||
);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------
|
||||
* 21.8 AI
|
||||
* ---------------------------------------------------------- */
|
||||
|
||||
const aiCandidates =
|
||||
getAiCandidates(
|
||||
regionDefinitions,
|
||||
regionProxyMap
|
||||
);
|
||||
|
||||
|
||||
const aiGroup = {
|
||||
|
||||
"name": "🤖 人工智能",
|
||||
|
||||
"type": "url-test",
|
||||
|
||||
"proxies": aiCandidates,
|
||||
|
||||
"url": speedTestUrl,
|
||||
|
||||
"interval": 600,
|
||||
|
||||
"timeout": 3000,
|
||||
|
||||
"lazy": true,
|
||||
|
||||
"tolerance": 80,
|
||||
|
||||
"max-failed-times": 3
|
||||
};
|
||||
|
||||
|
||||
/* ----------------------------------------------------------
|
||||
* 21.9 主节点选择
|
||||
* ---------------------------------------------------------- */
|
||||
|
||||
const nodeSelectCandidates =
|
||||
unique([
|
||||
|
||||
"♻️ 自动选择",
|
||||
|
||||
"🔯 故障转移",
|
||||
|
||||
...activeRegions
|
||||
]);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------
|
||||
* 21.10 构建策略组
|
||||
* ---------------------------------------------------------- */
|
||||
|
||||
const proxyGroups = [
|
||||
|
||||
/*
|
||||
* ========================================================
|
||||
* 核心策略组
|
||||
* ========================================================
|
||||
*
|
||||
* 按重要程度放在最顶部。
|
||||
*/
|
||||
|
||||
createSelectGroup(
|
||||
|
||||
"🚀 节点选择",
|
||||
|
||||
nodeSelectCandidates
|
||||
),
|
||||
|
||||
|
||||
autoSelectGroup,
|
||||
|
||||
|
||||
fallbackGroup,
|
||||
|
||||
|
||||
/*
|
||||
* ========================================================
|
||||
* 地区自动测速
|
||||
* ========================================================
|
||||
*/
|
||||
|
||||
...regionUrlTestGroups,
|
||||
|
||||
|
||||
/*
|
||||
* ========================================================
|
||||
* 人工智能
|
||||
* ========================================================
|
||||
*/
|
||||
|
||||
aiGroup,
|
||||
|
||||
|
||||
/*
|
||||
* ========================================================
|
||||
* 海外服务
|
||||
* ========================================================
|
||||
*/
|
||||
|
||||
createSelectGroup(
|
||||
|
||||
"🌐 海外服务",
|
||||
|
||||
[
|
||||
"🚀 节点选择",
|
||||
"♻️ 自动选择",
|
||||
"🔯 故障转移",
|
||||
...activeRegions
|
||||
]
|
||||
),
|
||||
|
||||
|
||||
/*
|
||||
* ========================================================
|
||||
* 代理域名
|
||||
* ========================================================
|
||||
*/
|
||||
|
||||
createSelectGroup(
|
||||
|
||||
"🪜 代理域名",
|
||||
|
||||
[
|
||||
"🚀 节点选择",
|
||||
"🎯 全球直连"
|
||||
]
|
||||
),
|
||||
|
||||
|
||||
/*
|
||||
* ========================================================
|
||||
* 网络测试
|
||||
* ========================================================
|
||||
*/
|
||||
|
||||
createSelectGroup(
|
||||
|
||||
"📈 网络测试",
|
||||
|
||||
[
|
||||
"🎯 全球直连",
|
||||
"🚀 节点选择",
|
||||
"♻️ 自动选择",
|
||||
"🔯 故障转移"
|
||||
]
|
||||
),
|
||||
|
||||
|
||||
/*
|
||||
* ========================================================
|
||||
* 广告拦截
|
||||
* ========================================================
|
||||
*/
|
||||
|
||||
createSelectGroup(
|
||||
|
||||
"🆎 广告拦截",
|
||||
|
||||
[
|
||||
"REJECT"
|
||||
]
|
||||
),
|
||||
|
||||
|
||||
/*
|
||||
* ========================================================
|
||||
* 最终兜底
|
||||
* ========================================================
|
||||
*/
|
||||
|
||||
createSelectGroup(
|
||||
|
||||
"🛟 兜底策略",
|
||||
|
||||
[
|
||||
"🚀 节点选择",
|
||||
"🎯 全球直连"
|
||||
]
|
||||
),
|
||||
|
||||
|
||||
/*
|
||||
* ========================================================
|
||||
* 全球直连
|
||||
* ========================================================
|
||||
*/
|
||||
|
||||
createSelectGroup(
|
||||
|
||||
"🎯 全球直连",
|
||||
|
||||
[
|
||||
"DIRECT"
|
||||
]
|
||||
)
|
||||
];
|
||||
|
||||
|
||||
/* ==========================================================
|
||||
* 22. 写入最终配置
|
||||
* ========================================================== */
|
||||
|
||||
Object.assign(
|
||||
config,
|
||||
generalConfig
|
||||
);
|
||||
|
||||
|
||||
config["sniffer"] =
|
||||
snifferConfig;
|
||||
|
||||
|
||||
config["tun"] =
|
||||
tunConfig;
|
||||
|
||||
|
||||
config["dns"] =
|
||||
dnsConfig;
|
||||
|
||||
|
||||
config["proxy-groups"] =
|
||||
proxyGroups;
|
||||
|
||||
|
||||
config["rule-providers"] =
|
||||
ruleProviders;
|
||||
|
||||
|
||||
config["rules"] =
|
||||
rules;
|
||||
|
||||
|
||||
/* ==========================================================
|
||||
* 23. 返回
|
||||
* ========================================================== */
|
||||
|
||||
return config;
|
||||
}
|
||||
Reference in New Issue
Block a user