rule重构
This commit is contained in:
18
README.md
18
README.md
@@ -40,6 +40,11 @@ sub-provider/
|
|||||||
rules.py
|
rules.py
|
||||||
subscriptions.py
|
subscriptions.py
|
||||||
config/
|
config/
|
||||||
|
app.yaml
|
||||||
|
clients.yaml
|
||||||
|
policy-groups.yaml
|
||||||
|
regions.yaml
|
||||||
|
rules.yaml
|
||||||
sources.yaml
|
sources.yaml
|
||||||
rules/
|
rules/
|
||||||
reject.yaml
|
reject.yaml
|
||||||
@@ -73,13 +78,22 @@ cp .env.example .env
|
|||||||
- 也可以直接填本地文件路径,例如 `/app/data/sources/airport-b.txt` 或 `file:///app/data/sources/airport-b.txt`
|
- 也可以直接填本地文件路径,例如 `/app/data/sources/airport-b.txt` 或 `file:///app/data/sources/airport-b.txt`
|
||||||
- 允许把其中一个留空;留空时这个机场会自动跳过
|
- 允许把其中一个留空;留空时这个机场会自动跳过
|
||||||
|
|
||||||
3. 启动:
|
3. 按需调整 `config/` 下拆分后的配置文件:
|
||||||
|
|
||||||
|
- `app.yaml`:公共访问路径
|
||||||
|
- `sources.yaml`:机场源配置
|
||||||
|
- `regions.yaml`:地区自动组
|
||||||
|
- `policy-groups.yaml`:选择器组和业务策略组
|
||||||
|
- `rules.yaml`:规则绑定
|
||||||
|
- `clients.yaml`:客户端模板
|
||||||
|
|
||||||
|
4. 启动:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose up -d --build
|
docker compose up -d --build
|
||||||
```
|
```
|
||||||
|
|
||||||
4. 访问检查:
|
5. 访问检查:
|
||||||
|
|
||||||
- 健康检查:`http://YOUR_HOST:18080/healthz`
|
- 健康检查:`http://YOUR_HOST:18080/healthz`
|
||||||
- 单 provider:
|
- 单 provider:
|
||||||
|
|||||||
@@ -27,7 +27,13 @@ class Settings(BaseSettings):
|
|||||||
max_proxy_name_length: int = 80
|
max_proxy_name_length: int = 80
|
||||||
default_user_agent: str = "sub-provider/0.2"
|
default_user_agent: str = "sub-provider/0.2"
|
||||||
|
|
||||||
|
config_dir: Path = CONFIG_DIR
|
||||||
sources_file: Path = CONFIG_DIR / "sources.yaml"
|
sources_file: Path = CONFIG_DIR / "sources.yaml"
|
||||||
|
app_config_file: Path = CONFIG_DIR / "app.yaml"
|
||||||
|
clients_file: Path = CONFIG_DIR / "clients.yaml"
|
||||||
|
regions_file: Path = CONFIG_DIR / "regions.yaml"
|
||||||
|
policy_groups_file: Path = CONFIG_DIR / "policy-groups.yaml"
|
||||||
|
rules_config_file: Path = CONFIG_DIR / "rules.yaml"
|
||||||
rules_dir: Path = CONFIG_DIR / "rules"
|
rules_dir: Path = CONFIG_DIR / "rules"
|
||||||
bundle_cache_dir: Path = ROOT_DIR / "output" / "bundle-cache"
|
bundle_cache_dir: Path = ROOT_DIR / "output" / "bundle-cache"
|
||||||
fetch_cache_dir: Path = DATA_DIR / "fetch-cache"
|
fetch_cache_dir: Path = DATA_DIR / "fetch-cache"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
@@ -21,7 +22,44 @@ def _expand_env(value):
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
def load_app_config(path: Path) -> AppConfig:
|
def _load_yaml(path: Path) -> dict[str, Any]:
|
||||||
|
if not path.is_file():
|
||||||
|
return {}
|
||||||
raw = yaml.safe_load(path.read_text(encoding="utf-8")) or {}
|
raw = yaml.safe_load(path.read_text(encoding="utf-8")) or {}
|
||||||
expanded = _expand_env(raw)
|
if not isinstance(raw, dict):
|
||||||
|
raise ValueError(f"Config file must contain a top-level mapping: {path}")
|
||||||
|
return raw
|
||||||
|
|
||||||
|
|
||||||
|
def _section_value(raw: dict[str, Any], section: str) -> Any:
|
||||||
|
if section in raw:
|
||||||
|
return raw[section]
|
||||||
|
return raw
|
||||||
|
|
||||||
|
|
||||||
|
def _load_split_config(path: Path) -> dict[str, Any]:
|
||||||
|
config_dir = path if path.is_dir() else path.parent
|
||||||
|
legacy_raw = _load_yaml(path) if path.is_file() else {}
|
||||||
|
|
||||||
|
app_raw = _load_yaml(config_dir / "app.yaml")
|
||||||
|
sources_raw = _load_yaml(config_dir / "sources.yaml")
|
||||||
|
regions_raw = _load_yaml(config_dir / "regions.yaml")
|
||||||
|
groups_raw = _load_yaml(config_dir / "policy-groups.yaml")
|
||||||
|
rules_raw = _load_yaml(config_dir / "rules.yaml")
|
||||||
|
clients_raw = _load_yaml(config_dir / "clients.yaml")
|
||||||
|
|
||||||
|
merged: dict[str, Any] = {}
|
||||||
|
merged.update({key: value for key, value in legacy_raw.items() if key not in AppConfig.model_fields})
|
||||||
|
merged["public_path"] = app_raw.get("public_path", legacy_raw.get("public_path"))
|
||||||
|
merged["sources"] = _section_value(sources_raw, "sources") if sources_raw else legacy_raw.get("sources", {})
|
||||||
|
merged["regions"] = _section_value(regions_raw, "regions") if regions_raw else legacy_raw.get("regions", {})
|
||||||
|
merged["selector_groups"] = groups_raw.get("selector_groups", legacy_raw.get("selector_groups", []))
|
||||||
|
merged["policy_groups"] = groups_raw.get("policy_groups", legacy_raw.get("policy_groups", []))
|
||||||
|
merged["rules"] = _section_value(rules_raw, "rules") if rules_raw else legacy_raw.get("rules", {})
|
||||||
|
merged["clients"] = _section_value(clients_raw, "clients") if clients_raw else legacy_raw.get("clients", {})
|
||||||
|
return merged
|
||||||
|
|
||||||
|
|
||||||
|
def load_app_config(path: Path) -> AppConfig:
|
||||||
|
expanded = _expand_env(_load_split_config(path))
|
||||||
return AppConfig.model_validate(expanded)
|
return AppConfig.model_validate(expanded)
|
||||||
|
|||||||
1
config/app.yaml
Normal file
1
config/app.yaml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
public_path: ${PUBLIC_PATH}
|
||||||
33
config/clients.yaml
Normal file
33
config/clients.yaml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
clients:
|
||||||
|
mihomo:
|
||||||
|
title: HomeLab Mihomo
|
||||||
|
provider_interval: 21600
|
||||||
|
rule_interval: 86400
|
||||||
|
test_url: https://www.gstatic.com/generate_204
|
||||||
|
test_interval: 300
|
||||||
|
main_policy: 🚀 节点选择
|
||||||
|
source_policy: ☁️ 机场选择
|
||||||
|
mixed_auto_policy: ♻️ 自动选择
|
||||||
|
manual_policy: 🚀 手动切换
|
||||||
|
direct_policy: DIRECT
|
||||||
|
mode: rule
|
||||||
|
allow_lan: true
|
||||||
|
ipv6: true
|
||||||
|
mixed_port: 7890
|
||||||
|
socks_port: 7891
|
||||||
|
log_level: info
|
||||||
|
|
||||||
|
stash:
|
||||||
|
title: HomeLab Stash
|
||||||
|
provider_interval: 21600
|
||||||
|
rule_interval: 86400
|
||||||
|
test_url: https://www.gstatic.com/generate_204
|
||||||
|
test_interval: 300
|
||||||
|
main_policy: 🚀 节点选择
|
||||||
|
source_policy: ☁️ 机场选择
|
||||||
|
mixed_auto_policy: ♻️ 自动选择
|
||||||
|
manual_policy: 🚀 手动切换
|
||||||
|
direct_policy: DIRECT
|
||||||
|
mode: rule
|
||||||
|
ipv6: true
|
||||||
|
log_level: info
|
||||||
180
config/policy-groups.yaml
Normal file
180
config/policy-groups.yaml
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
selector_groups:
|
||||||
|
- name: "🎥 奈飞节点"
|
||||||
|
type: select
|
||||||
|
filter: "(?i)(nf|奈飞|解锁|netflix|media)"
|
||||||
|
|
||||||
|
policy_groups:
|
||||||
|
- name: "📲 电报消息"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- "{{ main_policy }}"
|
||||||
|
- "{{ mixed_auto_policy }}"
|
||||||
|
- "🇸🇬 狮城节点"
|
||||||
|
- "🇭🇰 香港节点"
|
||||||
|
- "🇨🇳 台湾节点"
|
||||||
|
- "🇯🇵 日本节点"
|
||||||
|
- "🇺🇲 美国节点"
|
||||||
|
- "🇰🇷 韩国节点"
|
||||||
|
- "{{ manual_policy }}"
|
||||||
|
- "{{ direct_policy }}"
|
||||||
|
- name: "💬 Ai平台"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- "{{ main_policy }}"
|
||||||
|
- "{{ mixed_auto_policy }}"
|
||||||
|
- "🇺🇲 美国节点"
|
||||||
|
- "🇸🇬 狮城节点"
|
||||||
|
- "🇯🇵 日本节点"
|
||||||
|
- "🇭🇰 香港节点"
|
||||||
|
- "🇨🇳 台湾节点"
|
||||||
|
- "🇰🇷 韩国节点"
|
||||||
|
- "{{ manual_policy }}"
|
||||||
|
- "{{ direct_policy }}"
|
||||||
|
- name: "📹 油管视频"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- "{{ main_policy }}"
|
||||||
|
- "{{ mixed_auto_policy }}"
|
||||||
|
- "🇸🇬 狮城节点"
|
||||||
|
- "🇭🇰 香港节点"
|
||||||
|
- "🇨🇳 台湾节点"
|
||||||
|
- "🇯🇵 日本节点"
|
||||||
|
- "🇺🇲 美国节点"
|
||||||
|
- "🇰🇷 韩国节点"
|
||||||
|
- "{{ manual_policy }}"
|
||||||
|
- "{{ direct_policy }}"
|
||||||
|
- name: "🎥 奈飞视频"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- "🎥 奈飞节点"
|
||||||
|
- "{{ main_policy }}"
|
||||||
|
- "{{ mixed_auto_policy }}"
|
||||||
|
- "🇸🇬 狮城节点"
|
||||||
|
- "🇭🇰 香港节点"
|
||||||
|
- "🇨🇳 台湾节点"
|
||||||
|
- "🇯🇵 日本节点"
|
||||||
|
- "🇺🇲 美国节点"
|
||||||
|
- "🇰🇷 韩国节点"
|
||||||
|
- "{{ manual_policy }}"
|
||||||
|
- "{{ direct_policy }}"
|
||||||
|
- name: "🌍 国外媒体"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- "{{ main_policy }}"
|
||||||
|
- "{{ mixed_auto_policy }}"
|
||||||
|
- "🇭🇰 香港节点"
|
||||||
|
- "🇨🇳 台湾节点"
|
||||||
|
- "🇸🇬 狮城节点"
|
||||||
|
- "🇯🇵 日本节点"
|
||||||
|
- "🇺🇲 美国节点"
|
||||||
|
- "🇰🇷 韩国节点"
|
||||||
|
- "{{ manual_policy }}"
|
||||||
|
- "{{ direct_policy }}"
|
||||||
|
- name: "📢 谷歌"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- "{{ main_policy }}"
|
||||||
|
- "{{ direct_policy }}"
|
||||||
|
- "🇺🇲 美国节点"
|
||||||
|
- "🇭🇰 香港节点"
|
||||||
|
- "🇨🇳 台湾节点"
|
||||||
|
- "🇸🇬 狮城节点"
|
||||||
|
- "🇯🇵 日本节点"
|
||||||
|
- "🇰🇷 韩国节点"
|
||||||
|
- "{{ manual_policy }}"
|
||||||
|
- name: "Ⓜ️ 微软Bing"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- "{{ direct_policy }}"
|
||||||
|
- "{{ main_policy }}"
|
||||||
|
- "🇺🇲 美国节点"
|
||||||
|
- "🇭🇰 香港节点"
|
||||||
|
- "🇨🇳 台湾节点"
|
||||||
|
- "🇸🇬 狮城节点"
|
||||||
|
- "🇯🇵 日本节点"
|
||||||
|
- "🇰🇷 韩国节点"
|
||||||
|
- "{{ manual_policy }}"
|
||||||
|
- name: "Ⓜ️ 微软云盘"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- "{{ direct_policy }}"
|
||||||
|
- "{{ main_policy }}"
|
||||||
|
- "🇺🇲 美国节点"
|
||||||
|
- "🇭🇰 香港节点"
|
||||||
|
- "🇨🇳 台湾节点"
|
||||||
|
- "🇸🇬 狮城节点"
|
||||||
|
- "🇯🇵 日本节点"
|
||||||
|
- "🇰🇷 韩国节点"
|
||||||
|
- "{{ manual_policy }}"
|
||||||
|
- name: "Ⓜ️ 微软服务"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- "{{ direct_policy }}"
|
||||||
|
- "{{ main_policy }}"
|
||||||
|
- "🇺🇲 美国节点"
|
||||||
|
- "🇭🇰 香港节点"
|
||||||
|
- "🇨🇳 台湾节点"
|
||||||
|
- "🇸🇬 狮城节点"
|
||||||
|
- "🇯🇵 日本节点"
|
||||||
|
- "🇰🇷 韩国节点"
|
||||||
|
- "{{ manual_policy }}"
|
||||||
|
- name: "🍎 苹果服务"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- "{{ direct_policy }}"
|
||||||
|
- "{{ main_policy }}"
|
||||||
|
- "🇺🇲 美国节点"
|
||||||
|
- "🇭🇰 香港节点"
|
||||||
|
- "🇨🇳 台湾节点"
|
||||||
|
- "🇸🇬 狮城节点"
|
||||||
|
- "🇯🇵 日本节点"
|
||||||
|
- "🇰🇷 韩国节点"
|
||||||
|
- "{{ manual_policy }}"
|
||||||
|
- name: "🎮 游戏平台"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- "{{ main_policy }}"
|
||||||
|
- "{{ direct_policy }}"
|
||||||
|
- "🇺🇲 美国节点"
|
||||||
|
- "🇭🇰 香港节点"
|
||||||
|
- "🇨🇳 台湾节点"
|
||||||
|
- "🇸🇬 狮城节点"
|
||||||
|
- "🇯🇵 日本节点"
|
||||||
|
- "🇰🇷 韩国节点"
|
||||||
|
- "{{ manual_policy }}"
|
||||||
|
- name: "🎮 PT平台"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- "{{ main_policy }}"
|
||||||
|
- "{{ direct_policy }}"
|
||||||
|
- "🇭🇰 香港节点"
|
||||||
|
- "🇨🇳 台湾节点"
|
||||||
|
- "🇸🇬 狮城节点"
|
||||||
|
- "🇯🇵 日本节点"
|
||||||
|
- "🇺🇲 美国节点"
|
||||||
|
- "🇰🇷 韩国节点"
|
||||||
|
- "{{ manual_policy }}"
|
||||||
|
- name: "🎯 全球直连"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- "{{ direct_policy }}"
|
||||||
|
- "{{ main_policy }}"
|
||||||
|
- "{{ mixed_auto_policy }}"
|
||||||
|
- name: "🛑 广告拦截"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- REJECT
|
||||||
|
- "{{ direct_policy }}"
|
||||||
|
- name: "🍃 应用净化"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- REJECT
|
||||||
|
- "{{ direct_policy }}"
|
||||||
|
- name: "🐟 漏网之鱼"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- "{{ direct_policy }}"
|
||||||
|
- "{{ main_policy }}"
|
||||||
|
- "{{ mixed_auto_policy }}"
|
||||||
|
- "{{ selector_groups }}"
|
||||||
|
- "{{ manual_policy }}"
|
||||||
25
config/regions.yaml
Normal file
25
config/regions.yaml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
regions:
|
||||||
|
hk:
|
||||||
|
name: "🇭🇰 香港节点"
|
||||||
|
filter: "(?i)(港|hk|hong kong|hongkong)"
|
||||||
|
tolerance: 50
|
||||||
|
tw:
|
||||||
|
name: "🇨🇳 台湾节点"
|
||||||
|
filter: "(?i)(台|新北|彰化|tw|taiwan)"
|
||||||
|
tolerance: 50
|
||||||
|
sg:
|
||||||
|
name: "🇸🇬 狮城节点"
|
||||||
|
filter: "(?i)(新加坡|坡|狮城|sg|singapore)"
|
||||||
|
tolerance: 50
|
||||||
|
jp:
|
||||||
|
name: "🇯🇵 日本节点"
|
||||||
|
filter: "(?i)(日本|东京|大阪|埼玉|jp|japan)"
|
||||||
|
tolerance: 50
|
||||||
|
us:
|
||||||
|
name: "🇺🇲 美国节点"
|
||||||
|
filter: "(?i)(美|波特兰|达拉斯|俄勒冈|凤凰城|费利蒙|硅谷|拉斯维加斯|洛杉矶|圣何塞|圣克拉拉|西雅图|芝加哥|us|united states)"
|
||||||
|
tolerance: 150
|
||||||
|
kr:
|
||||||
|
name: "🇰🇷 韩国节点"
|
||||||
|
filter: "(?i)(kr|korea|kor|首尔|韩|韓)"
|
||||||
|
tolerance: 50
|
||||||
210
config/rules.yaml
Normal file
210
config/rules.yaml
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
rules:
|
||||||
|
custom-proxy:
|
||||||
|
behavior: classical
|
||||||
|
format: text
|
||||||
|
policy: "{{ main_policy }}"
|
||||||
|
payload:
|
||||||
|
- DOMAIN-KEYWORD,cloudflare
|
||||||
|
- DOMAIN-KEYWORD,hetzner
|
||||||
|
- DOMAIN-KEYWORD,hdkylin
|
||||||
|
- DOMAIN-KEYWORD,steamusercontent
|
||||||
|
- DOMAIN-KEYWORD,steamcontent
|
||||||
|
- DOMAIN-KEYWORD,nintendo
|
||||||
|
- DOMAIN-KEYWORD,vscode
|
||||||
|
- DOMAIN-KEYWORD,btschool
|
||||||
|
|
||||||
|
local-network:
|
||||||
|
file: acl4ssr/LocalAreaNetwork.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "🎯 全球直连"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
unban:
|
||||||
|
file: acl4ssr/UnBan.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "🎯 全球直连"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
reject:
|
||||||
|
file: acl4ssr/BanAD.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
interval: 86400
|
||||||
|
policy: "🛑 广告拦截"
|
||||||
|
|
||||||
|
app-purify:
|
||||||
|
file: acl4ssr/BanProgramAD.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
interval: 86400
|
||||||
|
policy: "🍃 应用净化"
|
||||||
|
|
||||||
|
google:
|
||||||
|
file: acl4ssr/Google.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "📢 谷歌"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
google-cn:
|
||||||
|
file: acl4ssr/GoogleCN.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "🎯 全球直连"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
steam-cn:
|
||||||
|
file: acl4ssr/SteamCN.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "🎯 全球直连"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
microsoft-bing:
|
||||||
|
file: acl4ssr/Bing.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "Ⓜ️ 微软Bing"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
microsoft-onedrive:
|
||||||
|
file: acl4ssr/OneDrive.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "Ⓜ️ 微软云盘"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
microsoft:
|
||||||
|
file: acl4ssr/Microsoft.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "Ⓜ️ 微软服务"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
apple:
|
||||||
|
file: acl4ssr/Apple.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "🍎 苹果服务"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
telegram:
|
||||||
|
file: acl4ssr/Telegram.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "📲 电报消息"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
ai:
|
||||||
|
file: acl4ssr/AI.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "💬 Ai平台"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
openai:
|
||||||
|
file: acl4ssr/OpenAi.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "💬 Ai平台"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
youtube:
|
||||||
|
file: acl4ssr/YouTube.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "📹 油管视频"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
netflix:
|
||||||
|
file: acl4ssr/Netflix.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "🎥 奈飞视频"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
proxy-media:
|
||||||
|
file: acl4ssr/ProxyMedia.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "🌍 国外媒体"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
games-epic:
|
||||||
|
file: acl4ssr/Epic.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "🎮 游戏平台"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
games-origin:
|
||||||
|
file: acl4ssr/Origin.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "🎮 游戏平台"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
games-sony:
|
||||||
|
file: acl4ssr/Sony.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "🎮 游戏平台"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
games-steam:
|
||||||
|
file: acl4ssr/Steam.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "🎮 游戏平台"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
games-nintendo:
|
||||||
|
file: acl4ssr/Nintendo.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "🎮 游戏平台"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
pt:
|
||||||
|
file: acl4ssr/PrivateTracker.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "🎮 PT平台"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
cn-domain:
|
||||||
|
file: acl4ssr/ChinaDomain.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "🎯 全球直连"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
cn-company-ip:
|
||||||
|
file: acl4ssr/ChinaCompanyIp.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "🎯 全球直连"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
download:
|
||||||
|
file: acl4ssr/Download.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "🎯 全球直连"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
proxy-gfw:
|
||||||
|
file: acl4ssr/ProxyGFWlist.yaml
|
||||||
|
behavior: classical
|
||||||
|
format: yaml
|
||||||
|
policy: "{{ main_policy }}"
|
||||||
|
interval: 86400
|
||||||
|
|
||||||
|
geoip-cn:
|
||||||
|
behavior: classical
|
||||||
|
format: text
|
||||||
|
policy: "🎯 全球直连"
|
||||||
|
payload:
|
||||||
|
- GEOIP,CN
|
||||||
@@ -1,7 +1,4 @@
|
|||||||
public_path: ${PUBLIC_PATH}
|
airport-a:
|
||||||
|
|
||||||
sources:
|
|
||||||
airport-a:
|
|
||||||
enabled: true
|
enabled: true
|
||||||
display_name: A
|
display_name: A
|
||||||
kind: auto
|
kind: auto
|
||||||
@@ -10,7 +7,7 @@ sources:
|
|||||||
include_regex: ""
|
include_regex: ""
|
||||||
exclude_regex: "流量|重置|到期|续费|官网|离线|套餐"
|
exclude_regex: "流量|重置|到期|续费|官网|离线|套餐"
|
||||||
|
|
||||||
airport-b:
|
airport-b:
|
||||||
enabled: true
|
enabled: true
|
||||||
display_name: B
|
display_name: B
|
||||||
kind: auto
|
kind: auto
|
||||||
@@ -21,7 +18,7 @@ sources:
|
|||||||
include_regex: ""
|
include_regex: ""
|
||||||
exclude_regex: "流量|重置|到期|续费|官网|离线|套餐"
|
exclude_regex: "流量|重置|到期|续费|官网|离线|套餐"
|
||||||
|
|
||||||
airport-c:
|
airport-c:
|
||||||
enabled: true
|
enabled: true
|
||||||
display_name: C
|
display_name: C
|
||||||
kind: auto
|
kind: auto
|
||||||
@@ -29,455 +26,3 @@ sources:
|
|||||||
prefix: "[C] "
|
prefix: "[C] "
|
||||||
include_regex: ""
|
include_regex: ""
|
||||||
exclude_regex: "流量|重置|到期|续费|官网|离线|套餐"
|
exclude_regex: "流量|重置|到期|续费|官网|离线|套餐"
|
||||||
|
|
||||||
regions:
|
|
||||||
hk:
|
|
||||||
name: "🇭🇰 香港节点"
|
|
||||||
filter: "(?i)(港|hk|hong kong|hongkong)"
|
|
||||||
tolerance: 50
|
|
||||||
tw:
|
|
||||||
name: "🇨🇳 台湾节点"
|
|
||||||
filter: "(?i)(台|新北|彰化|tw|taiwan)"
|
|
||||||
tolerance: 50
|
|
||||||
sg:
|
|
||||||
name: "🇸🇬 狮城节点"
|
|
||||||
filter: "(?i)(新加坡|坡|狮城|sg|singapore)"
|
|
||||||
tolerance: 50
|
|
||||||
jp:
|
|
||||||
name: "🇯🇵 日本节点"
|
|
||||||
filter: "(?i)(日本|东京|大阪|埼玉|jp|japan)"
|
|
||||||
tolerance: 50
|
|
||||||
us:
|
|
||||||
name: "🇺🇲 美国节点"
|
|
||||||
filter: "(?i)(美|波特兰|达拉斯|俄勒冈|凤凰城|费利蒙|硅谷|拉斯维加斯|洛杉矶|圣何塞|圣克拉拉|西雅图|芝加哥|us|united states)"
|
|
||||||
tolerance: 150
|
|
||||||
kr:
|
|
||||||
name: "🇰🇷 韩国节点"
|
|
||||||
filter: "(?i)(kr|korea|kor|首尔|韩|韓)"
|
|
||||||
tolerance: 50
|
|
||||||
|
|
||||||
selector_groups:
|
|
||||||
- name: "🎥 奈飞节点"
|
|
||||||
type: select
|
|
||||||
filter: "(?i)(nf|奈飞|解锁|netflix|media)"
|
|
||||||
|
|
||||||
policy_groups:
|
|
||||||
- name: "📲 电报消息"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- "{{ main_policy }}"
|
|
||||||
- "{{ mixed_auto_policy }}"
|
|
||||||
- "🇸🇬 狮城节点"
|
|
||||||
- "🇭🇰 香港节点"
|
|
||||||
- "🇨🇳 台湾节点"
|
|
||||||
- "🇯🇵 日本节点"
|
|
||||||
- "🇺🇲 美国节点"
|
|
||||||
- "🇰🇷 韩国节点"
|
|
||||||
- "{{ manual_policy }}"
|
|
||||||
- "{{ direct_policy }}"
|
|
||||||
- name: "💬 Ai平台"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- "{{ main_policy }}"
|
|
||||||
- "{{ mixed_auto_policy }}"
|
|
||||||
- "🇺🇲 美国节点"
|
|
||||||
- "🇸🇬 狮城节点"
|
|
||||||
- "🇯🇵 日本节点"
|
|
||||||
- "🇭🇰 香港节点"
|
|
||||||
- "🇨🇳 台湾节点"
|
|
||||||
- "🇰🇷 韩国节点"
|
|
||||||
- "{{ manual_policy }}"
|
|
||||||
- "{{ direct_policy }}"
|
|
||||||
- name: "📹 油管视频"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- "{{ main_policy }}"
|
|
||||||
- "{{ mixed_auto_policy }}"
|
|
||||||
- "🇸🇬 狮城节点"
|
|
||||||
- "🇭🇰 香港节点"
|
|
||||||
- "🇨🇳 台湾节点"
|
|
||||||
- "🇯🇵 日本节点"
|
|
||||||
- "🇺🇲 美国节点"
|
|
||||||
- "🇰🇷 韩国节点"
|
|
||||||
- "{{ manual_policy }}"
|
|
||||||
- "{{ direct_policy }}"
|
|
||||||
- name: "🎥 奈飞视频"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- "🎥 奈飞节点"
|
|
||||||
- "{{ main_policy }}"
|
|
||||||
- "{{ mixed_auto_policy }}"
|
|
||||||
- "🇸🇬 狮城节点"
|
|
||||||
- "🇭🇰 香港节点"
|
|
||||||
- "🇨🇳 台湾节点"
|
|
||||||
- "🇯🇵 日本节点"
|
|
||||||
- "🇺🇲 美国节点"
|
|
||||||
- "🇰🇷 韩国节点"
|
|
||||||
- "{{ manual_policy }}"
|
|
||||||
- "{{ direct_policy }}"
|
|
||||||
- name: "🌍 国外媒体"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- "{{ main_policy }}"
|
|
||||||
- "{{ mixed_auto_policy }}"
|
|
||||||
- "🇭🇰 香港节点"
|
|
||||||
- "🇨🇳 台湾节点"
|
|
||||||
- "🇸🇬 狮城节点"
|
|
||||||
- "🇯🇵 日本节点"
|
|
||||||
- "🇺🇲 美国节点"
|
|
||||||
- "🇰🇷 韩国节点"
|
|
||||||
- "{{ manual_policy }}"
|
|
||||||
- "{{ direct_policy }}"
|
|
||||||
- name: "📢 谷歌"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- "{{ main_policy }}"
|
|
||||||
- "{{ direct_policy }}"
|
|
||||||
- "🇺🇲 美国节点"
|
|
||||||
- "🇭🇰 香港节点"
|
|
||||||
- "🇨🇳 台湾节点"
|
|
||||||
- "🇸🇬 狮城节点"
|
|
||||||
- "🇯🇵 日本节点"
|
|
||||||
- "🇰🇷 韩国节点"
|
|
||||||
- "{{ manual_policy }}"
|
|
||||||
- name: "Ⓜ️ 微软Bing"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- "{{ direct_policy }}"
|
|
||||||
- "{{ main_policy }}"
|
|
||||||
- "🇺🇲 美国节点"
|
|
||||||
- "🇭🇰 香港节点"
|
|
||||||
- "🇨🇳 台湾节点"
|
|
||||||
- "🇸🇬 狮城节点"
|
|
||||||
- "🇯🇵 日本节点"
|
|
||||||
- "🇰🇷 韩国节点"
|
|
||||||
- "{{ manual_policy }}"
|
|
||||||
- name: "Ⓜ️ 微软云盘"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- "{{ direct_policy }}"
|
|
||||||
- "{{ main_policy }}"
|
|
||||||
- "🇺🇲 美国节点"
|
|
||||||
- "🇭🇰 香港节点"
|
|
||||||
- "🇨🇳 台湾节点"
|
|
||||||
- "🇸🇬 狮城节点"
|
|
||||||
- "🇯🇵 日本节点"
|
|
||||||
- "🇰🇷 韩国节点"
|
|
||||||
- "{{ manual_policy }}"
|
|
||||||
- name: "Ⓜ️ 微软服务"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- "{{ direct_policy }}"
|
|
||||||
- "{{ main_policy }}"
|
|
||||||
- "🇺🇲 美国节点"
|
|
||||||
- "🇭🇰 香港节点"
|
|
||||||
- "🇨🇳 台湾节点"
|
|
||||||
- "🇸🇬 狮城节点"
|
|
||||||
- "🇯🇵 日本节点"
|
|
||||||
- "🇰🇷 韩国节点"
|
|
||||||
- "{{ manual_policy }}"
|
|
||||||
- name: "🍎 苹果服务"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- "{{ direct_policy }}"
|
|
||||||
- "{{ main_policy }}"
|
|
||||||
- "🇺🇲 美国节点"
|
|
||||||
- "🇭🇰 香港节点"
|
|
||||||
- "🇨🇳 台湾节点"
|
|
||||||
- "🇸🇬 狮城节点"
|
|
||||||
- "🇯🇵 日本节点"
|
|
||||||
- "🇰🇷 韩国节点"
|
|
||||||
- "{{ manual_policy }}"
|
|
||||||
- name: "🎮 游戏平台"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- "{{ main_policy }}"
|
|
||||||
- "{{ direct_policy }}"
|
|
||||||
- "🇺🇲 美国节点"
|
|
||||||
- "🇭🇰 香港节点"
|
|
||||||
- "🇨🇳 台湾节点"
|
|
||||||
- "🇸🇬 狮城节点"
|
|
||||||
- "🇯🇵 日本节点"
|
|
||||||
- "🇰🇷 韩国节点"
|
|
||||||
- "{{ manual_policy }}"
|
|
||||||
- name: "🎮 PT平台"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- "{{ main_policy }}"
|
|
||||||
- "{{ direct_policy }}"
|
|
||||||
- "🇭🇰 香港节点"
|
|
||||||
- "🇨🇳 台湾节点"
|
|
||||||
- "🇸🇬 狮城节点"
|
|
||||||
- "🇯🇵 日本节点"
|
|
||||||
- "🇺🇲 美国节点"
|
|
||||||
- "🇰🇷 韩国节点"
|
|
||||||
- "{{ manual_policy }}"
|
|
||||||
- name: "🎯 全球直连"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- "{{ direct_policy }}"
|
|
||||||
- "{{ main_policy }}"
|
|
||||||
- "{{ mixed_auto_policy }}"
|
|
||||||
- name: "🛑 广告拦截"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- REJECT
|
|
||||||
- "{{ direct_policy }}"
|
|
||||||
- name: "🍃 应用净化"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- REJECT
|
|
||||||
- "{{ direct_policy }}"
|
|
||||||
- name: "🐟 漏网之鱼"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- "{{ direct_policy }}"
|
|
||||||
- "{{ main_policy }}"
|
|
||||||
- "{{ mixed_auto_policy }}"
|
|
||||||
- "{{ selector_groups }}"
|
|
||||||
- "{{ manual_policy }}"
|
|
||||||
|
|
||||||
rules:
|
|
||||||
custom-proxy:
|
|
||||||
behavior: classical
|
|
||||||
format: text
|
|
||||||
policy: "{{ main_policy }}"
|
|
||||||
payload:
|
|
||||||
- DOMAIN-KEYWORD,cloudflare
|
|
||||||
- DOMAIN-KEYWORD,hetzner
|
|
||||||
- DOMAIN-KEYWORD,hdkylin
|
|
||||||
- DOMAIN-KEYWORD,steamusercontent
|
|
||||||
- DOMAIN-KEYWORD,steamcontent
|
|
||||||
- DOMAIN-KEYWORD,nintendo
|
|
||||||
- DOMAIN-KEYWORD,vscode
|
|
||||||
- DOMAIN-KEYWORD,btschool
|
|
||||||
|
|
||||||
local-network:
|
|
||||||
file: acl4ssr/LocalAreaNetwork.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "🎯 全球直连"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
unban:
|
|
||||||
file: acl4ssr/UnBan.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "🎯 全球直连"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
reject:
|
|
||||||
file: acl4ssr/BanAD.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
interval: 86400
|
|
||||||
policy: "🛑 广告拦截"
|
|
||||||
|
|
||||||
app-purify:
|
|
||||||
file: acl4ssr/BanProgramAD.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
interval: 86400
|
|
||||||
policy: "🍃 应用净化"
|
|
||||||
|
|
||||||
google:
|
|
||||||
file: acl4ssr/Google.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "📢 谷歌"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
google-cn:
|
|
||||||
file: acl4ssr/GoogleCN.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "🎯 全球直连"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
steam-cn:
|
|
||||||
file: acl4ssr/SteamCN.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "🎯 全球直连"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
microsoft-bing:
|
|
||||||
file: acl4ssr/Bing.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "Ⓜ️ 微软Bing"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
microsoft-onedrive:
|
|
||||||
file: acl4ssr/OneDrive.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "Ⓜ️ 微软云盘"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
microsoft:
|
|
||||||
file: acl4ssr/Microsoft.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "Ⓜ️ 微软服务"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
apple:
|
|
||||||
file: acl4ssr/Apple.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "🍎 苹果服务"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
telegram:
|
|
||||||
file: acl4ssr/Telegram.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "📲 电报消息"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
ai:
|
|
||||||
file: acl4ssr/AI.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "💬 Ai平台"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
openai:
|
|
||||||
file: acl4ssr/OpenAi.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "💬 Ai平台"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
youtube:
|
|
||||||
file: acl4ssr/YouTube.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "📹 油管视频"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
netflix:
|
|
||||||
file: acl4ssr/Netflix.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "🎥 奈飞视频"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
proxy-media:
|
|
||||||
file: acl4ssr/ProxyMedia.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "🌍 国外媒体"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
games-epic:
|
|
||||||
file: acl4ssr/Epic.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "🎮 游戏平台"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
games-origin:
|
|
||||||
file: acl4ssr/Origin.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "🎮 游戏平台"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
games-sony:
|
|
||||||
file: acl4ssr/Sony.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "🎮 游戏平台"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
games-steam:
|
|
||||||
file: acl4ssr/Steam.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "🎮 游戏平台"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
games-nintendo:
|
|
||||||
file: acl4ssr/Nintendo.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "🎮 游戏平台"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
pt:
|
|
||||||
file: acl4ssr/PrivateTracker.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "🎮 PT平台"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
cn-domain:
|
|
||||||
file: acl4ssr/ChinaDomain.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "🎯 全球直连"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
cn-company-ip:
|
|
||||||
file: acl4ssr/ChinaCompanyIp.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "🎯 全球直连"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
download:
|
|
||||||
file: acl4ssr/Download.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "🎯 全球直连"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
proxy-gfw:
|
|
||||||
file: acl4ssr/ProxyGFWlist.yaml
|
|
||||||
behavior: classical
|
|
||||||
format: yaml
|
|
||||||
policy: "{{ main_policy }}"
|
|
||||||
interval: 86400
|
|
||||||
|
|
||||||
geoip-cn:
|
|
||||||
behavior: classical
|
|
||||||
format: text
|
|
||||||
policy: "🎯 全球直连"
|
|
||||||
payload:
|
|
||||||
- GEOIP,CN
|
|
||||||
|
|
||||||
clients:
|
|
||||||
mihomo:
|
|
||||||
title: HomeLab Mihomo
|
|
||||||
provider_interval: 21600
|
|
||||||
rule_interval: 86400
|
|
||||||
test_url: https://www.gstatic.com/generate_204
|
|
||||||
test_interval: 300
|
|
||||||
main_policy: 🚀 节点选择
|
|
||||||
source_policy: ☁️ 机场选择
|
|
||||||
mixed_auto_policy: ♻️ 自动选择
|
|
||||||
manual_policy: 🚀 手动切换
|
|
||||||
direct_policy: DIRECT
|
|
||||||
mode: rule
|
|
||||||
allow_lan: true
|
|
||||||
ipv6: true
|
|
||||||
mixed_port: 7890
|
|
||||||
socks_port: 7891
|
|
||||||
log_level: info
|
|
||||||
|
|
||||||
stash:
|
|
||||||
title: HomeLab Stash
|
|
||||||
provider_interval: 21600
|
|
||||||
rule_interval: 86400
|
|
||||||
test_url: https://www.gstatic.com/generate_204
|
|
||||||
test_interval: 300
|
|
||||||
main_policy: 🚀 节点选择
|
|
||||||
source_policy: ☁️ 机场选择
|
|
||||||
mixed_auto_policy: ♻️ 自动选择
|
|
||||||
manual_policy: 🚀 手动切换
|
|
||||||
direct_policy: DIRECT
|
|
||||||
mode: rule
|
|
||||||
ipv6: true
|
|
||||||
log_level: info
|
|
||||||
|
|||||||
686
docs/分阶段重构方案.md
Normal file
686
docs/分阶段重构方案.md
Normal file
@@ -0,0 +1,686 @@
|
|||||||
|
# sub-provider 分阶段重构方案
|
||||||
|
|
||||||
|
## 1. 文档目标
|
||||||
|
|
||||||
|
这份文档不是重新定义“最终想做成什么”,而是基于当前 `sub-provider` 已有实现,给出一版可逐步落地、每阶段都能交付可运行结果的重构路径。
|
||||||
|
|
||||||
|
当前项目已经具备以下基础能力:
|
||||||
|
|
||||||
|
* 读取 `config/sources.yaml`
|
||||||
|
* 拉取和缓存上游订阅
|
||||||
|
* 解析 Clash YAML / base64 URI / 明文 URI 订阅
|
||||||
|
* 合并节点并生成 bundle YAML
|
||||||
|
* 生成 thin client 配置
|
||||||
|
* 加载本地规则文件并拼接 `rules`
|
||||||
|
* 透传第一个源的 `Subscription-Userinfo`
|
||||||
|
|
||||||
|
因此重构的目标不是“从零搭系统”,而是把现有静态配置驱动的生成器,逐步改造成:
|
||||||
|
|
||||||
|
* 内部模块化更清晰
|
||||||
|
* 配置存储可演进到数据库
|
||||||
|
* 对外仍以完整 YAML 为主
|
||||||
|
* 保留现有已验证能力
|
||||||
|
* 后续可平滑加管理页和快照系统
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 总体原则
|
||||||
|
|
||||||
|
### 原则 1:对外接口尽量稳定
|
||||||
|
|
||||||
|
在重构前几阶段,尽量不打断现有输出能力:
|
||||||
|
|
||||||
|
* `/bundle/{client}.yaml`
|
||||||
|
* `/clients/{client}.yaml`
|
||||||
|
* `/providers/{name}.yaml`
|
||||||
|
* `/providers/merged.yaml`
|
||||||
|
|
||||||
|
即使最终主路线偏向 bundle,也不建议在早期重构中直接删除 thin/provider 能力。
|
||||||
|
|
||||||
|
### 原则 2:先拆“配置来源”,再拆“表现层”
|
||||||
|
|
||||||
|
当前项目的核心问题不是生成逻辑完全不可用,而是配置全部堆在 `sources.yaml` 里。
|
||||||
|
优先级应是:
|
||||||
|
|
||||||
|
1. 把配置从单一 YAML 拆到更清晰的数据结构
|
||||||
|
2. 再引入数据库承载配置
|
||||||
|
3. 最后再补管理页面
|
||||||
|
|
||||||
|
不要一上来把大量时间花在页面上。
|
||||||
|
|
||||||
|
### 原则 3:规则正文继续文件化
|
||||||
|
|
||||||
|
规则文件仍然保存在项目目录中,继续使用 Git 管理。
|
||||||
|
数据库只存:
|
||||||
|
|
||||||
|
* 规则模块元数据
|
||||||
|
* 规则启用关系
|
||||||
|
* 规则顺序
|
||||||
|
* 规则绑定到哪个策略组
|
||||||
|
|
||||||
|
不把 ACL4SSR 规则逐条拆进数据库。
|
||||||
|
|
||||||
|
### 原则 4:保留动态选源能力
|
||||||
|
|
||||||
|
当前项目支持通过 `?sources=` 在请求级动态组合源,这个能力实际很有价值。
|
||||||
|
重构后不建议退化成只能在 profile 中静态绑定源。
|
||||||
|
|
||||||
|
建议模型上同时支持:
|
||||||
|
|
||||||
|
* profile 默认源集合
|
||||||
|
* 请求级 `sources` override
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 对现有项目的基线判断
|
||||||
|
|
||||||
|
### 3.1 现状优点
|
||||||
|
|
||||||
|
当前代码结构虽然还偏轻量,但核心职责已经初步分开:
|
||||||
|
|
||||||
|
* `subscriptions.py` 负责源抓取、解析、节点转换
|
||||||
|
* `profiles.py` 负责 thin / bundle 配置组装
|
||||||
|
* `rules.py` 负责规则文件加载和规则输出
|
||||||
|
* `bundle_cache.py` / `fetch_cache.py` 负责磁盘缓存
|
||||||
|
|
||||||
|
这意味着重构时应该优先“抽象和替换内部数据来源”,而不是推倒服务层。
|
||||||
|
|
||||||
|
### 3.2 现状主要问题
|
||||||
|
|
||||||
|
当前主要限制有:
|
||||||
|
|
||||||
|
* `sources.yaml` 同时承载源配置、地区分组、业务策略组、规则绑定、客户端配置
|
||||||
|
* 配置模型偏静态,不利于面板管理
|
||||||
|
* bundle 缓存仍是 TTL 模式,不是内容指纹模式
|
||||||
|
* 没有配置快照、生成快照、审计能力
|
||||||
|
* 当前没有数据库层,也没有迁移体系
|
||||||
|
|
||||||
|
### 3.3 结论
|
||||||
|
|
||||||
|
最稳的路线不是“大重写”,而是:
|
||||||
|
|
||||||
|
1. 保持现有生成骨架
|
||||||
|
2. 把配置与渲染逻辑进一步解耦
|
||||||
|
3. 再把配置落进数据库
|
||||||
|
4. 最后加面板和快照
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 目标架构
|
||||||
|
|
||||||
|
推荐演进成如下结构:
|
||||||
|
|
||||||
|
```text
|
||||||
|
请求
|
||||||
|
-> API 路由
|
||||||
|
-> Profile 解析
|
||||||
|
-> Source 选择
|
||||||
|
-> Source 拉取 / 缓存
|
||||||
|
-> 节点解析 / 标准化 / 处理
|
||||||
|
-> 策略组装配
|
||||||
|
-> 规则模块解析
|
||||||
|
-> 完整 YAML 渲染
|
||||||
|
-> 结果缓存 / 快照
|
||||||
|
-> 返回响应头与 YAML
|
||||||
|
```
|
||||||
|
|
||||||
|
配置来源则逐步从:
|
||||||
|
|
||||||
|
```text
|
||||||
|
sources.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
演进为:
|
||||||
|
|
||||||
|
```text
|
||||||
|
数据库配置 + 本地规则资产文件 + 少量默认 YAML 模板
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 分阶段路线
|
||||||
|
|
||||||
|
建议拆成五个阶段,每个阶段结束都能保留一个稳定可运行版本。
|
||||||
|
|
||||||
|
### 阶段 0:重构准备与基线冻结
|
||||||
|
|
||||||
|
目标:
|
||||||
|
|
||||||
|
* 不改行为,先明确现有能力边界
|
||||||
|
* 为后续重构建立可回归的基线
|
||||||
|
|
||||||
|
本阶段任务:
|
||||||
|
|
||||||
|
1. 盘点当前公开接口、查询参数、响应头语义
|
||||||
|
2. 记录当前 `sources.yaml` 中各配置块的职责
|
||||||
|
3. 为核心生成路径补最小测试
|
||||||
|
4. 输出一份“当前行为基线”文档
|
||||||
|
|
||||||
|
验收标准:
|
||||||
|
|
||||||
|
* 至少覆盖以下场景:
|
||||||
|
* 单源 provider
|
||||||
|
* 多源 merged provider
|
||||||
|
* bundle 输出
|
||||||
|
* thin 输出
|
||||||
|
* 第一个源配额头透传
|
||||||
|
* 有一组固定输入可验证当前输出结构不被意外破坏
|
||||||
|
|
||||||
|
建议产物:
|
||||||
|
|
||||||
|
* `tests/` 下最小回归测试
|
||||||
|
* `docs/当前行为基线.md`
|
||||||
|
|
||||||
|
说明:
|
||||||
|
|
||||||
|
这一阶段很重要。没有基线,后面数据库化后很难判断是“重构带来的结构变化”,还是“偷偷改了行为”。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 阶段 1:配置解耦,但仍以 YAML 为配置源
|
||||||
|
|
||||||
|
目标:
|
||||||
|
|
||||||
|
* 先把“一个巨大的 `sources.yaml`”拆成多个清晰模块
|
||||||
|
* 暂时不引入数据库
|
||||||
|
* 不改变线上运行方式
|
||||||
|
|
||||||
|
本阶段任务:
|
||||||
|
|
||||||
|
1. 拆分当前 `sources.yaml`:
|
||||||
|
* `config/sources.yaml`
|
||||||
|
* `config/clients.yaml`
|
||||||
|
* `config/rule-bindings.yaml`
|
||||||
|
* `config/policy-groups.yaml`
|
||||||
|
* `config/regions.yaml`
|
||||||
|
2. 新增统一配置加载层,把多个 YAML 聚合成当前运行所需的内部配置对象
|
||||||
|
3. 把当前 `AppConfig` 进一步拆开,减少“大一统模型”
|
||||||
|
4. 让 `main.py` 不再直接依赖单个全局 `app_config`
|
||||||
|
5. 把“配置加载”和“配置解释”职责从“服务逻辑”中剥离
|
||||||
|
|
||||||
|
建议目录演进:
|
||||||
|
|
||||||
|
```text
|
||||||
|
app/
|
||||||
|
config.py
|
||||||
|
main.py
|
||||||
|
models/
|
||||||
|
source.py
|
||||||
|
client.py
|
||||||
|
profile.py
|
||||||
|
rule.py
|
||||||
|
group.py
|
||||||
|
services/
|
||||||
|
config_loader.py
|
||||||
|
subscriptions.py
|
||||||
|
profiles.py
|
||||||
|
rules.py
|
||||||
|
```
|
||||||
|
|
||||||
|
验收标准:
|
||||||
|
|
||||||
|
* 对外接口路径和行为保持不变
|
||||||
|
* `bundle` 与 `thin` 输出内容结构基本一致
|
||||||
|
* 已不再依赖单个巨型 YAML 文件
|
||||||
|
|
||||||
|
这一阶段收益:
|
||||||
|
|
||||||
|
* 先把系统结构理顺
|
||||||
|
* 后续接数据库时,只需要替换配置仓储层,不需要大改生成器本身
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 阶段 2:引入数据库配置层,保留 YAML 兼容导入
|
||||||
|
|
||||||
|
目标:
|
||||||
|
|
||||||
|
* 让配置从静态文件迁移到数据库
|
||||||
|
* 但仍支持从 YAML 导入初始数据
|
||||||
|
|
||||||
|
本阶段任务:
|
||||||
|
|
||||||
|
1. 引入 SQLAlchemy 与 Alembic
|
||||||
|
2. 增加 `DATABASE_URL`
|
||||||
|
3. 建立第一批核心表
|
||||||
|
4. 实现配置仓储层
|
||||||
|
5. 提供 YAML 初始化导入脚本
|
||||||
|
|
||||||
|
推荐第一批表:
|
||||||
|
|
||||||
|
* `sources`
|
||||||
|
* `profiles`
|
||||||
|
* `profile_sources`
|
||||||
|
* `rule_modules`
|
||||||
|
* `profile_rule_modules`
|
||||||
|
* `policy_groups`
|
||||||
|
* `profile_overrides`
|
||||||
|
|
||||||
|
推荐暂不引入的表:
|
||||||
|
|
||||||
|
* `generated_artifacts`
|
||||||
|
* `sync_logs`
|
||||||
|
* `rule_module_versions`
|
||||||
|
|
||||||
|
原因:
|
||||||
|
|
||||||
|
先把“当前运行配置”迁过去,比一开始就把快照、审计、版本全部做全更稳。
|
||||||
|
|
||||||
|
#### 推荐字段设计
|
||||||
|
|
||||||
|
`sources`
|
||||||
|
|
||||||
|
* `id`
|
||||||
|
* `key`
|
||||||
|
* `name`
|
||||||
|
* `enabled`
|
||||||
|
* `kind`
|
||||||
|
* `url`
|
||||||
|
* `display_name`
|
||||||
|
* `headers_json`
|
||||||
|
* `include_regex`
|
||||||
|
* `exclude_regex`
|
||||||
|
* `prefix`
|
||||||
|
* `suffix`
|
||||||
|
* `cache_ttl_seconds`
|
||||||
|
* `created_at`
|
||||||
|
* `updated_at`
|
||||||
|
|
||||||
|
`profiles`
|
||||||
|
|
||||||
|
* `id`
|
||||||
|
* `key`
|
||||||
|
* `name`
|
||||||
|
* `client_type`
|
||||||
|
* `description`
|
||||||
|
* `enabled`
|
||||||
|
* `allow_lan`
|
||||||
|
* `ipv6`
|
||||||
|
* `mixed_port`
|
||||||
|
* `socks_port`
|
||||||
|
* `mode`
|
||||||
|
* `log_level`
|
||||||
|
* `main_policy`
|
||||||
|
* `source_policy`
|
||||||
|
* `mixed_auto_policy`
|
||||||
|
* `manual_policy`
|
||||||
|
* `direct_policy`
|
||||||
|
* `test_url`
|
||||||
|
* `test_interval`
|
||||||
|
* `provider_interval`
|
||||||
|
* `rule_interval`
|
||||||
|
* `created_at`
|
||||||
|
* `updated_at`
|
||||||
|
|
||||||
|
`profile_sources`
|
||||||
|
|
||||||
|
* `id`
|
||||||
|
* `profile_id`
|
||||||
|
* `source_id`
|
||||||
|
* `order_index`
|
||||||
|
* `enabled`
|
||||||
|
|
||||||
|
`rule_modules`
|
||||||
|
|
||||||
|
* `id`
|
||||||
|
* `key`
|
||||||
|
* `name`
|
||||||
|
* `description`
|
||||||
|
* `file_path`
|
||||||
|
* `behavior`
|
||||||
|
* `format`
|
||||||
|
* `default_policy`
|
||||||
|
* `default_no_resolve`
|
||||||
|
* `default_payload_json`
|
||||||
|
* `category`
|
||||||
|
* `created_at`
|
||||||
|
* `updated_at`
|
||||||
|
|
||||||
|
`profile_rule_modules`
|
||||||
|
|
||||||
|
* `id`
|
||||||
|
* `profile_id`
|
||||||
|
* `rule_module_id`
|
||||||
|
* `enabled`
|
||||||
|
* `order_index`
|
||||||
|
* `policy_override`
|
||||||
|
* `payload_override_json`
|
||||||
|
* `no_resolve_override`
|
||||||
|
|
||||||
|
`policy_groups`
|
||||||
|
|
||||||
|
* `id`
|
||||||
|
* `profile_id`
|
||||||
|
* `name`
|
||||||
|
* `group_kind`
|
||||||
|
* `type`
|
||||||
|
* `order_index`
|
||||||
|
* `filter_regex`
|
||||||
|
* `proxies_json`
|
||||||
|
* `url`
|
||||||
|
* `interval`
|
||||||
|
* `tolerance`
|
||||||
|
* `enabled`
|
||||||
|
|
||||||
|
这里的 `group_kind` 建议至少支持:
|
||||||
|
|
||||||
|
* `static`
|
||||||
|
* `filter`
|
||||||
|
* `generated`
|
||||||
|
|
||||||
|
这比单纯用一个 `config_json` 更适合当前项目,因为现有组装里同时存在静态组和按 regex 选节点的组。
|
||||||
|
|
||||||
|
#### 仓储层建议
|
||||||
|
|
||||||
|
新增仓储抽象,例如:
|
||||||
|
|
||||||
|
* `SourceRepository`
|
||||||
|
* `ProfileRepository`
|
||||||
|
* `RuleModuleRepository`
|
||||||
|
* `PolicyGroupRepository`
|
||||||
|
|
||||||
|
让生成服务只依赖仓储接口,而不是依赖数据库实现细节。
|
||||||
|
|
||||||
|
验收标准:
|
||||||
|
|
||||||
|
* 使用数据库也能生成与阶段 1 基本一致的 bundle/thin 配置
|
||||||
|
* 可以从原 YAML 导入初始配置
|
||||||
|
* 切换配置来源时,渲染层无需大改
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 阶段 3:渲染流水线模块化与输出主路线收敛
|
||||||
|
|
||||||
|
目标:
|
||||||
|
|
||||||
|
* 把“源处理、规则处理、组装渲染”彻底做成稳定流水线
|
||||||
|
* 明确 bundle 是主输出路线
|
||||||
|
* thin/provider 进入兼容保留状态
|
||||||
|
|
||||||
|
本阶段任务:
|
||||||
|
|
||||||
|
1. 拆分服务层职责:
|
||||||
|
* `source_fetcher.py`
|
||||||
|
* `source_parser.py`
|
||||||
|
* `proxy_processor.py`
|
||||||
|
* `policy_group_builder.py`
|
||||||
|
* `rule_resolver.py`
|
||||||
|
* `profile_renderer.py`
|
||||||
|
2. 引入统一内部节点模型
|
||||||
|
3. 引入统一内部“已解析 profile”模型
|
||||||
|
4. 将当前 `build_bundle_profile()` 的逻辑拆成多步处理
|
||||||
|
5. 清理当前 token 展开逻辑,明确保留哪些模板 token
|
||||||
|
|
||||||
|
#### 内部模型建议
|
||||||
|
|
||||||
|
不要把节点模型收得太死。建议:
|
||||||
|
|
||||||
|
```python
|
||||||
|
class ProxyNode(BaseModel):
|
||||||
|
name: str
|
||||||
|
type: str
|
||||||
|
server: str | None = None
|
||||||
|
port: int | None = None
|
||||||
|
udp: bool = True
|
||||||
|
tags: list[str] = Field(default_factory=list)
|
||||||
|
attrs: dict[str, Any] = Field(default_factory=dict)
|
||||||
|
```
|
||||||
|
|
||||||
|
其中:
|
||||||
|
|
||||||
|
* 通用字段单独保留
|
||||||
|
* 协议特有字段放 `attrs`
|
||||||
|
* 最终输出时再按协议合并回 YAML 结构
|
||||||
|
|
||||||
|
这样比单纯的 `raw` 更可控。
|
||||||
|
|
||||||
|
#### 规则系统建议
|
||||||
|
|
||||||
|
这一阶段不要急着把所有规则文件改成 `{{ target_group }}` 模板格式。
|
||||||
|
先保留当前模式:
|
||||||
|
|
||||||
|
* 文件内容仍是 payload
|
||||||
|
* policy 在 profile 绑定关系上决定
|
||||||
|
|
||||||
|
原因:
|
||||||
|
|
||||||
|
* 当前 thin 模式的 `rule-providers` 仍依赖 payload 文件输出
|
||||||
|
* 先保留兼容性,后面再决定是否升级规则文件模板化
|
||||||
|
|
||||||
|
验收标准:
|
||||||
|
|
||||||
|
* bundle 渲染主路径清晰可测
|
||||||
|
* 服务层之间依赖方向清楚
|
||||||
|
* 配置仓储和渲染器分离
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 阶段 4:管理接口与最小面板
|
||||||
|
|
||||||
|
目标:
|
||||||
|
|
||||||
|
* 提供最小配置管理能力
|
||||||
|
* 不做复杂前后端分离
|
||||||
|
|
||||||
|
本阶段任务:
|
||||||
|
|
||||||
|
1. 增加管理 API:
|
||||||
|
* source CRUD
|
||||||
|
* profile CRUD
|
||||||
|
* rule module 查看与 profile 绑定管理
|
||||||
|
* policy group 查看与编辑
|
||||||
|
2. 增加预览接口
|
||||||
|
3. 增加最小页面:
|
||||||
|
* sources
|
||||||
|
* profiles
|
||||||
|
* rule bindings
|
||||||
|
* preview
|
||||||
|
4. 提供 profile 级 bundle 下载入口
|
||||||
|
|
||||||
|
建议接口:
|
||||||
|
|
||||||
|
* `GET /api/sources`
|
||||||
|
* `POST /api/sources`
|
||||||
|
* `PUT /api/sources/{id}`
|
||||||
|
* `GET /api/profiles`
|
||||||
|
* `POST /api/profiles`
|
||||||
|
* `PUT /api/profiles/{id}`
|
||||||
|
* `GET /api/profiles/{id}/rules`
|
||||||
|
* `PUT /api/profiles/{id}/rules`
|
||||||
|
* `GET /api/profiles/{id}/groups`
|
||||||
|
* `PUT /api/profiles/{id}/groups`
|
||||||
|
* `POST /api/profiles/{id}/preview`
|
||||||
|
* `GET /profiles/{key}/bundle.yaml`
|
||||||
|
|
||||||
|
面板技术建议:
|
||||||
|
|
||||||
|
* Jinja2
|
||||||
|
* HTMX 或最少量原生 JS
|
||||||
|
|
||||||
|
不建议此时做:
|
||||||
|
|
||||||
|
* React/Vue 前后端分离
|
||||||
|
* 复杂权限系统
|
||||||
|
* 在线全文规则编辑器
|
||||||
|
|
||||||
|
验收标准:
|
||||||
|
|
||||||
|
* 不改代码即可新增一个 source
|
||||||
|
* 不改 YAML 文件即可调整 profile 规则顺序
|
||||||
|
* 页面可直接预览 bundle 输出
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 阶段 5:快照、缓存升级与可追踪性
|
||||||
|
|
||||||
|
目标:
|
||||||
|
|
||||||
|
* 从“能生成”升级到“可追踪、可复现、可排查”
|
||||||
|
|
||||||
|
本阶段任务:
|
||||||
|
|
||||||
|
1. 增加 `generated_artifacts`
|
||||||
|
2. 增加内容指纹缓存
|
||||||
|
3. 增加源同步状态记录
|
||||||
|
4. 增加简单 diff 能力
|
||||||
|
5. 增加错误展示
|
||||||
|
|
||||||
|
推荐新增表:
|
||||||
|
|
||||||
|
`generated_artifacts`
|
||||||
|
|
||||||
|
* `id`
|
||||||
|
* `profile_id`
|
||||||
|
* `request_sources_json`
|
||||||
|
* `content`
|
||||||
|
* `content_hash`
|
||||||
|
* `source_hash`
|
||||||
|
* `rules_hash`
|
||||||
|
* `profile_hash`
|
||||||
|
* `headers_json`
|
||||||
|
* `generated_at`
|
||||||
|
|
||||||
|
`source_sync_logs`
|
||||||
|
|
||||||
|
* `id`
|
||||||
|
* `source_id`
|
||||||
|
* `status`
|
||||||
|
* `error_message`
|
||||||
|
* `response_headers_json`
|
||||||
|
* `content_hash`
|
||||||
|
* `created_at`
|
||||||
|
|
||||||
|
#### 缓存策略建议
|
||||||
|
|
||||||
|
当前项目 bundle 缓存是 TTL 模式。后续应逐步改为:
|
||||||
|
|
||||||
|
* fetch cache: TTL
|
||||||
|
* parsed snapshot cache: 源内容 hash
|
||||||
|
* bundle cache: `source_hash + rules_hash + profile_hash + request_sources`
|
||||||
|
|
||||||
|
这样才能真正做到:
|
||||||
|
|
||||||
|
* 配置没变就稳定复用
|
||||||
|
* 配置变了就精准失效
|
||||||
|
|
||||||
|
验收标准:
|
||||||
|
|
||||||
|
* 能查看某个 profile 最近几次生成记录
|
||||||
|
* 能知道本次 bundle 为什么重新生成
|
||||||
|
* 能追踪某个源最近一次同步是否失败
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 推荐实施顺序
|
||||||
|
|
||||||
|
如果按投入产出比排序,建议实际开发顺序如下:
|
||||||
|
|
||||||
|
1. 阶段 0
|
||||||
|
2. 阶段 1
|
||||||
|
3. 阶段 2
|
||||||
|
4. 阶段 3
|
||||||
|
5. 阶段 4
|
||||||
|
6. 阶段 5
|
||||||
|
|
||||||
|
其中真正的“第一版可交付里程碑”建议定在阶段 2 结束时。
|
||||||
|
|
||||||
|
因为到了阶段 2,已经具备:
|
||||||
|
|
||||||
|
* 数据库存储配置
|
||||||
|
* 可继续生成完整 YAML
|
||||||
|
* 配置不再绑死在单文件 YAML 中
|
||||||
|
|
||||||
|
这时即使还没有面板,系统内核已经完成了最关键升级。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 每阶段风险点
|
||||||
|
|
||||||
|
### 阶段 1 风险
|
||||||
|
|
||||||
|
风险:
|
||||||
|
|
||||||
|
* 拆 YAML 时容易出现字段兼容问题
|
||||||
|
|
||||||
|
控制方式:
|
||||||
|
|
||||||
|
* 先保留兼容加载层
|
||||||
|
* 老配置格式在一段时间内继续可读
|
||||||
|
|
||||||
|
### 阶段 2 风险
|
||||||
|
|
||||||
|
风险:
|
||||||
|
|
||||||
|
* 数据建模过度,导致表过多、实现过重
|
||||||
|
|
||||||
|
控制方式:
|
||||||
|
|
||||||
|
* 第一批只建运行必需表
|
||||||
|
* 快照与日志延后
|
||||||
|
|
||||||
|
### 阶段 3 风险
|
||||||
|
|
||||||
|
风险:
|
||||||
|
|
||||||
|
* 过早重写规则系统,导致 thin 模式兼容性下降
|
||||||
|
|
||||||
|
控制方式:
|
||||||
|
|
||||||
|
* 先保留 payload 模式
|
||||||
|
* 规则模板化放后续增量处理
|
||||||
|
|
||||||
|
### 阶段 4 风险
|
||||||
|
|
||||||
|
风险:
|
||||||
|
|
||||||
|
* 过早投入页面开发,拖慢主流程
|
||||||
|
|
||||||
|
控制方式:
|
||||||
|
|
||||||
|
* 先 API 后页面
|
||||||
|
* 页面只做最小可用
|
||||||
|
|
||||||
|
### 阶段 5 风险
|
||||||
|
|
||||||
|
风险:
|
||||||
|
|
||||||
|
* 快照和缓存逻辑做得太复杂,维护成本上升
|
||||||
|
|
||||||
|
控制方式:
|
||||||
|
|
||||||
|
* 先做内容哈希与生成记录
|
||||||
|
* diff 与审计能力逐步补
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 明确不建议的做法
|
||||||
|
|
||||||
|
1. 不建议一开始就删除当前 thin/provider 能力
|
||||||
|
2. 不建议一开始就把所有规则文件模板化
|
||||||
|
3. 不建议把 profile 的源集合只做成一个 `source_ids_json`
|
||||||
|
4. 不建议把策略组全塞进一个不透明 `config_json`
|
||||||
|
5. 不建议先做复杂前端再补业务内核
|
||||||
|
6. 不建议先做快照系统再做数据库配置层
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 建议的第一批实际改动
|
||||||
|
|
||||||
|
如果下一步开始真正动代码,建议先做这几件事:
|
||||||
|
|
||||||
|
1. 新建阶段 0 的测试和基线文档
|
||||||
|
2. 拆分 `sources.yaml`,完成阶段 1
|
||||||
|
3. 引入 SQLAlchemy/Alembic 和最小表结构
|
||||||
|
4. 增加 YAML -> DB 导入脚本
|
||||||
|
5. 让 bundle 渲染从数据库读取 profile / source / rules 配置
|
||||||
|
|
||||||
|
这五步完成后,再去做页面,整体节奏会稳很多。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. 一句话结论
|
||||||
|
|
||||||
|
`sub-provider` 的重构最稳路线是:
|
||||||
|
|
||||||
|
> 先做配置解耦,再做数据库配置层,再做渲染流水线固化,最后补管理页面和快照系统。
|
||||||
|
|
||||||
|
这样每一阶段都能保留一个可运行版本,也最符合当前项目已经有代码基础的现实情况。
|
||||||
976
docs/改造方案.md
Normal file
976
docs/改造方案.md
Normal file
@@ -0,0 +1,976 @@
|
|||||||
|
下面这份你可以直接丢给 Codex。
|
||||||
|
我把我们刚刚聊出来的**最终拍板结论**和**完整实现方案**都整理进去了。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# sub-provider 重构方案(最终版,完整 YAML 路线)
|
||||||
|
|
||||||
|
## 1. 最终结论
|
||||||
|
|
||||||
|
本项目后续重构,采用以下最终选择:
|
||||||
|
|
||||||
|
### 对外输出
|
||||||
|
|
||||||
|
* **统一输出单个完整 YAML**
|
||||||
|
* 不强依赖客户端支持 `rule-providers` / `proxy-providers`
|
||||||
|
* 目标是优先保证:
|
||||||
|
|
||||||
|
* 兼容性
|
||||||
|
* 可调试性
|
||||||
|
* 易分发
|
||||||
|
* 易维护
|
||||||
|
|
||||||
|
### 对内实现
|
||||||
|
|
||||||
|
* 内部仍然采用**模块化**设计
|
||||||
|
* 在 sub-provider 内部完成:
|
||||||
|
|
||||||
|
* 源拉取与缓存
|
||||||
|
* 节点解析与标准化
|
||||||
|
* 节点筛选、重命名、去重
|
||||||
|
* 规则模块组合
|
||||||
|
* 策略组装配
|
||||||
|
* DNS / TUN / 通用配置拼装
|
||||||
|
* 最终完整 YAML 渲染
|
||||||
|
|
||||||
|
### 规则存储方式
|
||||||
|
|
||||||
|
* **规则正文继续放项目文件**
|
||||||
|
* 采用类似 ACL4SSR 的维护方式:
|
||||||
|
|
||||||
|
* 一个类别的规则放一个文件
|
||||||
|
* 规则文件便于 Git 管理、diff、回滚、手工维护
|
||||||
|
* 不把 ACL4SSR 大量规则逐条入库
|
||||||
|
|
||||||
|
### 规则组合与面板配置
|
||||||
|
|
||||||
|
* **规则的组合关系、启用状态、绑定的策略组、顺序、参数等放 SQLite**
|
||||||
|
* 面板配置的是:
|
||||||
|
|
||||||
|
* 选哪些规则模块
|
||||||
|
* 每个模块绑定哪个策略组
|
||||||
|
* 模块顺序
|
||||||
|
* 模块参数
|
||||||
|
* profile 配置
|
||||||
|
* 源配置
|
||||||
|
* 少量 prepend / append 自定义规则
|
||||||
|
|
||||||
|
### 数据库选择
|
||||||
|
|
||||||
|
* **默认数据库:SQLite**
|
||||||
|
* 原因:
|
||||||
|
|
||||||
|
* 当前项目是单服务、轻量配置中心、生成器型应用
|
||||||
|
* SQLite 部署和迁移成本最低
|
||||||
|
* 最适合当前阶段快速落地
|
||||||
|
* 代码层要保留未来切 PostgreSQL 的能力:
|
||||||
|
|
||||||
|
* 使用 SQLAlchemy
|
||||||
|
* 使用 Alembic
|
||||||
|
* 用 `DATABASE_URL` 配置数据库连接
|
||||||
|
* 当前不推荐 Mongo 作为主库
|
||||||
|
* 当前不优先推荐 MySQL
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 目标
|
||||||
|
|
||||||
|
将现有 Python sub-provider 项目重构为一个:
|
||||||
|
|
||||||
|
* 可面板管理
|
||||||
|
* 配置解耦
|
||||||
|
* 规则模块化
|
||||||
|
* 输出完整 YAML
|
||||||
|
* 可缓存
|
||||||
|
* 可预览
|
||||||
|
* 可追踪生成结果
|
||||||
|
|
||||||
|
的配置生成系统。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 项目边界
|
||||||
|
|
||||||
|
### 本阶段要做
|
||||||
|
|
||||||
|
1. 面板化管理订阅源
|
||||||
|
2. 规则模块化
|
||||||
|
3. 规则组合关系数据库化
|
||||||
|
4. 支持多个输出 Profile
|
||||||
|
5. 服务端拼装生成完整 YAML
|
||||||
|
6. 做缓存和快照
|
||||||
|
7. 支持预览和下载
|
||||||
|
|
||||||
|
### 本阶段不做
|
||||||
|
|
||||||
|
1. 不强制对外输出 provider 模式
|
||||||
|
2. 不做“在线全文编辑 ACL4SSR 大规则文件”为主交互方式
|
||||||
|
3. 不做复杂多用户权限系统
|
||||||
|
4. 不做重型前后端分离
|
||||||
|
5. 不把所有规则全文放 SQLite
|
||||||
|
6. 不引入 Mongo 做主存储
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 架构原则
|
||||||
|
|
||||||
|
### 原则 1:外部简单,内部灵活
|
||||||
|
|
||||||
|
客户端只拿一个完整 YAML。
|
||||||
|
服务端内部怎么拆、怎么缓存、怎么组合,都由 sub-provider 负责。
|
||||||
|
|
||||||
|
### 原则 2:规则内容文件化,组合关系数据库化
|
||||||
|
|
||||||
|
规则正文属于“资产”,继续放文件。
|
||||||
|
面板管理的是“配置和组合关系”,放 SQLite。
|
||||||
|
|
||||||
|
### 原则 3:90% 的配置修改通过“选模块 + 改参数”完成
|
||||||
|
|
||||||
|
不要把面板做成“大文本框配置编辑器”。
|
||||||
|
|
||||||
|
### 原则 4:优先可维护,而不是一开始就追求炫技
|
||||||
|
|
||||||
|
先把结构跑顺,再考虑高级模式。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 总体架构
|
||||||
|
|
||||||
|
```text
|
||||||
|
输入源
|
||||||
|
-> 拉取缓存
|
||||||
|
-> 原始内容缓存
|
||||||
|
-> 解析节点
|
||||||
|
-> 节点标准化
|
||||||
|
-> 节点处理(过滤/去重/重命名/分类)
|
||||||
|
-> 策略组生成
|
||||||
|
-> 规则模块加载
|
||||||
|
-> 规则模块参数渲染
|
||||||
|
-> 规则按顺序拼接
|
||||||
|
-> 插入 prepend/append 自定义规则
|
||||||
|
-> 渲染完整 YAML
|
||||||
|
-> 结果缓存 / 生成快照
|
||||||
|
-> 提供下载 / 预览 / HEAD 信息
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 推荐技术栈
|
||||||
|
|
||||||
|
### 后端
|
||||||
|
|
||||||
|
* FastAPI
|
||||||
|
|
||||||
|
### 数据库
|
||||||
|
|
||||||
|
* SQLite(默认)
|
||||||
|
* SQLAlchemy ORM
|
||||||
|
* Alembic migration
|
||||||
|
|
||||||
|
### 模板
|
||||||
|
|
||||||
|
* Jinja2
|
||||||
|
|
||||||
|
### 前端
|
||||||
|
|
||||||
|
* 优先服务端渲染
|
||||||
|
* 可用 Jinja2 + HTMX 或简单模板页
|
||||||
|
* 先不要求 React/Vue 前后端分离
|
||||||
|
|
||||||
|
### 缓存
|
||||||
|
|
||||||
|
* 轻量场景下可先用:
|
||||||
|
|
||||||
|
* SQLite 表
|
||||||
|
* 本地文件缓存
|
||||||
|
* 不必一上来引入 Redis
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 目录结构建议
|
||||||
|
|
||||||
|
```text
|
||||||
|
app/
|
||||||
|
api/
|
||||||
|
routes_sources.py
|
||||||
|
routes_profiles.py
|
||||||
|
routes_rules.py
|
||||||
|
routes_preview.py
|
||||||
|
core/
|
||||||
|
config.py
|
||||||
|
database.py
|
||||||
|
cache.py
|
||||||
|
db/
|
||||||
|
base.py
|
||||||
|
session.py
|
||||||
|
models/
|
||||||
|
source.py
|
||||||
|
profile.py
|
||||||
|
rule_module.py
|
||||||
|
policy_group.py
|
||||||
|
artifact.py
|
||||||
|
schemas/
|
||||||
|
source.py
|
||||||
|
profile.py
|
||||||
|
rule_module.py
|
||||||
|
services/
|
||||||
|
source_fetcher.py
|
||||||
|
source_parser.py
|
||||||
|
proxy_normalizer.py
|
||||||
|
proxy_processor.py
|
||||||
|
policy_group_builder.py
|
||||||
|
rule_loader.py
|
||||||
|
rule_renderer.py
|
||||||
|
profile_renderer.py
|
||||||
|
artifact_service.py
|
||||||
|
templates/
|
||||||
|
base.html
|
||||||
|
sources.html
|
||||||
|
profiles.html
|
||||||
|
rules.html
|
||||||
|
preview.html
|
||||||
|
main.py
|
||||||
|
|
||||||
|
rules/
|
||||||
|
modules/
|
||||||
|
lan.list
|
||||||
|
private.list
|
||||||
|
cn_domain.list
|
||||||
|
cn_ip.list
|
||||||
|
apple.list
|
||||||
|
microsoft.list
|
||||||
|
github.list
|
||||||
|
telegram.list
|
||||||
|
openai.list
|
||||||
|
streaming.list
|
||||||
|
ads.list
|
||||||
|
final_proxy.list
|
||||||
|
final_direct.list
|
||||||
|
|
||||||
|
presets/
|
||||||
|
minimal.yaml
|
||||||
|
daily.yaml
|
||||||
|
router.yaml
|
||||||
|
|
||||||
|
group_templates/
|
||||||
|
basic.yaml
|
||||||
|
ai.yaml
|
||||||
|
streaming.yaml
|
||||||
|
|
||||||
|
data/
|
||||||
|
app.db
|
||||||
|
cache/
|
||||||
|
raw_sources/
|
||||||
|
parsed_sources/
|
||||||
|
generated/
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
migrations/
|
||||||
|
tests/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 规则系统设计
|
||||||
|
|
||||||
|
## 8.1 规则正文:继续放文件
|
||||||
|
|
||||||
|
规则正文文件继续按 ACL4SSR 风格维护。
|
||||||
|
|
||||||
|
例如:
|
||||||
|
|
||||||
|
* `rules/modules/apple.list`
|
||||||
|
* `rules/modules/openai.list`
|
||||||
|
* `rules/modules/telegram.list`
|
||||||
|
* `rules/modules/cn_domain.list`
|
||||||
|
* `rules/modules/final_proxy.list`
|
||||||
|
|
||||||
|
### 推荐格式
|
||||||
|
|
||||||
|
规则文件使用模板变量,不直接写死策略组:
|
||||||
|
|
||||||
|
```text
|
||||||
|
DOMAIN-SUFFIX,openai.com,{{ target_group }}
|
||||||
|
DOMAIN-SUFFIX,chatgpt.com,{{ target_group }}
|
||||||
|
DOMAIN-SUFFIX,oaistatic.com,{{ target_group }}
|
||||||
|
DOMAIN-SUFFIX,auth0.openai.com,{{ target_group }}
|
||||||
|
```
|
||||||
|
|
||||||
|
这样同一个规则模块可复用到不同策略组。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8.2 规则模块:放 SQLite
|
||||||
|
|
||||||
|
SQLite 里存规则模块元数据,而不是规则全文。
|
||||||
|
|
||||||
|
### 表:`rule_modules`
|
||||||
|
|
||||||
|
字段建议:
|
||||||
|
|
||||||
|
* `id`
|
||||||
|
* `key`
|
||||||
|
* `name`
|
||||||
|
* `description`
|
||||||
|
* `file_path`
|
||||||
|
* `category`
|
||||||
|
* `default_enabled`
|
||||||
|
* `default_order`
|
||||||
|
* `default_target_policy`
|
||||||
|
* `params_schema_json`
|
||||||
|
* `created_at`
|
||||||
|
* `updated_at`
|
||||||
|
|
||||||
|
### 示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"key": "openai",
|
||||||
|
"name": "OpenAI",
|
||||||
|
"file_path": "rules/modules/openai.list",
|
||||||
|
"category": "service",
|
||||||
|
"default_enabled": true,
|
||||||
|
"default_order": 80,
|
||||||
|
"default_target_policy": "🤖 AI",
|
||||||
|
"params_schema_json": {
|
||||||
|
"target_group": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "🤖 AI"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8.3 Profile 中的规则组合:放 SQLite
|
||||||
|
|
||||||
|
### 表:`profile_rule_modules`
|
||||||
|
|
||||||
|
字段建议:
|
||||||
|
|
||||||
|
* `id`
|
||||||
|
* `profile_id`
|
||||||
|
* `module_id`
|
||||||
|
* `enabled`
|
||||||
|
* `order_index`
|
||||||
|
* `target_policy`
|
||||||
|
* `params_json`
|
||||||
|
|
||||||
|
含义:
|
||||||
|
|
||||||
|
* 这个 profile 是否启用这个模块
|
||||||
|
* 顺序是什么
|
||||||
|
* 最终绑定到哪个策略组
|
||||||
|
* 参数是什么
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8.4 规则预设
|
||||||
|
|
||||||
|
可选支持“预设”。
|
||||||
|
|
||||||
|
例如:
|
||||||
|
|
||||||
|
* `minimal`
|
||||||
|
* `daily`
|
||||||
|
* `router`
|
||||||
|
|
||||||
|
但预设只作为**初始化模板**,最终仍落到具体 profile 配置里。
|
||||||
|
|
||||||
|
不要求上线初期就把预设做得很复杂。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 策略组系统设计
|
||||||
|
|
||||||
|
策略组不要硬编码死在一个大 YAML 模板里。
|
||||||
|
也要做成可配置对象。
|
||||||
|
|
||||||
|
### 表:`policy_groups`
|
||||||
|
|
||||||
|
字段建议:
|
||||||
|
|
||||||
|
* `id`
|
||||||
|
* `profile_id`
|
||||||
|
* `name`
|
||||||
|
* `type`
|
||||||
|
* `order_index`
|
||||||
|
* `config_json`
|
||||||
|
|
||||||
|
### `config_json` 示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"proxies": ["DIRECT", "REJECT", "香港节点", "日本节点"],
|
||||||
|
"include_all_nodes": false,
|
||||||
|
"filter": "HK|Hong Kong"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 支持的策略组类型
|
||||||
|
|
||||||
|
* `select`
|
||||||
|
* `url-test`
|
||||||
|
* `fallback`
|
||||||
|
* `load-balance`
|
||||||
|
|
||||||
|
### 建议的默认组
|
||||||
|
|
||||||
|
* `🚀 节点选择`
|
||||||
|
* `🤖 AI`
|
||||||
|
* `📺 流媒体`
|
||||||
|
* `🍎 苹果服务`
|
||||||
|
* `📲 Telegram`
|
||||||
|
* `🌍 国外网站`
|
||||||
|
* `🇨🇳 国内网站`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. 源管理设计
|
||||||
|
|
||||||
|
### 表:`sources`
|
||||||
|
|
||||||
|
字段建议:
|
||||||
|
|
||||||
|
* `id`
|
||||||
|
* `name`
|
||||||
|
* `type`
|
||||||
|
值可为:
|
||||||
|
|
||||||
|
* `base64`
|
||||||
|
* `url`
|
||||||
|
* `link`
|
||||||
|
* `static`
|
||||||
|
* `content`
|
||||||
|
* `headers_json`
|
||||||
|
* `enabled`
|
||||||
|
* `priority`
|
||||||
|
* `update_interval_sec`
|
||||||
|
* `rename_rules_json`
|
||||||
|
* `filter_rules_json`
|
||||||
|
* `dedupe_policy`
|
||||||
|
* `last_sync_at`
|
||||||
|
* `last_sync_status`
|
||||||
|
* `last_error`
|
||||||
|
* `created_at`
|
||||||
|
* `updated_at`
|
||||||
|
|
||||||
|
### 说明
|
||||||
|
|
||||||
|
这里的源是原始输入源,不是给客户端的 provider。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Profile 设计
|
||||||
|
|
||||||
|
Profile 是最终对外输出的配置单元。
|
||||||
|
|
||||||
|
例如:
|
||||||
|
|
||||||
|
* iPhone 配置
|
||||||
|
* Windows 配置
|
||||||
|
* OpenWrt 配置
|
||||||
|
* Apple TV 配置
|
||||||
|
* 精简版配置
|
||||||
|
* 完整版配置
|
||||||
|
|
||||||
|
### 表:`profiles`
|
||||||
|
|
||||||
|
字段建议:
|
||||||
|
|
||||||
|
* `id`
|
||||||
|
* `name`
|
||||||
|
* `description`
|
||||||
|
* `source_ids_json`
|
||||||
|
* `dns_template`
|
||||||
|
* `tun_enabled`
|
||||||
|
* `udp_enabled`
|
||||||
|
* `append_subscription_info`
|
||||||
|
* `expose_head_info`
|
||||||
|
* `enabled`
|
||||||
|
* `created_at`
|
||||||
|
* `updated_at`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. 自定义覆盖设计
|
||||||
|
|
||||||
|
为了兼容高级用户需求,支持少量覆盖,但不做全文编辑器。
|
||||||
|
|
||||||
|
### 表:`profile_overrides`
|
||||||
|
|
||||||
|
字段建议:
|
||||||
|
|
||||||
|
* `id`
|
||||||
|
* `profile_id`
|
||||||
|
* `custom_rules_prepend`
|
||||||
|
* `custom_rules_append`
|
||||||
|
* `custom_proxy_groups`
|
||||||
|
* `custom_dns_patch`
|
||||||
|
* `custom_yaml_patch`
|
||||||
|
|
||||||
|
### 原则
|
||||||
|
|
||||||
|
只提供:
|
||||||
|
|
||||||
|
* prepend rules
|
||||||
|
* append rules
|
||||||
|
* 少量 patch
|
||||||
|
|
||||||
|
不鼓励直接在面板里手写全部 YAML。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13. 缓存设计
|
||||||
|
|
||||||
|
## 13.1 原始源缓存
|
||||||
|
|
||||||
|
缓存拉回来的原始内容。
|
||||||
|
|
||||||
|
目的:
|
||||||
|
|
||||||
|
* 避免频繁请求订阅源
|
||||||
|
* 降低上游压力
|
||||||
|
* 出问题可复现
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13.2 解析结果缓存
|
||||||
|
|
||||||
|
把原始内容解析为统一节点模型后缓存。
|
||||||
|
|
||||||
|
目的:
|
||||||
|
|
||||||
|
* 多 profile 复用解析结果
|
||||||
|
* 避免重复解析
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13.3 最终 YAML 缓存
|
||||||
|
|
||||||
|
同一个 profile 在以下内容不变时,直接返回缓存:
|
||||||
|
|
||||||
|
* 订阅源内容未变
|
||||||
|
* profile 配置未变
|
||||||
|
* 规则模块未变
|
||||||
|
* 策略组未变
|
||||||
|
|
||||||
|
缓存键建议基于 hash:
|
||||||
|
|
||||||
|
* 源快照 hash
|
||||||
|
* 规则快照 hash
|
||||||
|
* profile 配置 hash
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 14. 生成快照设计
|
||||||
|
|
||||||
|
### 表:`generated_artifacts`
|
||||||
|
|
||||||
|
字段建议:
|
||||||
|
|
||||||
|
* `id`
|
||||||
|
* `profile_id`
|
||||||
|
* `version`
|
||||||
|
* `content`
|
||||||
|
* `content_hash`
|
||||||
|
* `source_snapshot_json`
|
||||||
|
* `rule_snapshot_json`
|
||||||
|
* `generated_at`
|
||||||
|
|
||||||
|
### 用途
|
||||||
|
|
||||||
|
* 预览
|
||||||
|
* diff
|
||||||
|
* 回滚
|
||||||
|
* 调试
|
||||||
|
* 追踪“为什么这次生成结果变了”
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 15. 内部统一节点模型
|
||||||
|
|
||||||
|
建议在解析层统一成一个内部对象。
|
||||||
|
|
||||||
|
### Python 草案
|
||||||
|
|
||||||
|
```python
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
class ProxyNode(BaseModel):
|
||||||
|
name: str
|
||||||
|
type: str
|
||||||
|
server: str
|
||||||
|
port: int
|
||||||
|
udp: bool = True
|
||||||
|
tags: list[str] = []
|
||||||
|
raw: dict[str, Any] = {}
|
||||||
|
```
|
||||||
|
|
||||||
|
对不同类型协议(ss、vmess、vless、trojan、hysteria 等)额外字段可放在 `raw` 里。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 16. 生成流水线
|
||||||
|
|
||||||
|
## 第 1 步:拉取源
|
||||||
|
|
||||||
|
* 读取启用的 sources
|
||||||
|
* 获取原始订阅内容
|
||||||
|
* 更新缓存
|
||||||
|
* 记录同步状态
|
||||||
|
|
||||||
|
## 第 2 步:解析源
|
||||||
|
|
||||||
|
* 解析 base64
|
||||||
|
* 解析单链接
|
||||||
|
* 解析远程订阅
|
||||||
|
* 标准化成统一节点模型
|
||||||
|
|
||||||
|
## 第 3 步:节点处理
|
||||||
|
|
||||||
|
* 去重
|
||||||
|
* 重命名
|
||||||
|
* 按国家/协议/标签分类
|
||||||
|
* 过滤无效节点
|
||||||
|
* 应用 profile 的筛选逻辑
|
||||||
|
|
||||||
|
## 第 4 步:生成策略组
|
||||||
|
|
||||||
|
* 读取 profile 绑定的 policy groups
|
||||||
|
* 根据节点分类与过滤规则生成 `proxy-groups`
|
||||||
|
|
||||||
|
## 第 5 步:加载规则模块
|
||||||
|
|
||||||
|
* 读取 profile 启用的规则模块
|
||||||
|
* 按顺序加载规则文件
|
||||||
|
* 渲染模板变量(如 `target_group`)
|
||||||
|
|
||||||
|
## 第 6 步:组装规则
|
||||||
|
|
||||||
|
* 拼接所有规则模块
|
||||||
|
* 插入 prepend rules
|
||||||
|
* 插入 append rules
|
||||||
|
* 保证 `MATCH` 规则最后输出
|
||||||
|
|
||||||
|
## 第 7 步:生成完整 YAML
|
||||||
|
|
||||||
|
输出包含:
|
||||||
|
|
||||||
|
* mixed-port / socks-port / redir-port / tproxy-port(按需)
|
||||||
|
* mode
|
||||||
|
* log-level
|
||||||
|
* dns
|
||||||
|
* tun
|
||||||
|
* proxies
|
||||||
|
* proxy-groups
|
||||||
|
* rules
|
||||||
|
|
||||||
|
## 第 8 步:缓存与快照
|
||||||
|
|
||||||
|
* 计算 hash
|
||||||
|
* 命中缓存则复用
|
||||||
|
* 否则生成新 artifact
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 17. 输出设计
|
||||||
|
|
||||||
|
### 对外输出接口
|
||||||
|
|
||||||
|
* `/profiles/{id}/clash.yaml`
|
||||||
|
* `/profiles/{id}/download`
|
||||||
|
* `/profiles/{id}/preview`
|
||||||
|
* `/profiles/{id}/head`
|
||||||
|
|
||||||
|
### 输出原则
|
||||||
|
|
||||||
|
* 默认返回完整 YAML
|
||||||
|
* 对客户端透明
|
||||||
|
* 客户端无需理解内部模块化结构
|
||||||
|
|
||||||
|
### 可选响应头
|
||||||
|
|
||||||
|
支持将源站订阅信息透传到最终响应头,例如:
|
||||||
|
|
||||||
|
* `subscription-userinfo`
|
||||||
|
* 其他流量额度相关头
|
||||||
|
|
||||||
|
如果多个源混合:
|
||||||
|
|
||||||
|
* 默认只透传第一个主源的额度信息
|
||||||
|
* 或后续设计聚合策略,但不是当前必做
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 18. API 草案
|
||||||
|
|
||||||
|
## 源管理
|
||||||
|
|
||||||
|
* `GET /api/sources`
|
||||||
|
* `POST /api/sources`
|
||||||
|
* `PUT /api/sources/{id}`
|
||||||
|
* `DELETE /api/sources/{id}`
|
||||||
|
* `POST /api/sources/{id}/test`
|
||||||
|
* `POST /api/sources/{id}/sync`
|
||||||
|
|
||||||
|
## 规则模块
|
||||||
|
|
||||||
|
* `GET /api/rule-modules`
|
||||||
|
* `GET /api/rule-modules/{id}`
|
||||||
|
* `PUT /api/rule-modules/{id}`
|
||||||
|
|
||||||
|
## Profile
|
||||||
|
|
||||||
|
* `GET /api/profiles`
|
||||||
|
* `POST /api/profiles`
|
||||||
|
* `PUT /api/profiles/{id}`
|
||||||
|
* `DELETE /api/profiles/{id}`
|
||||||
|
|
||||||
|
## Profile 规则配置
|
||||||
|
|
||||||
|
* `GET /api/profiles/{id}/rules`
|
||||||
|
* `PUT /api/profiles/{id}/rules`
|
||||||
|
|
||||||
|
## Profile 策略组配置
|
||||||
|
|
||||||
|
* `GET /api/profiles/{id}/policy-groups`
|
||||||
|
* `PUT /api/profiles/{id}/policy-groups`
|
||||||
|
|
||||||
|
## 预览与生成
|
||||||
|
|
||||||
|
* `POST /api/profiles/{id}/preview`
|
||||||
|
* `POST /api/profiles/{id}/generate`
|
||||||
|
* `GET /api/profiles/{id}/artifacts`
|
||||||
|
* `GET /api/artifacts/{id}`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 19. 面板设计原则
|
||||||
|
|
||||||
|
### 普通模式
|
||||||
|
|
||||||
|
允许:
|
||||||
|
|
||||||
|
* 配源
|
||||||
|
* 选 profile
|
||||||
|
* 勾选规则模块
|
||||||
|
* 选择规则模块绑定的策略组
|
||||||
|
* 调模块顺序
|
||||||
|
* 加 prepend / append 规则
|
||||||
|
* 预览生成结果
|
||||||
|
|
||||||
|
### 高级模式
|
||||||
|
|
||||||
|
允许:
|
||||||
|
|
||||||
|
* 编辑少量覆盖配置
|
||||||
|
* 自定义组模板
|
||||||
|
* 导入自定义规则模块
|
||||||
|
|
||||||
|
### 不建议
|
||||||
|
|
||||||
|
* 直接在线编辑整份 ACL4SSR 规则大文件作为主要操作方式
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 20. 示例规则模块
|
||||||
|
|
||||||
|
## `rules/modules/openai.list`
|
||||||
|
|
||||||
|
```text
|
||||||
|
DOMAIN-SUFFIX,openai.com,{{ target_group }}
|
||||||
|
DOMAIN-SUFFIX,chatgpt.com,{{ target_group }}
|
||||||
|
DOMAIN-SUFFIX,oaistatic.com,{{ target_group }}
|
||||||
|
DOMAIN-SUFFIX,auth0.openai.com,{{ target_group }}
|
||||||
|
```
|
||||||
|
|
||||||
|
## `rules/modules/apple.list`
|
||||||
|
|
||||||
|
```text
|
||||||
|
DOMAIN-SUFFIX,apple.com,{{ target_group }}
|
||||||
|
DOMAIN-SUFFIX,icloud.com,{{ target_group }}
|
||||||
|
DOMAIN-SUFFIX,itunes.apple.com,{{ target_group }}
|
||||||
|
DOMAIN-SUFFIX,apps.apple.com,{{ target_group }}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 21. 示例最终输出 YAML 骨架
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
mixed-port: 7890
|
||||||
|
allow-lan: true
|
||||||
|
mode: rule
|
||||||
|
log-level: info
|
||||||
|
|
||||||
|
dns:
|
||||||
|
enable: true
|
||||||
|
ipv6: false
|
||||||
|
nameserver:
|
||||||
|
- 223.5.5.5
|
||||||
|
- 119.29.29.29
|
||||||
|
|
||||||
|
proxies:
|
||||||
|
- name: 香港节点 01
|
||||||
|
type: ss
|
||||||
|
server: 1.2.3.4
|
||||||
|
port: 443
|
||||||
|
cipher: aes-128-gcm
|
||||||
|
password: xxxx
|
||||||
|
|
||||||
|
proxy-groups:
|
||||||
|
- name: 🚀 节点选择
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- 香港节点 01
|
||||||
|
- 日本节点 01
|
||||||
|
- DIRECT
|
||||||
|
|
||||||
|
- name: 🤖 AI
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- 🚀 节点选择
|
||||||
|
- 香港节点 01
|
||||||
|
- 日本节点 01
|
||||||
|
|
||||||
|
rules:
|
||||||
|
- DOMAIN-SUFFIX,openai.com,🤖 AI
|
||||||
|
- DOMAIN-SUFFIX,chatgpt.com,🤖 AI
|
||||||
|
- DOMAIN-SUFFIX,apple.com,🍎 苹果服务
|
||||||
|
- GEOIP,CN,DIRECT
|
||||||
|
- MATCH,🚀 节点选择
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 22. 数据库配置要求
|
||||||
|
|
||||||
|
### 默认
|
||||||
|
|
||||||
|
```env
|
||||||
|
DATABASE_URL=sqlite:///./data/app.db
|
||||||
|
```
|
||||||
|
|
||||||
|
### 未来切 PostgreSQL
|
||||||
|
|
||||||
|
```env
|
||||||
|
DATABASE_URL=postgresql+psycopg://user:pass@postgres:5432/subprovider
|
||||||
|
```
|
||||||
|
|
||||||
|
### 要求
|
||||||
|
|
||||||
|
* 所有数据库访问都走 SQLAlchemy
|
||||||
|
* migration 走 Alembic
|
||||||
|
* 不写死 SQLite 特性到业务逻辑中
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 23. 开发阶段建议
|
||||||
|
|
||||||
|
## 第一阶段:解耦与最小可用
|
||||||
|
|
||||||
|
目标:
|
||||||
|
|
||||||
|
* 先跑通结构
|
||||||
|
|
||||||
|
任务:
|
||||||
|
|
||||||
|
1. 引入 SQLAlchemy + Alembic
|
||||||
|
2. 建 sources / profiles / rule_modules / profile_rule_modules / policy_groups / artifacts 表
|
||||||
|
3. 将现有规则整理为 `rules/modules/*.list`
|
||||||
|
4. 将现有单体生成逻辑拆成 service
|
||||||
|
5. 支持生成一个完整 YAML
|
||||||
|
6. 提供最简预览页面
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 第二阶段:面板化
|
||||||
|
|
||||||
|
目标:
|
||||||
|
|
||||||
|
* 基础可用
|
||||||
|
|
||||||
|
任务:
|
||||||
|
|
||||||
|
1. 源管理页面
|
||||||
|
2. Profile 管理页面
|
||||||
|
3. 规则模块勾选和排序页面
|
||||||
|
4. 策略组配置页面
|
||||||
|
5. 预览和下载页面
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 第三阶段:增强能力
|
||||||
|
|
||||||
|
目标:
|
||||||
|
|
||||||
|
* 更稳定、更可追踪
|
||||||
|
|
||||||
|
任务:
|
||||||
|
|
||||||
|
1. 快照与 diff
|
||||||
|
2. 生成缓存优化
|
||||||
|
3. 同步日志和错误展示
|
||||||
|
4. 自定义规则导入
|
||||||
|
5. 自定义组模板
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 24. 明确不推荐的方向
|
||||||
|
|
||||||
|
1. 不推荐把 ACL4SSR 规则逐条入 SQLite
|
||||||
|
2. 不推荐面板主交互是“编辑一万条规则文本”
|
||||||
|
3. 不推荐一开始就做 rule-provider / proxy-provider 对外发布
|
||||||
|
4. 不推荐 Mongo 作为主配置库
|
||||||
|
5. 不推荐先做复杂权限系统
|
||||||
|
6. 不推荐先做重前端再补业务逻辑
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 25. 给 Codex 的明确执行要求
|
||||||
|
|
||||||
|
请按以下要求重构项目:
|
||||||
|
|
||||||
|
1. 保留对外输出为单个完整 YAML
|
||||||
|
2. 将内部生成逻辑改为模块化流水线
|
||||||
|
3. 规则正文继续使用文件存储
|
||||||
|
4. 使用 SQLite 存储:
|
||||||
|
|
||||||
|
* 源配置
|
||||||
|
* profile 配置
|
||||||
|
* 规则模块元数据
|
||||||
|
* profile 与规则模块的绑定关系
|
||||||
|
* 策略组配置
|
||||||
|
* 生成快照
|
||||||
|
5. 使用 SQLAlchemy + Alembic,数据库 URL 可配置
|
||||||
|
6. 代码结构按 service 分层,避免单文件堆逻辑
|
||||||
|
7. 首先实现最小可运行版本:
|
||||||
|
|
||||||
|
* 能配置 source
|
||||||
|
* 能配置 profile
|
||||||
|
* 能选择规则模块
|
||||||
|
* 能选择目标策略组
|
||||||
|
* 能生成并预览完整 YAML
|
||||||
|
8. 不要实现对外 provider 模式作为默认路线
|
||||||
|
9. 不要将规则正文全文入库
|
||||||
|
10. 不要将面板设计成规则全文编辑器
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 26. 最终一句话总结
|
||||||
|
|
||||||
|
本项目的最终路线是:
|
||||||
|
|
||||||
|
> **内部模块化、缓存化、可配置化**
|
||||||
|
> **对外输出完整单文件 YAML**
|
||||||
|
> **规则正文继续文件维护**
|
||||||
|
> **规则组合关系和面板配置放 SQLite**
|
||||||
|
|
||||||
|
这条路线最符合当前项目阶段,也最稳。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
如果你要,我下一条可以继续给你一份**更像任务单的 Codex 执行拆分版**,我会按“先改哪些文件、再改哪些文件、每步验收什么”来写。
|
||||||
Reference in New Issue
Block a user