feat(huya): 支持四段式账号导入接码及旋转/文本点选多级验证码闭环过验

- 账号导入:支持'账号----密码----手机号----接码链接'四段式解析与持久化存储
- 旋转验证码 (rotate_auth / xz):逆向分析官方协议,基于圆周边界采样互相关算法秒级计算旋转还原角度
- 文本点选验证码 (dx_auth):内置成语与古诗名句语料,支持题干菜名提取与古诗/成语挖空正则求解及小图动态合成
- 短信二次验证 (sms_auth2):结合 sms_url 自动轮询接码链接并 Hex 编码提交官方过验
- 前端交互:增加接码标签、在线查询短信验证码、一键自动短信登录与测试接码链接功能
- 回归测试:新增旋转验证、短信接码流与文本点选测试用例(173 passed)
This commit is contained in:
yml2213
2026-09-06 13:56:44 +08:00
parent 4f9a6864eb
commit d3005478a9
15 changed files with 31411 additions and 24 deletions
+7
View File
@@ -20,6 +20,7 @@ import type {
HuyaAppPasswordLoginRequest,
HuyaPasswordLoginResult,
HuyaPasswordLoginSelectedRequest,
HuyaFetchSmsCodeResult,
HuyaRechargeGoodsItem,
HuyaRegisterSuccessLog,
HuyaSmsCodeRequest,
@@ -73,6 +74,12 @@ export const huyaApi = {
api.post<HuyaSmsCodeResult, HuyaSmsCodeResult>('/huya/accounts/sms-code', data, { timeout: 120000 }),
smsLogin: (data: HuyaSmsLoginRequest) =>
api.post<HuyaSmsLoginResult, HuyaSmsLoginResult>('/huya/accounts/sms-login', data, { timeout: 120000 }),
testSmsUrl: (sms_url: string) =>
api.post<HuyaFetchSmsCodeResult, HuyaFetchSmsCodeResult>('/huya/accounts/test-sms-url', { sms_url }),
fetchSmsCode: (accountId: number) =>
api.post<HuyaFetchSmsCodeResult, HuyaFetchSmsCodeResult>(`/huya/accounts/${accountId}/fetch-sms-code`),
autoSmsLogin: (accountId: number) =>
api.post<HuyaPasswordLoginResult, HuyaPasswordLoginResult>(`/huya/accounts/${accountId}/auto-sms-login`),
startAutoRegister: (data: HuyaAutoRegisterRequest) =>
api.post<HuyaAutoRegisterBatch, HuyaAutoRegisterBatch>('/huya/register/batches', data),
listAutoRegisterBatches: (limit = 50) =>
+9
View File
@@ -458,12 +458,21 @@ export interface HuyaAccountItem {
game_name: string;
game_channel: string;
game_phone: string;
sms_url?: string;
assigned_to: number | null;
assigned_username: string | null;
created_at: string | null;
updated_at: string | null;
}
export interface HuyaFetchSmsCodeResult {
code: string | null;
raw: string;
success: boolean;
message: string;
}
/** 工作台账号集合范围: elite=精英宝典 / browser_exchange=浏览器兑换 */
export type HuyaWorkbenchScope = 'elite' | 'browser_exchange';
+60 -6
View File
@@ -4,7 +4,7 @@ import {
} from 'antd';
import { message } from '../utils/antdMessage';
import type { TableProps } from 'antd';
import { DeleteOutlined, FilterOutlined, ImportOutlined, LoginOutlined, MobileOutlined, ReloadOutlined, SearchOutlined, TagOutlined } from '@ant-design/icons';
import { DeleteOutlined, FilterOutlined, ImportOutlined, LoginOutlined, MailOutlined, MobileOutlined, ReloadOutlined, SearchOutlined, TagOutlined } from '@ant-design/icons';
import {
huyaApi,
type HuyaAccountItem,
@@ -351,6 +351,41 @@ export default function HuyaAccountsPage() {
}
};
const [fetchingSmsId, setFetchingSmsId] = useState<number | null>(null);
const handleFetchSmsCode = async (record: HuyaAccountItem) => {
setFetchingSmsId(record.id);
try {
const res = await huyaApi.fetchSmsCode(record.id);
if (res.success && res.code) {
Modal.success({
title: '已获取最新短信验证码',
content: (
<div style={{ marginTop: 12 }}>
<div style={{ marginBottom: 8, fontSize: 16 }}>
验证码: <b style={{ color: '#1677ff', fontSize: 22 }}>{res.code}</b>
</div>
<Paragraph type="secondary" copyable>{res.raw}</Paragraph>
</div>
),
});
} else {
Modal.info({
title: '接码链接查询结果',
content: (
<div style={{ marginTop: 12 }}>
<p>{res.message}</p>
<Paragraph type="secondary">{res.raw || '尚未收到新短信'}</Paragraph>
</div>
),
});
}
} catch (e: unknown) {
message.error(getErrorMessage(e));
} finally {
setFetchingSmsId(null);
}
};
const handleWebLoginSelected = async () => {
if (selectedCount === 0) {
message.warning('请先选择虎牙账号');
@@ -537,9 +572,18 @@ export default function HuyaAccountsPage() {
{
title: '手机号',
dataIndex: 'game_phone',
width: 140,
width: 150,
ellipsis: true,
render: (value: string) => value || <Text type="secondary">-</Text>,
render: (value: string, record) => (
<Space size={4}>
<Text>{value || '-'}</Text>
{record.sms_url ? (
<Tooltip title={`已绑定接码: ${record.sms_url}`}>
<Tag color="cyan" style={{ margin: 0, fontSize: 10, cursor: 'pointer' }}>接码</Tag>
</Tooltip>
) : null}
</Space>
),
},
{
title: 'Cookie',
@@ -600,7 +644,7 @@ export default function HuyaAccountsPage() {
},
{
title: '操作',
width: 150,
width: 180,
fixed: 'right',
align: 'center',
render: (_: unknown, record) => (
@@ -626,6 +670,16 @@ export default function HuyaAccountsPage() {
</Tooltip>
</>
)}
{record.sms_url && (
<Tooltip title="从接码链接读取最新短信验证码">
<Button
size="small"
icon={<MailOutlined />}
loading={fetchingSmsId === record.id}
onClick={() => handleFetchSmsCode(record)}
/>
</Tooltip>
)}
{canDelete && (
<Popconfirm title="确认删除这条虎牙账号?" onConfirm={() => handleDelete(record.id)}>
<Button danger size="small" icon={<DeleteOutlined />} />
@@ -897,7 +951,7 @@ export default function HuyaAccountsPage() {
rows={10}
value={passwordImportText}
onChange={(e) => setPasswordImportText(e.target.value)}
placeholder="每行一条:账号----密码;也支持:虎牙号----密码----手机号----验证码链接"
placeholder={`每行一条格式:\n1. 账号----密码\n2. 账号----密码----手机号----接码链接\n例如:hy_299112483----aa778899----+14504409332----http://194.163.45.144/api/get_sms?key=c16fe33219924363fa362ed69dc6fd4f`}
disabled={passwordImporting}
/>
<Select
@@ -911,7 +965,7 @@ export default function HuyaAccountsPage() {
disabled={passwordImporting}
/>
<Paragraph type="secondary" style={{ marginBottom: 0 }}>
四段格式会保存手机号;验证码链接用于接码池兼容,不会写入账号表。
四段格式:<code>账号----密码----手机号----接码链接</code>。接码链接与手机号将自动保存入库。后续 App 密码登录如触发短信二次验证(sms_auth2),系统将自动从接码链接获取验证码完成全自动过验!
</Paragraph>
</Space>
</Modal>