- 账号导入:支持'账号----密码----手机号----接码链接'四段式解析与持久化存储 - 旋转验证码 (rotate_auth / xz):逆向分析官方协议,基于圆周边界采样互相关算法秒级计算旋转还原角度 - 文本点选验证码 (dx_auth):内置成语与古诗名句语料,支持题干菜名提取与古诗/成语挖空正则求解及小图动态合成 - 短信二次验证 (sms_auth2):结合 sms_url 自动轮询接码链接并 Hex 编码提交官方过验 - 前端交互:增加接码标签、在线查询短信验证码、一键自动短信登录与测试接码链接功能 - 回归测试:新增旋转验证、短信接码流与文本点选测试用例(173 passed)
143 lines
4.7 KiB
Python
143 lines
4.7 KiB
Python
"""虎牙四段式账号 (账号----密码----手机号----接码链接) 导入与短信自动求解测试。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
from core.huya.verification.solver import (
|
|
HuyaSmsAuthRequiredError,
|
|
HuyaVerificationSolver,
|
|
)
|
|
from web.backend.services.huya_service import (
|
|
import_huya_password_accounts,
|
|
split_huya_password_line,
|
|
)
|
|
|
|
|
|
def test_parse_password_line_with_sms_url():
|
|
"""测试四段式账号行解析 (账号----密码----手机号----接码链接)。"""
|
|
line = (
|
|
"hy_299112483----aa778899----+14504409332----"
|
|
"http://194.163.45.144/api/get_sms?key=c16fe33219924363fa362ed69dc6fd4f"
|
|
)
|
|
parsed = split_huya_password_line(line)
|
|
assert parsed is not None
|
|
assert parsed.username == "hy_299112483"
|
|
assert parsed.password == "aa778899"
|
|
assert parsed.phone == "+14504409332"
|
|
assert (
|
|
parsed.sms_url
|
|
== "http://194.163.45.144/api/get_sms?key=c16fe33219924363fa362ed69dc6fd4f"
|
|
)
|
|
|
|
|
|
def test_parse_password_line_backward_compatible():
|
|
"""测试老格式向后兼容性。"""
|
|
# 2段
|
|
p2 = split_huya_password_line("user123----pass456")
|
|
assert p2 is not None
|
|
assert p2.username == "user123"
|
|
assert p2.password == "pass456"
|
|
assert p2.phone == ""
|
|
assert p2.sms_url == ""
|
|
|
|
# 3段 (带手机号或cookie)
|
|
p3 = split_huya_password_line("user123----pass456----13800138000")
|
|
assert p3 is not None
|
|
assert p3.username == "user123"
|
|
assert p3.password == "pass456"
|
|
assert p3.cookie == "13800138000"
|
|
assert p3.sms_url == ""
|
|
|
|
|
|
def test_import_password_accounts_persists_sms_url():
|
|
"""测试导入账号密码服务会正确写入 sms_url 和 game_phone。"""
|
|
mock_db = MagicMock()
|
|
# 模拟无现有账号
|
|
mock_db.query().filter().first.return_value = None
|
|
|
|
text = (
|
|
"hy_299112483----aa778899----+14504409332----"
|
|
"http://194.163.45.144/api/get_sms?key=c16fe33219924363fa362ed69dc6fd4f"
|
|
)
|
|
created, skipped = import_huya_password_accounts(mock_db, text, tag="测试接码")
|
|
assert created == 1
|
|
assert skipped == 0
|
|
|
|
added_account = mock_db.add.call_args[0][0]
|
|
assert added_account.username == "hy_299112483"
|
|
assert added_account.game_phone == "+14504409332"
|
|
assert (
|
|
added_account.sms_url
|
|
== "http://194.163.45.144/api/get_sms?key=c16fe33219924363fa362ed69dc6fd4f"
|
|
)
|
|
assert added_account.tag == "测试接码"
|
|
|
|
|
|
def test_solver_strategy_with_and_without_sms_url():
|
|
"""测试在遇到 sms_auth2 时,有接码链接不抛异常,无接码链接抛出短信异常。"""
|
|
url = "https://aq.huya.com/p/safe_auth/sms_auth2.html?param=xyz&mobile=14504409332"
|
|
|
|
# 无 sms_url,应触发 HuyaSmsAuthRequiredError
|
|
solver_no_sms = HuyaVerificationSolver(page_url=url)
|
|
with pytest.raises(HuyaSmsAuthRequiredError):
|
|
solver_no_sms._parse_strategy(url)
|
|
|
|
# 有 sms_url,应正常解析为 sms_auth
|
|
solver_with_sms = HuyaVerificationSolver(
|
|
page_url=url,
|
|
sms_url="http://194.163.45.144/api/get_sms?key=test",
|
|
)
|
|
solver_with_sms._parse_strategy(url)
|
|
assert solver_with_sms.auth_type == "sms_auth"
|
|
|
|
|
|
def test_solver_sms_flow():
|
|
"""测试 solver._solve_sms_strategy 自动发码、接码与提码闭环。"""
|
|
from core.sms_provider import SmsPollResult
|
|
|
|
url = "https://aq.huya.com/p/safe_auth/sms_auth2.html?param=mock_param&mobile=14504409332&appId=5002"
|
|
solver = HuyaVerificationSolver(
|
|
page_url=url,
|
|
sms_url="http://194.163.45.144/api/get_sms?key=test_key",
|
|
account="hy_test",
|
|
)
|
|
solver._parse_strategy(url)
|
|
|
|
mock_send_res = {"returnCode": 0, "message": "发送成功"}
|
|
mock_verify_res = {
|
|
"returnCode": 0,
|
|
"data": {"authId": "auth_token_success_123"},
|
|
}
|
|
|
|
with (
|
|
patch.object(
|
|
solver,
|
|
"_request_json",
|
|
return_value=mock_send_res,
|
|
) as mock_req_json,
|
|
patch.object(
|
|
solver,
|
|
"_submit_verify",
|
|
return_value=mock_verify_res["data"],
|
|
) as mock_submit,
|
|
patch(
|
|
"core.sms_provider.SmsProviderClient.poll",
|
|
return_value=SmsPollResult(status="code", code="654321"),
|
|
) as mock_poll,
|
|
):
|
|
data = solver._solve_sms_strategy()
|
|
|
|
assert data["authId"] == "auth_token_success_123"
|
|
mock_req_json.assert_called_once()
|
|
assert "send-sms-code" in mock_req_json.call_args[0][1]
|
|
|
|
mock_poll.assert_called_once()
|
|
|
|
mock_submit.assert_called_once()
|
|
verify_url, verify_payload = mock_submit.call_args[0]
|
|
assert "verify-sms-code" in verify_url
|
|
assert verify_payload["data"]["smsCode"] == "654321".encode().hex()
|