Last active
March 9, 2024 18:49
-
-
Save puttin/e53d5303941c38af20260bd5f3c493a3 to your computer and use it in GitHub Desktop.
parse SSR subscribe to Surge Mac External list
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 sys | |
import requests | |
import base64 | |
# https://github.com/shadowsocksr-backup/shadowsocks-rss/wiki/SSR-QRcode-scheme | |
# usage: $0 https://example.com/list '/usr/local/bin/ss-local' | |
subscribe_url = sys.argv[1] | |
exec_path = sys.argv[2] | |
# https://stackoverflow.com/a/16891418/1298043 | |
def remove_prefix(text, prefix): | |
if text.startswith(prefix): | |
return text[len(prefix):] | |
return text # or whatever | |
# modified from https://stackoverflow.com/a/9807138/1298043 | |
def urlsafe_b64decode_fix_padding(str): | |
data = str.encode('utf-8') | |
missing_padding = len(data) % 4 | |
if missing_padding != 0: | |
data += b'='* (4 - missing_padding) | |
return base64.urlsafe_b64decode(data).decode("utf-8") | |
def get_subscribe_list(url): | |
# request | |
request = requests.get(url) | |
response_text = request.text | |
# decode | |
decoded_response_text = urlsafe_b64decode_fix_padding(response_text) | |
lists = decoded_response_text.splitlines() | |
return lists | |
def parse_optional_params(str): | |
lists = str.split('&') | |
results = {} | |
for item in lists: | |
splitted = item.split('=') | |
if len(splitted) == 2: | |
decoded_value = urlsafe_b64decode_fix_padding(splitted[1]) | |
results[ splitted[0] ] = decoded_value | |
return results | |
def parse_list(lists): | |
results = [] | |
for item in lists: | |
encoded_config = remove_prefix(item, "ssr://") | |
config = urlsafe_b64decode_fix_padding(encoded_config) | |
# print(config) | |
splitted = config.split('/?') | |
key_params = splitted[0].split(':') | |
# print(key_params) | |
optional_params = None | |
if len(splitted) > 1: | |
optional_params = parse_optional_params(splitted[1]) | |
# print(optional_params) | |
results.append([key_params, optional_params]) | |
return results | |
def parse_to_Surge_External_list(servers, exec_path): | |
i = 1 | |
local_port = 24000 | |
lists = [] | |
for server in servers: | |
key_params = server[0] | |
optional_params = server[1] | |
remarks = group = obfsparam = protoparam = None | |
if optional_params is not None: | |
remarks = optional_params['remarks'] | |
group = optional_params['group'] | |
obfsparam = optional_params['obfsparam'] | |
protoparam = optional_params['protoparam'] | |
name = 'Server '+str(i) | |
if remarks is not None and group is not None: | |
name = group+' '+remarks | |
# print(name) | |
line = name + ' = external, exec = "' + exec_path + '", ' | |
# https://github.com/shadowsocksr-backup/shadowsocksr/blob/manyuser/shadowsocks/shell.py#L175 | |
# https://github.com/shadowsocksr-backup/shadowsocksr-libev/blob/master/src/local.c#L1549 | |
line += 'args = "-s", args = "' + key_params[0] + '", ' # server | |
line += 'args = "-p", args = "' + key_params[1] + '", ' # server_port | |
line += 'args = "-O", args = "' + key_params[2] + '", ' # protocol | |
line += 'args = "-m", args = "' + key_params[3] + '", ' # method | |
line += 'args = "-o", args = "' + key_params[4] + '", ' # obfs | |
line += 'args = "-k", args = "' + urlsafe_b64decode_fix_padding(key_params[5]) + '", ' # password | |
if protoparam is not None: # protocol_param | |
line += 'args = "-G", args = "' + protoparam + '", ' | |
if obfsparam is not None: # obfs_param | |
line += 'args = "-g", args = "' + obfsparam + '", ' | |
line += 'args = "-l", args = "' + str(local_port) + '", ' # local_port | |
# line += 'args = "-t", args = "' + str(60) + '", ' # timeout | |
line += 'local-port = ' + str(local_port) | |
# print(line) | |
lists.append(line) | |
i += 1 | |
local_port += 1 | |
return lists | |
encoded_ssr_url_list = get_subscribe_list(subscribe_url) | |
ssr_servers = parse_list(encoded_ssr_url_list) | |
print(ssr_servers) | |
print('---------') | |
Surge_External_list = parse_to_Surge_External_list(ssr_servers, exec_path) | |
# print(Surge_External_list) | |
for item in Surge_External_list: | |
print(item) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment