Created
May 3, 2019 17:50
-
-
Save ZeppLu/9c955d56799a7081f09bad0968a14956 to your computer and use it in GitHub Desktop.
Convert the famous https://github.com/h2y/Shadowrocket-ADBlock-Rules to V2Ray routing rules, in JSON format.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import json | |
import requests | |
# usage: ./h2y_to_v2ray.py > rules.json | |
# then open rules.json, there's a list of RuleObjects, copy N' paste, enjoy! | |
SR_CONF_URL = "https://raw.githubusercontent.com/h2y/Shadowrocket-ADBlock-Rules/master/sr_top500_banlist_ad.conf" | |
PROXY_TAG = "proxy" | |
BLOCK_TAG = "block" | |
INDENT = 2 | |
INIT_LEVEL = 2 | |
def parse(sr_conf): | |
""" | |
a simple shadowrocket config file parser, which returns [Rule] section only | |
""" | |
# all states: "before rule", "in rule", "after rule" | |
# I'm too lazy to use an enum | |
state = "before rule" | |
next_state = "before rule" | |
# I'm too lazy to use a dataframe, too | |
sr_rules = { | |
"DOMAIN-SUFFIX": { "Reject": [], "Proxy" : [], }, | |
"DOMAIN-KEYWORD": { "Reject": [], "Proxy" : [], }, | |
"IP-CIDR": { "Reject": [], "Proxy" : [], } | |
} | |
for line in sr_conf.split('\n'): | |
if state == "before rule": | |
if line == "[Rule]": | |
next_state = "in rule" | |
elif state == "in rule": | |
if line.startswith(('#', 'FINAL')): # ignore comment and default rule | |
pass | |
elif not line: # ignore empty line | |
pass | |
elif line[0] == '[': # new section | |
next_state = "after rule" | |
else: | |
[match_method, target, outbound] = line.split(',') | |
sr_rules[match_method][outbound].append(target) | |
elif state == "after rule": | |
pass | |
else: | |
raise | |
state = next_state | |
return sr_rules | |
def convert(sr_rules): | |
""" | |
convert shadowrocket rules to v2ray rules | |
""" | |
process = lambda domain_suffix: "domain:" + domain_suffix.strip('.') | |
v2_rules = [ | |
{ | |
"domain": (sr_rules['DOMAIN-KEYWORD']['Reject'] + | |
[process(d) for d in sr_rules['DOMAIN-SUFFIX']['Reject']]), | |
"outboundTag": BLOCK_TAG, | |
"type": "field" | |
}, | |
{ | |
"domain": (sr_rules['DOMAIN-KEYWORD']['Proxy'] + | |
[process(d) for d in sr_rules['DOMAIN-SUFFIX']['Proxy']]), | |
"outboundTag": PROXY_TAG, | |
"type": "field" | |
}, | |
{ | |
"ip": sr_rules['IP-CIDR']['Reject'], | |
"outboundTag": BLOCK_TAG, | |
"type": "field" | |
}, | |
{ | |
"ip": sr_rules['IP-CIDR']['Proxy'], | |
"outboundTag": PROXY_TAG, | |
"type": "field" | |
}, | |
] | |
return v2_rules | |
def main(): | |
r = requests.get(SR_CONF_URL) | |
if r.status_code != 200: | |
raise | |
sr_conf = r.text | |
sr_rules = parse(sr_conf) | |
v2_rules = convert(sr_rules) | |
rule_objects = json.dumps(v2_rules, indent=INDENT) | |
for line in rule_objects.split('\n'): | |
print(" "*(INDENT*INIT_LEVEL) + line) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment