重构框架 提供更多API 无需json&&新增Surge-RULE-SET转换&&修复singbox转换bug

This commit is contained in:
heinu123 2024-05-12 02:41:51 +08:00
parent 0905aa8429
commit 6cc145b92b
23 changed files with 168 additions and 227 deletions

0
.github/workflows/build.yaml vendored Normal file → Executable file
View File

0
LICENSE Normal file → Executable file
View File

4
README.md Normal file → Executable file
View File

@ -1,8 +1,8 @@
## build
此分支将[rule](./rule)中的 `domain.txt` `domain_regex.txt`基础规则转换
此分支将构建[rule](./rule)中的基础规则
插件文档见[script](./script)
转换插件文档见[script](./script)
添加规则文档见[rule](./rule)

View File

@ -1,20 +0,0 @@
{
"version": "1.4.8",
"out_path": "/out",
"domain_name": "domain.txt",
"regex_name": "domain_regex.txt",
"title": "Title: AWAvenue 秋风广告规则AWAvenue-Ads-Rule\n规则版本: version\n更新时间: format_time\n\n项目地址https://github.com/TG-Twilight/AWAvenue-Ads-Rule\n\n如果需要在其它规则中混合此规则请在您的规则显眼处注明本规则的出处谢谢\n加入Telegram群组 秋風がく山道 (@AWAvenueAdsChat) 与编写者交流,期待着您的到来!\n群组链接https://t.me/AWAvenueAdsChat\n订阅Telegram频道 AWAvenue Ads Rule (@AWAvenueAdsRule) 获取最新公告,期待着您的订阅!\n频道链接https://t.me/AWAvenueAdsRule\n\nThis project is licensed under the Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) license.\n\n倾城极速 - 畅游世界高速互联官网https://wcnmdmht.lol/sb 官网2https://panel.qc02.xyz\n",
"suffix": [
{"name": "AdClose", "suffix": ".txt", "comment": "!"},
{"name": "Adblock", "suffix": ".txt", "comment": "!"},
{"name": "Clash", "suffix": ".yaml", "comment": "#"},
{"name": "hosts", "suffix": ".txt" , "comment": "#"},
{"name": "RouterOS", "suffix": ".txt" , "comment": "#"},
{"name": "Surge", "suffix": ".txt" , "comment": "#"},
{"name": "Singbox", "suffix": ".json" , "comment": "//"},
{"name": "Singbox-regex", "suffix": ".json" , "comment": "//"},
{"name": "QuantumultX", "suffix": ".list" , "comment": "##"},
{"name": "RouterOS-Adlist", "suffix": ".txt" , "comment": "#"},
{"name": "Mosdns_v5", "suffix": ".txt" , "comment": "#"}
]
}

52
main.py
View File

@ -3,40 +3,37 @@ import sys
import json
import importlib
from datetime import datetime
try:
with open("build.json", 'r', encoding="utf-8") as file:
config = json.loads(file.read())
except Exception as e:
print(f"读取json失败: {e}")
sys.exit(1)
global output, domain_file, domain_file, suffix_file, regex_file
current_time = datetime.now()
format_time = current_time.strftime("%Y-%m-%d")
SCRIPT_PATH = os.path.join(os.getcwd(), "script")
RULE_PATH = os.path.join(os.getcwd(), "rule")
OUT_PATH = os.getcwd() + config["out_path"]
domain_file=RULE_PATH + "/" + config["domain_name"]
regex_file=RULE_PATH + "/" + config["regex_name"]
OUT_PATH = os.getcwd() + "/out"
domain_file=RULE_PATH + "/domain.txt"
regex_file=RULE_PATH + "/domain_regex.txt"
ip_file=RULE_PATH + "/ip.txt"
if not os.path.exists(OUT_PATH):
print(f"{OUT_PATH} 目录不存在!")
sys.exit(1)
def WriteFile(name, text):
class RuleList:
def __init__(self, domain_file, regex_file, ip_file):
with open(domain_file, 'r') as file:
self.domain_list = file.readlines()
with open(regex_file, 'r') as file:
self.regex_list = file.readlines()
with open(ip_file, 'r') as file:
self.ip_list = file.readlines()
rule = RuleList(domain_file, regex_file, ip_file)
def WriteFile(name, text, suffix):
try:
for File in config["suffix"]:
if name == File["name"]:
with open(OUT_PATH + "/AWAvenue-Ads-Rule-" + name + File["suffix"], 'w', encoding="utf-8") as file:
title = [File["comment"] + " " + line for line in config["title"].split('\n')]
title = '\n'.join(title)
file.write(title.replace("version", config["version"]).replace("format_time", format_time) + "\n\n")
for line in text:
file.write(line + "\n")
with open(OUT_PATH + "/AWAvenue-Ads-Rule-" + name + suffix, 'w', encoding="utf-8") as file:
for line in text:
file.write(line + "\n")
except Exception as e:
print(f"读取json失败: {e}")
print(f"写入插件:{module_name}执行失败: {e}")
def RunScript():
for filename in os.listdir(SCRIPT_PATH):
@ -45,10 +42,9 @@ def RunScript():
full_module_name = f"script.{module_name}"
try:
module = importlib.import_module(full_module_name)
print(f"正在转换:{module_name}")
module_list = module.build(domain_file, regex_file)
WriteFile(module_name, module_list)
except ImportError as e:
module_list, module_suffix = module.build(rule)
WriteFile(module_name, module_list, module_suffix)
except Exception as e:
print(f"转换插件:{module_name}执行失败: {e}")

