298 lines
10 KiB
Python
298 lines
10 KiB
Python
"""虎牙手机号自动注册流程。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import threading
|
|
import time
|
|
from dataclasses import dataclass
|
|
from datetime import datetime
|
|
|
|
from core.sms_provider import SmsLine, SmsProviderClient
|
|
|
|
from .change_password import change_huya_password_with_sms_line, generate_huya_password
|
|
from .cookie_utils import cookie_value
|
|
from .login import HuyaLoginError
|
|
from .sms_login import login_huya_sms, normalize_huya_phone, send_huya_sms_code
|
|
|
|
|
|
@dataclass
|
|
class HuyaAutoRegisterResult:
|
|
"""单个手机号自动注册结果。"""
|
|
|
|
phone: str
|
|
provider: str
|
|
success: bool
|
|
status: str
|
|
message: str
|
|
cookie: str = ""
|
|
code: str = ""
|
|
change_code: str = ""
|
|
sdid: str = ""
|
|
normalized_phone: str = ""
|
|
username: str = ""
|
|
uid: str = ""
|
|
password: str = ""
|
|
sms_url: str = ""
|
|
attempts: int = 0
|
|
change_attempts: int = 0
|
|
password_changed: bool = False
|
|
|
|
|
|
def _sleep_or_stop(stop_event: threading.Event | None, seconds: float) -> bool:
|
|
"""等待一小段时间;返回 False 表示收到停止信号。"""
|
|
if seconds <= 0:
|
|
return not (stop_event and stop_event.is_set())
|
|
if stop_event:
|
|
return not stop_event.wait(seconds)
|
|
time.sleep(seconds)
|
|
return True
|
|
|
|
|
|
def register_huya_with_sms_line(
|
|
item: SmsLine,
|
|
wait_seconds: float = 180,
|
|
poll_interval: float = 5,
|
|
change_password: bool = True,
|
|
password_prefix: str = "hy",
|
|
fixed_password: str = "",
|
|
stop_event: threading.Event | None = None,
|
|
) -> HuyaAutoRegisterResult:
|
|
"""使用固定手机号和接码地址完成虎牙短信注册/登录。"""
|
|
phone = item.phone.strip()
|
|
normalized_phone = normalize_huya_phone(phone)
|
|
wait_seconds = max(15.0, float(wait_seconds or 180))
|
|
poll_interval = max(1.0, float(poll_interval or 5))
|
|
|
|
if stop_event and stop_event.is_set():
|
|
return HuyaAutoRegisterResult(
|
|
phone=phone,
|
|
provider=item.provider,
|
|
success=False,
|
|
status="stopped",
|
|
message="已停止",
|
|
normalized_phone=normalized_phone,
|
|
sms_url=item.url,
|
|
)
|
|
|
|
sent_at = datetime.now()
|
|
try:
|
|
code_result = send_huya_sms_code(phone=phone)
|
|
except HuyaLoginError as exc:
|
|
return HuyaAutoRegisterResult(
|
|
phone=phone,
|
|
provider=item.provider,
|
|
success=False,
|
|
status="error",
|
|
message=str(exc),
|
|
normalized_phone=normalized_phone,
|
|
sms_url=item.url,
|
|
)
|
|
except Exception as exc:
|
|
return HuyaAutoRegisterResult(
|
|
phone=phone,
|
|
provider=item.provider,
|
|
success=False,
|
|
status="error",
|
|
message=f"发送虎牙短信失败: {exc}",
|
|
normalized_phone=normalized_phone,
|
|
sms_url=item.url,
|
|
)
|
|
|
|
if not code_result.success or not code_result.state:
|
|
return HuyaAutoRegisterResult(
|
|
phone=phone,
|
|
provider=item.provider,
|
|
success=False,
|
|
status="error",
|
|
message=code_result.message or "发送虎牙短信失败",
|
|
sdid=code_result.sdid,
|
|
normalized_phone=normalized_phone,
|
|
sms_url=item.url,
|
|
)
|
|
|
|
client = SmsProviderClient()
|
|
deadline = time.monotonic() + wait_seconds
|
|
attempts = 0
|
|
last_message = "等待验证码"
|
|
|
|
while time.monotonic() < deadline:
|
|
if stop_event and stop_event.is_set():
|
|
return HuyaAutoRegisterResult(
|
|
phone=phone,
|
|
provider=item.provider,
|
|
success=False,
|
|
status="stopped",
|
|
message="已停止",
|
|
sdid=code_result.sdid,
|
|
normalized_phone=normalized_phone,
|
|
sms_url=item.url,
|
|
attempts=attempts,
|
|
)
|
|
|
|
attempts += 1
|
|
poll_result = client.poll(item, after_time=sent_at)
|
|
last_message = poll_result.message or last_message
|
|
if poll_result.has_code:
|
|
try:
|
|
login_result = login_huya_sms(
|
|
authcode=poll_result.code,
|
|
state=code_result.state,
|
|
phone=phone,
|
|
)
|
|
except HuyaLoginError as exc:
|
|
return HuyaAutoRegisterResult(
|
|
phone=phone,
|
|
provider=item.provider,
|
|
success=False,
|
|
status="error",
|
|
message=str(exc),
|
|
code=poll_result.code,
|
|
sdid=code_result.sdid,
|
|
normalized_phone=normalized_phone,
|
|
sms_url=item.url,
|
|
attempts=attempts,
|
|
)
|
|
except Exception as exc:
|
|
return HuyaAutoRegisterResult(
|
|
phone=phone,
|
|
provider=item.provider,
|
|
success=False,
|
|
status="error",
|
|
message=f"提交虎牙短信登录失败: {exc}",
|
|
code=poll_result.code,
|
|
sdid=code_result.sdid,
|
|
normalized_phone=normalized_phone,
|
|
sms_url=item.url,
|
|
attempts=attempts,
|
|
)
|
|
|
|
if login_result.success and login_result.cookie:
|
|
cookie = login_result.cookie
|
|
uid = cookie_value(cookie, "udb_uid") or cookie_value(cookie, "yyuid")
|
|
username = cookie_value(cookie, "udb_passport") or cookie_value(cookie, "username") or uid
|
|
if not change_password:
|
|
return HuyaAutoRegisterResult(
|
|
phone=phone,
|
|
provider=item.provider,
|
|
success=True,
|
|
status="success",
|
|
message="注册/登录成功",
|
|
cookie=cookie,
|
|
code=poll_result.code,
|
|
sdid=login_result.sdid or code_result.sdid,
|
|
normalized_phone=normalized_phone,
|
|
username=username,
|
|
uid=uid,
|
|
sms_url=item.url,
|
|
attempts=attempts,
|
|
)
|
|
|
|
if not uid:
|
|
return HuyaAutoRegisterResult(
|
|
phone=phone,
|
|
provider=item.provider,
|
|
success=False,
|
|
status="error",
|
|
message="注册成功但 Cookie 中没有识别到虎牙 uid,无法改密",
|
|
cookie=cookie,
|
|
code=poll_result.code,
|
|
sdid=login_result.sdid or code_result.sdid,
|
|
normalized_phone=normalized_phone,
|
|
username=username,
|
|
uid=uid,
|
|
sms_url=item.url,
|
|
attempts=attempts,
|
|
)
|
|
|
|
password = fixed_password.strip() or generate_huya_password(password_prefix)
|
|
change_result = change_huya_password_with_sms_line(
|
|
uid=uid,
|
|
cookie=cookie,
|
|
password=password,
|
|
item=item,
|
|
wait_seconds=wait_seconds,
|
|
poll_interval=poll_interval,
|
|
ignore_codes={poll_result.code},
|
|
stop_event=stop_event,
|
|
)
|
|
if not change_result.success:
|
|
failed_status = "stopped" if change_result.message == "已停止" else "error"
|
|
return HuyaAutoRegisterResult(
|
|
phone=phone,
|
|
provider=item.provider,
|
|
success=False,
|
|
status=failed_status,
|
|
message=f"注册成功但改密失败: {change_result.message}",
|
|
cookie=cookie,
|
|
code=poll_result.code,
|
|
change_code=change_result.code,
|
|
sdid=change_result.sdid or login_result.sdid or code_result.sdid,
|
|
normalized_phone=normalized_phone,
|
|
username=username,
|
|
uid=uid,
|
|
password=password,
|
|
sms_url=item.url,
|
|
attempts=attempts,
|
|
change_attempts=change_result.attempts,
|
|
)
|
|
|
|
return HuyaAutoRegisterResult(
|
|
phone=phone,
|
|
provider=item.provider,
|
|
success=True,
|
|
status="success",
|
|
message="注册并改密成功",
|
|
cookie=cookie,
|
|
code=poll_result.code,
|
|
change_code=change_result.code,
|
|
sdid=login_result.sdid or code_result.sdid,
|
|
normalized_phone=normalized_phone,
|
|
username=username,
|
|
uid=uid,
|
|
password=password,
|
|
sms_url=item.url,
|
|
attempts=attempts,
|
|
change_attempts=change_result.attempts,
|
|
password_changed=True,
|
|
)
|
|
return HuyaAutoRegisterResult(
|
|
phone=phone,
|
|
provider=item.provider,
|
|
success=False,
|
|
status="error",
|
|
message=login_result.message or "虎牙短信登录失败",
|
|
code=poll_result.code,
|
|
sdid=login_result.sdid or code_result.sdid,
|
|
normalized_phone=normalized_phone,
|
|
sms_url=item.url,
|
|
attempts=attempts,
|
|
)
|
|
|
|
remaining = deadline - time.monotonic()
|
|
if remaining <= 0:
|
|
break
|
|
if not _sleep_or_stop(stop_event, min(poll_interval, remaining)):
|
|
return HuyaAutoRegisterResult(
|
|
phone=phone,
|
|
provider=item.provider,
|
|
success=False,
|
|
status="stopped",
|
|
message="已停止",
|
|
sdid=code_result.sdid,
|
|
normalized_phone=normalized_phone,
|
|
sms_url=item.url,
|
|
attempts=attempts,
|
|
)
|
|
|
|
return HuyaAutoRegisterResult(
|
|
phone=phone,
|
|
provider=item.provider,
|
|
success=False,
|
|
status="error",
|
|
message=f"等待验证码超时: {last_message}",
|
|
sdid=code_result.sdid,
|
|
normalized_phone=normalized_phone,
|
|
sms_url=item.url,
|
|
attempts=attempts,
|
|
)
|