完善自动注册代理和状态恢复

This commit is contained in:
yml2213
2026-07-06 02:58:17 +08:00
parent db4ca78280
commit 72e7947a39
7 changed files with 223 additions and 19 deletions
+5 -1
View File
@@ -23,7 +23,7 @@ from core.sms_provider import parse_sms_lines
from ..database import SessionLocal, get_db
from ..deps import authenticate_websocket, get_current_user, require_permission
from ..models import HuyaAccount, HuyaConfig, HuyaGoodsSnapshot, HuyaRechargeGoodsSnapshot, HuyaTask, User
from ..models import HuyaAccount, HuyaConfig, HuyaGoodsSnapshot, HuyaRechargeGoodsSnapshot, HuyaTask, ProxyConfig, User
from ..permissions import user_has_permission
from ..schemas import (
AccountAssign,
@@ -344,6 +344,7 @@ def sms_login_account(
@router.post("/register/batches", response_model=HuyaAutoRegisterBatchOut)
def create_auto_register_batch(
req: HuyaAutoRegisterRequest,
db: Session = Depends(get_db),
current: User = Depends(get_current_user),
):
"""启动虎牙手机号自动注册批次。"""
@@ -352,6 +353,7 @@ def create_auto_register_batch(
if not sms_lines:
raise HTTPException(status_code=400, detail="没有识别到有效手机号,格式为:手机号----短信查询URL")
proxy_config = db.query(ProxyConfig).first() if req.use_proxy else None
runner = huya_register_registry.create(
sms_lines=sms_lines,
tag=req.tag.strip(),
@@ -361,6 +363,8 @@ def create_auto_register_batch(
poll_interval=req.poll_interval,
password_prefix=req.password_prefix,
fixed_password=req.fixed_password,
use_proxy=req.use_proxy,
proxy_config=proxy_config,
)
thread = threading.Thread(target=runner.run, daemon=True)
thread.start()
+2
View File
@@ -206,6 +206,7 @@ class HuyaAutoRegisterRequest(BaseModel):
poll_interval: float = Field(5, ge=1, le=30)
password_prefix: str = Field("hy", max_length=8)
fixed_password: str = Field("", max_length=64)
use_proxy: bool = False
class HuyaAutoRegisterItemOut(BaseModel):
@@ -240,6 +241,7 @@ class HuyaAutoRegisterBatchOut(BaseModel):
wait_seconds: float
poll_interval: float
password_prefix: str = "hy"
use_proxy: bool = False
total: int
success_count: int
failed_count: int
+68 -1
View File
@@ -7,12 +7,15 @@ import uuid
from concurrent.futures import ThreadPoolExecutor, as_completed
from dataclasses import dataclass, field
from datetime import datetime, timezone
from typing import Optional
from core.douyu.proxy_fetcher import ProxyFetcher
from core.huya.auto_register import HuyaAutoRegisterResult, register_huya_with_sms_line
from core.huya.cookie_utils import normalize_huya_cookie
from core.sms_provider import SmsLine
from ..database import SessionLocal
from ..models import ProxyConfig as ProxyConfigModel
from .huya_service import upsert_huya_cookie
@@ -88,6 +91,7 @@ class HuyaRegisterBatch:
items: list[HuyaRegisterItemState]
password_prefix: str = "hy"
fixed_password: str = ""
use_proxy: bool = False
status: str = "pending"
message: str = "等待开始"
created_at: datetime = field(default_factory=_now)
@@ -102,11 +106,39 @@ class HuyaRegisterRunner:
self,
batch: HuyaRegisterBatch,
sms_lines: list[SmsLine],
proxy_config: Optional[ProxyConfigModel] = None,
):
self.batch = batch
self.sms_lines = sms_lines
self.proxy_config = proxy_config
self._lock = threading.Lock()
self._stop = threading.Event()
self._shared_proxy_fetcher = self._create_proxy_fetcher()
def _create_proxy_fetcher(self) -> ProxyFetcher | None:
"""按需创建 API 代理获取器。"""
if not self.batch.use_proxy or not self.proxy_config or not self.proxy_config.enabled:
return None
if not self.proxy_config.api_url:
return None
wl_platform = "xiequ"
wl_credentials = None
if self.proxy_config.whitelist_enabled:
wl_platform = getattr(self.proxy_config, "whitelist_platform", None) or "xiequ"
wl_credentials = getattr(self.proxy_config, "whitelist_credentials", None)
if not wl_credentials and self.proxy_config.whitelist_uid and self.proxy_config.whitelist_ukey:
wl_credentials = {
"uid": self.proxy_config.whitelist_uid,
"ukey": self.proxy_config.whitelist_ukey,
}
return ProxyFetcher(
api_url=self.proxy_config.api_url,
whitelist_platform=wl_platform,
whitelist_credentials=wl_credentials,
stop_event=self._stop,
)
def stop(self):
self._stop.set()
@@ -131,6 +163,7 @@ class HuyaRegisterRunner:
"wait_seconds": self.batch.wait_seconds,
"poll_interval": self.batch.poll_interval,
"password_prefix": self.batch.password_prefix,
"use_proxy": self.batch.use_proxy,
"total": total,
"success_count": success,
"failed_count": failed,
@@ -166,11 +199,35 @@ class HuyaRegisterRunner:
finally:
db.close()
def _resolve_proxy(self) -> tuple[dict[str, str] | None, str]:
"""为单个手机号解析代理;返回代理字典和错误消息。"""
if not self.batch.use_proxy:
return None, ""
if not self.proxy_config or not self.proxy_config.enabled:
return None, "已开启代理,但代理配置未启用"
if self.proxy_config.http or self.proxy_config.https:
proxy_url = self.proxy_config.http or self.proxy_config.https
return {"http": proxy_url, "https": proxy_url}, ""
if self._shared_proxy_fetcher:
proxy_url = self._shared_proxy_fetcher.fetch_new_proxy(max_attempts=3)
if proxy_url:
return {"http": proxy_url, "https": proxy_url}, ""
return None, "获取代理失败"
return None, "已开启代理,但未配置静态代理或代理 API"
def _run_one(self, index: int, item: SmsLine):
if self._stop.is_set():
self._set_item(index, status="stopped", message="已停止", finished_at=_now())
return
proxies, proxy_error = self._resolve_proxy()
if proxy_error:
self._set_item(index, status="error", message=proxy_error, finished_at=_now())
return
self._set_item(index, status="sending", message="注册并改密", started_at=_now(), finished_at=None)
result = register_huya_with_sms_line(
item,
@@ -178,6 +235,7 @@ class HuyaRegisterRunner:
poll_interval=self.batch.poll_interval,
password_prefix=self.batch.password_prefix,
fixed_password=self.batch.fixed_password,
proxies=proxies,
stop_event=self._stop,
)
@@ -236,6 +294,12 @@ class HuyaRegisterRunner:
self.batch.started_at = _now()
try:
if self._shared_proxy_fetcher:
ok, msg = self._shared_proxy_fetcher.warmup_whitelist()
if not ok:
with self._lock:
self.batch.message = f"代理白名单预热失败: {msg}"
with ThreadPoolExecutor(max_workers=self.batch.concurrency) as executor:
futures = []
for index, item in enumerate(self.sms_lines):
@@ -280,6 +344,8 @@ class HuyaRegisterRegistry:
poll_interval: float,
password_prefix: str = "hy",
fixed_password: str = "",
use_proxy: bool = False,
proxy_config: Optional[ProxyConfigModel] = None,
) -> HuyaRegisterRunner:
batch_id = uuid.uuid4().hex[:12]
batch = HuyaRegisterBatch(
@@ -291,12 +357,13 @@ class HuyaRegisterRegistry:
poll_interval=max(1.0, float(poll_interval or 5)),
password_prefix=(password_prefix or "hy").strip()[:8] or "hy",
fixed_password=(fixed_password or "").strip(),
use_proxy=bool(use_proxy),
items=[
HuyaRegisterItemState(line=index + 1, phone=item.phone, provider=item.provider, sms_url=item.url)
for index, item in enumerate(sms_lines)
],
)
runner = HuyaRegisterRunner(batch=batch, sms_lines=sms_lines)
runner = HuyaRegisterRunner(batch=batch, sms_lines=sms_lines, proxy_config=proxy_config)
with self._lock:
self._runners[batch_id] = runner
return runner