Skip to content

Commit 8f13776

Browse files
committed
initial commit
0 parents  commit 8f13776

File tree

4 files changed

+187
-0
lines changed

4 files changed

+187
-0
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
venv
2+
__pycache__
3+
.idea

main.py

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from collections import OrderedDict
2+
3+
import sys
4+
import yaml
5+
import utils
6+
import v1
7+
8+
9+
def main():
10+
utils.setup_order_yaml()
11+
12+
if len(sys.argv) != 2:
13+
print("Argument source required")
14+
return
15+
16+
with open(sys.argv[1], "r") as f:
17+
data: OrderedDict = yaml.load(f, Loader=yaml.Loader)
18+
19+
if data["preprocessor"]["version"] == 1:
20+
result = v1.handle_v1(data)
21+
else:
22+
result = None
23+
print("Unsupported version")
24+
25+
print(yaml.dump(result, default_flow_style=False))
26+
27+
28+
if __name__ == "__main__":
29+
main()

utils.py

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from collections import OrderedDict
2+
3+
import yaml
4+
import yaml.resolver
5+
6+
7+
def setup_order_yaml():
8+
def represent_dict_order(self, data):
9+
return self.represent_mapping('tag:yaml.org,2002:map', data.items())
10+
11+
def constructor_dict_order(self, node):
12+
return OrderedDict(self.construct_pairs(node))
13+
14+
yaml.add_representer(OrderedDict, represent_dict_order)
15+
yaml.add_constructor(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, constructor_dict_order)
16+
17+
18+
class ParseException(Exception):
19+
def __init__(self, message: str):
20+
self.message = message

v1.py

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import requests
2+
import utils
3+
import yaml
4+
import re
5+
6+
from collections import OrderedDict
7+
8+
9+
def handle_v1(data: OrderedDict) -> OrderedDict:
10+
preprocessor: OrderedDict = data["preprocessor"]
11+
12+
if preprocessor is None or preprocessor["version"] != 1:
13+
raise utils.ParseException("Version != 1")
14+
15+
result: OrderedDict = OrderedDict()
16+
17+
general_block: OrderedDict = data["clash-general"]
18+
result.update(general_block)
19+
20+
proxy_sources_dicts: list = data["proxy-sources"]
21+
proxies: list = []
22+
23+
for item in proxy_sources_dicts:
24+
if item["type"] == "url":
25+
proxies += load_url_proxies(item["url"])
26+
elif item["type"] == "file":
27+
proxies += load_file_proxies(item["path"])
28+
elif item["type"] == "plain":
29+
proxies.append(load_plain_proxies(item))
30+
31+
proxy_group_dispatch_dicts: list = data["proxy-group-dispatch"]
32+
proxy_groups: list = []
33+
34+
for item in proxy_group_dispatch_dicts:
35+
group_data: OrderedDict = item.copy()
36+
ps: list = []
37+
38+
black_regex = re.compile(item["proxies-filters"]["black-regex"])
39+
white_regex = re.compile(item["proxies-filters"]["white-regex"])
40+
41+
for p in proxies:
42+
p_name: str = p["name"]
43+
if white_regex.match(p_name) and not black_regex.match(p_name):
44+
ps.append(p_name)
45+
46+
if "flat-proxies" in item:
47+
ps.extend(item["flat-proxies"])
48+
49+
group_data.pop("proxies-filters", None)
50+
group_data.pop("flat-proxies", None)
51+
52+
group_data["proxies"] = ps
53+
54+
proxy_groups.append(group_data)
55+
56+
rule_sets_dicts: list = data["rule-sets"]
57+
rule_sets: dict = {}
58+
59+
if not rule_sets_dicts is None:
60+
for item in rule_sets_dicts:
61+
item_name: str = item["name"]
62+
item_type: str = item["type"]
63+
item_map: dict = {}
64+
65+
for target_map_element in item.get("target-map", {}):
66+
kv: list = target_map_element.split(",")
67+
item_map[kv[0]] = kv[1]
68+
69+
if item_type == "url":
70+
rule_sets[item_name] = load_url_rule_set(item["url"], item_map)
71+
elif item_type == "file":
72+
rule_sets[item_name] = load_file_rule_set(item["path"], item_map)
73+
74+
rules: list = []
75+
76+
for rule in data["rule"]:
77+
if str(rule).startswith("RULE-SET"):
78+
rules.extend(rule_sets[str(rule).split(",")[1]])
79+
else:
80+
rules.append(rule)
81+
82+
result["Proxy"] = proxies
83+
result["Proxy Group"] = proxy_groups
84+
result["Rule"] = rules
85+
86+
return result
87+
88+
89+
def load_url_proxies(url: str) -> OrderedDict:
90+
data = requests.get(url)
91+
data_yaml: OrderedDict = yaml.load(data.content.decode(), Loader=yaml.Loader)
92+
93+
return data_yaml["Proxy"]
94+
95+
96+
def load_file_proxies(path: str) -> OrderedDict:
97+
with open(path, "r") as f:
98+
data_yaml: OrderedDict = yaml.load(f, Loader=yaml.Loader)
99+
100+
return data_yaml["Proxy"]
101+
102+
103+
def load_plain_proxies(data: OrderedDict) -> OrderedDict:
104+
return data["data"]
105+
106+
107+
def load_url_rule_set(url: str, targetMap: dict) -> list:
108+
data = yaml.load(requests.get(url).content, Loader=yaml.Loader)
109+
result: list = []
110+
111+
for rule in data["Rule"]:
112+
original_target = str(rule).split(",")[-1]
113+
map_to: str = targetMap.get(original_target)
114+
if not map_to is None:
115+
result.append(str(rule).replace(original_target, map_to))
116+
else:
117+
result.append(rule)
118+
119+
return result
120+
121+
122+
def load_file_rule_set(path: str, targetMap: dict) -> list:
123+
with open(path, "r") as f:
124+
data = yaml.load(f, Loader=yaml.Loader)
125+
result: list = []
126+
127+
for rule in data["Rule"]:
128+
original_target = str(rule).split(",")[-1]
129+
map_to: str = targetMap.get(original_target)
130+
if not map_to is None:
131+
result.append(str(rule).replace(original_target, map_to))
132+
else:
133+
result.append(rule)
134+
135+
return result

0 commit comments

Comments
 (0)