import os import yaml import json import logging from pathlib import Path from urllib.parse import urlparse, parse_qs def init_config(conf_dir): """初始化配置文件""" config_path = Path(conf_dir) / "config.yaml" if not config_path.exists(): default_config = { 'proxy_url': '', 'config_version': '1.0', 'app_version': '1.0', 'domains': [ 'google.com', 'youtube.com', 'facebook.com', 'twitter.com', 'instagram.com', 'netflix.com', 'github.com', 'gitlab.com', 'stackoverflow.com', 'reddit.com' ], 'v2ray_config_path': str(Path(conf_dir) / "v2ray.json"), 'v2ray_template_path': str(Path(conf_dir) / "v2ray_template.json"), 'v2ray_log_path': str(Path(__file__).parent.parent / "logs" / "v2ray.log") } with open(config_path, 'w') as f: yaml.dump(default_config, f) logging.info("Default config file created") return load_config() def load_config(): """加载配置文件""" config_path = Path(__file__).parent.parent / "conf" / "config.yaml" try: with open(config_path, 'r') as f: return yaml.safe_load(f) except Exception as e: logging.error(f"Failed to load config: {str(e)}") return { 'proxy_url': '', 'config_version': '1.0', 'app_version': '1.0', 'domains': [], 'v2ray_config_path': str(Path(__file__).parent.parent / "conf" / "v2ray.json"), 'v2ray_template_path': str(Path(__file__).parent.parent / "conf" / "v2ray_template.json"), 'v2ray_log_path': str(Path(__file__).parent.parent / "logs" / "v2ray.log") } def save_config(config): """保存配置文件""" config_path = Path(__file__).parent.parent / "conf" / "config.yaml" try: with open(config_path, 'w') as f: yaml.dump(config, f) return True except Exception as e: logging.error(f"Failed to save config: {str(e)}") return False def parse_vless_url(url): """解析vless://URL""" try: # 移除URL编码 url = url.replace('%2F', '/').replace('%3D', '=').replace('%3F', '?') # 解析URL parsed = urlparse(url) query_params = parse_qs(parsed.query) # 提取必要参数 uuid = parsed.username address = parsed.hostname port = parsed.port name = parsed.fragment # 提取REALITY参数 security = query_params.get('security', ['none'])[0] encryption = query_params.get('encryption', ['none'])[0] flow = query_params.get('flow', [''])[0] type_ = query_params.get('type', ['tcp'])[0] sni = query_params.get('sni', [''])[0] fp = query_params.get('fp', ['chrome'])[0] pbk = query_params.get('pbk', [''])[0] sid = query_params.get('sid', [''])[0] spx = query_params.get('spx', [''])[0] return { 'uuid': uuid, 'address': address, 'port': port, 'name': name, 'security': security, 'encryption': encryption, 'flow': flow, 'type': type_, 'sni': sni, 'fp': fp, 'pbk': pbk, 'sid': sid, 'spx': spx } except Exception as e: logging.error(f"Failed to parse vless URL: {str(e)}") return None def generate_v2ray_config(template_path, output_path, proxy_info, domains): """生成v2ray配置文件""" try: # 读取模板 with open(template_path, 'r') as f: template = json.load(f) # 替换模板中的占位符 outbound = template['outbounds'][0] # 设置vless服务器信息 outbound['settings']['vnext'][0]['address'] = proxy_info['address'] outbound['settings']['vnext'][0]['port'] = proxy_info['port'] outbound['settings']['vnext'][0]['users'][0]['id'] = proxy_info['uuid'] outbound['settings']['vnext'][0]['users'][0]['encryption'] = proxy_info['encryption'] outbound['settings']['vnext'][0]['users'][0]['flow'] = proxy_info['flow'] # 设置streamSettings stream_settings = outbound['streamSettings'] stream_settings['network'] = proxy_info['type'] stream_settings['security'] = proxy_info['security'] if proxy_info['security'] == 'reality': reality_settings = { 'serverName': proxy_info['sni'], 'fingerprint': proxy_info['fp'], 'publicKey': proxy_info['pbk'], 'shortId': proxy_info['sid'], 'spiderX': proxy_info['spx'] } stream_settings['realitySettings'] = reality_settings # 替换域名列表 for rule in template['routing']['rules']: if 'domain' in rule and 'REPLACE_DOMAINS' in rule['domain']: rule['domain'] = domains # 保存配置 with open(output_path, 'w') as f: json.dump(template, f, indent=2) return True except Exception as e: logging.error(f"Failed to generate v2ray config: {str(e)}") return False