A simple cli for n3ro
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

97 行
3.5KB

  1. import base64
  2. import csv
  3. import sys
  4. import os
  5. import urllib.request
  6. from urllib.parse import parse_qs
  7. class N3ROCLI:
  8. def __init__(self):
  9. self.config_path = os.path.expanduser('~/.config/n3ro-cli')
  10. self.ssr_command = f"python {self.config_path}/shadowsocksr/shadowsocks/local.py"
  11. self.url_path = os.path.join(self.config_path, 'url')
  12. self.cache_path = os.path.join(self.config_path, 'cache')
  13. self.subscribe_url = self.read_url()
  14. os.makedirs(self.config_path, exist_ok=True)
  15. def read_url(self):
  16. path_ok = os.path.exists(self.url_path)
  17. if path_ok:
  18. with open(self.url_path) as u:
  19. url = u.read()
  20. return url
  21. else:
  22. return None
  23. def decode_str(self, s, to_str=True):
  24. paddings = 4 - len(s) % 4
  25. padded_s = f"{s}{'='*paddings}"
  26. decoded = base64.urlsafe_b64decode(padded_s)
  27. if to_str:
  28. decoded = str(decoded, encoding='utf-8')
  29. return decoded
  30. def sync(self):
  31. if not self.subscribe_url:
  32. print("add a ssr subscribe url in ~/.config/n3ro-cli/url")
  33. else:
  34. with urllib.request.urlopen(self.subscribe_url) as resp:
  35. data = str(resp.read(), encoding='utf-8')
  36. ssr_urls = self.decode_str(data).strip().split('\n')
  37. ssr_paths = (self.decode_str(u[6:]) for u in ssr_urls)
  38. with open(self.cache_path, 'w') as c:
  39. fields = ['id', 'info', 'args']
  40. server_writer = csv.DictWriter(c, fieldnames=fields)
  41. server_writer.writeheader()
  42. for n, p in enumerate(ssr_paths):
  43. path, params = p.split('/?')
  44. d = self.decode_str
  45. host, port, proto, enc, obfs, passwd = path.split(':')
  46. raw_passwd = d(passwd)
  47. parsed_params = parse_qs(params)
  48. obfs_param = parsed_params.get('obfsparam', '')
  49. if obfs_param:
  50. obfs_param = d(obfs_param)
  51. proto_param = parsed_params.get('proto_param', '')
  52. if proto_param:
  53. proto_param = d(proto_param)
  54. name = d(parsed_params.get('remarks', ''),
  55. to_str=False).decode()
  56. group = d(parsed_params.get('group', ''),
  57. to_str=False).decode()
  58. args = f"-s {host} -p {port} -k {raw_passwd} -m {enc} -O {proto} -o {obfs} -b 127.0.0.1 -l 1080"
  59. if obfs_param:
  60. args = f"{args} -g {obfs_param}"
  61. if proto_param:
  62. args = f"{args} -G {proto_param}"
  63. server_writer.writerow({'id': n,
  64. 'args': args,
  65. 'info': f"{name} {group}"})
  66. def conn(self, node_id):
  67. with open(self.cache_path) as c:
  68. reader = csv.DictReader(c)
  69. ssr_args = None
  70. for row in reader:
  71. if row['id'] == str(node_id):
  72. ssr_args = row['args']
  73. os.system(f"{self.ssr_command} {ssr_args}")
  74. def ls(self):
  75. with open(self.cache_path) as c:
  76. reader = csv.DictReader(c)
  77. for row in reader:
  78. s = f"{row['id']}:{row['info']} "
  79. sys.stdout.write(s)
  80. cli = N3ROCLI()
  81. ls = cli.ls
  82. l = cli.ls
  83. conn = cli.conn
  84. c = cli.conn
  85. sync = cli.sync
  86. s = cli.sync