def line2dict(line: str): """ Convert text line to dict. :param str line: Text line :return: dict """ r = dict() try: t = list_fn.remove(line.split(' ')) length = len(t) if 3 <= length: r['protocol'] = t[0] r['host'] = t[1] r['port'] = int(t[2]) if 5 <= length: r['username'] = t[3] r['password'] = t[4] except Exception as e: cp.error('[proxy_fn] {}'.format(e)) return None if not r: cp.error('[proxy_fn] Cannot parse a proxy from string: "{}"'.format(line)) return None return r
def dict2string(proxy: dict): """ Convert a proxy dict to string. :param dict proxy: Proxy dict :return: str or None """ length = len(proxy) try: if 5 <= length: return '{protocol}://{username}:{password}@{host}:{port}'.format( protocol=proxy['protocol'], username=proxy['username'], password=proxy['password'], host=proxy['host'], port=proxy['port'], ) elif 3 <= length: return '{protocol}://{host}:{port}'.format( protocol=proxy['protocol'], host=proxy['host'], port=proxy['port'], ) except Exception as e: cp.error('[proxy_fn] {}'.format(e)) return None cp.error('[proxy_fn] Cannot parse a proxy from dict: {}'.format(proxy)) return None
def dict2pyrogram_dict(proxy: dict): """ Convert a proxy dict for pyrogram. :param dict proxy: Proxy dict :return: dict or None """ try: if proxy['protocol'] == 'socks5': length = len(proxy) if 5 <= length: return { 'hostname': proxy['host'], 'port': proxy['port'], 'username': proxy['username'], 'password': proxy['password'], } elif 3 <= length: return { 'hostname': proxy['host'], 'port': proxy['port'], } except Exception as e: cp.error('[proxy_fn] {}'.format(e)) return None cp.error('[proxy_fn] Cannot parse a proxy from dict: {}'.format(proxy)) return None
def __init__( self, path_to_python: str = None, path_to_python_ssr: str = None, ): self._path_to_python = path_to_python or '/usr/bin/python3' self._path_to_python_ssr = path_to_python_ssr or '/data/repo/shadowsocksr/shadowsocks/local.py' if not os.path.exists(self._path_to_python_ssr): cp.error('"{}" does not exists.'.format(self._path_to_python_ssr)) exit() self._server = None self._port = None self._method = None self._password = None self._protocol = None self._proto_param = None self._obfs = None self._obfs_param = None self._remarks = None self._group = None self._server_ip = None self._server_domain = None self._local_address = None self._local_port = None self._path_to_ssr_conf = None self._exit_ip = None self._cmd = None self._sub_progress = None pass
def pc4_conf_file(self): if os.path.exists(self._cfg['ssr_utils.path_to_pre_proxy']): path_to_pc4_conf_file = os.path.join(tempfile.gettempdir(), 'ssr_utils_pc4.conf') if os.path.exists(path_to_pc4_conf_file) and \ time.time() - os.stat(path_to_pc4_conf_file).st_mtime \ < self._cfg['ssr_utils.proxychains4_cache_time']: return path_to_pc4_conf_file lines = file_fn.read_to_list(self._cfg['ssr_utils.path_to_pre_proxy']) if lines: lines = list_fn.unique(lines) for line in lines: requests_proxies = proxy_fn.line2requests_proxies(line) # valid, and generate pc4 conf try: ip = ip_query.ip_query(requests_proxies=requests_proxies) if ip: g = proxychains_conf_generator.Generator( proxy=line, quiet_mode=True, ) return g.write(path_to_conf=path_to_pc4_conf_file) except Exception as e: cp.error(e) pass cp.error('No available proxy in "{}". Remove it if do not need a proxy.'.format( self._cfg['ssr_utils.path_to_pre_proxy'], )) cp.ex() return None
def get_list_from(path_to_file: str, comment: str = '#'): """ Read the file, and returns a list of the valid lines. :param str path_to_file: /path/to/file :param str comment: Allow comment, ignore the lines which is starts with '#' as default :return: list """ rows = list() if os.path.exists(path_to_file): for _line in open(path_to_file).readlines(): _line = _line.strip() if _line: if comment: if not _line.startswith(comment): rows.append(_line) else: rows.append(_line) return rows import cli_print as cp cp.error('"{}" does not exist.'.format(path_to_file)) return rows
def requests_get_json(url: str, requests_proxies: dict = None, timeout: int = TIMEOUT): """ Get data and convert to json. :param url: URL :param requests_proxies: ... :param timeout: ... :return: json object or None """ try: resp = requests.get( url, proxies=requests_proxies, timeout=timeout, ) if 200 == resp.status_code: return resp.json() else: cp.error('[ip_query] requests.status_code: {}'.format( resp.status_code)) return None except Exception as e: cp.error('[ip_query] {}'.format(e)) return None
def main(): if "SUB_URL" in os.environ: cp.about_to("获取到 sub订阅号", os.environ.get("SUB_URL")) sub_file(os.environ.get("SUB_URL")) return if "SSR_URL" in os.environ: cp.about_to("获取到 ssr服务器地址", os.environ.get("SSR_URL")) ssr_file(os.environ.get("SSR_URL")) return cp.error("无法获取服务配置参数 SUB_URL SSR_URL ")
def __ip_query(self, hint: str): cp.about_t('Start a sub progress of SSR', hint) # sub progress self._sub_progress = subprocess.Popen( self._cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid, ) # Group PID gpid = os.getpgid(self._sub_progress.pid) cp.wr(cp.Fore.LIGHTYELLOW_EX + '(G)PID {}:{} '.format(gpid, self.local_port)) # wait, during the progress launching. for i in range(0, 5): cp.wr(cp.Fore.LIGHTBLUE_EX + '.') cp.fi() time.sleep(1) cp.success(' Next.') # Request for IP ip = None try: cp.about_t('Try to request for the IP address') ip = ip_query.ip_query(requests_proxies=proxy_fn.requests_proxies( host=self.local_address, port=self.local_port, )) if ip: cp.success('{} {}'.format(ip['ip'], ip['country'])) else: cp.fx() except Exception as e: # ConnectionError? cp.fx() cp.error(e) finally: cp.about_t('Kill SSR sub progress', 'PID {pid}'.format(pid=gpid)) os.killpg(gpid, 9) cp.success('Done.') if ip: self._exit_ip = ip return ip return None
def url(self, url: str): self.__reset_attributes() r = url.split('://') try: if r[0] == 'ssr': self.__parse_ssr(r[1]) elif r[0] == 'ss': self.__parse_ss(r[1]) except Exception as e: cp.error(e) pass
def get_sms(self, mobile=None, item_id=None): """ Get the SMS :param mobile: :param item_id: :return: """ mobile = mobile or self._mobile item_id = item_id or self._item_id if self._cli: cp.watching('Getting SMS') # get sms query = { 'action': 'getsms', 'token': self._token, 'itemid': item_id, 'mobile': mobile, 'release': 1, } started_at = time.time() while True: now = time.time() # try to get sms r = self._req_text(query=query) # success if r.split('|')[0] == 'success': txt = r.split('|')[1] if self._cli: cp.wr(cp.Fore.LIGHTBLACK_EX + ' {}'.format(txt)) cp.fx() return txt # error if '3001' != r: self._raise(r) # timed out -> release mobile if (now - started_at) > self._sms_wait_max: cp.wr(' ') if self._cli: cp.error(' TIMED OUT.') self.release_mobile() return False time.sleep(self._sms_interval) if self._cli: cp.step()
def read(path_to_file: str): """ Read the file, and returns the content directly. :param str path_to_file: /path/to/file :return: """ if os.path.exists(path_to_file): with open(path_to_file, 'r') as f: return f.read().strip() import cli_print as cp cp.error('"{}" does not exist.'.format(path_to_file)) return None
def invalid_attributes(self): keys = [ 'server', 'port', 'method', 'password', 'protocol', 'obfs', ] for key in keys: if not getattr(self, key): cp.error('Attribute `{}` is invalid.'.format(key)) return True return False
def geoip(ip_address, country_mmdb: str = None, asn_mmdb: str = None): """ GeoLite2 https://dev.maxmind.com/geoip/geoip2/geolite2/ :param ip_address: :param country_mmdb: :param asn_mmdb: :return: dict or None """ data = IP_DICT.copy() data['ip'] = ip_address try: mmdb_dir = os.path.dirname(os.path.abspath(__file__)) # country if country_mmdb and os.path.exists(country_mmdb): path_to_country_mmdb = country_mmdb else: path_to_country_mmdb = os.path.join(mmdb_dir, 'GeoLite2-Country.py') with geoip2.database.Reader(path_to_country_mmdb) as reader: resp = reader.country(ip_address) data['country'] = resp.country.name data['country_code'] = resp.country.iso_code # asn if asn_mmdb and os.path.exists(asn_mmdb): path_to_asn_mmdb = asn_mmdb else: path_to_asn_mmdb = os.path.join(mmdb_dir, 'GeoLite2-ASN.py') with geoip2.database.Reader(path_to_asn_mmdb) as reader: resp = reader.asn(ip_address) data['asn'] = resp.autonomous_system_number data['aso'] = resp.autonomous_system_organization return data except Exception as e: cp.error('[ip_query] geoip: {}'.format(e)) return None
def random_a_proxy_dict_from_file(path_to_file: str): """ Random a proxy dict from a certain file, with verification. :param str path_to_file: /path/to/file :return: dict or None """ lines = file_fn.read_to_list(path_to_file) if lines: while len(lines) > 0: cp.getting('Random a proxy') # random _line = random.choice(lines) proxy_dict = line2dict(_line) # verify if proxy_dict: cp.wr('{host}:{port} '.format(host=proxy_dict['host'], port=proxy_dict['port'], )) cp.step(with_spaces=1) try: ip = ip_query(requests_proxies=dict2requests_proxies(proxy_dict)) if ip: cp.value(ip['ip'], inline=True) if ip['country']: cp.value(' ({})'.format(ip['country']), inline=True) cp.fx() return proxy_dict except Exception as e: cp.error('[proxy_fn] {}'.format(e)) lines.remove(_line) return None