├── .gitignore ├── ReadMe.md ├── exec.sh ├── merge.py ├── meta_merge.py ├── requirements.txt ├── sub ├── merged_proxies.yaml ├── merged_proxies_new.yaml ├── merged_warp_proxies.yaml ├── merged_warp_proxies_new.yaml ├── shadowrocket.txt └── shadowrocket_base64.txt ├── templates ├── clash.yaml ├── clash_template.yaml └── clash_warp_template.yaml └── urls ├── clash_new_urls.txt ├── clash_urls.txt ├── hysteria2_urls.txt ├── hysteria_urls.txt ├── naiverproxy_urls.txt ├── sb_urls.txt ├── ss_urls.txt └── xray_urls.txt /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | logs/ 7 | *.log 8 | docs/ 9 | 10 | ### STS ### 11 | .apt_generated 12 | .classpath 13 | .factorypath 14 | .project 15 | .settings 16 | .springBeans 17 | .sts4-cache 18 | 19 | ### IntelliJ IDEA ### 20 | .idea 21 | *.iws 22 | *.iml 23 | *.ipr 24 | 25 | ### NetBeans ### 26 | /nbproject/private/ 27 | /nbbuild/ 28 | /dist/ 29 | /nbdist/ 30 | /.nb-gradle/ 31 | build/ 32 | 33 | ### VS Code ### 34 | .vscode/ 35 | -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 | ## 简介 2 | 3 | **注意:clash内核无法使用这些节点,你要用clashmeta** 4 | 5 | ## 订阅链接分享(需要翻墙版-托管自github) 6 | 7 | ### 不套warp版本 clashmeta 8 | ``` 9 | https://raw.githubusercontent.com/im-yunzetian/chromego/main/sub/merged_proxies.yaml 10 | ``` 11 | ### 套warp版本 clashmeta 12 | ``` 13 | https://raw.githubusercontent.com/im-yunzetian/chromego/main/sub/merged_warp_proxies.yaml 14 | ``` 15 | ### 通用链接 v2ray 16 | ``` 17 | https://raw.githubusercontent.com/im-yunzetian/chromego/main/sub/shadowrocket_base64.txt 18 | ``` 19 | 20 | ## 致谢 21 | [Alvin9999](https://github.com/Alvin9999/pac2/tree/master) 22 | -------------------------------------------------------------------------------- /exec.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | python merge.py 3 | git add . 4 | git commit -m "update" 5 | git push 6 | -------------------------------------------------------------------------------- /merge.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import json 3 | import logging 4 | import urllib.request 5 | import traceback 6 | 7 | import yaml 8 | 9 | 10 | # 提取节点 11 | def process_urls(url_file, processor): 12 | try: 13 | with open(url_file, 'r') as file: 14 | urls = file.read().splitlines() 15 | 16 | for index, url in enumerate(urls): 17 | try: 18 | response = urllib.request.urlopen(url) 19 | data = response.read().decode('utf-8') 20 | processor(data, index) 21 | except Exception as e: 22 | traceback.print_exc() 23 | logging.error(f"Error processing URL {url}: {e}") 24 | except Exception as e: 25 | logging.error(f"Error reading file {url_file}: {e}") 26 | 27 | 28 | # 提取clash节点 29 | def process_clash(data, index): 30 | try: 31 | # 解析YAML格式的内容 32 | content = yaml.safe_load(data) 33 | 34 | # 提取proxies部分并合并到merged_proxies中 35 | proxies = content.get('proxies', []) 36 | 37 | for proxy in proxies: 38 | # 如果类型是vless 39 | if proxy['type'] == 'vless': 40 | server = proxy.get("server", "") 41 | port = int(proxy.get("port", 443)) 42 | udp = proxy.get("udp", "") 43 | uuid = proxy.get("uuid", "") 44 | network = proxy.get("network", "") 45 | tls = int(proxy.get("tls", 0)) 46 | xudp = proxy.get("xudp", "") 47 | sni = proxy.get("servername", "") 48 | flow = proxy.get("flow", "") 49 | publicKey = proxy.get('reality-opts', {}).get('public-key', '') 50 | short_id = proxy.get('reality-opts', {}).get('short-id', '') 51 | fp = proxy.get("client-fingerprint", "") 52 | insecure = int(proxy.get("skip-cert-verify", 0)) 53 | grpc_serviceName = proxy.get('grpc-opts', {}).get('grpc-service-name', '') 54 | 55 | ws_path = proxy.get('ws-opts', {}).get('path', '') 56 | ws_headers_host = proxy.get('ws-opts', {}).get('headers', {}).get('Host', '') 57 | if tls == 0: 58 | security = 'none' 59 | elif tls == 1 and publicKey != '': 60 | security = 'reality' 61 | else: 62 | security = 'tls' 63 | 64 | proxy_res = f"vless://{uuid}@{server}:{port}?security={security}&allowInsecure={insecure}&flow={flow}&type={network}&fp={fp}&pbk={publicKey}&sid={short_id}&sni={sni}&serviceName={grpc_serviceName}&path={ws_path}&host={ws_headers_host}" 65 | 66 | if proxy_res in merged_proxies: 67 | print(proxy_res, '已存在') 68 | else: 69 | merged_proxies.append(proxy_res) 70 | merged_proxies.sort() 71 | 72 | if proxy['type'] == 'vmess': 73 | server = proxy.get("server", "") 74 | port = int(proxy.get("port", 443)) 75 | uuid = proxy.get("uuid", "") 76 | # cipher = proxy.get("cipher", "") 77 | alterId = proxy.get("alterId", "") 78 | network = proxy.get("network", "") 79 | tls = int(proxy.get("tls", 0)) 80 | 81 | if tls == 0: 82 | security = "none" 83 | elif tls == 1: 84 | security = "tls" 85 | sni = proxy.get("servername", "") 86 | ws_path = proxy.get('ws-opts', {}).get('path', '') 87 | ws_headers_host = proxy.get('ws-opts', {}).get('headers', {}).get('host', '') 88 | insecure = int(proxy.get("skip-cert-verify", 0)) 89 | 90 | proxy_res = f"vmess://{uuid}@{server}:{port}?security={security}&allowInsecure={insecure}&type={network}&sni={sni}&path={ws_path}&host={ws_headers_host}" 91 | 92 | if proxy_res in merged_proxies: 93 | print(proxy_res, '已存在') 94 | else: 95 | merged_proxies.append(proxy_res) 96 | merged_proxies.sort() 97 | 98 | elif proxy['type'] == 'tuic': 99 | server = proxy.get("server", "") 100 | port = int(proxy.get("port", 443)) 101 | uuid = proxy.get("uuid", "") 102 | password = proxy.get("password", "") 103 | sni = proxy.get("sni", "") 104 | insecure = int(proxy.get("skip-cert-verify", 0)) 105 | udp_relay_mode = proxy.get("udp-relay-mode", "naive") 106 | congestion = proxy.get("congestion-controller", "bbr") 107 | alpn = proxy.get("alpn", [])[0] if proxy.get("alpn") and len(proxy["alpn"]) > 0 else None 108 | # tuic_meta_neko = f"tuic://{server}:{port}?uuid={uuid}&version=5&password={password}&insecure={insecure}&alpn={alpn}&mode={udp_relay_mode}" 109 | 110 | proxy_res = f"tuic://{uuid}:{password}@{server}:{port}?sni={sni}&congestion_control={congestion}&udp_relay_mode={udp_relay_mode}&alpn={alpn}&allow_insecure={insecure}" 111 | 112 | if proxy_res in merged_proxies: 113 | print(proxy_res, '已存在') 114 | else: 115 | merged_proxies.append(proxy_res) 116 | merged_proxies.sort() 117 | 118 | elif proxy['type'] == "hysteria2": 119 | server = proxy.get("server", "") 120 | port = int(proxy.get("port", 443)) 121 | auth = proxy.get("password", "") 122 | obfs = proxy.get("obfs", "") 123 | obfs_password = proxy.get("obfs-password", "") 124 | sni = proxy.get("sni", "") 125 | insecure = int(proxy.get("skip-cert-verify", 0)) 126 | 127 | proxy_res = f"hysteria2://{auth}@{server}:{port}?insecure={insecure}&sni={sni}&obfs={obfs}&obfs-password={obfs_password}" 128 | 129 | if proxy_res in merged_proxies: 130 | print(proxy_res, '已存在') 131 | else: 132 | merged_proxies.append(proxy_res) 133 | merged_proxies.sort() 134 | 135 | elif proxy['type'] == 'hysteria': 136 | server = proxy.get("server", "") 137 | port = int(proxy.get("port", 443)) 138 | ports = proxy.get("port", "") 139 | protocol = proxy.get("protocol", "udp") 140 | up_mbps = 50 141 | down_mbps = 80 142 | alpn = proxy.get("alpn", [])[0] if proxy.get("alpn") and len(proxy["alpn"]) > 0 else None 143 | obfs = proxy.get("obfs", "") 144 | insecure = int(proxy.get("skip-cert-verify", 0)) 145 | sni = proxy.get("sni", "") 146 | fast_open = int(proxy.get("fast_open", 1)) 147 | auth = proxy.get("auth-str", "") 148 | # 生成URL 149 | 150 | proxy_res = f"hysteria://{server}:{port}?peer={sni}&auth={auth}&insecure={insecure}&upmbps={up_mbps}&downmbps={down_mbps}&alpn={alpn}&mport={ports}&obfs={obfs}&protocol={protocol}&fastopen={fast_open}" 151 | 152 | if proxy_res in merged_proxies: 153 | print(proxy_res, '已存在') 154 | else: 155 | merged_proxies.append(proxy_res) 156 | merged_proxies.sort() 157 | except Exception as e: 158 | traceback.print_exc() 159 | 160 | 161 | def process_naive(data, index): 162 | try: 163 | json_data = json.loads(data) 164 | 165 | proxy_str = json_data["proxy"] 166 | proxy_str = proxy_str.replace("https://", "") 167 | naiveproxy = base64.b64encode(proxy_str.encode()).decode() 168 | proxy = "https://" + naiveproxy 169 | 170 | if proxy in merged_proxies: 171 | print(proxy, '已存在') 172 | else: 173 | merged_proxies.append(proxy) 174 | merged_proxies.sort() 175 | 176 | except Exception as e: 177 | logging.error(f"Error processing naive data for index {index}: {e}") 178 | 179 | 180 | # 处理sing-box节点,待办 181 | def process_sb(data, index): 182 | try: 183 | json_data = json.loads(data) 184 | # 处理 shadowtls 数据 185 | server = json_data["outbounds"][0].get("server", "") 186 | server_port = json_data["outbounds"][0].get("server_port", "") 187 | method = json_data["outbounds"][0].get("method", "") 188 | password = json_data["outbounds"][0].get("password", "") 189 | version = int(json_data["outbounds"][0].get("version", 0)) 190 | host = json_data["outbounds"][0]["tls"].get("server_name", "") 191 | shadowtls_password = json_data["outbounds"][1].get("password", "") 192 | 193 | ss = f"{method}:{password}@{server}:{server_port}" 194 | shadowtls = f'{{"version": "{version}", "host": "{host}","password":{shadowtls_password}}}' 195 | proxy = "ss://" + base64.b64encode(ss.encode()).decode() + "?shadow-tls=" + base64.b64encode( 196 | shadowtls.encode()).decode() 197 | 198 | if proxy in merged_proxies: 199 | print(proxy, '已存在') 200 | else: 201 | merged_proxies.append(proxy) 202 | merged_proxies.sort() 203 | 204 | except Exception as e: 205 | traceback.print_exc() 206 | logging.error(f"Error processing shadowtls data for index {index}: {e}") 207 | 208 | 209 | # hysteria 210 | def process_hysteria(data, index): 211 | try: 212 | json_data = json.loads(data) 213 | # 处理 hysteria 数据 214 | # 提取字段值 215 | server = json_data.get("server", "") 216 | protocol = json_data.get("protocol", "") 217 | up_mbps = json_data.get("up_mbps", "") 218 | down_mbps = json_data.get("down_mbps", "") 219 | alpn = json_data.get("alpn", "") 220 | obfs = json_data.get("obfs", "") 221 | insecure = int(json_data.get("insecure", 0)) 222 | server_name = json_data.get("server_name", "") 223 | fast_open = int(json_data.get("fast_open", 0)) 224 | auth = json_data.get("auth_str", "") 225 | # 生成URL 226 | 227 | proxy = f"hysteria://{server}?peer={server_name}&auth={auth}&insecure={insecure}&upmbps={up_mbps}&downmbps={down_mbps}&alpn={alpn}&obfs={obfs}&protocol={protocol}&fastopen={fast_open}" 228 | 229 | if proxy in merged_proxies: 230 | print(proxy, '已存在') 231 | else: 232 | merged_proxies.append(proxy) 233 | merged_proxies.sort() 234 | 235 | 236 | except Exception as e: 237 | logging.error(f"Error processing hysteria data for index {index}: {e}") 238 | 239 | 240 | # 处理hysteria2 241 | def process_hysteria2(data, index): 242 | try: 243 | json_data = json.loads(data) 244 | # 处理 hysteria2 数据 245 | # 提取字段值 246 | server = json_data["server"] 247 | insecure = int(json_data["tls"]["insecure"]) 248 | sni = json_data["tls"]["sni"] 249 | auth = json_data["auth"] 250 | # 生成URL 251 | proxy = f"hysteria2://{auth}@{server}?insecure={insecure}&sni={sni}" 252 | 253 | if proxy in merged_proxies: 254 | print(proxy, '已存在') 255 | else: 256 | merged_proxies.append(proxy) 257 | merged_proxies.sort() 258 | except Exception as e: 259 | logging.error(f"Error processing hysteria2 data for index {index}: {e}") 260 | 261 | 262 | # 处理xray 263 | def process_xray(data, index): 264 | try: 265 | json_data = json.loads(data) 266 | outbounds = json_data["outbounds"][0] 267 | # 处理 xray 数据 268 | protocol = outbounds.get("protocol") 269 | 270 | if protocol == "vless": 271 | vnext = outbounds["settings"]["vnext"] 272 | 273 | if vnext: 274 | server = vnext[0].get("address", "") 275 | port = int(vnext[0].get("port", 0)) 276 | users = vnext[0]["users"] 277 | 278 | if users: 279 | user = users[0] 280 | uuid = user.get("id", "") 281 | flow = user.get("flow", "") 282 | 283 | stream_settings = outbounds.get("streamSettings", {}) 284 | network = stream_settings.get("network", "") 285 | security = stream_settings.get("security", "") 286 | reality_settings = stream_settings.get("realitySettings", {}) 287 | 288 | publicKey = reality_settings.get("publicKey", "") 289 | short_id = reality_settings.get("shortId", "") 290 | sni = reality_settings.get("serverName", "") 291 | # tls 292 | tls_settings = stream_settings.get("tlsSettings", {}) 293 | sni = tls_settings.get("serverName", sni) 294 | insecure = int(tls_settings.get("allowInsecure", 0)) 295 | 296 | fp = reality_settings.get("fingerprint", "") 297 | fp = tls_settings.get("fingerprint", fp) 298 | # spx = reality_settings.get("spiderX", "") 299 | 300 | grpc_settings = stream_settings.get("grpcSettings", {}) 301 | grpc_serviceName = grpc_settings.get("serviceName", "") 302 | 303 | ws_settings = stream_settings.get("wsSettings", {}) 304 | ws_path = ws_settings.get("path", "") 305 | ws_headers_host = ws_settings.get("headers", {}).get("Host", "") 306 | 307 | proxy = f"vless://{uuid}@{server}:{port}?security={security}&allowInsecure={insecure}&flow={flow}&type={network}&fp={fp}&pbk={publicKey}&sid={short_id}&sni={sni}&serviceName={grpc_serviceName}&path={ws_path}&host={ws_headers_host}" 308 | 309 | if proxy in merged_proxies: 310 | print(proxy, '已存在') 311 | else: 312 | merged_proxies.append(proxy) 313 | merged_proxies.sort() 314 | # 不支持插件 315 | if protocol == "shadowsocks": 316 | servers = outbounds['settings']['servers'][0] 317 | server = servers['address'] 318 | method = servers['method'] 319 | password = servers['password'] 320 | port = servers['port'] 321 | # 生成URL 322 | ss_source = f"{method}:{password}@{server}:{port}" 323 | ss_source = base64.b64encode(ss_source.encode()).decode() 324 | proxy = f"ss://{ss_source}" 325 | 326 | if proxy in merged_proxies: 327 | print(proxy, '已存在') 328 | else: 329 | merged_proxies.append(proxy) 330 | merged_proxies.sort() 331 | except Exception as err: 332 | logging.error(f"Error processing xray data for index {index}: {err},{err.__traceback__.tb_lineno}") 333 | 334 | 335 | # 定义一个空列表用于存储合并后的代理配置 336 | merged_proxies = [] 337 | 338 | # 处理 clash URLs 339 | process_urls('./urls/clash_new_urls.txt', process_clash) 340 | 341 | # 处理 shadowtls URLs 342 | # process_urls('./urls/sb_urls.txt', process_sb) 343 | 344 | # 处理 naive URLs 345 | process_urls('./urls/naiverproxy_urls.txt', process_naive) 346 | 347 | # 处理 hysteria URLs 348 | process_urls('./urls/hysteria_urls.txt', process_hysteria) 349 | 350 | # 处理 hysteria2 URLs 351 | process_urls('./urls/hysteria2_urls.txt', process_hysteria2) 352 | 353 | # 处理 xray URLs 354 | process_urls('./urls/xray_urls.txt', process_xray) 355 | 356 | # 将结果写入文件 357 | try: 358 | with open("./sub/shadowrocket.txt", "w") as file: 359 | for proxy in merged_proxies: 360 | file.write(proxy + "\n") 361 | except Exception as e: 362 | print(f"Error writing to file: {e}") 363 | 364 | try: 365 | with open("./sub/shadowrocket.txt", "r") as file: 366 | content = file.read() 367 | encoded_content = base64.b64encode(content.encode("utf-8")).decode("utf-8") 368 | 369 | with open("./sub/shadowrocket_base64.txt", "w") as encoded_file: 370 | encoded_file.write(encoded_content) 371 | 372 | print("Content successfully encoded and written to file.") 373 | except Exception as e: 374 | print(f"Error encoding file content: {e}") 375 | -------------------------------------------------------------------------------- /meta_merge.py: -------------------------------------------------------------------------------- 1 | import yaml 2 | import json 3 | import urllib.request 4 | import logging 5 | 6 | # 提取节点 7 | def process_urls(url_file, processor): 8 | try: 9 | with open(url_file, 'r') as file: 10 | urls = file.read().splitlines() 11 | 12 | for index, url in enumerate(urls): 13 | try: 14 | response = urllib.request.urlopen(url) 15 | data = response.read().decode('utf-8') 16 | processor(data, index) 17 | except Exception as e: 18 | logging.error(f"Error processing URL {url}: {e}") 19 | except Exception as e: 20 | logging.error(f"Error reading file {url_file}: {e}") 21 | #提取clash节点 22 | def process_clash(data, index): 23 | content = yaml.safe_load(data) 24 | proxies = content.get('proxies', []) 25 | for i, proxy in enumerate(proxies): 26 | proxy['name'] = f"meta_{proxy['type']}_{index}{i+1}" 27 | merged_proxies.extend(proxies) 28 | # 处理sb,待办 29 | def process_sb(data, index): 30 | try: 31 | json_data = json.loads(data) 32 | # 处理 shadowtls 数据 33 | 34 | # 提取所需字段 35 | method = json_data["outbounds"][0]["method"] 36 | password = json_data["outbounds"][0]["password"] 37 | server = json_data["outbounds"][1]["server"] 38 | server_port = json_data["outbounds"][1]["server_port"] 39 | server_name = json_data["outbounds"][1]["tls"]["server_name"] 40 | shadowtls_password = json_data["outbounds"][1]["password"] 41 | version = json_data["outbounds"][1]["version"] 42 | name = f"shadowtls_{index}" 43 | # 创建当前网址的proxy字典 44 | proxy = { 45 | "name": name, 46 | "type": "ss", 47 | "server": server, 48 | "port": server_port, 49 | "cipher": method, 50 | "password": password, 51 | "plugin": "shadow-tls", 52 | "client-fingerprint": "chrome", 53 | "plugin-opts": { 54 | "host": server_name, 55 | "password": shadowtls_password, 56 | "version": int(version) 57 | } 58 | } 59 | 60 | # 将当前proxy字典添加到所有proxies列表中 61 | merged_proxies.append(proxy) 62 | 63 | except Exception as e: 64 | logging.error(f"Error processing shadowtls data for index {index}: {e}") 65 | 66 | def process_hysteria(data, index): 67 | try: 68 | json_data = json.loads(data) 69 | # 处理 hysteria 数据 70 | # 提取所需字段 71 | auth = json_data["auth_str"] 72 | server_ports = json_data["server"] 73 | server_ports_slt = server_ports.split(":") 74 | server = server_ports_slt[0] 75 | ports = server_ports_slt[1] 76 | ports_slt = ports.split(",") 77 | server_port = int(ports_slt[0]) 78 | if len(ports_slt) > 1: 79 | mport = ports_slt[1] 80 | else: 81 | mport = server_port 82 | fast_open = json_data["fast_open"] 83 | insecure = json_data["insecure"] 84 | server_name = json_data["server_name"] 85 | alpn = json_data["alpn"] 86 | protocol = json_data["protocol"] 87 | name = f"hysteria_{index}" 88 | 89 | # 创建当前网址的proxy字典 90 | proxy = { 91 | "name": name, 92 | "type": "hysteria", 93 | "server": server, 94 | "port": server_port, 95 | "ports": mport, 96 | "auth_str": auth, 97 | "up": 80, 98 | "down": 100, 99 | "fast-open": fast_open, 100 | "protocol": protocol, 101 | "sni": server_name, 102 | "skip-cert-verify": insecure, 103 | "alpn": [alpn] 104 | } 105 | 106 | # 将当前proxy字典添加到所有proxies列表中 107 | merged_proxies.append(proxy) 108 | 109 | except Exception as e: 110 | logging.error(f"Error processing hysteria data for index {index}: {e}") 111 | # 处理hysteria2 112 | def process_hysteria2(data, index): 113 | try: 114 | json_data = json.loads(data) 115 | # 处理 hysteria2 数据 116 | # 提取所需字段 117 | auth = json_data["auth"] 118 | server_ports = json_data["server"] 119 | server_ports_slt = server_ports.split(":") 120 | server = server_ports_slt[0] 121 | ports = server_ports_slt[1] 122 | ports_slt = ports.split(",") 123 | server_port = int(ports_slt[0]) 124 | fast_open = json_data["fastOpen"] 125 | insecure = json_data["tls"]["insecure"] 126 | sni = json_data["tls"]["sni"] 127 | name = f"hysteria2_{index}" 128 | 129 | # 创建当前网址的proxy字典 130 | proxy = { 131 | "name": name, 132 | "type": "hysteria2", 133 | "server": server, 134 | "port": server_port, 135 | "password": auth, 136 | "fast-open": fast_open, 137 | "sni": sni, 138 | "skip-cert-verify": insecure 139 | } 140 | 141 | # 将当前proxy字典添加到所有proxies列表中 142 | merged_proxies.append(proxy) 143 | 144 | except Exception as e: 145 | logging.error(f"Error processing hysteria2 data for index {index}: {e}") 146 | 147 | #处理xray 148 | def process_xray(data, index): 149 | try: 150 | json_data = json.loads(data) 151 | # 处理 xray 数据 152 | protocol = json_data["outbounds"][0]["protocol"] 153 | #vless操作 154 | if protocol == "vless": 155 | # 提取所需字段 156 | server = json_data["outbounds"][0]["settings"]["vnext"][0]["address"] 157 | port = json_data["outbounds"][0]["settings"]["vnext"][0]["port"] 158 | uuid = json_data["outbounds"][0]["settings"]["vnext"][0]["users"][0]["id"] 159 | istls = True 160 | flow = json_data["outbounds"][0]["settings"]["vnext"][0]["users"][0]["flow"] 161 | # 传输方式 162 | network = json_data["outbounds"][0]["streamSettings"]["network"] 163 | publicKey = json_data["outbounds"][0]["streamSettings"]["realitySettings"]["publicKey"] 164 | shortId = json_data["outbounds"][0]["streamSettings"]["realitySettings"]["shortId"] 165 | serverName = json_data["outbounds"][0]["streamSettings"]["realitySettings"]["serverName"] 166 | fingerprint = json_data["outbounds"][0]["streamSettings"]["realitySettings"]["fingerprint"] 167 | # udp转发 168 | isudp = True 169 | name = f"reality_{index}" 170 | 171 | # 根据network判断tcp 172 | if network == "tcp": 173 | proxy = { 174 | "name": name, 175 | "type": protocol, 176 | "server": server, 177 | "port": port, 178 | "uuid": uuid, 179 | "network": network, 180 | "tls": istls, 181 | "udp": isudp, 182 | "flow": flow, 183 | "client-fingerprint": fingerprint, 184 | "servername": serverName, 185 | "reality-opts":{ 186 | "public-key": publicKey, 187 | "short-id": shortId} 188 | } 189 | 190 | # 根据network判断grpc 191 | elif network == "grpc": 192 | serviceName = json_data["outbounds"][0]["streamSettings"]["grpcSettings"]["serviceName"] 193 | 194 | # 创建当前网址的proxy字典 195 | proxy = { 196 | "name": name, 197 | "type": protocol, 198 | "server": server, 199 | "port": port, 200 | "uuid": uuid, 201 | "network": network, 202 | "tls": istls, 203 | "udp": isudp, 204 | "flow": flow, 205 | "client-fingerprint": fingerprint, 206 | "servername": serverName, 207 | "grpc-opts":{ 208 | "grpc-service-name": serviceName 209 | }, 210 | "reality-opts":{ 211 | "public-key": publicKey, 212 | "short-id": shortId} 213 | } 214 | 215 | # 将当前proxy字典添加到所有proxies列表中 216 | merged_proxies.append(proxy) 217 | except Exception as e: 218 | logging.error(f"Error processing xray data for index {index}: {e}") 219 | 220 | def update_proxy_groups(config_data, merged_proxies): 221 | for group in config_data['proxy-groups']: 222 | if group['name'] in ['🚀 节点选择']: 223 | if 'proxies' not in group.keys(): 224 | group['proxies']=[] 225 | group['proxies'].extend(proxy['name'] for proxy in merged_proxies) 226 | 227 | def update_warp_proxy_groups(config_warp_data, merged_proxies): 228 | for group in config_warp_data['proxy-groups']: 229 | if group['name'] in ['🚀 节点选择','WARP前置节点']: 230 | if 'proxies' not in group.keys(): 231 | group['proxies']=[] 232 | group['proxies'].extend(proxy['name'] for proxy in merged_proxies) 233 | # 定义一个空列表用于存储合并后的代理配置 234 | merged_proxies = [] 235 | 236 | # 处理 clash URLs 237 | process_urls('./urls/clash_new_urls.txt', process_clash) 238 | 239 | # 处理 shadowtls URLs 240 | process_urls('./urls/sb_urls.txt', process_sb) 241 | 242 | # 处理 hysteria URLs 243 | process_urls('./urls/hysteria_urls.txt', process_hysteria) 244 | 245 | # 处理 hysteria2 URLs 246 | process_urls('./urls/hysteria2_urls.txt', process_hysteria2) 247 | 248 | # 处理 xray URLs 249 | process_urls('./urls/xray_urls.txt', process_xray) 250 | 251 | # 读取普通的配置文件内容 252 | with open('./templates/clash_template.yaml', 'r', encoding='utf-8') as file: 253 | config_data = yaml.safe_load(file) 254 | 255 | # 读取warp配置文件内容 256 | with open('./templates/clash_warp_template.yaml', 'r', encoding='utf-8') as file: 257 | config_warp_data = yaml.safe_load(file) 258 | 259 | # 添加合并后的代理到proxies部分 260 | if 'proxies' not in config_data.keys(): 261 | config_data['proxies']=[] 262 | config_data['proxies'].extend(merged_proxies) 263 | config_warp_data['proxies'].extend(merged_proxies) 264 | 265 | # 更新节点选择的proxies的name部分 266 | update_proxy_groups(config_data, merged_proxies) 267 | update_warp_proxy_groups(config_warp_data, merged_proxies) 268 | 269 | # 将更新后的数据写入到一个YAML文件中,并指定编码格式为UTF-8 270 | with open('./sub/merged_proxies_new.yaml', 'w', encoding='utf-8') as file: 271 | yaml.dump(config_data, file, sort_keys=False, allow_unicode=True) 272 | 273 | with open('./sub/merged_warp_proxies_new.yaml', 'w', encoding='utf-8') as file: 274 | yaml.dump(config_warp_data, file, sort_keys=False, allow_unicode=True) 275 | 276 | print("聚合完成") 277 | 278 | # 处理其他 279 | merged_proxies = [] 280 | 281 | # 处理 clash URLs 282 | process_urls('./urls/clash_urls.txt', process_clash) 283 | 284 | # 处理 shadowtls URLs 285 | process_urls('./urls/sb_urls.txt', process_sb) 286 | 287 | # 处理 hysteria URLs 288 | process_urls('./urls/hysteria_urls.txt', process_hysteria) 289 | 290 | # 处理 hysteria2 URLs 291 | #process_urls('./urls/hysteria2_urls.txt', process_hysteria2) 292 | 293 | # 处理 xray URLs 294 | process_urls('./urls/xray_urls.txt', process_xray) 295 | 296 | # 读取普通的配置文件内容 297 | with open('./templates/clash_template.yaml', 'r', encoding='utf-8') as file: 298 | config_data = yaml.safe_load(file) 299 | 300 | # 读取warp配置文件内容 301 | with open('./templates/clash_warp_template.yaml', 'r', encoding='utf-8') as file: 302 | config_warp_data = yaml.safe_load(file) 303 | 304 | # 添加合并后的代理到proxies部分 305 | if 'proxies' not in config_data.keys(): 306 | config_data['proxies']=[] 307 | config_data['proxies'].extend(merged_proxies) 308 | config_warp_data['proxies'].extend(merged_proxies) 309 | 310 | # 更新节点选择的proxies的name部分 311 | update_proxy_groups(config_data, merged_proxies) 312 | update_warp_proxy_groups(config_warp_data, merged_proxies) 313 | 314 | # 将更新后的数据写入到一个YAML文件中,并指定编码格式为UTF-8 315 | with open('./sub/merged_proxies.yaml', 'w', encoding='utf-8') as file: 316 | yaml.dump(config_data, file, sort_keys=False, allow_unicode=True) 317 | 318 | with open('./sub/merged_warp_proxies.yaml', 'w', encoding='utf-8') as file: 319 | yaml.dump(config_warp_data, file, sort_keys=False, allow_unicode=True) 320 | 321 | print("聚合完成") -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | PyYAML==6.0.1 2 | -------------------------------------------------------------------------------- /urls/clash_new_urls.txt: -------------------------------------------------------------------------------- 1 | https://raw.githubusercontent.com/Alvin9999/pac2/master/clash.meta2/1/config.yaml 2 | https://raw.githubusercontent.com/Alvin9999/pac2/master/clash.meta2/config.yaml 3 | https://raw.githubusercontent.com/Alvin9999/pac2/master/clash.meta2/13/config.yaml 4 | https://raw.githubusercontent.com/Alvin9999/pac2/master/clash.meta2/15/config.yaml 5 | https://raw.githubusercontent.com/Alvin9999/pac2/master/clash.meta2/2/config.yaml 6 | https://raw.githubusercontent.com/Alvin9999/pac2/master/clash.meta2/3/config.yaml 7 | https://raw.githubusercontent.com/Alvin9999/pac2/master/clash.meta/1/config.yaml 8 | https://raw.githubusercontent.com/Alvin9999/pac2/master/clash.meta/config.yaml 9 | https://raw.githubusercontent.com/Alvin9999/pac2/master/clash.meta/13/config.yaml 10 | https://raw.githubusercontent.com/Alvin9999/pac2/master/clash.meta/15/config.yaml 11 | https://raw.githubusercontent.com/Alvin9999/pac2/master/clash.meta/2/config.yaml 12 | https://raw.githubusercontent.com/Alvin9999/pac2/master/clash.meta/3/config.yaml 13 | https://raw.githubusercontent.com/Alvin9999/pac2/master/quick/4/config.yaml 14 | https://raw.githubusercontent.com/Alvin9999/pac2/master/quick/3/config.yaml 15 | https://raw.githubusercontent.com/Alvin9999/pac2/master/quick/1/config.yaml 16 | https://raw.githubusercontent.com/Alvin9999/pac2/master/quick/config.yaml 17 | -------------------------------------------------------------------------------- /urls/clash_urls.txt: -------------------------------------------------------------------------------- 1 | https://raw.githubusercontent.com/Alvin9999/pac2/master/clash.meta/1/config.yaml 2 | https://raw.githubusercontent.com/Alvin9999/pac2/master/clash.meta/config.yaml 3 | https://raw.githubusercontent.com/Alvin9999/pac2/master/clash.meta/13/config.yaml 4 | https://raw.githubusercontent.com/Alvin9999/pac2/master/clash.meta/15/config.yaml 5 | https://raw.githubusercontent.com/Alvin9999/pac2/master/clash.meta/2/config.yaml 6 | https://raw.githubusercontent.com/Alvin9999/pac2/master/clash.meta/3/config.yaml 7 | https://raw.githubusercontent.com/Alvin9999/pac2/master/quick/4/config.yaml 8 | https://raw.githubusercontent.com/Alvin9999/pac2/master/quick/3/config.yaml 9 | https://raw.githubusercontent.com/Alvin9999/pac2/master/quick/1/config.yaml 10 | https://raw.githubusercontent.com/Alvin9999/pac2/master/quick/config.yaml 11 | -------------------------------------------------------------------------------- /urls/hysteria2_urls.txt: -------------------------------------------------------------------------------- 1 | https://raw.githubusercontent.com/Alvin9999/pac2/master/hysteria2/config.json 2 | https://raw.githubusercontent.com/Alvin9999/pac2/master/hysteria2/1/config.json 3 | https://raw.githubusercontent.com/Alvin9999/pac2/master/hysteria2/13/config.json 4 | https://raw.githubusercontent.com/Alvin9999/pac2/master/hysteria2/2/config.json -------------------------------------------------------------------------------- /urls/hysteria_urls.txt: -------------------------------------------------------------------------------- 1 | https://raw.githubusercontent.com/Alvin9999/pac2/master/hysteria/1/config.json 2 | https://raw.githubusercontent.com/Alvin9999/pac2/master/hysteria/13/config.json 3 | https://raw.githubusercontent.com/Alvin9999/pac2/master/hysteria/2/config.json 4 | https://raw.githubusercontent.com/Alvin9999/pac2/master/hysteria/config.json -------------------------------------------------------------------------------- /urls/naiverproxy_urls.txt: -------------------------------------------------------------------------------- 1 | https://raw.githubusercontent.com/Alvin9999/PAC/master/naiveproxy/1/config.json 2 | https://raw.githubusercontent.com/Alvin9999/PAC/master/naiveproxy/config.json -------------------------------------------------------------------------------- /urls/sb_urls.txt: -------------------------------------------------------------------------------- 1 | https://raw.githubusercontent.com/Alvin9999/pac2/master/singbox/1/config.json 2 | https://raw.githubusercontent.com/Alvin9999/pac2/master/singbox/config.json -------------------------------------------------------------------------------- /urls/ss_urls.txt: -------------------------------------------------------------------------------- 1 | https://raw.githubusercontent.com/Alvin9999/pac2/master/ssr-wj/ssconfig.txt 2 | https://raw.githubusercontent.com/Alvin9999/pac2/master/ssr-wj/1/ssconfig.txt -------------------------------------------------------------------------------- /urls/xray_urls.txt: -------------------------------------------------------------------------------- 1 | https://raw.githubusercontent.com/Alvin9999/pac2/master/xray/1/config.json 2 | https://raw.githubusercontent.com/Alvin9999/pac2/master/xray/2/config.json 3 | https://raw.githubusercontent.com/Alvin9999/pac2/master/xray/3/config.json 4 | https://raw.githubusercontent.com/Alvin9999/pac2/master/xray/config.json --------------------------------------------------------------------------------