Skip to content

Commit 98c71e9

Browse files
committed
添加读取原始规则的合法性 有效性校验以及修复之前的部分错误,对dns层拦截的插件添加ipv6屏蔽兼容
1 parent 6a85fec commit 98c71e9

File tree

11 files changed

+119
-64
lines changed

11 files changed

+119
-64
lines changed

.github/workflows/build.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ jobs:
2424
git clone "https://${{ github.actor }}:${{ secrets.TOKEN }}@github.com/${{ github.repository }}" -b build build
2525
cd build
2626
mkdir out
27+
pip install -r requirements.txt
2728
python main.py
2829
cd out
2930
mkdir Filters

config.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import os
2+
import dns.resolver
3+
24

35
SCRIPT_PATH = os.path.join(os.getcwd(), "script") # 插件文件夹
46
RULE_PATH = os.path.join(os.getcwd(), "rule") # 规则文件夹
@@ -8,21 +10,21 @@
810
ip_file=RULE_PATH + "/ip.txt" # IP规则文件
911
ip6_file=RULE_PATH + "/ip6.txt" # IPv6规则文件
1012

11-
if not os.path.exists(OUT_PATH) or not os.path.exists(OUT_PATH):
12-
print("插件或者规则目录不存在!")
13-
exit(1)
14-
if not os.path.exists(OUT_PATH):
15-
os.makedirs(OUT_PATH)
1613

17-
class RuleList:
18-
# 初始化规则列表
19-
def __init__(self, domain_file, regex_file, ip_file, ip6_file):
20-
with open(domain_file, 'r') as file:
21-
self.domain_list = sorted(set(line.strip() for line in file))
22-
with open(regex_file, 'r') as file:
23-
self.regex_list = sorted(set(line.strip() for line in file))
24-
with open(ip_file, 'r') as file:
25-
self.ip_list = sorted(set(line.strip() for line in file))
26-
with open(ip6_file, 'r') as file:
27-
self.ip6_list = sorted(set(line.strip() for line in file))
28-
rule = RuleList(domain_file, regex_file, ip_file, ip6_file)
14+
def check_domain(domain):
15+
try:
16+
resolver = dns.resolver.Resolver()
17+
resolver.nameservers = ['8.8.8.8', '1.1.1.1', '223.5.5.5', '9.9.9.9', '94.140.14.140']
18+
resolver.timeout = 1
19+
resolver.lifetime = 5
20+
21+
A = resolver.resolve(domain, "A", raise_on_no_answer=False)
22+
AAAA = resolver.resolve(domain, "AAAA", raise_on_no_answer=False)
23+
# 返回包含 A 和 AAAA 记录的字典
24+
return {"A": bool(A.rrset), "AAAA": bool(AAAA.rrset)}
25+
except dns.resolver.NXDOMAIN:
26+
print(f"未查询到 {domain} 的解析记录")
27+
return {"A": False, "AAAA": False}
28+
except Exception as e:
29+
print(f"查询 {domain} 时发生错误: {e}")
30+
return {"A": False, "AAAA": False}

main.py

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import re
12
import os
3+
import config
24
import importlib
35
import subprocess
4-
from config import *
6+
import concurrent.futures
57
from datetime import datetime
68

79

@@ -15,9 +17,65 @@ def get_latest_git_tag(): # 获取最新的git tag
1517
else:
1618
return None
1719

20+
21+
class RuleList:
22+
def __init__(self, domain_file, regex_file, ip_file, ip6_file):
23+
self.domain_list, self.domainv6_list = self.domain_file(domain_file)
24+
self.regex_list = self.regex_file(regex_file)
25+
self.ip_list = self.ip_file(ip_file)
26+
self.ip6_list = self.ip6_file(ip6_file)
27+
28+
29+
## 以下内容由deepseek提供技术支持(bushi
30+
31+
def domain_file(self, filename):
32+
with open(filename, 'r') as file:
33+
domains = {line.strip() for line in file}
34+
35+
valid_domains = set()
36+
valid_domains_v6 = set()
37+
with concurrent.futures.ThreadPoolExecutor(max_workers=50) as executor:
38+
future_to_domain = {executor.submit(config.check_domain, domain): domain for domain in domains}
39+
for future in concurrent.futures.as_completed(future_to_domain):
40+
domain = future_to_domain[future]
41+
result = future.result()
42+
if result["A"] or result["AAAA"]:
43+
valid_domains.add(domain)
44+
if result["AAAA"]:
45+
valid_domains_v6.add(domain)
46+
return sorted(valid_domains), sorted(valid_domains_v6)
47+
48+
def regex_file(self, filename):
49+
with open(filename, 'r') as file:
50+
return sorted({line.strip() for line in file})
51+
52+
def ip_file(self, filename):
53+
ipv4_pattern = re.compile(r'^(\d{1,3}\.){3}\d{1,3}$')
54+
ips = set()
55+
with open(filename, 'r') as file:
56+
for line in file:
57+
ip = line.strip()
58+
if ipv4_pattern.match(ip):
59+
parts = ip.split('.')
60+
if all(0 <= int(part) <= 255 for part in parts):
61+
ips.add(ip)
62+
return sorted(ips)
63+
64+
def ip6_file(self, filename):
65+
ipv6_pattern = re.compile(r'^([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}$')
66+
ips = set()
67+
with open(filename, 'r') as file:
68+
for line in file:
69+
ip = line.strip()
70+
if ipv6_pattern.match(ip):
71+
ips.add(ip)
72+
return sorted(ips)
73+
74+
75+
1876
def WriteFile(name, text, suffix, comment, module_total): # 写入文件
1977
try:
20-
with open(OUT_PATH + "/AWAvenue-Ads-Rule-" + name + suffix, 'w', encoding="utf-8") as file:
78+
with open(config.OUT_PATH + "/AWAvenue-Ads-Rule-" + name + suffix, 'w', encoding="utf-8") as file:
2179

2280
if comment != "":
2381
now = datetime.now()
@@ -43,13 +101,16 @@ def WriteFile(name, text, suffix, comment, module_total): # 写入文件
43101

44102

45103
def RunScript():
46-
for filename in os.listdir(SCRIPT_PATH): # 遍历script目录下的所有文件
104+
rule = RuleList(config.domain_file, config.regex_file, config.ip_file, config.ip6_file)
105+
config.rule = rule
106+
107+
for filename in os.listdir(config.SCRIPT_PATH): # 遍历script目录下的所有文件
47108
if filename.endswith(".py"):
48109
plugins_name = filename[:-3]
49110
full_plugins_name = f"script.{plugins_name}" # 拼接完整的插件名
50111

51112
try:
52-
plugins = importlib.import_module(full_plugins_name).build(rule) # 传入规则列表(config.RuleList)类的实例
113+
plugins = importlib.import_module(full_plugins_name).build(rule=rule) # 传入规则列表(config.RuleList)类的实例
53114

54115
if plugins['list'] == True:
55116
print(f"{plugins_name}转换成功")
@@ -67,5 +128,9 @@ def RunScript():
67128

68129
if __name__ == "__main__":
69130

70-
131+
if not os.path.exists(config.RULE_PATH) or not os.path.exists(config.SCRIPT_PATH):
132+
print("插件或者规则目录不存在!")
133+
exit(1)
134+
if not os.path.exists(config.OUT_PATH):
135+
os.makedirs(config.OUT_PATH)
71136
RunScript()

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dnspython

script/Dnsmasq.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11

2-
def format_domain(List):
2+
def format_domain(List, Listv6):
33
domain = []
44
for line in List:
55
domain_lines = f"address=/{line.strip()}/0.0.0.0"
66
domain.append(domain_lines)
7+
8+
for line in Listv6:
9+
domain_lines = f"address=/{line.strip()}/::"
10+
domain.append(domain_lines)
711
return domain
812

913

1014
def build(rule):
11-
return {'list': format_domain(rule.domain_list), 'suffix': '.conf', 'comment': '#', 'total': len(rule.domain_list)}
15+
return {'list': format_domain(rule.domain_list, rule.domainv6_list), 'suffix': '.conf', 'comment': '#', 'total': len(rule.domain_list)}

script/README.md

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,40 +14,10 @@
1414
1515
API:
1616
- rule.domain_list(获取域名列表)
17+
- rule.domain_v6_list(获取支持ipv6域名列表)
1718
- rule.regex_list(获取正则表达式的域名列表)
1819
- rule.ip_list(获取ip列表)
1920
- rule.ip6_list(获取ipv6列表)
2021

2122
> 所有变量均为列表 也可以导入config.py获取
22-
23-
模板:
24-
```python
25-
26-
def format_domain(List): # 转换域名规则
27-
domain = []
28-
for line in List:
29-
domain_lines = f" - DOMAIN,{line.strip()}"
30-
domain.append(domain_lines)
31-
return domain
32-
33-
def format_regex(List): # 转换正则表达式规则
34-
regex = []
35-
for line in List:
36-
regex_lines = f" - DOMAIN-REGEX,'{line.strip()}'"
37-
regex.append(regex_lines)
38-
return regex
39-
40-
def format_ip(List): # 转换ip列表
41-
ip = []
42-
for line in List:
43-
ip_lines = f" - IP-CIDR,{line.strip()}"
44-
ip.append(ip_lines)
45-
return ip
46-
47-
def build(rule): # 入口函数
48-
clash_list = ["payload:"] + format_ip(rule.ip_list) + format_domain(rule.domain_list) + format_regex(rule.regex_list)
49-
return clash_list, ".yaml", "#", len(clash_list)
50-
#
51-
52-
```
53-
> 输出文件名=插件名
23+
输出文件名=插件名

script/RouterOS-Adlist.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import json
22

3-
def format_domain(List):
3+
def format_domain(List, Listv6):
44
domain = ["0.0.0.0 localhost", "::1 localhost", "", ""]
55
for line in List:
66
domain_lines = f"0.0.0.0 {line.strip()}"
77
domain.append(domain_lines)
8+
9+
for line in Listv6:
10+
domain_lines = f":: {line.strip()}"
11+
domain.append(domain_lines)
812
return domain
913

1014

1115
def build(rule):
12-
return {'list': format_domain(rule.domain_list), 'suffix': '.txt', 'comment': '#', 'total': len(rule.domain_list)}
16+
return {'list': format_domain(rule.domain_list, rule.domainv6_list), 'suffix': '.txt', 'comment': '#', 'total': len(rule.domain_list)}

script/RouterOS.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
import json
22

3-
def format_domain(List):
3+
def format_domain(List, Listv6):
44
domain = []
55
for line in List:
66
domain_line = f"ip dns static add address=240.0.0.1 name={line.strip()}"
77
domain.append(domain_line)
8+
9+
for line in Listv6:
10+
domain_line = f"ip dns static add address=:: name={line.strip()}"
11+
domain.append(domain_line)
812
return domain
913

1014
def build(rule):
11-
return {'list': format_domain(rule.domain_list), 'suffix': '.txt', 'comment': '!', 'total': len(rule.regex_list)}
15+
return {'list': format_domain(rule.domain_list, rule.domainv6_list), 'suffix': '.txt', 'comment': '!', 'total': len(rule.regex_list)}

script/Singbox-regex.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@ def build(rule):
3030
}
3131

3232
json_data = [json.dumps(List, indent=2)]
33-
return {'list': json_data, 'suffix': '.json', 'comment': '//', 'total': len(json_data)}
33+
return {'list': json_data, 'suffix': '.json', 'comment': '', 'total': len(json_data)}

script/Singbox.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ def build(rule):
2121
}
2222

2323
json_data = [json.dumps(rule, indent=2)]
24-
return {'list': json_data, 'suffix': '.json', 'comment': '//', 'total': len(json_data)}
24+
return {'list': json_data, 'suffix': '.json', 'comment': '', 'total': len(json_data)}

0 commit comments

Comments
 (0)