File size: 2,159 Bytes
c1f87fd | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | import re
from typing import List, Tuple
class ProxyPatterns:
HTTP_IP_PORT = re.compile(
r"\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}"
r"(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
r":([0-9]{1,5})\b"
)
VMESS_URL = re.compile(r"vmess://[A-Za-z0-9+/=]+")
VLESS_URL = re.compile(r"vless://[a-zA-Z0-9-]+@[a-zA-Z0-9.-]+:[0-9]+[^\s]*")
TROJAN_URL = re.compile(r"trojan://[^@\s]+@[a-zA-Z0-9.-]+:[0-9]+[^\s]*")
SS_URL = re.compile(r"ss://[A-Za-z0-9+/=]+@[a-zA-Z0-9.-]+:[0-9]+")
@classmethod
def extract_http_proxies(cls, text: str) -> List[Tuple[str, str]]:
result = []
for match in cls.HTTP_IP_PORT.finditer(text):
ip_port = match.group(0)
ip, port = ip_port.rsplit(":", 1)
result.append((ip, port))
return result
@classmethod
def is_vmess(cls, url: str) -> bool:
return bool(cls.VMESS_URL.match(url))
@classmethod
def extract_vmess_urls(cls, text: str) -> List[str]:
return cls.VMESS_URL.findall(text)
@classmethod
def is_vless(cls, url: str) -> bool:
return bool(cls.VLESS_URL.match(url))
@classmethod
def extract_vless_urls(cls, text: str) -> List[str]:
return cls.VLESS_URL.findall(text)
@classmethod
def is_trojan(cls, url: str) -> bool:
return bool(cls.TROJAN_URL.match(url))
@classmethod
def extract_trojan_urls(cls, text: str) -> List[str]:
return cls.TROJAN_URL.findall(text)
@classmethod
def is_shadowsocks(cls, url: str) -> bool:
return bool(cls.SS_URL.match(url))
@classmethod
def extract_ss_urls(cls, text: str) -> List[str]:
return cls.SS_URL.findall(text)
@classmethod
def is_valid_ip(cls, ip: str) -> bool:
try:
octets = ip.split(".")
return len(octets) == 4 and all(0 <= int(o) <= 255 for o in octets)
except (ValueError, AttributeError):
return False
@classmethod
def is_valid_port(cls, port: int) -> bool:
return 1 <= port <= 65535
|