fix: 提前捕获NapCat验证码日志
This commit is contained in:
parent
3dec63b5d2
commit
e5709e00e1
@ -1760,26 +1760,39 @@ export class QqbotNapcatLoginService {
|
|||||||
}
|
}
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
const qrcodeChallenge = this.isPasswordQrcodeChallenge(latestStatus);
|
||||||
|
const captchaRequired = this.toolsService.isNapcatCaptchaRequiredMessage(
|
||||||
|
latestStatus.loginError,
|
||||||
|
);
|
||||||
|
const hasRestartTimestamp =
|
||||||
|
typeof sinceMs === 'number' && Number.isFinite(sinceMs);
|
||||||
if (
|
if (
|
||||||
latestStatus.isLogin ||
|
!latestStatus.isLogin &&
|
||||||
this.isPasswordQrcodeChallenge(latestStatus) ||
|
!qrcodeChallenge &&
|
||||||
this.toolsService.isNapcatCaptchaRequiredMessage(
|
(hasRestartTimestamp || captchaRequired)
|
||||||
latestStatus.loginError,
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
|
latestStatus.captchaUrl =
|
||||||
|
this.getCaptchaUrlFromStatus(latestStatus) ||
|
||||||
|
(await this.detectPasswordCaptchaUrl(
|
||||||
|
container,
|
||||||
|
sinceMs,
|
||||||
|
captchaRequired,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if (latestStatus.isLogin || qrcodeChallenge || captchaRequired) {
|
||||||
if (
|
if (
|
||||||
!this.getCaptchaUrlFromStatus(latestStatus) &&
|
!this.getCaptchaUrlFromStatus(latestStatus) &&
|
||||||
this.toolsService.isNapcatCaptchaRequiredMessage(
|
captchaRequired
|
||||||
latestStatus.loginError,
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
latestStatus.captchaUrl = await this.detectPasswordCaptchaUrl(
|
latestStatus.captchaUrl = await this.detectPasswordCaptchaUrl(
|
||||||
container,
|
container,
|
||||||
sinceMs,
|
sinceMs,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return latestStatus;
|
return latestStatus;
|
||||||
}
|
}
|
||||||
|
if (latestStatus.captchaUrl) return latestStatus;
|
||||||
}
|
}
|
||||||
return latestStatus;
|
return latestStatus;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -759,8 +759,9 @@ describe('QqbotNapcatLoginService', () => {
|
|||||||
const containerService = {
|
const containerService = {
|
||||||
detectRuntimeCaptchaUrl: jest
|
detectRuntimeCaptchaUrl: jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockResolvedValueOnce(null)
|
.mockImplementation(async (_runtime: unknown, sinceMs?: number) =>
|
||||||
.mockResolvedValueOnce(staleCaptchaUrl),
|
typeof sinceMs === 'number' ? null : staleCaptchaUrl,
|
||||||
|
),
|
||||||
ensureRuntimeLoginEnv: jest
|
ensureRuntimeLoginEnv: jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockResolvedValue({ changed: true, ok: true }),
|
.mockResolvedValue({ changed: true, ok: true }),
|
||||||
@ -815,10 +816,52 @@ describe('QqbotNapcatLoginService', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(session.captchaUrl).toBeUndefined();
|
expect(session.captchaUrl).toBeUndefined();
|
||||||
expect(containerService.detectRuntimeCaptchaUrl).toHaveBeenCalledTimes(1);
|
expect(containerService.detectRuntimeCaptchaUrl).toHaveBeenCalledTimes(2);
|
||||||
|
expect(containerService.detectRuntimeCaptchaUrl).not.toHaveBeenCalledWith(
|
||||||
|
container,
|
||||||
|
);
|
||||||
expect(session.qrcode).toBe('fallback-qrcode');
|
expect(session.qrcode).toBe('fallback-qrcode');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not read tail captcha logs for processing status without restart timestamp', async () => {
|
||||||
|
const staleCaptchaUrl =
|
||||||
|
'https://ti.qq.com/safe/tools/captcha/sms-verify-login?uin=10001';
|
||||||
|
const containerService = {
|
||||||
|
detectRuntimeCaptchaUrl: jest.fn().mockResolvedValue(staleCaptchaUrl),
|
||||||
|
};
|
||||||
|
const refreshService = new QqbotNapcatLoginService(
|
||||||
|
{
|
||||||
|
get: jest.fn((key: string) => {
|
||||||
|
const values: Record<string, string> = {
|
||||||
|
QQBOT_NAPCAT_LOGIN_POLL_INTERVAL_MS: '1',
|
||||||
|
QQBOT_NAPCAT_PASSWORD_LOGIN_WAIT_MS: '1',
|
||||||
|
};
|
||||||
|
return values[key] || '';
|
||||||
|
}),
|
||||||
|
} as unknown as ConfigService,
|
||||||
|
{} as QqbotAccountService,
|
||||||
|
containerService as unknown as QqbotNapcatContainerService,
|
||||||
|
new ToolsService(),
|
||||||
|
);
|
||||||
|
jest
|
||||||
|
.spyOn((refreshService as any).toolsService, 'sleep')
|
||||||
|
.mockResolvedValue(undefined);
|
||||||
|
jest.spyOn(refreshService as any, 'getLoginStatus').mockResolvedValue({
|
||||||
|
isLogin: false,
|
||||||
|
loginError: '密码登录处理中',
|
||||||
|
});
|
||||||
|
|
||||||
|
const status = await (refreshService as any).waitForPasswordLoginStatus({
|
||||||
|
baseUrl: 'http://127.0.0.1:6103/',
|
||||||
|
id: 'container-stale-tail-no-since',
|
||||||
|
name: 'napcat-10001',
|
||||||
|
webuiToken: 'token',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(status.captchaUrl).toBeUndefined();
|
||||||
|
expect(containerService.detectRuntimeCaptchaUrl).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
it('keeps password captcha pending before cleanup when status check throws captcha error', async () => {
|
it('keeps password captcha pending before cleanup when status check throws captcha error', async () => {
|
||||||
const captchaUrl =
|
const captchaUrl =
|
||||||
'https://ti.qq.com/safe/tools/captcha/sms-verify-login?uin=10001';
|
'https://ti.qq.com/safe/tools/captcha/sms-verify-login?uin=10001';
|
||||||
@ -1329,6 +1372,60 @@ describe('QqbotNapcatLoginService', () => {
|
|||||||
expect(sleep).not.toHaveBeenCalled();
|
expect(sleep).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns captcha status during password wait when processing logs already contain captcha url', async () => {
|
||||||
|
const restartedAt = Date.now() - 1500;
|
||||||
|
const captchaUrl =
|
||||||
|
'https://ti.qq.com/safe/tools/captcha/sms-verify-login?uin=10001';
|
||||||
|
const containerService = {
|
||||||
|
detectRuntimeCaptchaUrl: jest.fn().mockResolvedValue(captchaUrl),
|
||||||
|
};
|
||||||
|
const refreshService = new QqbotNapcatLoginService(
|
||||||
|
{
|
||||||
|
get: jest.fn((key: string) => {
|
||||||
|
const values: Record<string, string> = {
|
||||||
|
QQBOT_NAPCAT_LOGIN_POLL_INTERVAL_MS: '1000',
|
||||||
|
QQBOT_NAPCAT_PASSWORD_LOGIN_WAIT_MS: '3000',
|
||||||
|
};
|
||||||
|
return values[key] || '';
|
||||||
|
}),
|
||||||
|
} as unknown as ConfigService,
|
||||||
|
{} as QqbotAccountService,
|
||||||
|
containerService as unknown as QqbotNapcatContainerService,
|
||||||
|
new ToolsService(),
|
||||||
|
);
|
||||||
|
const getLoginStatus = jest
|
||||||
|
.spyOn(refreshService as any, 'getLoginStatus')
|
||||||
|
.mockResolvedValue({
|
||||||
|
isLogin: false,
|
||||||
|
loginError: '密码登录处理中',
|
||||||
|
});
|
||||||
|
const sleep = jest
|
||||||
|
.spyOn((refreshService as any).toolsService, 'sleep')
|
||||||
|
.mockResolvedValue(undefined);
|
||||||
|
|
||||||
|
const status = await (refreshService as any).waitForPasswordLoginStatus(
|
||||||
|
{
|
||||||
|
baseUrl: 'http://127.0.0.1:6103/',
|
||||||
|
id: 'container-captcha-log-processing',
|
||||||
|
name: 'napcat-10001',
|
||||||
|
webuiToken: 'token',
|
||||||
|
},
|
||||||
|
restartedAt,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(status).toMatchObject({
|
||||||
|
captchaUrl,
|
||||||
|
isLogin: false,
|
||||||
|
loginError: '密码登录处理中',
|
||||||
|
});
|
||||||
|
expect(containerService.detectRuntimeCaptchaUrl).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({ name: 'napcat-10001' }),
|
||||||
|
restartedAt,
|
||||||
|
);
|
||||||
|
expect(getLoginStatus).toHaveBeenCalledTimes(1);
|
||||||
|
expect(sleep).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
it('returns qrcode status immediately without waiting full password window', async () => {
|
it('returns qrcode status immediately without waiting full password window', async () => {
|
||||||
const refreshService = new QqbotNapcatLoginService(
|
const refreshService = new QqbotNapcatLoginService(
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user