forked from boos/BoosAPI
fix anyrouter balance refresh challenge errors (#368)
This commit is contained in:
@@ -20,6 +20,7 @@ const CHECKIN_INVALID_URL_EXPIRED_SESSION_TOKEN = 'checkin-invalid-url-expired-s
|
||||
const CHECKIN_INVALID_URL_FORBIDDEN_SESSION_TOKEN = 'checkin-invalid-url-forbidden-session-token';
|
||||
const CHECKIN_CLOUDFLARE_530_TOKEN = 'checkin-cloudflare-530-token';
|
||||
const BALANCE_FAIL_TOKEN = 'balance-fail-token';
|
||||
const BALANCE_SHIELD_FAILURE_TOKEN = 'balance-shield-failure-token';
|
||||
const GROUP_EXPIRED_TOKEN = 'group-expired-token';
|
||||
const SHIELD_LOGIN_USERNAME = 'shield-user';
|
||||
const SHIELD_LOGIN_PASSWORD = 'shield-pass';
|
||||
@@ -257,12 +258,38 @@ describe('NewApiAdapter', () => {
|
||||
}
|
||||
|
||||
if (req.url === '/api/user/self') {
|
||||
if (typeof req.headers.authorization === 'string' && req.headers.authorization === `Bearer ${BALANCE_SHIELD_FAILURE_TOKEN}`) {
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'text/html; charset=utf-8',
|
||||
'Set-Cookie': `cdn_sec_tc=${SHIELD_LOGIN_COOKIE}; Path=/; HttpOnly`,
|
||||
});
|
||||
res.end(ANYROUTER_CHALLENGE_HTML);
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof req.headers.authorization === 'string' && req.headers.authorization === `Bearer ${BALANCE_FAIL_TOKEN}`) {
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ success: false, message: '无权进行此操作,access token 无效' }));
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
typeof req.headers.cookie === 'string' &&
|
||||
(
|
||||
req.headers.cookie.includes(`session=${BALANCE_SHIELD_FAILURE_TOKEN}`) ||
|
||||
req.headers.cookie.includes(`token=${BALANCE_SHIELD_FAILURE_TOKEN}`)
|
||||
)
|
||||
) {
|
||||
if (!req.headers.cookie.includes(`acw_sc__v2=${ANYROUTER_CHALLENGE_ACW}`)) {
|
||||
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
||||
res.end(ANYROUTER_CHALLENGE_HTML);
|
||||
return;
|
||||
}
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ success: false, message: '无权进行此操作,未登录且未提供 access token' }));
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
typeof req.headers.cookie === 'string' &&
|
||||
(
|
||||
@@ -663,6 +690,13 @@ describe('NewApiAdapter', () => {
|
||||
await expect(adapter.getBalance(baseUrl, BALANCE_FAIL_TOKEN)).rejects.toThrow('access token');
|
||||
});
|
||||
|
||||
it('prefers post-challenge cookie failure over raw html parse error when reading balance', async () => {
|
||||
const adapter = new AnyRouterAdapter();
|
||||
|
||||
await expect(adapter.getBalance(baseUrl, BALANCE_SHIELD_FAILURE_TOKEN)).rejects
|
||||
.toThrow('无权进行此操作,未登录且未提供 access token');
|
||||
});
|
||||
|
||||
it('preserves nested checkin error message instead of generic fallback', async () => {
|
||||
const adapter = new NewApiAdapter();
|
||||
const result = await adapter.checkin(baseUrl, CHECKIN_INVALID_URL_TOKEN, 11494);
|
||||
|
||||
@@ -549,6 +549,15 @@ export class NewApiAdapter extends BasePlatformAdapter {
|
||||
return '';
|
||||
}
|
||||
|
||||
private isHtmlJsonParseErrorMessage(message?: string | null): boolean {
|
||||
if (!message) return false;
|
||||
const text = message.toLowerCase();
|
||||
return (
|
||||
text.includes("unexpected token '<'")
|
||||
|| (text.includes('not valid json') && (text.includes('<html') || text.includes('<script')))
|
||||
);
|
||||
}
|
||||
|
||||
private isShieldChallenge(contentType: string, text: string): boolean {
|
||||
const ct = (contentType || '').toLowerCase();
|
||||
if (ct.includes('text/html') && /var\s+arg1\s*=|acw_sc__v2|cdn_sec_tc|<script/i.test(text)) {
|
||||
@@ -1162,10 +1171,15 @@ export class NewApiAdapter extends BasePlatformAdapter {
|
||||
const resolvedUserId = platformUserId || await this.discoverUserId(baseUrl, accessToken);
|
||||
let failureMessage: string | null = null;
|
||||
const rememberFailure = (message?: string | null) => {
|
||||
if (failureMessage) return;
|
||||
const text = typeof message === 'string' ? message.trim() : '';
|
||||
if (!text) return;
|
||||
failureMessage = text;
|
||||
if (!failureMessage) {
|
||||
failureMessage = text;
|
||||
return;
|
||||
}
|
||||
if (this.isHtmlJsonParseErrorMessage(failureMessage) && !this.isHtmlJsonParseErrorMessage(text)) {
|
||||
failureMessage = text;
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user