4
rule/README.md Normal file → Executable file
View File

@ -6,4 +6,6 @@ fork本分支修改本目录的文件
`domain.txt` 文件为域名列表 一行一个 不会匹配子域名
`domain_regex.txt` 文件为`domain.txt`的正则表达式版本
`domain_regex.txt` 文件为`domain.txt`的正则表达式版本(并不是所有插件都会调用此规则)
`ip.txt` 文件为ip列表(并不是所有插件都会调用此规则)

View File

@ -1,7 +1,4 @@
1010pic.com
123.56.23.22
182.254.116.116
203.205.137.89
8le8le.com
a0.app.xiaomi.com
aaid.umeng.com

3
rule/ip.txt Normal file
View File

@ -0,0 +1,3 @@
123.56.23.22
182.254.116.116
203.205.137.89

19
script/AdClose.py Normal file → Executable file
View File

@ -1,23 +1,18 @@
def format_domain(domain_file):
def format_domain(List):
domain = []
with open(domain_file, 'r') as file:
lines = file.readlines()
for line in lines:
for line in List:
domain_lines = f"{line.strip()}"
domain.append(domain_lines)
return domain
def format_regex(regex_file):
def format_regex(List):
regex = []
with open(regex_file, 'r') as file:
lines = file.readlines()
for line in lines:
for line in List:
regex_lines = f"{line.strip()}"
regex.append(regex_lines)
return regex
def build(domain_file, regex_file):
Adclose_list = format_domain(domain_file) + format_regex(regex_file)
return Adclose_list
def build(rule):
Adclose_list = format_domain(rule.domain_list) + format_regex(rule.regex_list)
return Adclose_list, ".txt"

19
script/Adblock.py Normal file → Executable file
View File

@ -1,23 +1,18 @@
def format_domain(domain_file):
def format_domain(List):
domain = []
with open(domain_file, 'r') as file:
lines = file.readlines()
for line in lines:
for line in List:
domain_lines = f"||{line.strip()}^"
domain.append(domain_lines)
return domain
def format_regex(regex_file):
def format_regex(List):
regex = []
with open(regex_file, 'r') as file:
lines = file.readlines()
for line in lines:
for line in List:
regex_lines = f"/{line.strip()}/".replace("\.","\\\.").replace("\*","\.\*")
regex.append(regex_lines)
return regex
def build(domain_file, regex_file):
Adblock_list = format_domain(domain_file) + format_regex(regex_file)
return Adblock_list
def build(rule):
Adblock_list = format_domain(rule.domain_list) + format_regex(rule.regex_list)
return Adblock_list, ".txt"

19
script/Adguard.py Normal file → Executable file
View File

@ -1,23 +1,18 @@
def format_domain(domain_file):
def format_domain(List):
domain = []
with open(domain_file, 'r') as file:
lines = file.readlines()
for line in lines:
for line in List:
domain_lines = f"||{line.strip()}^"
domain.append(domain_lines)
return domain
def format_regex(regex_file):
def format_regex(List):
regex = []
with open(regex_file, 'r') as file:
lines = file.readlines()
for line in lines:
for line in List:
regex_lines = f"/{line.strip()}/".replace("\.","\\\.").replace("\*","\.\*")
regex.append(regex_lines)
return regex
def build(domain_file, regex_file):
Adguard_list = format_domain(domain_file) + format_regex(regex_file)
return Adguard_list
def build(rule):
Adguard_list = format_domain(rule.domain_list) + format_regex(rule.regex_list)
return Adguard_list, ".txt"

View File

