Skip to content

Commit

Permalink
feat: add custom rule sets supported
Browse files Browse the repository at this point in the history
  • Loading branch information
7Sageer committed Aug 5, 2024
1 parent d19a865 commit 04f57b1
Show file tree
Hide file tree
Showing 7 changed files with 358 additions and 156 deletions.
14 changes: 6 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@
- Sing-Box
- Clash
- Xray/V2Ray
- 提供快速上手的Web界面
- 提供快速上手的Web界面,支持自定义路由规则
- 支持短链接生成(基于R2)
- 浅色/深色主题切换

## 最近更新

### 5/8

- 支持自定义规则集

### 4/8

- 重构配置文件生成逻辑
Expand All @@ -34,13 +38,6 @@

---

### 30/7

- 简化路由逻辑
- 修复了一些小问题

---

## 部署

[![Deploy to Cloudflare Workers](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/7Sageer/sublink-worker)
Expand All @@ -50,6 +47,7 @@
## 项目结构

- `index.js`: 主要的服务器逻辑,处理请求路由
- `BaseConfigBuilder.js`: 构建基础配置
- `SingboxConfigBuilder.js`: 构建Sing-Box配置
- `ClashConfigBuilder.js`: 构建Clash配置
- `ProxyParsers.js`: 解析各种代理协议的URL
Expand Down
Binary file modified doc/image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 35 additions & 7 deletions src/ClashConfigBuilder.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import yaml from 'js-yaml';
import { CLASH_CONFIG, SELECTORS_LIST } from './config.js';
import { CLASH_CONFIG, generateRuleSets, generateRules, getOutbounds} from './config.js';
import { BaseConfigBuilder } from './BaseConfigBuilder.js';
import { DeepCopy } from './utils.js';

export class ClashConfigBuilder extends BaseConfigBuilder {
constructor(inputString) {
constructor(inputString, selectedRules) {
super(inputString, CLASH_CONFIG);
this.selectedRules = selectedRules;
}

addCustomItems(customItems) {
Expand All @@ -17,7 +18,9 @@ export class ClashConfigBuilder extends BaseConfigBuilder {
}

addSelectors() {
const outbounds = getOutbounds(this.selectedRules);
const proxyList = this.config.proxies.map(proxy => proxy.name);

this.config['proxy-groups'].push({
name: '⚡ 自动选择',
type: 'url-test',
Expand All @@ -26,21 +29,46 @@ export class ClashConfigBuilder extends BaseConfigBuilder {
interval: 300,
lazy: false
});

proxyList.unshift('DIRECT', 'REJECT', '⚡ 自动选择');
SELECTORS_LIST.forEach(selector => {
if (!this.config['proxy-groups'].some(g => g.name === selector)) {
outbounds.unshift('🚀 节点选择', 'GLOBAL');

outbounds.forEach(outbound => {
if (outbound !== '🚀 节点选择') {
this.config['proxy-groups'].push({
type: "select",
name: outbound,
proxies: ['🚀 节点选择', ...proxyList]
});
} else {
this.config['proxy-groups'].push({
type: "select",
name: selector,
proxies: selector !== '🚀 节点选择' ? ['🚀 节点选择', ...proxyList] : proxyList
name: outbound,
proxies: proxyList
});
}
});
}

this.config['proxy-groups'].push({
type: "select",
name: "🐟 漏网之鱼",
proxies: ['🚀 节点选择', ...proxyList]
});
}
formatConfig() {
const rules = generateRules(this.selectedRules);

this.config.rules = rules.flatMap(rule => [
...rule.site_rules.map(site => `GEOSITE,${site},${rule.outbound}`),
...rule.ip_rules.map(ip => `GEOIP,${ip},${rule.outbound}`)
]);

// Add the final catch-all rule
this.config.rules.push('MATCH,🐟 漏网之鱼');

return yaml.dump(this.config);
}

convertToClashProxy(proxy) {
switch(proxy.type) {
case 'shadowsocks':
Expand Down
58 changes: 47 additions & 11 deletions src/SingboxConfigBuilder.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { SING_BOX_CONFIG, SELECTORS_LIST } from './config.js';
import { SING_BOX_CONFIG, generateRuleSets, generateRules, getOutbounds} from './config.js';
import { BaseConfigBuilder } from './BaseConfigBuilder.js';
import { DeepCopy } from './utils.js';

export class ConfigBuilder extends BaseConfigBuilder {
constructor(inputString) {
constructor(inputString, selectedRules) {
super(inputString, SING_BOX_CONFIG);
this.selectedRules = selectedRules;
}

addCustomItems(customItems) {
Expand All @@ -13,23 +14,58 @@ export class ConfigBuilder extends BaseConfigBuilder {
}

addSelectors() {
const tagList = this.config.outbounds.filter(outbound => outbound?.server != undefined).map(outbound => outbound.tag);
const outbounds = getOutbounds(this.selectedRules);
const proxyList = this.config.outbounds.filter(outbound => outbound?.server != undefined).map(outbound => outbound.tag);

this.config.outbounds.push({
type: "urltest",
tag: "⚡ 自动选择",
outbounds: DeepCopy(tagList),
outbounds: DeepCopy(proxyList),
});
tagList.unshift('DIRECT', 'REJECT', '⚡ 自动选择');
SELECTORS_LIST.forEach(selector => {
this.config.outbounds.push({
type: "selector",
tag: selector,
outbounds: selector !== '🚀 节点选择' ? ['🚀 节点选择', ...tagList] : tagList
});

proxyList.unshift('DIRECT', 'REJECT', '⚡ 自动选择');
outbounds.unshift('🚀 节点选择', 'GLOBAL');
outbounds.forEach(outbound => {
if (outbound !== '🚀 节点选择') {
this.config.outbounds.push({
type: "selector",
tag: outbound,
outbounds: ['🚀 节点选择', ...proxyList]
});
} else {
this.config.outbounds.push({
type: "selector",
tag: outbound,
outbounds: proxyList
});
}
});

this.config.outbounds.push({
type: "selector",
tag: "🐟 漏网之鱼",
outbounds: ['🚀 节点选择', ...proxyList]
});
}

formatConfig() {
const rules = generateRules(this.selectedRules);
const { site_rule_sets, ip_rule_sets } = generateRuleSets(this.selectedRules);

this.config.route.rule_set = [...site_rule_sets, ...ip_rule_sets];

this.config.route.rules = rules.map(rule => ({
rule_set: [...rule.site_rules, ...rule.ip_rules.map(ip => `${ip}-ip`)],
outbound: rule.outbound
}));

// Add any default rules that should always be present
this.config.route.rules.push(
{ protocol: 'dns', port: 53, outbound: 'dns-out' },
{ clash_mode: 'direct', outbound: 'DIRECT' },
{ clash_mode: 'global', outbound: 'GLOBAL' }
);

return this.config;
}
}
Loading

0 comments on commit 04f57b1

Please sign in to comment.