Grouped services by category for clarity and maintainability. Added new entries for Medium and OKX, and reordered existing services to improve logical structure.
690 lines
19 KiB
JavaScript
690 lines
19 KiB
JavaScript
// from https://github.com/xixu-me/META
|
|
|
|
// ################################################### this section can be flexibly customized ###################################################
|
|
|
|
const LOCATION_ICON_SET_URL = "https://img.icons8.com/color/144/";
|
|
|
|
// Routing rules are matched in order from top to bottom, with the rule at the top of the list taking precedence over the rules below it.
|
|
const services = [
|
|
// AI/LLM Services
|
|
{ name: "Anthropic", tld: "com" },
|
|
{ name: "Gemini", tld: "google", alias: "Google-Gemini" },
|
|
{ name: "NotebookLM", tld: "google", alias: "Google-NotebookLM" },
|
|
{ name: "OpenAI", tld: "com" },
|
|
{ name: "Perplexity", tld: "ai" },
|
|
{ name: "xAI", tld: "ai", sld: "x" },
|
|
|
|
// Media & Content
|
|
{ name: "bilibili", tld: "com" },
|
|
{ name: "Medium", tld: "com" },
|
|
{ name: "YouTube", tld: "com" },
|
|
// Social Media & Communication
|
|
{ name: "rednote", tld: "com", sld: "xiaohongshu", alias: "Xiaohongshu" },
|
|
{ name: "Telegram", tld: "org" },
|
|
{ name: "X", tld: "com" },
|
|
|
|
// Financial Services
|
|
{ name: "Binance", tld: "com" },
|
|
{ name: "OKX", tld: "com" },
|
|
|
|
// Technology Companies
|
|
{ name: "Google", tld: "google", sld: "about" },
|
|
{ name: "Microsoft", tld: "com" },
|
|
|
|
// Infrastructure & Tools
|
|
{ name: "Speedtest", tld: "net" },
|
|
{ name: "Xget", domain: "xget.xi-xu.me" },
|
|
{ name: "Cloudflare", tld: "com" },
|
|
];
|
|
|
|
const locations = [
|
|
{
|
|
name: "Argentina 🇦🇷",
|
|
icon: `${LOCATION_ICON_SET_URL}argentina`,
|
|
filter: "(?i)\u963f\u6839\u5ef7|Argentina|ARG|AR|argentina|arg|ar|🇦🇷",
|
|
},
|
|
{
|
|
name: "Canada 🇨🇦",
|
|
icon: `${LOCATION_ICON_SET_URL}canada`,
|
|
filter: "(?i)\u52a0\u62ff\u5927|Canada|CAN|CA|canada|ca|🇨🇦",
|
|
},
|
|
{
|
|
name: "Finland 🇫🇮",
|
|
icon: `${LOCATION_ICON_SET_URL}finland`,
|
|
filter: "(?i)\u82ac\u5170|Finland|FIN|FI|finland|fin|fi|🇫🇮",
|
|
},
|
|
{
|
|
name: "France 🇫🇷",
|
|
icon: `${LOCATION_ICON_SET_URL}france`,
|
|
filter: "(?i)\u6cd5\u56fd|France|FR|france|fr|🇫🇷",
|
|
},
|
|
{
|
|
name: "Germany 🇩🇪",
|
|
icon: `${LOCATION_ICON_SET_URL}germany`,
|
|
filter: "(?i)\u5fb7\u56fd|Germany|GER|DE|germany|ger|de|🇩🇪",
|
|
},
|
|
{
|
|
name: "Hong Kong, China 🇭🇰",
|
|
icon: `${LOCATION_ICON_SET_URL}hongkong-circular`,
|
|
filter: "(?i)\u9999\u6e2f|Hong Kong|HK|hong kong|hk|🇭🇰",
|
|
},
|
|
{
|
|
name: "Iraq 🇮🇶",
|
|
icon: `${LOCATION_ICON_SET_URL}iraq`,
|
|
filter: "(?i)\u4f0a\u62c9\u514b|Iraq|IRQ|IQ|iraq|iq|🇮🇶",
|
|
},
|
|
{
|
|
name: "Japan 🇯🇵",
|
|
icon: `${LOCATION_ICON_SET_URL}japan`,
|
|
filter: "(?i)\u65e5\u672c|Japan|japan|ja|🇯🇵",
|
|
},
|
|
{
|
|
name: "Korea 🇰🇷",
|
|
icon: `${LOCATION_ICON_SET_URL}south-korea`,
|
|
filter: "(?i)\u97e9\u56fd|Korea|KR|korea|kr|🇰🇷",
|
|
},
|
|
{
|
|
name: "Russia 🇷🇺",
|
|
icon: `${LOCATION_ICON_SET_URL}russian-federation`,
|
|
filter:
|
|
"(?i)\u4fc4\u7f57\u65af|Russia Federation|Russia|RU|russia federation|russia|ru|🇷🇺",
|
|
},
|
|
{
|
|
name: "Singapore 🇸🇬",
|
|
icon: `${LOCATION_ICON_SET_URL}singapore`,
|
|
filter: "(?i)\u65b0\u52a0\u5761|Singapore|SG|singapore|sg|🇸🇬",
|
|
},
|
|
{
|
|
name: "Taiwan, China 🇨🇳",
|
|
icon: `${LOCATION_ICON_SET_URL}china-circular`,
|
|
filter: "(?i)\u53f0\u6e7e|Taiwan|TW|taiwan|tw|\uD83C\uDDF9\uD83C\uDDFC",
|
|
},
|
|
{
|
|
name: "Thailand 🇹🇭",
|
|
icon: `${LOCATION_ICON_SET_URL}thailand`,
|
|
filter: "(?i)\u6cf0\u56fd|Thailand|TH|thailand|th|🇹🇭",
|
|
},
|
|
{
|
|
name: "Türkiye 🇹🇷",
|
|
icon: `${LOCATION_ICON_SET_URL}turkey`,
|
|
filter:
|
|
"(?i)\u571f\u8033\u5176|Türkiye|Turkey|TUR|TR|türkiye|turkey|tur|tr|🇹🇷",
|
|
},
|
|
{
|
|
name: "Ukraine 🇺🇦",
|
|
icon: `${LOCATION_ICON_SET_URL}ukraine`,
|
|
filter: "(?i)\u4e4c\u514b\u5170|Ukraine|UKR|UA|ukraine|ukr|ua|🇺🇦",
|
|
},
|
|
{
|
|
name: "United Kingdom 🇬🇧",
|
|
icon: `${LOCATION_ICON_SET_URL}great-britain`,
|
|
filter:
|
|
"(?i)\u82f1\u56fd|United Kingdom|Great Britain|UK|GB|united kingdom|great britain|uk|gb|🇬🇧",
|
|
},
|
|
{
|
|
name: "United States 🇺🇸",
|
|
icon: `${LOCATION_ICON_SET_URL}usa`,
|
|
filter:
|
|
"(?i)\u7f8e\u56fd|United States of America|United States|USA|US|united states of america|united states|usa|us|🇺🇸",
|
|
},
|
|
{
|
|
name: "Global 🌐",
|
|
icon: "https://img.icons8.com/?size=144&id=3685&format=png&color=7bbbe9",
|
|
filter: "(?i)Global|GL|global|gl|Cloudflare|CF|cloudflare|cf|🌐",
|
|
},
|
|
];
|
|
|
|
// ####################################### DO NOT MODIFY THE CODE BELOW UNLESS YOU KNOW WHAT YOU ARE DOING #######################################
|
|
|
|
function extractFavicon(domain) {
|
|
return `https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=https://${domain}&size=256`;
|
|
}
|
|
|
|
// General Configuration
|
|
|
|
const generalConfig = {
|
|
"allow-lan": false,
|
|
mode: "rule",
|
|
"log-level": "info",
|
|
ipv6: true,
|
|
"find-process-mode": "strict",
|
|
"external-controller": "",
|
|
profile: {
|
|
"store-selected": true,
|
|
"store-fake-ip": true,
|
|
},
|
|
"unified-delay": true,
|
|
"tcp-concurrent": true,
|
|
"global-client-fingerprint": "chrome",
|
|
"global-ua": "\u0063\u006c\u0061\u0073\u0068.\u006D\u0065\u0074\u0061",
|
|
"etag-support": true,
|
|
};
|
|
|
|
// DNS
|
|
|
|
const chineseNameservers = [
|
|
"https://doh.pub/dns-query",
|
|
"https://dns.alidns.com/dns-query",
|
|
];
|
|
|
|
const internationalNameservers = [
|
|
"quic://unfiltered.adguard-dns.com:784",
|
|
"https://dns.google/dns-query",
|
|
"https://doh.dns.sb/dns-query",
|
|
"https://dns.quad9.net/dns-query",
|
|
"https://doh.opendns.com/dns-query",
|
|
"https://dns.mullvad.net/dns-query",
|
|
"https://doh.umbrella.com/dns-query",
|
|
"https://wikimedia-dns.org/dns-query",
|
|
"https://doh.dns.apple.com/dns-query",
|
|
"https://cloudflare-dns.com/dns-query",
|
|
"https://common.dot.dns.yandex.net/dns-query",
|
|
"https://unfiltered.adguard-dns.com/dns-query",
|
|
];
|
|
|
|
const adguardDefaultNameservers = [
|
|
"quic://dns.adguard-dns.com:784",
|
|
"https://dns.adguard-dns.com/dns-query",
|
|
];
|
|
|
|
const adguardFamilyNameservers = [
|
|
"quic://family.adguard-dns.com:784",
|
|
"https://family.adguard-dns.com/dns-query",
|
|
];
|
|
|
|
const dns = {
|
|
enable: true,
|
|
"prefer-h3": false,
|
|
"use-hosts": true,
|
|
"use-system-hosts": false,
|
|
"respect-rules": true,
|
|
listen: "0.0.0.0:1053",
|
|
ipv6: true,
|
|
"enhanced-mode": "fake-ip",
|
|
"fake-ip-range": "198.18.0.1/16",
|
|
"fake-ip-filter-mode": "blacklist",
|
|
"fake-ip-filter": [
|
|
"rule-set:fake-ip-filter",
|
|
"rule-set:direct",
|
|
"rule-set:private",
|
|
"rule-set:connectivity-check",
|
|
],
|
|
"default-nameserver": [
|
|
"119.29.29.29",
|
|
"223.5.5.5",
|
|
"223.6.6.6",
|
|
"8.8.8.8",
|
|
"8.8.4.4",
|
|
"1.1.1.1",
|
|
"1.0.0.1",
|
|
"9.9.9.9",
|
|
"149.112.112.112",
|
|
"208.67.222.222",
|
|
"208.67.220.220",
|
|
],
|
|
"proxy-server-nameserver": chineseNameservers,
|
|
"nameserver-policy": {
|
|
"rule-set:private,direct,geolocation-cn": chineseNameservers,
|
|
"rule-set:proxy": internationalNameservers,
|
|
},
|
|
nameserver: [
|
|
...chineseNameservers,
|
|
...internationalNameservers,
|
|
// ...adguardDefaultNameservers,
|
|
// ...adguardFamilyNameservers,
|
|
],
|
|
};
|
|
|
|
// Hosts
|
|
|
|
const hosts = {};
|
|
|
|
// Domain Sniffing
|
|
|
|
const sniffer = {
|
|
enable: false,
|
|
};
|
|
|
|
// TUN
|
|
|
|
const tun = {
|
|
enable: true,
|
|
stack: "mixed",
|
|
"auto-route": true,
|
|
"auto-redirect": true,
|
|
"auto-detect-interface": true,
|
|
"strict-route": true,
|
|
"dns-hijack": ["any:53", "tcp://any:53"],
|
|
};
|
|
|
|
// Proxy Groups
|
|
|
|
const proxyGroupDefaults = {
|
|
url: "https://www.gstatic.com/generate_204",
|
|
interval: 300,
|
|
lazy: true,
|
|
timeout: 5000,
|
|
"max-failed-times": 5,
|
|
};
|
|
|
|
const serviceProxyGroupProxies = [
|
|
"PROXY",
|
|
"AUTO",
|
|
"STATIC",
|
|
"DIRECT",
|
|
"Mainland China 🇨🇳",
|
|
...locations.map(({ name }) => name),
|
|
];
|
|
|
|
const locationPolicyProxyGroupDefaults = {
|
|
...proxyGroupDefaults,
|
|
proxies: ["REJECT"],
|
|
"include-all": true,
|
|
};
|
|
|
|
const SERVICE_ICON_SET_URL =
|
|
"https://raw.githubusercontent.com/xixu-me/favicons/refs/heads/assets/";
|
|
|
|
function getServiceIcon(service) {
|
|
if (service.icon) return service.icon;
|
|
if (service.domain) return extractFavicon(service.domain);
|
|
if (service.tld) {
|
|
const secondLevelDomain = service.sld || service.name.toLowerCase();
|
|
return `${SERVICE_ICON_SET_URL}${secondLevelDomain}.${service.tld}.png`;
|
|
}
|
|
console.warn(`No icon configuration for service: ${service.name}`);
|
|
return null;
|
|
}
|
|
|
|
services.forEach((service) => {
|
|
service.icon = getServiceIcon(service);
|
|
});
|
|
|
|
function generateServiceProxyGroups(items, defaultConfig) {
|
|
return items.map(({ name, icon }) => ({
|
|
...defaultConfig,
|
|
name,
|
|
icon,
|
|
type: "select",
|
|
proxies: serviceProxyGroupProxies,
|
|
}));
|
|
}
|
|
|
|
function generateLocationPolicyProxyGroups(
|
|
items,
|
|
defaultConfig,
|
|
type,
|
|
extraProps = {}
|
|
) {
|
|
const getStrategyName = (type, strategy) => {
|
|
switch (type) {
|
|
case "url-test":
|
|
return "AUTO";
|
|
case "fallback":
|
|
return "FALLBACK";
|
|
case "load-balance":
|
|
switch (strategy) {
|
|
case "consistent-hashing":
|
|
return "LOAD BALANCING (consistent hashing)";
|
|
case "round-robin":
|
|
return "LOAD BALANCING (round-robin)";
|
|
case "sticky-sessions":
|
|
return "LOAD BALANCING (sticky sessions)";
|
|
default:
|
|
return "LOAD BALANCING";
|
|
}
|
|
default:
|
|
return type.toUpperCase();
|
|
}
|
|
};
|
|
return items.map(({ name, icon, filter }) => {
|
|
const strategyName = getStrategyName(type, extraProps.strategy);
|
|
const emoji = name.split(" ").pop();
|
|
const newName = `${strategyName} ${emoji}`;
|
|
return {
|
|
...defaultConfig,
|
|
name: newName,
|
|
type,
|
|
icon,
|
|
filter,
|
|
hidden: true,
|
|
...extraProps,
|
|
};
|
|
});
|
|
}
|
|
|
|
function generateLocationSelectProxyGroups() {
|
|
return locations.map(({ name, icon }) => ({
|
|
...proxyGroupDefaults,
|
|
name,
|
|
type: "select",
|
|
icon,
|
|
proxies: [
|
|
`AUTO ${name.split(" ").pop()}`,
|
|
`FALLBACK ${name.split(" ").pop()}`,
|
|
`LOAD BALANCING (consistent hashing) ${name.split(" ").pop()}`,
|
|
`LOAD BALANCING (round-robin) ${name.split(" ").pop()}`,
|
|
`LOAD BALANCING (sticky sessions) ${name.split(" ").pop()}`,
|
|
],
|
|
}));
|
|
}
|
|
|
|
const BASE_ICON_SET_URL =
|
|
"https://cdn.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/";
|
|
|
|
const proxyGroups = [
|
|
{
|
|
...proxyGroupDefaults,
|
|
name: "PROXY",
|
|
type: "select",
|
|
proxies: [
|
|
"AUTO",
|
|
"STATIC",
|
|
"Mainland China 🇨🇳",
|
|
...locations.map(({ name }) => name),
|
|
],
|
|
icon: `${BASE_ICON_SET_URL}Proxy.png`,
|
|
},
|
|
{
|
|
...proxyGroupDefaults,
|
|
name: "AUTO",
|
|
type: "url-test",
|
|
tolerance: 50,
|
|
"include-all": true,
|
|
icon: `${BASE_ICON_SET_URL}Auto.png`,
|
|
hidden: true,
|
|
},
|
|
{
|
|
...proxyGroupDefaults,
|
|
name: "STATIC",
|
|
type: "select",
|
|
"include-all": true,
|
|
icon: `${BASE_ICON_SET_URL}Static.png`,
|
|
},
|
|
...generateServiceProxyGroups(services, proxyGroupDefaults),
|
|
{
|
|
...proxyGroupDefaults,
|
|
name: "Others",
|
|
type: "select",
|
|
proxies: [...serviceProxyGroupProxies],
|
|
icon: `${BASE_ICON_SET_URL}Final.png`,
|
|
},
|
|
{
|
|
...proxyGroupDefaults,
|
|
name: "Advertising",
|
|
type: "select",
|
|
proxies: ["REJECT", "DIRECT", "STATIC"],
|
|
icon: `${BASE_ICON_SET_URL}Advertising.png`,
|
|
},
|
|
{
|
|
...locationPolicyProxyGroupDefaults,
|
|
name: "Mainland China 🇨🇳",
|
|
type: "select",
|
|
icon: `${LOCATION_ICON_SET_URL}china`,
|
|
proxies: ["DIRECT"],
|
|
"include-all": true,
|
|
filter:
|
|
"(?i)\u5927\u9646|\u4e2d\u56fd|\u7535\u4fe1|\u79fb\u52a8|\u8054\u901a|Mainland|China|CN|mainland|china|cn|🇨🇳",
|
|
},
|
|
...generateLocationPolicyProxyGroups(
|
|
locations,
|
|
locationPolicyProxyGroupDefaults,
|
|
"url-test",
|
|
{
|
|
tolerance: 50,
|
|
}
|
|
),
|
|
...generateLocationPolicyProxyGroups(
|
|
locations,
|
|
locationPolicyProxyGroupDefaults,
|
|
"fallback"
|
|
),
|
|
...generateLocationPolicyProxyGroups(
|
|
locations,
|
|
locationPolicyProxyGroupDefaults,
|
|
"load-balance",
|
|
{
|
|
strategy: "round-robin",
|
|
}
|
|
),
|
|
...generateLocationPolicyProxyGroups(
|
|
locations,
|
|
locationPolicyProxyGroupDefaults,
|
|
"load-balance",
|
|
{
|
|
strategy: "consistent-hashing",
|
|
}
|
|
),
|
|
...generateLocationPolicyProxyGroups(
|
|
locations,
|
|
locationPolicyProxyGroupDefaults,
|
|
"load-balance",
|
|
{
|
|
strategy: "sticky-sessions",
|
|
}
|
|
),
|
|
...generateLocationSelectProxyGroups(),
|
|
];
|
|
|
|
// Routing Rules
|
|
|
|
function generateServiceRules(services) {
|
|
return services.map(({ name }) => `RULE-SET,${name.toLowerCase()},${name}`);
|
|
}
|
|
|
|
const rules = [
|
|
"RULE-SET,applications,DIRECT",
|
|
"RULE-SET,lancidr,DIRECT,no-resolve",
|
|
"RULE-SET,private,DIRECT",
|
|
"RULE-SET,reject,Advertising",
|
|
"RULE-SET,win-spy,Advertising",
|
|
...generateServiceRules(services),
|
|
"RULE-SET,direct,Mainland China 🇨🇳",
|
|
"RULE-SET,proxy,PROXY",
|
|
"RULE-SET,telegramcidr,Telegram",
|
|
"RULE-SET,xcidr,X",
|
|
"RULE-SET,googlecidr,Google",
|
|
"RULE-SET,cloudflarecidr,Cloudflare",
|
|
"RULE-SET,cncidr,Mainland China 🇨🇳",
|
|
"MATCH,Others",
|
|
];
|
|
|
|
// Rule Providers
|
|
|
|
const ruleProviderDefaults = {
|
|
type: "http",
|
|
interval: 14400,
|
|
};
|
|
|
|
function generateServiceRuleProviders(services, defaultConfig) {
|
|
return services.reduce((acc, { name, alias }) => {
|
|
const ruleName = alias || name;
|
|
acc[name.toLowerCase()] = {
|
|
...defaultConfig,
|
|
format: "mrs",
|
|
behavior: "domain",
|
|
url: `https://cdn.jsdelivr.net/gh/xixu-me/RFM@universal/${ruleName.toLowerCase()}.mrs`,
|
|
path: `./rulesets/${name.toLowerCase()}.mrs`,
|
|
};
|
|
return acc;
|
|
}, {});
|
|
}
|
|
|
|
const ruleProviders = {
|
|
"fake-ip-filter": {
|
|
...ruleProviderDefaults,
|
|
format: "mrs",
|
|
behavior: "domain",
|
|
url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/fake-ip-filter.mrs",
|
|
path: "./rulesets/fake-ip-filter.mrs",
|
|
},
|
|
"connectivity-check": {
|
|
...ruleProviderDefaults,
|
|
format: "mrs",
|
|
behavior: "domain",
|
|
url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@universal/connectivity-check.mrs",
|
|
path: "./rulesets/connectivity-check.mrs",
|
|
},
|
|
applications: {
|
|
...ruleProviderDefaults,
|
|
format: "yaml",
|
|
behavior: "classical",
|
|
url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/applications.yaml",
|
|
path: "./rulesets/applications.yaml",
|
|
},
|
|
lancidr: {
|
|
...ruleProviderDefaults,
|
|
format: "mrs",
|
|
behavior: "ipcidr",
|
|
url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/lancidr.mrs",
|
|
path: "./rulesets/lancidr.mrs",
|
|
},
|
|
cncidr: {
|
|
...ruleProviderDefaults,
|
|
format: "mrs",
|
|
behavior: "ipcidr",
|
|
url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/cncidr.mrs",
|
|
path: "./rulesets/cncidr.mrs",
|
|
},
|
|
cloudflarecidr: {
|
|
...ruleProviderDefaults,
|
|
format: "mrs",
|
|
behavior: "ipcidr",
|
|
url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/cloudflarecidr.mrs",
|
|
path: "./rulesets/cloudflarecidr.mrs",
|
|
},
|
|
googlecidr: {
|
|
...ruleProviderDefaults,
|
|
format: "mrs",
|
|
behavior: "ipcidr",
|
|
url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/googlecidr.mrs",
|
|
path: "./rulesets/googlecidr.mrs",
|
|
},
|
|
telegramcidr: {
|
|
...ruleProviderDefaults,
|
|
format: "mrs",
|
|
behavior: "ipcidr",
|
|
url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/telegramcidr.mrs",
|
|
path: "./rulesets/telegramcidr.mrs",
|
|
},
|
|
xcidr: {
|
|
...ruleProviderDefaults,
|
|
format: "mrs",
|
|
behavior: "ipcidr",
|
|
url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/xcidr.mrs",
|
|
path: "./rulesets/xcidr.mrs",
|
|
},
|
|
private: {
|
|
...ruleProviderDefaults,
|
|
format: "mrs",
|
|
behavior: "domain",
|
|
url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/private.mrs",
|
|
path: "./rulesets/private.mrs",
|
|
},
|
|
direct: {
|
|
...ruleProviderDefaults,
|
|
format: "mrs",
|
|
behavior: "domain",
|
|
url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/direct.mrs",
|
|
path: "./rulesets/direct.mrs",
|
|
},
|
|
proxy: {
|
|
...ruleProviderDefaults,
|
|
format: "mrs",
|
|
behavior: "domain",
|
|
url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/proxy.mrs",
|
|
path: "./rulesets/proxy.mrs",
|
|
},
|
|
"geolocation-cn": {
|
|
...ruleProviderDefaults,
|
|
format: "mrs",
|
|
behavior: "domain",
|
|
url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@universal/geolocation-cn.mrs",
|
|
path: "./rulesets/geolocation-cn.mrs",
|
|
},
|
|
reject: {
|
|
...ruleProviderDefaults,
|
|
format: "mrs",
|
|
behavior: "domain",
|
|
url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@basic/reject.mrs",
|
|
path: "./rulesets/reject.mrs",
|
|
},
|
|
"win-spy": {
|
|
...ruleProviderDefaults,
|
|
format: "mrs",
|
|
behavior: "domain",
|
|
url: "https://cdn.jsdelivr.net/gh/xixu-me/RFM@universal/win-spy.mrs",
|
|
path: "./rulesets/win-spy.mrs",
|
|
},
|
|
...generateServiceRuleProviders(services, ruleProviderDefaults),
|
|
};
|
|
|
|
// generate configuration using the above settings
|
|
|
|
function validateOriginalConfig(config) {
|
|
if (!config)
|
|
throw new Error("Configuration object cannot be null or undefined");
|
|
const proxyCount = Array.isArray(config.proxies) ? config.proxies.length : 0;
|
|
const proxyProviderCount = Object.keys(
|
|
config["proxy-providers"] || {}
|
|
).length;
|
|
if (proxyCount === 0 && proxyProviderCount === 0)
|
|
throw new Error(
|
|
"The original configuration must contain a non-empty proxies array (see https://wiki.\u006D\u0065\u0074\u0061\u0063\u0075\u0062\u0065\u0078.one/en/config/proxies/) or a proxy-providers object with at least one property (see https://wiki.\u006D\u0065\u0074\u0061\u0063\u0075\u0062\u0065\u0078.one/en/config/proxy-providers/)"
|
|
);
|
|
if (proxyCount > 0) {
|
|
config.proxies.forEach((proxy, index) => {
|
|
if (!proxy.name || !proxy.type || !proxy.server || !proxy.port) {
|
|
throw new Error(
|
|
`Invalid proxy number ${
|
|
index + 1
|
|
} configuration (see https://wiki.\u006D\u0065\u0074\u0061\u0063\u0075\u0062\u0065\u0078.one/en/config/proxies/)`
|
|
);
|
|
}
|
|
});
|
|
console.log(
|
|
`The original configuration contains ${proxyCount} proxies, which will be preserved`
|
|
);
|
|
}
|
|
if (proxyProviderCount > 0) {
|
|
Object.entries(config["proxy-providers"]).forEach(
|
|
([name, provider], index) => {
|
|
if (!provider.type || (provider.type === "http" && !provider.url)) {
|
|
throw new Error(
|
|
`Invalid proxy provider number ${
|
|
index + 1
|
|
} configuration (see https://wiki.\u006D\u0065\u0074\u0061\u0063\u0075\u0062\u0065\u0078.one/en/config/proxy-providers/)`
|
|
);
|
|
}
|
|
}
|
|
);
|
|
console.log(
|
|
`The original configuration contains ${proxyProviderCount} proxy providers, which will be preserved`
|
|
);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function main(config) {
|
|
try {
|
|
validateOriginalConfig(config);
|
|
Object.assign(config, generalConfig, {
|
|
dns,
|
|
hosts,
|
|
sniffer,
|
|
tun,
|
|
"proxy-groups": proxyGroups,
|
|
rules,
|
|
"rule-providers": ruleProviders,
|
|
});
|
|
console.log("The generated configuration is as follows");
|
|
console.log(config);
|
|
return config;
|
|
} catch (error) {
|
|
console.error(
|
|
`An error occurred during configuration generation: ${error.message}`
|
|
);
|
|
return { error: error.message, originalConfig: config };
|
|
}
|
|
}
|