@ -1,23 +1,25 @@
def format_domain(domain_file):
def format_domain(List):
domain = []
with open(domain_file, 'r') as file:
lines = file.readlines()
for line in lines:
for line in List:
domain_lines = f" - '{line.strip()}'"
domain.append(domain_lines)
return domain
def format_regex(regex_file):
def format_regex(List):
regex = []
with open(regex_file, 'r') as file:
lines = file.readlines()
for line in lines:
for line in List:
regex_lines = f" - '{line.strip()}'".replace("$","").replace("^","")
regex.append(regex_lines)
return regex
def build(domain_file, regex_file):
clash_list = ["payload:"] + format_domain(domain_file) + format_regex(regex_file)
return clash_list
def format_ip(List):
ip = []
for line in List:
ip_lines = f" - '{line.strip()}'".replace("$","").replace("^","")
ip.append(ip_lines)
return ip
def build(rule):
clash_list = ["payload:"] + format_ip(rule.ip_list) + format_domain(rule.domain_list) + format_regex(rule.regex_list)
return clash_list, ".yaml"

View File

@ -1,15 +1,12 @@
import json
def format_domain(domain_file):
def format_domain(List):
domain = []
with open(domain_file, 'r') as file:
lines = file.readlines()
for line in lines:
for line in List:
domain_lines = f"domain:{line.strip()}"
domain.append(domain_lines)
return domain
def build(domain_file, regex_file):
return format_domain(domain_file)
def build(rule):
return format_domain(rule.domain_list), ".txt"

24
script/QuantumultX.py Normal file → Executable file
View File

@ -1,22 +1,24 @@
def format_domain(domain_file):
def format_domain(List):
domain = []
with open(domain_file, 'r') as file:
lines = file.readlines()
for line in lines:
for line in List:
domain_lines = f"DOMAIN,{line.strip()},reject"
domain.append(domain_lines)
return domain
def format_regex(regex_file):
def format_regex(List):
regex = []
with open(regex_file, 'r') as file:
lines = file.readlines()
for line in lines:
for line in List:
regex_lines = f"DOMAIN-KEYWORD,{line.strip()},reject".replace("$","").replace("^","").replace("*","")
regex.append(regex_lines)
return regex
def build(domain_file, regex_file):
return format_domain(domain_file) + format_regex(regex_file)
def format_ip(List):
ip = []
for line in List:
ip_lines = f"IP-CIDR,{line.strip()},reject"
ip.append(ip_lines)
return ip
def build(rule):
return format_ip(rule.ip_list) + format_domain(rule.domain_list) + format_regex(rule.regex_list), ".list"

29
script/README.md Normal file → Executable file
View File

@ -1,23 +1,28 @@
## 插件开发文档
插件入口函数为`build()`
插件入口函数为`build(rule)`
参考[Clash.py](./Clash.py)
插件返回的list格式参考下面的模板
插件返回的list格式参考:
`Adguard.py`:
```python
["||xxx.com^","||xxx.cc^"]
["||xxx.com^","||xxx.cc^"], ".txt"
```
> 后缀名以及注释符请在build.json中添加 如果不存在则不执行此插件
> **有两个返回值**
提供的变量:
API:
- rule.domain_list(获取域名列表)
- rule.regex_list(获取正则表达式的域名列表)
- rule.ip_list(获取ip列表)
> 所有变量均为列表 无需读取文件
## domain_file
> 获取 rule目录的 domain.txt 路径
## regex_file
>获取 rule目录的 domain_regex.txt 路径
模板:
```
# 主函数并且引入rule(对象)
def build(rule):
list = rule.domain_list + rule.regex_list + rule.ip_list
return list, ".yaml" # 返回处理后的列表和文件后缀名
```
> 输出文件名=插件名

11
script/RouterOS-Adlist.py Normal file → Executable file
View File

@ -1,15 +1,12 @@
import json
def format_domain(domain_file):
def format_domain(List):
domain = ["0.0.0.0 localhost", "::1 localhost", "", ""]
with open(domain_file, 'r') as file:
lines = file.readlines()
for line in lines:
for line in List:
domain_lines = f"0.0.0.0 {line.strip()}"
domain.append(domain_lines)
return domain
def build(domain_file, regex_file):
return format_domain(domain_file)
def build(rule):
return format_domain(rule.domain_list), ".txt"

30
script/RouterOS.py Normal file → Executable file
View File

@ -1,25 +1,11 @@
import json
def format_domain(domain_file):
domain = []
with open(domain_file, 'r') as file:
lines = file.readlines()
def format_domain(List):
domain = []
for line in List:
domain_line = f"ip dns static add address=240.0.0.1 name={line.strip()}"
domain.append(domain_line)
return domain
for line in lines:
domain_line = f"ip dns static add address=240.0.0.1 name={line.strip()}"
domain.append(domain_line)
return domain
def build(domain_file, regex_file):
return format_domain(domain_file)
if __name__ == '__main__':
domain_file = 'rule/domain.txt'
regex_file = 'rule/domain_regex.txt'
mikrotik_ros= build(domain_file, regex_file)
with open('mikrotik_ros.rsc', 'w') as file:
file.write('\n'.join(mikrotik_ros))
print('生成 mikrotik_ros.rsc 文件成功!')
def build(rule):
return format_domain(rule.regex_list), ".txt"

