import http.server
import urllib.request
import base64
import urllib.parse
import re
import traceback

PORT = 2087

class ClashSubHandler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        try:
            path = self.path
            token = ""
            m = re.search(r'/(?:clash|sub)/([a-zA-Z0-9_-]+)', path)
            if m:
                token = m.group(1)
                
            if not token:
                self.send_response(400)
                self.end_headers()
                self.wfile.write(b"Invalid subscription token")
                return

            url = f"http://127.0.0.1:2096/sub/{token}"
            req = urllib.request.Request(url, headers={"Host": "129.225.181.46", "User-Agent": "v2rayN"})
            raw = urllib.request.urlopen(req, timeout=5).read().decode('utf-8').strip()
            raw += '=' * (-len(raw) % 4)
            decoded = base64.b64decode(raw).decode('utf-8', errors='ignore')
            links = decoded.splitlines()

            proxies = []

            # 1. Hysteria 2 node with user's specific token as password for 3X-UI accounting!
            hy2_pass = token if token != "admin" else "oracle_hy2_pass_2026"
            proxies.append({
                "name": "⚡ 极速抗拥堵-Hysteria2 (UDP 8443-晚高峰专用)",
                "type": "hysteria2",
                "server": "129.225.181.46",
                "port": 8443,
                "password": hy2_pass,
                "sni": "lilili.shop",
                "skip-cert-verify": True,
                "up": "50 Mbps",
                "down": "200 Mbps"
            })

            for line in links:
                line = line.strip()
                if not line or not line.startswith("vless://"):
                    continue
                
                p1 = line[8:].split('#', 1)
                name = urllib.parse.unquote(p1[1]) if len(p1) > 1 else "VLESS-Node"
                main_part = p1[0]
                u_host = main_part.split('?', 1)
                params = dict(urllib.parse.parse_qsl(u_host[1])) if len(u_host) > 1 else {}
                user_host = u_host[0].split('@', 1)
                uuid = user_host[0]
                host_port = user_host[1].split(':', 1)
                server = host_port[0]
                port = int(host_port[1])

                network = params.get("type", "tcp")
                px = {
                    "name": name,
                    "type": "vless",
                    "server": server,
                    "port": port,
                    "uuid": uuid,
                    "udp": True,
                    "network": network
                }

                if network == "kcp":
                    header_type = params.get("headerType", "wechat-video")
                    px["kcp-opts"] = {"header-type": header_type}

                if params.get("security") == "reality":
                    px["tls"] = True
                    px["flow"] = params.get("flow", "xtls-rprx-vision")
                    px["servername"] = params.get("sni", "dl.google.com")
                    px["reality-opts"] = {
                        "public-key": params.get("pbk", ""),
                        "short-id": params.get("sid", "")
                    }
                    px["client-fingerprint"] = params.get("fp", "chrome")
                elif params.get("security") == "tls":
                    px["tls"] = True
                    if "sni" in params:
                        px["servername"] = params["sni"]
                
                if px["network"] == "ws":
                    px["ws-opts"] = {
                        "path": urllib.parse.unquote(params.get("path", "/")),
                        "headers": {"Host": params.get("host", server)}
                    }

                proxies.append(px)

            yaml_lines = [
                "port: 7890",
                "socks-port: 7891",
                "allow-lan: true",
                "mode: rule",
                "log-level: info",
                "ipv6: false",
                "",
                "proxies:"
            ]
            proxy_names = []
            for p in proxies:
                proxy_names.append(f'"{p["name"]}"')
                yaml_lines.append(f'  - name: "{p["name"]}"')
                yaml_lines.append(f'    type: {p["type"]}')
                yaml_lines.append(f'    server: {p["server"]}')
                yaml_lines.append(f'    port: {p["port"]}')
                if p.get("type") == "hysteria2":
                    yaml_lines.append(f'    password: {p["password"]}')
                    yaml_lines.append(f'    sni: {p["sni"]}')
                    yaml_lines.append(f'    skip-cert-verify: true')
                    yaml_lines.append(f'    up: "{p["up"]}"')
                    yaml_lines.append(f'    down: "{p["down"]}"')
                    yaml_lines.append("")
                    continue

                yaml_lines.append(f'    uuid: {p["uuid"]}')
                yaml_lines.append(f'    udp: true')
                yaml_lines.append(f'    network: {p["network"]}')
                if p.get("tls"):
                    yaml_lines.append(f'    tls: true')
                if p.get("flow"):
                    yaml_lines.append(f'    flow: {p["flow"]}')
                if p.get("servername"):
                    yaml_lines.append(f'    servername: {p["servername"]}')
                if p.get("client-fingerprint"):
                    yaml_lines.append(f'    client-fingerprint: {p["client-fingerprint"]}')
                if p.get("reality-opts"):
                    yaml_lines.append(f'    reality-opts:')
                    yaml_lines.append(f'      public-key: {p["reality-opts"]["public-key"]}')
                    yaml_lines.append(f'      short-id: "{p["reality-opts"]["short-id"]}"')
                if p.get("kcp-opts"):
                    yaml_lines.append(f'    kcp-opts:')
                    yaml_lines.append(f'      header-type: {p["kcp-opts"]["header-type"]}')
                if p.get("ws-opts"):
                    yaml_lines.append(f'    ws-opts:')
                    yaml_lines.append(f'      path: {p["ws-opts"]["path"]}')
                    yaml_lines.append(f'      headers:')
                    yaml_lines.append(f'        Host: {p["ws-opts"]["headers"]["Host"]}')
                yaml_lines.append("")

            if not proxy_names:
                proxy_names = ["DIRECT"]

            yaml_lines.extend([
                "proxy-groups:",
                '  - name: "🚀 节点选择"',
                "    type: select",
                "    proxies:",
                *[f"      - {name}" for name in proxy_names],
                "      - DIRECT",
                "",
                "rules:",
                "  - GEOIP,LAN,DIRECT",
                "  - GEOIP,CN,DIRECT",
                '  - MATCH,🚀 节点选择'
            ])

            output_yaml = "\n".join(yaml_lines)
            self.send_response(200)
            self.send_header("Content-Type", "text/yaml; charset=utf-8")
            self.send_header("Content-Disposition", f"attachment; filename*=UTF-8''clash.yaml")
            self.end_headers()
            self.wfile.write(output_yaml.encode('utf-8'))
        except Exception as e:
            traceback.print_exc()
            self.send_response(500)
            self.end_headers()
            self.wfile.write(str(e).encode())

if __name__ == '__main__':
    server = http.server.ThreadingHTTPServer(('0.0.0.0', PORT), ClashSubHandler)
    print("Serving on port 2087...")
    server.serve_forever()
