| import base64
|
| import json
|
| from typing import Optional
|
| from app.models.proxy import Proxy
|
|
|
|
|
| class VMessParser:
|
| @staticmethod
|
| def parse(url: str) -> Proxy:
|
| if not url.startswith("vmess://"):
|
| raise ValueError("Invalid VMess URL")
|
|
|
| try:
|
| encoded = url.replace("vmess://", "")
|
| missing_padding = len(encoded) % 4
|
| if missing_padding:
|
| encoded += "=" * (4 - missing_padding)
|
|
|
| decoded = base64.b64decode(encoded).decode("utf-8")
|
| config = json.loads(decoded)
|
|
|
| return Proxy(
|
| ip=config.get("add", ""),
|
| port=int(config.get("port", 0)),
|
| protocol="vmess",
|
| source="subscription",
|
| )
|
| except Exception as e:
|
| raise ValueError(f"Failed to parse VMess URL: {e}")
|
|
|
|
|
| class VLESSParser:
|
| @staticmethod
|
| def parse(url: str) -> Proxy:
|
| if not url.startswith("vless://"):
|
| raise ValueError("Invalid VLESS URL")
|
|
|
| try:
|
| url_parts = url.replace("vless://", "")
|
| uuid_part, server_part = url_parts.split("@", 1)
|
| server_port = server_part.split("?")[0]
|
| server, port = server_port.rsplit(":", 1)
|
|
|
| return Proxy(
|
| ip=server, port=int(port), protocol="vless", source="subscription"
|
| )
|
| except Exception as e:
|
| raise ValueError(f"Failed to parse VLESS URL: {e}")
|
|
|
|
|
| class TrojanParser:
|
| @staticmethod
|
| def parse(url: str) -> Proxy:
|
| if not url.startswith("trojan://"):
|
| raise ValueError("Invalid Trojan URL")
|
|
|
| try:
|
| url_parts = url.replace("trojan://", "")
|
| password_part, server_part = url_parts.split("@", 1)
|
| server_port = server_part.split("?")[0]
|
| server, port = server_port.rsplit(":", 1)
|
|
|
| return Proxy(
|
| ip=server, port=int(port), protocol="trojan", source="subscription"
|
| )
|
| except Exception as e:
|
| raise ValueError(f"Failed to parse Trojan URL: {e}")
|
|
|
|
|
| class SSParser:
|
| @staticmethod
|
| def parse(url: str) -> Proxy:
|
| if not url.startswith("ss://"):
|
| raise ValueError("Invalid Shadowsocks URL")
|
|
|
| try:
|
| url_parts = url.replace("ss://", "")
|
| config_part, server_part = url_parts.split("@", 1)
|
| server, port = server_part.split(":", 1)
|
|
|
| return Proxy(
|
| ip=server, port=int(port), protocol="shadowsocks", source="subscription"
|
| )
|
| except Exception as e:
|
| raise ValueError(f"Failed to parse Shadowsocks URL: {e}")
|
|
|