39
script/Singbox-regex.py Normal file → Executable file
View File

@ -1,48 +1,33 @@
import json
def format_domain(domain_file):
def format_domain(List):
domain = []
with open(domain_file, 'r') as file:
lines = file.readlines()
for line in lines:
for line in List:
domain_lines = f"{line.strip()}"
domain.append(domain_lines)
return domain
def format_suffix(domain_file):
suffix = []
with open(domain_file, 'r') as file:
lines = file.readlines()
for line in lines:
suffix_lines = f".{line.strip()}"
suffix.append(suffix_lines)
return suffix
def format_regex(regex_file):
def format_regex(List):
regex = []
with open(regex_file, 'r') as file:
lines = file.readlines()
for line in lines:
for line in List:
regex_lines = f"{line.strip()}"
regex.append(regex_lines)
return regex
def build(domain_file, regex_file):
domain_list = format_domain(domain_file)
domain_regex_list = format_regex(regex_file)
domain_suffix_list = format_suffix(domain_file)
rule = {
def build(rule):
domain_list = format_domain(rule.domain_list)
regex_list = format_regex(rule.regex_list)
List = {
"version": 1,
"rules": [
{
"domain": domain_list,
"domain_regex": domain_regex_list,
"domain_suffix": domain_suffix_list
"domain_regex": regex_list,
"domain_suffix": []
}
]
}
json_data = json.dumps(rule, indent=2)
return [json_data]
json_data = json.dumps(List, indent=2)
return [json_data], ".json"

25
script/Singbox.py Normal file → Executable file
View File

@ -1,37 +1,24 @@
import json
def format_domain(domain_file):
def format_domain(List):
domain = []
with open(domain_file, 'r') as file:
lines = file.readlines()
for line in lines:
for line in List:
domain_lines = f"{line.strip()}"
domain.append(domain_lines)
return domain
def format_suffix(domain_file):
suffix = []
with open(domain_file, 'r') as file:
lines = file.readlines()
for line in lines:
suffix_lines = f".{line.strip()}"
suffix.append(suffix_lines)
return suffix
def build(domain_file, regex_file):
domain_list = format_domain(domain_file)
domain_suffix_list = format_suffix(domain_file)
def build(rule):
domain_list = format_domain(rule.domain_list)
rule = {
"version": 1,
"rules": [
{
"domain": domain_list,
"domain_regex": [],
"domain_suffix": domain_suffix_list
"domain_suffix": []
}
]
}
json_data = json.dumps(rule, indent=2)
return [json_data]
return [json_data], ".json"

10
script/Surge-DOMAIN-SET.py Executable file
View File

@ -0,0 +1,10 @@
def format_domain(List):
domain = []
for line in List:
domain_lines = f".{line.strip()}"
domain.append(domain_lines)
return domain
def build(rule):
surge_list = format_domain(rule.domain_list)
return surge_list, ".list"

23
script/Surge-RULE-SET.py Executable file
View File

@ -0,0 +1,23 @@
def format_domain(List):
domain = []
for line in List:
domain_lines = f"DOMAIN,{line.strip()},reject"
domain.append(domain_lines)
return domain
def format_regex(List):
regex = []
for line in List:
regex_lines = f"DOMAIN-KEYWORD,{line.strip()},reject".replace("$","").replace("^","").replace("*","")
regex.append(regex_lines)
return regex
def format_ip(List):
ip = []
for line in List:
ip_lines = f"IP-CIDR,{line.strip()},reject"
ip.append(ip_lines)
return ip
def build(rule):
return format_ip(rule.ip_list) + format_domain(rule.domain_list) + format_regex(rule.regex_list), ".list"

View File

@ -1,12 +0,0 @@
def format_domain(domain_file):
domain = []
with open(domain_file, 'r') as file:
lines = file.readlines()
for line in lines:
domain_lines = f".{line.strip()}"
domain.append(domain_lines)
return domain
def build(domain_file, regex_file):
surge_list = format_domain(domain_file)
return surge_list

12
script/hosts.py Normal file → Executable file
View File

@ -1,15 +1,11 @@
import json
def format_domain(domain_file):
def format_domain(List):
domain = ["127.0.0.1 localhost", "::1 localhost", "", ""]
with open(domain_file, 'r') as file:
lines = file.readlines()
for line in lines:
for line in List:
domain_lines = f"127.0.0.1 {line.strip()}"
domain.append(domain_lines)
return domain
def build(domain_file, regex_file):
return format_domain(domain_file)
def build(rule):
return format_domain(rule.domain_list), ".txt"