feat: 添加代理支持

- 在 .env 中通过 PROXY_URL 配置代理
- 支持 http/https/socks4/socks5 代理
- 所有网络请求(curl_cffi 和 requests)都走代理
- 服务类构造函数新增 proxies 参数传递代理配置
This commit is contained in:
Debug Assistant
2026-02-20 00:05:03 +08:00
parent 91b187903c
commit 6798426c7b
6 changed files with 47 additions and 13 deletions

View File

@@ -6,7 +6,7 @@ from dotenv import load_dotenv
class EmailService:
def __init__(self):
def __init__(self, proxies=None):
load_dotenv()
self.worker_domain = os.getenv("WORKER_DOMAIN")
self.freemail_token = os.getenv("FREEMAIL_TOKEN")
@@ -14,6 +14,7 @@ class EmailService:
raise ValueError("Missing: WORKER_DOMAIN or FREEMAIL_TOKEN")
self.base_url = f"https://{self.worker_domain}"
self.headers = {"Authorization": f"Bearer {self.freemail_token}"}
self.proxies = proxies or {}
def create_email(self):
"""创建临时邮箱 GET /api/generate"""
@@ -21,6 +22,7 @@ class EmailService:
res = requests.get(
f"{self.base_url}/api/generate",
headers=self.headers,
proxies=self.proxies,
timeout=10
)
if res.status_code == 200:
@@ -44,6 +46,7 @@ class EmailService:
f"{self.base_url}/api/emails",
params={"mailbox": email},
headers=self.headers,
proxies=self.proxies,
timeout=10
)
if debug:
@@ -91,6 +94,7 @@ class EmailService:
f"{self.base_url}/api/mailboxes",
params={"address": address},
headers=self.headers,
proxies=self.proxies,
timeout=10
)
return res.status_code == 200 and res.json().get("success")

View File

@@ -25,6 +25,7 @@ class NsfwSettingsService:
user_agent: Optional[str] = None,
cf_clearance: Optional[str] = None,
timeout: int = 15,
proxies: Optional[Dict[str, str]] = None,
) -> Dict[str, Any]:
"""
启用 always_show_nsfw_content。
@@ -88,6 +89,7 @@ class NsfwSettingsService:
data=data,
impersonate=impersonate or "chrome120",
timeout=timeout,
proxies=proxies or {},
)
hex_reply = response.content.hex()
grpc_status = response.headers.get("grpc-status")
@@ -124,6 +126,7 @@ class NsfwSettingsService:
impersonate: str = "chrome120",
user_agent: Optional[str] = None,
timeout: int = 30,
proxies: Optional[Dict[str, str]] = None,
) -> Dict[str, Any]:
"""
使用帖子方法开启 Unhinged 模式(二次验证)。
@@ -153,6 +156,7 @@ class NsfwSettingsService:
data=data,
impersonate=impersonate,
timeout=timeout,
proxies=proxies or {},
)
return {
"ok": response.status_code == 200,

View File

@@ -12,13 +12,14 @@ load_dotenv()
class TurnstileService:
"""Turnstile验证服务类"""
def __init__(self, solver_url="http://127.0.0.1:5072"):
def __init__(self, solver_url="http://127.0.0.1:5072", proxies=None):
"""
初始化Turnstile服务
"""
self.yescaptcha_key = os.getenv('YESCAPTCHA_KEY', '').strip()
self.solver_url = solver_url
self.yescaptcha_api = "https://api.yescaptcha.com"
self.proxies = proxies or {}
def create_task(self, siteurl, sitekey):
"""
@@ -35,7 +36,7 @@ class TurnstileService:
"websiteKey": sitekey
}
}
response = requests.post(url, json=payload)
response = requests.post(url, json=payload, proxies=self.proxies)
response.raise_for_status()
data = response.json()
if data.get('errorId') != 0:
@@ -44,7 +45,7 @@ class TurnstileService:
else:
# 使用本地 Turnstile Solver
url = f"{self.solver_url}/turnstile?url={siteurl}&sitekey={sitekey}"
response = requests.get(url)
response = requests.get(url, proxies=self.proxies)
response.raise_for_status()
return response.json()['taskId']
@@ -63,7 +64,7 @@ class TurnstileService:
"clientKey": self.yescaptcha_key,
"taskId": task_id
}
response = requests.post(url, json=payload)
response = requests.post(url, json=payload, proxies=self.proxies)
response.raise_for_status()
data = response.json()
@@ -86,7 +87,7 @@ class TurnstileService:
else:
# 使用本地 Turnstile Solver
url = f"{self.solver_url}/result?id={task_id}"
response = requests.get(url)
response = requests.get(url, proxies=self.proxies)
response.raise_for_status()
data = response.json()
captcha = data.get('solution', {}).get('token', None)

View File

@@ -25,6 +25,7 @@ class UserAgreementService:
user_agent: Optional[str] = None,
cf_clearance: Optional[str] = None,
timeout: int = 15,
proxies: Optional[Dict[str, str]] = None,
) -> Dict[str, Any]:
"""
同意 TOS 版本。
@@ -85,6 +86,7 @@ class UserAgreementService:
data=data,
impersonate=impersonate or "chrome120",
timeout=timeout,
proxies=proxies or {},
)
hex_reply = response.content.hex()
grpc_status = response.headers.get("grpc-status")