Skip to content

Instantly share code, notes, and snippets.

@moetayuko
Created July 12, 2019 11:40
Show Gist options
  • Select an option

  • Save moetayuko/53fb977e3e49696a5b179bf5e5fb15bb to your computer and use it in GitHub Desktop.

Select an option

Save moetayuko/53fb977e3e49696a5b179bf5e5fb15bb to your computer and use it in GitHub Desktop.
import base64
import json
import sys
def to_bytes(s):
if bytes != str:
if type(s) == str:
return s.encode('utf-8')
return s
def to_str(s):
if bytes != str:
if type(s) == bytes:
return s.decode('utf-8')
return s
def b64decode(data):
if b':' in data:
return data
if len(data) % 4 == 2:
data += b'=='
elif len(data) % 4 == 3:
data += b'='
return base64.urlsafe_b64decode(data)
def decode_ssr_subscription(ssr_subscription):
ssr_subscription = to_bytes(ssr_subscription)
ssr_profiles = to_str(b64decode(ssr_subscription))
return ssr_profiles.split()
def decode_ssr_profile(ssr_profile):
if ssr_profile[:6] != 'ssr://':
raise ValueError('Invalid SSR profile URI!')
ssr_profile = to_bytes(ssr_profile[6:])
ssr_profile = to_str(b64decode(ssr_profile))
ssr_profile_params = {}
if '/' in ssr_profile:
ssr_profile, extra_params = ssr_profile.split('/', 1)
delimiter_pos = extra_params.find('?')
if delimiter_pos >= 0:
extra_params = extra_params[delimiter_pos + 1:]
extra_params = extra_params.split('&')
for param in extra_params:
k, v = param.split('=', 1)
if k in ['obfsparam', 'protoparam', 'group', 'remarks']:
v = to_str(b64decode(to_bytes(v)))
key_mapping = {'obfsparam': 'obfs_param',
'protoparam': 'protocol_param'}
k = key_mapping.get(k, k)
ssr_profile_params[k] = v
ssr_profile = ssr_profile.split(':')
if len(ssr_profile) != 6:
raise ValueError('Invalid SSR profile configuration!')
ssr_profile_params.update({
'server': ssr_profile[0],
'server_port': int(ssr_profile[1]),
'protocol': ssr_profile[2],
'method': ssr_profile[3],
'obfs': ssr_profile[4],
'password': to_str(b64decode(to_bytes(ssr_profile[5]))),
'local_address': '127.0.0.1',
'local_port': 1080
})
return ssr_profile_params
def to_ss_qt5(ssr_profile_params):
if ssr_profile_params['protocol'] != 'origin':
return None
ss_conf_key = ['method', 'password', 'remarks', 'server', 'server_port']
return dict((k, ssr_profile_params[k]) for k in ss_conf_key if k in ssr_profile_params)
def main():
ssr_subscription_file = sys.argv[1]
with open(ssr_subscription_file) as f:
ssr_subscription = f.read()
ssr_profiles = decode_ssr_subscription(ssr_subscription)
ss_qt5_params = {
'configs': [],
'localPort': 1080,
'shareOverLan': False
}
for ssr_profile in ssr_profiles:
ssr_profile_params = decode_ssr_profile(ssr_profile)
ss_profile_params = to_ss_qt5(ssr_profile_params)
if ss_profile_params is not None:
ss_qt5_params['configs'].append(ss_profile_params)
with open('gui-config.json', 'w') as f:
json.dump(ss_qt5_params, f, indent=4,
sort_keys=True, ensure_ascii=False)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment