Last active
May 7, 2026 01:21
-
-
Save xuyuquan/ebc142d5efb8afbe241fd654c2c3a8f0 to your computer and use it in GitHub Desktop.
clashpart覆写
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /*! | |
| powerfullz 的 Substore 订阅转换脚本 | |
| https://github.com/powerfullz/override-rules | |
| 支持的传入参数: | |
| - loadbalance: 启用负载均衡(url-test/load-balance,默认 false) | |
| - landing: 启用落地节点功能(如机场家宽/星链/落地分组,默认 false) | |
| - ipv6: 启用 IPv6 支持(默认 false) | |
| - full: 输出完整配置(适合纯内核启动,默认 false) | |
| - keepalive: 启用 tcp-keep-alive(默认 false) | |
| - fakeip: DNS 使用 FakeIP 模式(默认 false,false 为 RedirHost) | |
| - quic: 允许 QUIC 流量(UDP 443,默认 false) | |
| - threshold: 国家节点数量小于该值时不显示分组 (默认 0) | |
| - regex: 使用正则过滤模式(include-all + filter)写入各国家代理组,而非直接枚举节点名称(默认 false) | |
| - claude: 启用 Claude 专用规则(默认 true) | |
| - github: 启用 GitHub 专用规则(默认 true) | |
| */ | |
| const NODE_SUFFIX = "节点"; | |
| const DISPLAY_TOGGLES = { | |
| SogouInput: true, | |
| StaticResources: true, | |
| CDNResources: true, | |
| AdditionalCDNResources: true, | |
| TikTok: true, | |
| EHentai: true, | |
| SteamFix: true, | |
| GoogleFCM: true, | |
| Crypto: true, | |
| AI: true, | |
| Apple: true, | |
| Microsoft: true, | |
| Google: true, | |
| YouTube: true, | |
| Telegram: true, | |
| Netflix: true, | |
| Spotify: true, | |
| Bahamut: true, | |
| Bilibili: true, | |
| PikPak: true, | |
| TruthSocial: true, | |
| SSH: true, | |
| Claude: true, | |
| GitHub: true | |
| }; | |
| function isShown(key) { | |
| return DISPLAY_TOGGLES[key] !== false; | |
| } | |
| function parseBool(value) { | |
| return typeof value === "boolean" | |
| ? value | |
| : typeof value === "string" && | |
| (value.toLowerCase() === "true" || value === "1"); | |
| } | |
| function parseNumber(value, fallback = 0) { | |
| if (value == null) { | |
| return fallback; | |
| } | |
| const parsed = parseInt(value, 10); | |
| return Number.isNaN(parsed) ? fallback : parsed; | |
| } | |
| function parseToggle(value, defaultValue) { | |
| return value == null ? defaultValue : parseBool(value); | |
| } | |
| function buildFeatureFlags(args) { | |
| const flags = Object.entries({ | |
| loadbalance: "loadBalance", | |
| landing: "landing", | |
| ipv6: "ipv6Enabled", | |
| full: "fullConfig", | |
| keepalive: "keepAliveEnabled", | |
| fakeip: "fakeIPEnabled", | |
| quic: "quicEnabled", | |
| regex: "regexFilter" | |
| }).reduce((result, [argument, key]) => { | |
| result[key] = parseBool(args[argument]) || false; | |
| return result; | |
| }, {}); | |
| flags.countryThreshold = parseNumber(args.threshold, 0); | |
| flags.claudeEnabled = parseToggle(args.claude, true); | |
| flags.githubEnabled = parseToggle(args.github, true); | |
| return flags; | |
| } | |
| const rawArgs = typeof $arguments !== "undefined" ? $arguments : {}; | |
| const { | |
| loadBalance, | |
| landing, | |
| ipv6Enabled, | |
| fullConfig, | |
| keepAliveEnabled, | |
| fakeIPEnabled, | |
| quicEnabled, | |
| regexFilter, | |
| countryThreshold, | |
| claudeEnabled, | |
| githubEnabled | |
| } = buildFeatureFlags(rawArgs); | |
| function getCountryGroupNames(countryInfo, threshold) { | |
| const groups = countryInfo.filter(item => item.nodes.length >= threshold); | |
| groups.sort( | |
| (left, right) => | |
| (countriesMeta[left.country]?.weight ?? Infinity) - | |
| (countriesMeta[right.country]?.weight ?? Infinity) | |
| ); | |
| return groups.map(item => item.country + NODE_SUFFIX); | |
| } | |
| function stripNodeSuffix(names) { | |
| const suffixRegex = new RegExp(`${NODE_SUFFIX}$`); | |
| return names.map(name => name.replace(suffixRegex, "")); | |
| } | |
| const PROXY_GROUPS = { | |
| SELECT: "选择代理", | |
| AUTO: "自动选择", | |
| MANUAL: "手动选择", | |
| FALLBACK: "故障转移", | |
| DIRECT: "直连", | |
| LANDING: "落地节点", | |
| LOW_COST: "低倍率节点" | |
| }; | |
| const buildList = (...items) => items.flat().filter(Boolean); | |
| function buildBaseLists({ landing: enableLanding, lowCostNodes, countryGroupNames }) { | |
| const hasLowCostGroup = lowCostNodes.length > 0 || regexFilter; | |
| const autoCandidates = buildList( | |
| enableLanding && PROXY_GROUPS.LANDING, | |
| countryGroupNames, | |
| hasLowCostGroup && PROXY_GROUPS.LOW_COST, | |
| PROXY_GROUPS.MANUAL | |
| ); | |
| const defaultSelector = buildList( | |
| PROXY_GROUPS.AUTO, | |
| PROXY_GROUPS.FALLBACK, | |
| enableLanding && PROXY_GROUPS.LANDING, | |
| countryGroupNames, | |
| hasLowCostGroup && PROXY_GROUPS.LOW_COST, | |
| PROXY_GROUPS.MANUAL, | |
| "DIRECT" | |
| ); | |
| return { | |
| defaultProxies: buildList( | |
| PROXY_GROUPS.SELECT, | |
| PROXY_GROUPS.AUTO, | |
| countryGroupNames, | |
| hasLowCostGroup && PROXY_GROUPS.LOW_COST, | |
| PROXY_GROUPS.MANUAL, | |
| PROXY_GROUPS.DIRECT | |
| ), | |
| defaultProxiesDirect: buildList( | |
| PROXY_GROUPS.DIRECT, | |
| PROXY_GROUPS.AUTO, | |
| countryGroupNames, | |
| hasLowCostGroup && PROXY_GROUPS.LOW_COST, | |
| PROXY_GROUPS.SELECT, | |
| PROXY_GROUPS.MANUAL | |
| ), | |
| autoCandidates, | |
| defaultSelector, | |
| defaultFallback: buildList( | |
| enableLanding && PROXY_GROUPS.LANDING, | |
| countryGroupNames, | |
| hasLowCostGroup && PROXY_GROUPS.LOW_COST, | |
| PROXY_GROUPS.MANUAL, | |
| "DIRECT" | |
| ) | |
| }; | |
| } | |
| const baseRuleProviders = { | |
| ADBlock: { | |
| type: "http", | |
| behavior: "domain", | |
| format: "mrs", | |
| interval: 86400, | |
| url: "https://gcore.jsdelivr.net/gh/217heidai/adblockfilters@main/rules/adblockmihomolite.mrs", | |
| path: "./ruleset/ADBlock.mrs" | |
| }, | |
| SogouInput: { | |
| type: "http", | |
| behavior: "classical", | |
| format: "text", | |
| interval: 86400, | |
| url: "https://ruleset.skk.moe/Clash/non_ip/sogouinput.txt", | |
| path: "./ruleset/SogouInput.txt" | |
| }, | |
| StaticResources: { | |
| type: "http", | |
| behavior: "domain", | |
| format: "text", | |
| interval: 86400, | |
| url: "https://ruleset.skk.moe/Clash/domainset/cdn.txt", | |
| path: "./ruleset/StaticResources.txt" | |
| }, | |
| CDNResources: { | |
| type: "http", | |
| behavior: "classical", | |
| format: "text", | |
| interval: 86400, | |
| url: "https://ruleset.skk.moe/Clash/non_ip/cdn.txt", | |
| path: "./ruleset/CDNResources.txt" | |
| }, | |
| TikTok: { | |
| type: "http", | |
| behavior: "classical", | |
| format: "text", | |
| interval: 86400, | |
| url: "https://gcore.jsdelivr.net/gh/powerfullz/override-rules@master/ruleset/TikTok.list", | |
| path: "./ruleset/TikTok.list" | |
| }, | |
| EHentai: { | |
| type: "http", | |
| behavior: "classical", | |
| format: "text", | |
| interval: 86400, | |
| url: "https://gcore.jsdelivr.net/gh/powerfullz/override-rules@master/ruleset/EHentai.list", | |
| path: "./ruleset/EHentai.list" | |
| }, | |
| SteamFix: { | |
| type: "http", | |
| behavior: "classical", | |
| format: "text", | |
| interval: 86400, | |
| url: "https://gcore.jsdelivr.net/gh/powerfullz/override-rules@master/ruleset/SteamFix.list", | |
| path: "./ruleset/SteamFix.list" | |
| }, | |
| GoogleFCM: { | |
| type: "http", | |
| behavior: "classical", | |
| format: "text", | |
| interval: 86400, | |
| url: "https://gcore.jsdelivr.net/gh/powerfullz/override-rules@master/ruleset/FirebaseCloudMessaging.list", | |
| path: "./ruleset/FirebaseCloudMessaging.list" | |
| }, | |
| AdditionalFilter: { | |
| type: "http", | |
| behavior: "classical", | |
| format: "text", | |
| interval: 86400, | |
| url: "https://gcore.jsdelivr.net/gh/powerfullz/override-rules@master/ruleset/AdditionalFilter.list", | |
| path: "./ruleset/AdditionalFilter.list" | |
| }, | |
| AdditionalCDNResources: { | |
| type: "http", | |
| behavior: "classical", | |
| format: "text", | |
| interval: 86400, | |
| url: "https://gcore.jsdelivr.net/gh/powerfullz/override-rules@master/ruleset/AdditionalCDNResources.list", | |
| path: "./ruleset/AdditionalCDNResources.list" | |
| }, | |
| Crypto: { | |
| type: "http", | |
| behavior: "classical", | |
| format: "text", | |
| interval: 86400, | |
| url: "https://gcore.jsdelivr.net/gh/powerfullz/override-rules@master/ruleset/Crypto.list", | |
| path: "./ruleset/Crypto.list" | |
| } | |
| }; | |
| function buildRuleProviders({ claudeEnabled: enableClaude, githubEnabled: enableGitHub }) { | |
| return { | |
| ADBlock: baseRuleProviders.ADBlock, | |
| AdditionalFilter: baseRuleProviders.AdditionalFilter, | |
| ...(isShown("SogouInput") ? { SogouInput: baseRuleProviders.SogouInput } : {}), | |
| ...(isShown("StaticResources") | |
| ? { StaticResources: baseRuleProviders.StaticResources } | |
| : {}), | |
| ...(isShown("CDNResources") ? { CDNResources: baseRuleProviders.CDNResources } : {}), | |
| ...(isShown("TikTok") ? { TikTok: baseRuleProviders.TikTok } : {}), | |
| ...(isShown("EHentai") ? { EHentai: baseRuleProviders.EHentai } : {}), | |
| ...(isShown("SteamFix") ? { SteamFix: baseRuleProviders.SteamFix } : {}), | |
| ...(isShown("GoogleFCM") ? { GoogleFCM: baseRuleProviders.GoogleFCM } : {}), | |
| ...(isShown("AdditionalCDNResources") | |
| ? { AdditionalCDNResources: baseRuleProviders.AdditionalCDNResources } | |
| : {}), | |
| ...(isShown("Crypto") ? { Crypto: baseRuleProviders.Crypto } : {}), | |
| ...(enableClaude | |
| ? { | |
| Claude: { | |
| type: "http", | |
| behavior: "classical", | |
| url: "https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Claude/Claude.yaml", | |
| path: "./ruleset/custom/Claude.yaml" | |
| } | |
| } | |
| : {}), | |
| ...(enableGitHub | |
| ? { | |
| GitHub: { | |
| type: "http", | |
| behavior: "classical", | |
| format: "text", | |
| interval: 86400, | |
| url: "https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Loon/GitHub/GitHub.list", | |
| path: "./ruleset/custom/GitHub.list" | |
| } | |
| } | |
| : {}) | |
| }; | |
| } | |
| const baseRules = [ | |
| "RULE-SET,ADBlock,广告拦截", | |
| "RULE-SET,AdditionalFilter,广告拦截", | |
| isShown("SogouInput") && "RULE-SET,SogouInput,搜狗输入法", | |
| isShown("TruthSocial") && "DOMAIN-SUFFIX,truthsocial.com,真相社交", | |
| isShown("StaticResources") && "RULE-SET,StaticResources,静态资源", | |
| isShown("CDNResources") && "RULE-SET,CDNResources,静态资源", | |
| isShown("AdditionalCDNResources") && "RULE-SET,AdditionalCDNResources,静态资源", | |
| isShown("Crypto") && "RULE-SET,Crypto,加密货币", | |
| isShown("EHentai") && "RULE-SET,EHentai,E-Hentai", | |
| isShown("TikTok") && "RULE-SET,TikTok,TikTok", | |
| isShown("YouTube") && "GEOSITE,YOUTUBE,YouTube", | |
| isShown("Telegram") && "GEOSITE,TELEGRAM,Telegram", | |
| isShown("SteamFix") && `RULE-SET,SteamFix,${PROXY_GROUPS.DIRECT}`, | |
| isShown("GoogleFCM") && `RULE-SET,GoogleFCM,${PROXY_GROUPS.DIRECT}`, | |
| isShown("AI") && "GEOSITE,CATEGORY-AI-!CN,AI服务", | |
| `GEOSITE,GOOGLE-PLAY@CN,${PROXY_GROUPS.DIRECT}`, | |
| `GEOSITE,MICROSOFT@CN,${PROXY_GROUPS.DIRECT}`, | |
| isShown("Apple") && "GEOSITE,APPLE,Apple", | |
| isShown("Microsoft") && "GEOSITE,MICROSOFT,微软服务", | |
| isShown("Google") && "GEOSITE,GOOGLE,Google", | |
| isShown("Netflix") && "GEOSITE,NETFLIX,Netflix", | |
| isShown("Spotify") && "GEOSITE,SPOTIFY,Spotify", | |
| isShown("Bahamut") && "GEOSITE,BAHAMUT,巴哈姆特", | |
| isShown("Bilibili") && "GEOSITE,BILIBILI,哔哩哔哩", | |
| isShown("PikPak") && "GEOSITE,PIKPAK,PikPak网盘", | |
| `GEOSITE,GFW,${PROXY_GROUPS.SELECT}`, | |
| `GEOSITE,CN,${PROXY_GROUPS.DIRECT}`, | |
| `GEOSITE,PRIVATE,${PROXY_GROUPS.DIRECT}`, | |
| isShown("Netflix") && "GEOIP,NETFLIX,Netflix,no-resolve", | |
| isShown("Telegram") && "GEOIP,TELEGRAM,Telegram,no-resolve", | |
| `GEOIP,CN,${PROXY_GROUPS.DIRECT}`, | |
| `GEOIP,PRIVATE,${PROXY_GROUPS.DIRECT}`, | |
| isShown("SSH") && "DST-PORT,22,SSH(22端口)", | |
| `MATCH,${PROXY_GROUPS.SELECT}` | |
| ].filter(Boolean); | |
| function buildRules({ | |
| quicEnabled: enableQuic, | |
| claudeEnabled: enableClaude, | |
| githubEnabled: enableGitHub | |
| }) { | |
| const rules = [...baseRules]; | |
| const insertAt = rules.indexOf(`GEOSITE,GFW,${PROXY_GROUPS.SELECT}`); | |
| const customRules = []; | |
| if (enableClaude) { | |
| customRules.push("RULE-SET,Claude,Claude"); | |
| } | |
| if (enableGitHub) { | |
| customRules.push("RULE-SET,GitHub,GitHub"); | |
| } | |
| if (customRules.length > 0) { | |
| const targetIndex = insertAt === -1 ? rules.length - 1 : insertAt; | |
| rules.splice(targetIndex, 0, ...customRules); | |
| } | |
| if (!enableQuic) { | |
| rules.unshift("AND,((DST-PORT,443),(NETWORK,UDP)),REJECT"); | |
| } | |
| return rules; | |
| } | |
| const snifferConfig = { | |
| sniff: { | |
| TLS: { ports: [443, 8443] }, | |
| HTTP: { ports: [80, 8080, 8880] }, | |
| QUIC: { ports: [443, 8443] } | |
| }, | |
| "override-destination": false, | |
| enable: true, | |
| "force-dns-mapping": true, | |
| "skip-domain": ["Mijia Cloud", "dlg.io.mi.com", "+.push.apple.com"] | |
| }; | |
| function buildDnsConfig({ mode, fakeIpFilter }) { | |
| const config = { | |
| enable: true, | |
| ipv6: ipv6Enabled, | |
| "prefer-h3": true, | |
| "enhanced-mode": mode, | |
| "default-nameserver": ["119.29.29.29", "223.5.5.5"], | |
| nameserver: ["system", "223.5.5.5", "119.29.29.29", "180.184.1.1"], | |
| fallback: [ | |
| "quic://dns0.eu", | |
| "https://dns.cloudflare.com/dns-query", | |
| "https://dns.sb/dns-query", | |
| "tcp://208.67.222.222", | |
| "tcp://8.26.56.2" | |
| ], | |
| "proxy-server-nameserver": ["https://dns.alidns.com/dns-query", "tls://dot.pub"] | |
| }; | |
| if (fakeIpFilter) { | |
| config["fake-ip-filter"] = fakeIpFilter; | |
| } | |
| return config; | |
| } | |
| const dnsConfig = buildDnsConfig({ mode: "redir-host" }); | |
| const dnsConfigFakeIp = buildDnsConfig({ | |
| mode: "fake-ip", | |
| fakeIpFilter: [ | |
| "geosite:private", | |
| "geosite:connectivity-check", | |
| "geosite:cn", | |
| "Mijia Cloud", | |
| "dig.io.mi.com", | |
| "localhost.ptlogin2.qq.com", | |
| "*.icloud.com", | |
| "*.stun.*.*", | |
| "*.stun.*.*.*" | |
| ] | |
| }); | |
| const geoxURL = { | |
| geoip: "https://gcore.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/geoip.dat", | |
| geosite: "https://gcore.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/geosite.dat", | |
| mmdb: "https://gcore.jsdelivr.net/gh/Loyalsoldier/geoip@release/Country.mmdb", | |
| asn: "https://gcore.jsdelivr.net/gh/Loyalsoldier/geoip@release/GeoLite2-ASN.mmdb" | |
| }; | |
| const countriesMeta = { | |
| 香港: { | |
| weight: 10, | |
| pattern: "香港|港|HK|hk|Hong Kong|HongKong|hongkong|🇭🇰", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Hong_Kong.png" | |
| }, | |
| 澳门: { | |
| pattern: "澳门|MO|Macau|🇲🇴", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Macao.png" | |
| }, | |
| 台湾: { | |
| weight: 20, | |
| pattern: "台|新北|彰化|TW|Taiwan|🇹🇼", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Taiwan.png" | |
| }, | |
| 新加坡: { | |
| weight: 30, | |
| pattern: "新加坡|坡|狮城|SG|Singapore|🇸🇬", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Singapore.png" | |
| }, | |
| 日本: { | |
| weight: 40, | |
| pattern: "日本|川日|东京|大阪|泉日|埼玉|沪日|深日|JP|Japan|🇯🇵", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Japan.png" | |
| }, | |
| 韩国: { | |
| pattern: "KR|Korea|KOR|首尔|韩|韓|🇰🇷", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Korea.png" | |
| }, | |
| 美国: { | |
| weight: 50, | |
| pattern: "美国|美|US|United States|🇺🇸", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/United_States.png" | |
| }, | |
| 加拿大: { | |
| pattern: "加拿大|Canada|CA|🇨🇦", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Canada.png" | |
| }, | |
| 英国: { | |
| weight: 60, | |
| pattern: "英国|United Kingdom|UK|伦敦|London|🇬🇧", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/United_Kingdom.png" | |
| }, | |
| 澳大利亚: { | |
| pattern: "澳洲|澳大利亚|AU|Australia|🇦🇺", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Australia.png" | |
| }, | |
| 德国: { | |
| weight: 70, | |
| pattern: "德国|德|DE|Germany|🇩🇪", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Germany.png" | |
| }, | |
| 法国: { | |
| weight: 80, | |
| pattern: "法国|法|FR|France|🇫🇷", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/France.png" | |
| }, | |
| 俄罗斯: { | |
| pattern: "俄罗斯|俄|RU|Russia|🇷🇺", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Russia.png" | |
| }, | |
| 泰国: { | |
| pattern: "泰国|泰|TH|Thailand|🇹🇭", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Thailand.png" | |
| }, | |
| 印度: { | |
| pattern: "印度|IN|India|🇮🇳", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/India.png" | |
| }, | |
| 马来西亚: { | |
| pattern: "马来西亚|马来|MY|Malaysia|🇲🇾", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Malaysia.png" | |
| } | |
| }; | |
| const LOW_COST_REGEX = /0\.[0-5]|低倍率|省流|大流量|实验性/i; | |
| const LANDING_REGEX = /家宽|家庭|家庭宽带|商宽|商业宽带|星链|Starlink|落地/i; | |
| const LANDING_PATTERN = "(?i)家宽|家庭|家庭宽带|商宽|商业宽带|星链|Starlink|落地"; | |
| function parseLowCost(source) { | |
| return (source.proxies || []) | |
| .filter(proxy => LOW_COST_REGEX.test(proxy.name)) | |
| .map(proxy => proxy.name); | |
| } | |
| function parseLandingNodes(source) { | |
| return (source.proxies || []) | |
| .filter(proxy => LANDING_REGEX.test(proxy.name)) | |
| .map(proxy => proxy.name); | |
| } | |
| function parseCountries(source) { | |
| const proxies = source.proxies || []; | |
| const grouped = Object.create(null); | |
| const patterns = {}; | |
| for (const [country, meta] of Object.entries(countriesMeta)) { | |
| patterns[country] = new RegExp(meta.pattern.replace(/^\(\?i\)/, "")); | |
| } | |
| for (const proxy of proxies) { | |
| const name = proxy.name || ""; | |
| if (LANDING_REGEX.test(name) || LOW_COST_REGEX.test(name)) { | |
| continue; | |
| } | |
| for (const [country, pattern] of Object.entries(patterns)) { | |
| if (!pattern.test(name)) { | |
| continue; | |
| } | |
| if (!grouped[country]) { | |
| grouped[country] = []; | |
| } | |
| grouped[country].push(name); | |
| break; | |
| } | |
| } | |
| const countries = []; | |
| for (const [country, nodes] of Object.entries(grouped)) { | |
| countries.push({ country, nodes }); | |
| } | |
| return countries; | |
| } | |
| function buildCountryProxyGroups({ | |
| countries, | |
| landing: enableLanding, | |
| loadBalance: enableLoadBalance, | |
| regexFilter: enableRegexFilter, | |
| countryInfo | |
| }) { | |
| const groups = []; | |
| const lowCostPattern = "0\\.[0-5]|低倍率|省流|大流量|实验性"; | |
| const groupType = enableLoadBalance ? "load-balance" : "url-test"; | |
| const nodesByCountry = enableRegexFilter | |
| ? null | |
| : Object.fromEntries(countryInfo.map(item => [item.country, item.nodes])); | |
| for (const country of countries) { | |
| const meta = countriesMeta[country]; | |
| if (!meta) { | |
| continue; | |
| } | |
| let group; | |
| if (enableRegexFilter) { | |
| group = { | |
| name: `${country}${NODE_SUFFIX}`, | |
| icon: meta.icon, | |
| "include-all": true, | |
| filter: meta.pattern, | |
| "exclude-filter": enableLanding | |
| ? `${LANDING_PATTERN}|${lowCostPattern}` | |
| : lowCostPattern, | |
| type: groupType | |
| }; | |
| } else { | |
| group = { | |
| name: `${country}${NODE_SUFFIX}`, | |
| icon: meta.icon, | |
| type: groupType, | |
| proxies: nodesByCountry[country] || [] | |
| }; | |
| } | |
| if (!enableLoadBalance) { | |
| Object.assign(group, { | |
| url: "https://cp.cloudflare.com/generate_204", | |
| interval: 60, | |
| tolerance: 20, | |
| lazy: false | |
| }); | |
| } | |
| groups.push(group); | |
| } | |
| return groups; | |
| } | |
| function buildProxyGroups({ | |
| landing: enableLanding, | |
| countries, | |
| countryProxyGroups, | |
| lowCostNodes, | |
| landingNodes, | |
| defaultProxies, | |
| defaultProxiesDirect, | |
| autoCandidates, | |
| defaultSelector, | |
| defaultFallback, | |
| claudeEnabled: enableClaude, | |
| githubEnabled: enableGitHub | |
| }) { | |
| const hasTaiwan = countries.includes("台湾"); | |
| const hasHongKong = countries.includes("香港"); | |
| const hasUnitedStates = countries.includes("美国"); | |
| const preProxyOptions = enableLanding | |
| ? defaultSelector.filter( | |
| name => name !== PROXY_GROUPS.LANDING && name !== PROXY_GROUPS.FALLBACK | |
| ) | |
| : []; | |
| return [ | |
| { | |
| name: PROXY_GROUPS.SELECT, | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Proxy.png", | |
| type: "select", | |
| proxies: defaultSelector | |
| }, | |
| { | |
| name: PROXY_GROUPS.AUTO, | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Auto.png", | |
| type: "url-test", | |
| url: "https://cp.cloudflare.com/generate_204", | |
| proxies: autoCandidates, | |
| interval: 180, | |
| tolerance: 20, | |
| lazy: false | |
| }, | |
| { | |
| name: PROXY_GROUPS.MANUAL, | |
| icon: "https://gcore.jsdelivr.net/gh/shindgewongxj/WHATSINStash@master/icon/select.png", | |
| "include-all": true, | |
| type: "select" | |
| }, | |
| enableLanding | |
| ? { | |
| name: "前置代理", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Area.png", | |
| type: "select", | |
| ...(regexFilter | |
| ? { | |
| "include-all": true, | |
| "exclude-filter": LANDING_PATTERN, | |
| proxies: preProxyOptions | |
| } | |
| : { proxies: preProxyOptions }) | |
| } | |
| : null, | |
| enableLanding | |
| ? { | |
| name: PROXY_GROUPS.LANDING, | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Airport.png", | |
| type: "select", | |
| ...(regexFilter | |
| ? { "include-all": true, filter: LANDING_PATTERN } | |
| : { proxies: landingNodes }) | |
| } | |
| : null, | |
| { | |
| name: PROXY_GROUPS.FALLBACK, | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Bypass.png", | |
| type: "fallback", | |
| url: "https://cp.cloudflare.com/generate_204", | |
| proxies: defaultFallback, | |
| interval: 180, | |
| tolerance: 20, | |
| lazy: false | |
| }, | |
| (isShown("StaticResources") || | |
| isShown("CDNResources") || | |
| isShown("AdditionalCDNResources")) && { | |
| name: "静态资源", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Cloudflare.png", | |
| type: "select", | |
| proxies: defaultProxies | |
| }, | |
| isShown("AI") && { | |
| name: "AI服务", | |
| icon: "https://gcore.jsdelivr.net/gh/powerfullz/override-rules@master/icons/chatgpt.png", | |
| type: "select", | |
| proxies: defaultProxies | |
| }, | |
| isShown("Claude") && enableClaude | |
| ? { | |
| name: "Claude", | |
| icon: "https://fastly.jsdelivr.net/gh/clash-verge-rev/clash-verge-rev.github.io@main/docs/assets/icons/claude.svg", | |
| type: "select", | |
| proxies: defaultProxies | |
| } | |
| : null, | |
| isShown("Crypto") && { | |
| name: "加密货币", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Cryptocurrency_3.png", | |
| type: "select", | |
| proxies: defaultProxies | |
| }, | |
| isShown("Apple") && { | |
| name: "Apple", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Apple.png", | |
| type: "select", | |
| proxies: defaultProxies | |
| }, | |
| isShown("Google") && { | |
| name: "Google", | |
| icon: "https://gcore.jsdelivr.net/gh/powerfullz/override-rules@master/icons/Google.png", | |
| type: "select", | |
| proxies: defaultProxies | |
| }, | |
| isShown("GitHub") && enableGitHub | |
| ? { | |
| name: "GitHub", | |
| icon: "https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Color/GitHub.png", | |
| type: "select", | |
| proxies: defaultProxiesDirect | |
| } | |
| : null, | |
| isShown("Microsoft") && { | |
| name: "微软服务", | |
| icon: "https://gcore.jsdelivr.net/gh/powerfullz/override-rules@master/icons/Microsoft_Copilot.png", | |
| type: "select", | |
| proxies: defaultProxies | |
| }, | |
| isShown("YouTube") && { | |
| name: "YouTube", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/YouTube.png", | |
| type: "select", | |
| proxies: defaultProxies | |
| }, | |
| isShown("Bilibili") && { | |
| name: "哔哩哔哩", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/bilibili.png", | |
| type: "select", | |
| proxies: | |
| hasTaiwan && hasHongKong | |
| ? [PROXY_GROUPS.DIRECT, "台湾节点", "香港节点"] | |
| : defaultProxiesDirect | |
| }, | |
| isShown("Bahamut") && { | |
| name: "巴哈姆特", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Bahamut.png", | |
| type: "select", | |
| proxies: hasTaiwan | |
| ? ["台湾节点", PROXY_GROUPS.SELECT, PROXY_GROUPS.MANUAL, PROXY_GROUPS.DIRECT] | |
| : defaultProxies | |
| }, | |
| isShown("Netflix") && { | |
| name: "Netflix", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Netflix.png", | |
| type: "select", | |
| proxies: defaultProxies | |
| }, | |
| isShown("TikTok") && { | |
| name: "TikTok", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/TikTok.png", | |
| type: "select", | |
| proxies: defaultProxies | |
| }, | |
| isShown("Spotify") && { | |
| name: "Spotify", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Spotify.png", | |
| type: "select", | |
| proxies: defaultProxies | |
| }, | |
| isShown("EHentai") && { | |
| name: "E-Hentai", | |
| icon: "https://gcore.jsdelivr.net/gh/powerfullz/override-rules@master/icons/Ehentai.png", | |
| type: "select", | |
| proxies: defaultProxies | |
| }, | |
| isShown("Telegram") && { | |
| name: "Telegram", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Telegram.png", | |
| type: "select", | |
| proxies: defaultProxies | |
| }, | |
| isShown("TruthSocial") && { | |
| name: "真相社交", | |
| icon: "https://gcore.jsdelivr.net/gh/powerfullz/override-rules@master/icons/TruthSocial.png", | |
| type: "select", | |
| proxies: hasUnitedStates | |
| ? ["美国节点", PROXY_GROUPS.SELECT, PROXY_GROUPS.MANUAL] | |
| : defaultProxies | |
| }, | |
| isShown("PikPak") && { | |
| name: "PikPak网盘", | |
| icon: "https://gcore.jsdelivr.net/gh/powerfullz/override-rules@master/icons/PikPak.png", | |
| type: "select", | |
| proxies: defaultProxies | |
| }, | |
| isShown("SSH") && { | |
| name: "SSH(22端口)", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Server.png", | |
| type: "select", | |
| proxies: defaultProxies | |
| }, | |
| isShown("SogouInput") && { | |
| name: "搜狗输入法", | |
| icon: "https://gcore.jsdelivr.net/gh/powerfullz/override-rules@master/icons/Sougou.png", | |
| type: "select", | |
| proxies: [PROXY_GROUPS.DIRECT, "REJECT"] | |
| }, | |
| { | |
| name: PROXY_GROUPS.DIRECT, | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Direct.png", | |
| type: "select", | |
| proxies: ["DIRECT", PROXY_GROUPS.SELECT] | |
| }, | |
| { | |
| name: "广告拦截", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/AdBlack.png", | |
| type: "select", | |
| proxies: ["REJECT", "REJECT-DROP", PROXY_GROUPS.DIRECT] | |
| }, | |
| lowCostNodes.length > 0 || regexFilter | |
| ? { | |
| name: PROXY_GROUPS.LOW_COST, | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Lab.png", | |
| type: "url-test", | |
| url: "https://cp.cloudflare.com/generate_204", | |
| ...(regexFilter | |
| ? { | |
| "include-all": true, | |
| filter: "(?i)0\\.[0-5]|低倍率|省流|大流量|实验性" | |
| } | |
| : { proxies: lowCostNodes }) | |
| } | |
| : null, | |
| ...countryProxyGroups | |
| ].filter(Boolean); | |
| } | |
| function main(config) { | |
| const result = { | |
| proxies: config.proxies | |
| }; | |
| const countryInfo = parseCountries(result); | |
| const lowCostNodes = parseLowCost(result); | |
| const landingNodes = landing ? parseLandingNodes(result) : []; | |
| const countryGroupNames = getCountryGroupNames(countryInfo, countryThreshold); | |
| const countries = stripNodeSuffix(countryGroupNames); | |
| const { | |
| defaultProxies, | |
| defaultProxiesDirect, | |
| autoCandidates, | |
| defaultSelector, | |
| defaultFallback | |
| } = buildBaseLists({ | |
| landing, | |
| lowCostNodes, | |
| countryGroupNames | |
| }); | |
| const countryProxyGroups = buildCountryProxyGroups({ | |
| countries, | |
| landing, | |
| loadBalance, | |
| regexFilter, | |
| countryInfo | |
| }); | |
| const proxyGroups = buildProxyGroups({ | |
| landing, | |
| countries, | |
| countryProxyGroups, | |
| lowCostNodes, | |
| landingNodes, | |
| defaultProxies, | |
| defaultProxiesDirect, | |
| autoCandidates, | |
| defaultSelector, | |
| defaultFallback, | |
| claudeEnabled, | |
| githubEnabled | |
| }); | |
| const groupNames = proxyGroups.map(group => group.name); | |
| proxyGroups.push({ | |
| name: "GLOBAL", | |
| icon: "https://gcore.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Global.png", | |
| "include-all": true, | |
| type: "select", | |
| proxies: groupNames | |
| }); | |
| const rules = buildRules({ | |
| quicEnabled, | |
| claudeEnabled, | |
| githubEnabled | |
| }); | |
| const ruleProviders = buildRuleProviders({ | |
| claudeEnabled, | |
| githubEnabled | |
| }); | |
| if (fullConfig) { | |
| Object.assign(result, { | |
| "mixed-port": 7890, | |
| "redir-port": 7892, | |
| "tproxy-port": 7893, | |
| "routing-mark": 7894, | |
| "allow-lan": true, | |
| "bind-address": "*", | |
| ipv6: ipv6Enabled, | |
| mode: "rule", | |
| "unified-delay": true, | |
| "tcp-concurrent": true, | |
| "find-process-mode": "off", | |
| "log-level": "info", | |
| "geodata-loader": "standard", | |
| "external-controller": ":9999", | |
| "disable-keep-alive": !keepAliveEnabled, | |
| profile: { | |
| "store-selected": true | |
| } | |
| }); | |
| } | |
| Object.assign(result, { | |
| "proxy-groups": proxyGroups, | |
| "rule-providers": ruleProviders, | |
| rules, | |
| sniffer: snifferConfig, | |
| dns: fakeIPEnabled ? dnsConfigFakeIp : dnsConfig, | |
| "geodata-mode": true, | |
| "geox-url": geoxURL | |
| }); | |
| return result; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment