forked from boos/BoosAPI
Merge branch 'main' into codex/run-release.yml-to-simulate-github-actions-ohq25x
This commit is contained in:
@@ -114,75 +114,6 @@ jobs:
|
|||||||
name: metapi-dist-${{ github.sha }}
|
name: metapi-dist-${{ github.sha }}
|
||||||
path: dist
|
path: dist
|
||||||
|
|
||||||
|
|
||||||
- name: Normalize downloaded dist layout (Windows)
|
|
||||||
if: runner.os == 'Windows'
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
if (Test-Path 'dist/desktop/main.js') {
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
if (Test-Path 'dist/dist/desktop/main.js') {
|
|
||||||
Copy-Item 'dist/dist/*' 'dist/' -Recurse -Force
|
|
||||||
Remove-Item 'dist/dist' -Recurse -Force
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
if ((Test-Path 'desktop/main.js') -or (Test-Path 'web/index.html') -or (Test-Path 'server/index.js')) {
|
|
||||||
New-Item -ItemType Directory -Path 'dist' -Force | Out-Null
|
|
||||||
if (Test-Path 'desktop') { Move-Item 'desktop' 'dist/' -Force }
|
|
||||||
if (Test-Path 'web') { Move-Item 'web' 'dist/' -Force }
|
|
||||||
if (Test-Path 'server') { Move-Item 'server' 'dist/' -Force }
|
|
||||||
}
|
|
||||||
if (-not (Test-Path 'dist/desktop/main.js')) {
|
|
||||||
throw 'Missing dist/desktop/main.js after downloading dist artifact'
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: Normalize downloaded dist layout (Linux/macOS)
|
|
||||||
if: runner.os != 'Windows'
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
if [ -f dist/desktop/main.js ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
if [ -f dist/dist/desktop/main.js ]; then
|
|
||||||
cp -R dist/dist/. dist/
|
|
||||||
rm -rf dist/dist
|
|
||||||
elif [ -f desktop/main.js ] || [ -f web/index.html ] || [ -f server/index.js ]; then
|
|
||||||
mkdir -p dist
|
|
||||||
[ -d desktop ] && mv desktop dist/
|
|
||||||
[ -d web ] && mv web dist/
|
|
||||||
[ -d server ] && mv server dist/
|
|
||||||
fi
|
|
||||||
test -f dist/desktop/main.js
|
|
||||||
|
|
||||||
- name: Ensure desktop entry exists (Windows)
|
|
||||||
if: runner.os == 'Windows'
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
if (Test-Path 'dist/desktop/main.js') {
|
|
||||||
Write-Host 'Found dist/desktop/main.js from downloaded artifact.'
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
Write-Host 'dist/desktop/main.js missing, rebuilding dist locally...'
|
|
||||||
npm run build
|
|
||||||
if (-not (Test-Path 'dist/desktop/main.js')) {
|
|
||||||
throw 'dist/desktop/main.js is still missing after npm run build'
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: Ensure desktop entry exists (Linux/macOS)
|
|
||||||
if: runner.os != 'Windows'
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
if [ -f dist/desktop/main.js ]; then
|
|
||||||
echo 'Found dist/desktop/main.js from downloaded artifact.'
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
echo 'dist/desktop/main.js missing, rebuilding dist locally...'
|
|
||||||
npm run build
|
|
||||||
test -f dist/desktop/main.js
|
|
||||||
|
|
||||||
- name: Build desktop artifacts (Windows)
|
- name: Build desktop artifacts (Windows)
|
||||||
if: runner.os == 'Windows'
|
if: runner.os == 'Windows'
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ const COOKIE_ONLY_LOGIN_SESSION = 'cookie-only-session';
|
|||||||
const COOKIE_SHIELDED_TOKEN = Buffer.from(
|
const COOKIE_SHIELDED_TOKEN = Buffer.from(
|
||||||
`1771864970|${Buffer.from('username=linuxdo_131936').toString('base64')}|sig`,
|
`1771864970|${Buffer.from('username=linuxdo_131936').toString('base64')}|sig`,
|
||||||
).toString('base64');
|
).toString('base64');
|
||||||
|
const COOKIE_GOB_USER_TOKEN = Buffer.from(
|
||||||
|
`1772806887|${Buffer.from(
|
||||||
|
'0d7f040102ff8000011001100000ff93ff80000506737472696e670c060004726f6c6503696e740402000206737472696e670c08000673746174757303696e740402000206737472696e670c07000567726f757006737472696e670c09000764656661756c7406737472696e670c040002696403696e74040500fd04683006737472696e670c0a0008757365726e616d6506737472696e670c09000773756974313539',
|
||||||
|
'hex',
|
||||||
|
).toString('base64')}|sig`,
|
||||||
|
).toString('base64');
|
||||||
const ANYROUTER_CHALLENGE_HTML = readFileSync(
|
const ANYROUTER_CHALLENGE_HTML = readFileSync(
|
||||||
new URL('./__fixtures__/anyrouter-challenge.html', import.meta.url),
|
new URL('./__fixtures__/anyrouter-challenge.html', import.meta.url),
|
||||||
'utf8',
|
'utf8',
|
||||||
@@ -293,6 +299,20 @@ describe('NewApiAdapter', () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof req.headers.cookie === 'string' && req.headers.cookie.includes(`session=${COOKIE_GOB_USER_TOKEN}`)) {
|
||||||
|
if (req.headers['new-api-user'] !== '144408') {
|
||||||
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||||
|
res.end(JSON.stringify({ success: false, message: 'missing New-Api-User' }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||||
|
res.end(JSON.stringify({
|
||||||
|
success: true,
|
||||||
|
data: { id: 144408, username: 'suit159', quota: 50000000, used_quota: 0 },
|
||||||
|
}));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
res.writeHead(401, { 'Content-Type': 'application/json' });
|
res.writeHead(401, { 'Content-Type': 'application/json' });
|
||||||
res.end(JSON.stringify({ success: false, message: 'unauthorized' }));
|
res.end(JSON.stringify({ success: false, message: 'unauthorized' }));
|
||||||
return;
|
return;
|
||||||
@@ -467,6 +487,29 @@ describe('NewApiAdapter', () => {
|
|||||||
).toBe(true);
|
).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('extracts gob-encoded user id from anyrouter session cookie when reading balance', async () => {
|
||||||
|
const adapter = new NewApiAdapter();
|
||||||
|
const balance = await adapter.getBalance(baseUrl, COOKIE_GOB_USER_TOKEN);
|
||||||
|
|
||||||
|
expect(balance.balance).toBe(100);
|
||||||
|
expect(
|
||||||
|
requests.some((r) => r.url === '/api/user/self' && r.headers['new-api-user'] === '144408'),
|
||||||
|
).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('recovers from mismatched provided user id by probing gob-encoded session payload', async () => {
|
||||||
|
const adapter = new NewApiAdapter();
|
||||||
|
const balance = await adapter.getBalance(baseUrl, COOKIE_GOB_USER_TOKEN, 159);
|
||||||
|
|
||||||
|
expect(balance.balance).toBe(100);
|
||||||
|
expect(
|
||||||
|
requests.some((r) => r.url === '/api/user/self' && r.headers['new-api-user'] === '159'),
|
||||||
|
).toBe(true);
|
||||||
|
expect(
|
||||||
|
requests.some((r) => r.url === '/api/user/self' && r.headers['new-api-user'] === '144408'),
|
||||||
|
).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
it('uses shielded cookie flow for balance and checkin', async () => {
|
it('uses shielded cookie flow for balance and checkin', async () => {
|
||||||
const adapter = new NewApiAdapter();
|
const adapter = new NewApiAdapter();
|
||||||
const balance = await adapter.getBalance(baseUrl, COOKIE_SHIELDED_TOKEN);
|
const balance = await adapter.getBalance(baseUrl, COOKIE_SHIELDED_TOKEN);
|
||||||
|
|||||||
@@ -72,6 +72,76 @@ export class NewApiAdapter extends BasePlatformAdapter {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private decodeBase64BufferLoose(value: string): Buffer | null {
|
||||||
|
if (!value) return null;
|
||||||
|
try {
|
||||||
|
return Buffer.from(value, 'base64');
|
||||||
|
} catch {}
|
||||||
|
try {
|
||||||
|
const normalized = value.replace(/-/g, '+').replace(/_/g, '/');
|
||||||
|
return Buffer.from(normalized, 'base64');
|
||||||
|
} catch {}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private decodeGobSignedInt(encoded: Buffer): number | null {
|
||||||
|
if (!encoded.length) return null;
|
||||||
|
|
||||||
|
let unsigned = 0n;
|
||||||
|
if (encoded[0] < 0x80) {
|
||||||
|
unsigned = BigInt(encoded[0]);
|
||||||
|
} else {
|
||||||
|
const width = 0x100 - encoded[0];
|
||||||
|
if (width <= 0 || encoded.length !== width + 1) return null;
|
||||||
|
for (let i = 1; i < encoded.length; i += 1) {
|
||||||
|
unsigned = (unsigned << 8n) | BigInt(encoded[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const signed = (unsigned & 1n) === 0n
|
||||||
|
? unsigned >> 1n
|
||||||
|
: -((unsigned >> 1n) + 1n);
|
||||||
|
if (signed <= 0n || signed > BigInt(Number.MAX_SAFE_INTEGER)) return null;
|
||||||
|
return Number(signed);
|
||||||
|
}
|
||||||
|
|
||||||
|
private extractGobFieldInts(payload: Buffer, fieldName: string): number[] {
|
||||||
|
const ids: number[] = [];
|
||||||
|
const push = (value: number | null) => {
|
||||||
|
if (typeof value !== 'number' || Number.isNaN(value)) return;
|
||||||
|
if (value <= 0 || value > 10_000_000) return;
|
||||||
|
if (!ids.includes(value)) ids.push(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const marker = Buffer.concat([
|
||||||
|
Buffer.from(fieldName, 'utf8'),
|
||||||
|
Buffer.from([0x03]),
|
||||||
|
Buffer.from('int', 'utf8'),
|
||||||
|
Buffer.from([0x04]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
let start = 0;
|
||||||
|
while (start < payload.length) {
|
||||||
|
const position = payload.indexOf(marker, start);
|
||||||
|
if (position < 0) break;
|
||||||
|
|
||||||
|
const encodedLength = payload[position + marker.length];
|
||||||
|
const delimiter = payload[position + marker.length + 1];
|
||||||
|
if (typeof encodedLength === 'number' && delimiter === 0x00) {
|
||||||
|
const byteLength = encodedLength - 1;
|
||||||
|
const valueStart = position + marker.length + 2;
|
||||||
|
const valueEnd = valueStart + byteLength;
|
||||||
|
if (byteLength > 0 && valueEnd <= payload.length) {
|
||||||
|
push(this.decodeGobSignedInt(payload.subarray(valueStart, valueEnd)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
start = position + marker.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
private extractLikelyUserIds(token: string): number[] {
|
private extractLikelyUserIds(token: string): number[] {
|
||||||
const ids: number[] = [];
|
const ids: number[] = [];
|
||||||
const push = (value: unknown) => {
|
const push = (value: unknown) => {
|
||||||
@@ -96,14 +166,20 @@ export class NewApiAdapter extends BasePlatformAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const sessionValue of sessionValues) {
|
for (const sessionValue of sessionValues) {
|
||||||
const decoded = this.decodeBase64Loose(sessionValue);
|
const decodedBuffer = this.decodeBase64BufferLoose(sessionValue);
|
||||||
if (!decoded) continue;
|
if (!decodedBuffer) continue;
|
||||||
|
|
||||||
|
const decoded = decodedBuffer.toString('utf8');
|
||||||
|
|
||||||
const payloadCandidates: string[] = [decoded];
|
const payloadCandidates: string[] = [decoded];
|
||||||
|
const payloadBuffers: Buffer[] = [decodedBuffer];
|
||||||
const parts = decoded.split('|');
|
const parts = decoded.split('|');
|
||||||
if (parts.length >= 2) {
|
if (parts.length >= 2) {
|
||||||
const middlePayload = this.decodeBase64Loose(parts[1]);
|
const middlePayloadBuffer = this.decodeBase64BufferLoose(parts[1]);
|
||||||
if (middlePayload) payloadCandidates.push(middlePayload);
|
if (middlePayloadBuffer) {
|
||||||
|
payloadCandidates.push(middlePayloadBuffer.toString('utf8'));
|
||||||
|
payloadBuffers.push(middlePayloadBuffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const payload of payloadCandidates) {
|
for (const payload of payloadCandidates) {
|
||||||
@@ -114,6 +190,12 @@ export class NewApiAdapter extends BasePlatformAdapter {
|
|||||||
push(m[1]);
|
push(m[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const payload of payloadBuffers) {
|
||||||
|
for (const value of this.extractGobFieldInts(payload, 'id')) {
|
||||||
|
push(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ids;
|
return ids;
|
||||||
@@ -584,6 +666,19 @@ export class NewApiAdapter extends BasePlatformAdapter {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async probeAlternateUserIdByCookie(
|
||||||
|
baseUrl: string,
|
||||||
|
token: string,
|
||||||
|
currentUserId?: number | null,
|
||||||
|
): Promise<number | null> {
|
||||||
|
const probed = await this.probeUserIdByCookie(baseUrl, token);
|
||||||
|
if (!probed) return null;
|
||||||
|
if (typeof currentUserId === 'number' && currentUserId > 0 && probed === currentUserId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return probed;
|
||||||
|
}
|
||||||
|
|
||||||
private async getApiTokensByCookie(baseUrl: string, token: string, userId?: number | null): Promise<ApiTokenInfo[]> {
|
private async getApiTokensByCookie(baseUrl: string, token: string, userId?: number | null): Promise<ApiTokenInfo[]> {
|
||||||
for (const cookie of this.buildCookieCandidates(token)) {
|
for (const cookie of this.buildCookieCandidates(token)) {
|
||||||
try {
|
try {
|
||||||
@@ -670,6 +765,16 @@ export class NewApiAdapter extends BasePlatformAdapter {
|
|||||||
}
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const fallbackUserId = await this.probeAlternateUserIdByCookie(baseUrl, accessToken, platformUserId);
|
||||||
|
if (fallbackUserId) {
|
||||||
|
const cookieRetry = await this.fetchUserSelfByCookie(baseUrl, accessToken, fallbackUserId);
|
||||||
|
if (cookieRetry?.success && cookieRetry?.data) {
|
||||||
|
return this.parseUserInfo(cookieRetry.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -771,17 +876,15 @@ export class NewApiAdapter extends BasePlatformAdapter {
|
|||||||
return { tokenType: 'session', userInfo, balance, apiToken };
|
return { tokenType: 'session', userInfo, balance, apiToken };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!platformUserId) {
|
const cookieUserId = await this.probeAlternateUserIdByCookie(baseUrl, token, platformUserId);
|
||||||
const cookieUserId = await this.probeUserIdByCookie(baseUrl, token);
|
if (cookieUserId) {
|
||||||
if (cookieUserId) {
|
const cookieRetry = await this.fetchUserSelfByCookie(baseUrl, token, cookieUserId);
|
||||||
const cookieRetry = await this.fetchUserSelfByCookie(baseUrl, token, cookieUserId);
|
if (cookieRetry?.success && cookieRetry?.data) {
|
||||||
if (cookieRetry?.success && cookieRetry?.data) {
|
const userInfo = this.parseUserInfo(cookieRetry.data);
|
||||||
const userInfo = this.parseUserInfo(cookieRetry.data);
|
const balance = this.parseBalance(cookieRetry.data);
|
||||||
const balance = this.parseBalance(cookieRetry.data);
|
let apiToken: string | null = null;
|
||||||
let apiToken: string | null = null;
|
try { apiToken = await this.getApiTokenWithUser(baseUrl, token, cookieUserId); } catch {}
|
||||||
try { apiToken = await this.getApiTokenWithUser(baseUrl, token, cookieUserId); } catch {}
|
return { tokenType: 'session', userInfo, balance, apiToken };
|
||||||
return { tokenType: 'session', userInfo, balance, apiToken };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -839,47 +942,59 @@ export class NewApiAdapter extends BasePlatformAdapter {
|
|||||||
return { success: false, message: firstFailureMessage };
|
return { success: false, message: firstFailureMessage };
|
||||||
}
|
}
|
||||||
|
|
||||||
const cookieUserId = resolvedUserId || await this.probeUserIdByCookie(baseUrl, accessToken);
|
const tryCookieCheckin = async (cookieUserId?: number | null): Promise<CheckinResult | null> => {
|
||||||
for (const cookie of this.buildCookieCandidates(accessToken)) {
|
for (const cookie of this.buildCookieCandidates(accessToken)) {
|
||||||
try {
|
try {
|
||||||
const signInRes = await this.fetchJsonRaw<any>(`${baseUrl}/api/user/sign_in`, {
|
const signInRes = await this.fetchJsonRaw<any>(`${baseUrl}/api/user/sign_in`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: '{}',
|
body: '{}',
|
||||||
headers: {
|
headers: {
|
||||||
Cookie: cookie,
|
Cookie: cookie,
|
||||||
'X-Requested-With': 'XMLHttpRequest',
|
'X-Requested-With': 'XMLHttpRequest',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (signInRes?.success) {
|
if (signInRes?.success) {
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: signInRes.message || 'checked in',
|
message: signInRes.message || 'checked in',
|
||||||
reward: signInRes.data?.reward?.toString(),
|
reward: signInRes.data?.reward?.toString(),
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
const signInMessage = this.extractResponseMessage(signInRes);
|
||||||
|
if (!firstFailureMessage && signInMessage) firstFailureMessage = signInMessage;
|
||||||
|
} catch (err) {
|
||||||
|
const parsed = this.formatRequestErrorMessage(err);
|
||||||
|
if (!firstFailureMessage && parsed) firstFailureMessage = parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const headers: Record<string, string> = { Cookie: cookie };
|
||||||
|
if (cookieUserId) headers['New-Api-User'] = String(cookieUserId);
|
||||||
|
const res = await this.fetchJsonRaw<any>(`${baseUrl}/api/user/checkin`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
if (res?.success) {
|
||||||
|
return { success: true, message: res.message || 'checkin success', reward: res.data?.reward?.toString() };
|
||||||
|
}
|
||||||
|
const cookieMessage = this.extractResponseMessage(res);
|
||||||
|
if (cookieMessage) firstFailureMessage = cookieMessage;
|
||||||
|
} catch (err) {
|
||||||
|
const parsed = this.formatRequestErrorMessage(err);
|
||||||
|
if (parsed) firstFailureMessage = parsed;
|
||||||
}
|
}
|
||||||
const signInMessage = this.extractResponseMessage(signInRes);
|
|
||||||
if (!firstFailureMessage && signInMessage) firstFailureMessage = signInMessage;
|
|
||||||
} catch (err) {
|
|
||||||
const parsed = this.formatRequestErrorMessage(err);
|
|
||||||
if (!firstFailureMessage && parsed) firstFailureMessage = parsed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
return null;
|
||||||
const headers: Record<string, string> = { Cookie: cookie };
|
};
|
||||||
if (cookieUserId) headers['New-Api-User'] = String(cookieUserId);
|
|
||||||
const res = await this.fetchJsonRaw<any>(`${baseUrl}/api/user/checkin`, {
|
const initialCookieResult = await tryCookieCheckin(resolvedUserId);
|
||||||
method: 'POST',
|
if (initialCookieResult) return initialCookieResult;
|
||||||
headers,
|
|
||||||
});
|
const alternateCookieUserId = await this.probeAlternateUserIdByCookie(baseUrl, accessToken, resolvedUserId);
|
||||||
if (res?.success) {
|
if (alternateCookieUserId) {
|
||||||
return { success: true, message: res.message || 'checkin success', reward: res.data?.reward?.toString() };
|
const retriedCookieResult = await tryCookieCheckin(alternateCookieUserId);
|
||||||
}
|
if (retriedCookieResult) return retriedCookieResult;
|
||||||
const cookieMessage = this.extractResponseMessage(res);
|
|
||||||
if (cookieMessage) firstFailureMessage = cookieMessage;
|
|
||||||
} catch (err) {
|
|
||||||
const parsed = this.formatRequestErrorMessage(err);
|
|
||||||
if (parsed) firstFailureMessage = parsed;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return { success: false, message: firstFailureMessage || 'checkin failed' };
|
return { success: false, message: firstFailureMessage || 'checkin failed' };
|
||||||
@@ -917,13 +1032,11 @@ export class NewApiAdapter extends BasePlatformAdapter {
|
|||||||
return this.parseBalance(cookieRes.data);
|
return this.parseBalance(cookieRes.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!resolvedUserId) {
|
const cookieUserId = await this.probeAlternateUserIdByCookie(baseUrl, accessToken, resolvedUserId);
|
||||||
const cookieUserId = await this.probeUserIdByCookie(baseUrl, accessToken);
|
if (cookieUserId) {
|
||||||
if (cookieUserId) {
|
const cookieRetry = await this.fetchUserSelfByCookie(baseUrl, accessToken, cookieUserId, rememberFailure);
|
||||||
const cookieRetry = await this.fetchUserSelfByCookie(baseUrl, accessToken, cookieUserId, rememberFailure);
|
if (cookieRetry?.success && cookieRetry?.data) {
|
||||||
if (cookieRetry?.success && cookieRetry?.data) {
|
return this.parseBalance(cookieRetry.data);
|
||||||
return this.parseBalance(cookieRetry.data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -952,6 +1065,12 @@ export class NewApiAdapter extends BasePlatformAdapter {
|
|||||||
const cookieModels = await this.getSessionModelsByCookie(baseUrl, token, userId || platformUserId);
|
const cookieModels = await this.getSessionModelsByCookie(baseUrl, token, userId || platformUserId);
|
||||||
if (cookieModels.length > 0) return cookieModels;
|
if (cookieModels.length > 0) return cookieModels;
|
||||||
|
|
||||||
|
const alternateCookieUserId = await this.probeAlternateUserIdByCookie(baseUrl, token, userId || platformUserId);
|
||||||
|
if (alternateCookieUserId) {
|
||||||
|
const fallbackModels = await this.getSessionModelsByCookie(baseUrl, token, alternateCookieUserId);
|
||||||
|
if (fallbackModels.length > 0) return fallbackModels;
|
||||||
|
}
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1119,6 +1238,15 @@ export class NewApiAdapter extends BasePlatformAdapter {
|
|||||||
if (normalized.length > 0) return normalized;
|
if (normalized.length > 0) return normalized;
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
return this.getApiTokensByCookie(baseUrl, accessToken, userId);
|
const cookieTokens = await this.getApiTokensByCookie(baseUrl, accessToken, userId);
|
||||||
|
if (cookieTokens.length > 0) return cookieTokens;
|
||||||
|
|
||||||
|
const alternateCookieUserId = await this.probeAlternateUserIdByCookie(baseUrl, accessToken, userId);
|
||||||
|
if (alternateCookieUserId) {
|
||||||
|
const fallbackTokens = await this.getApiTokensByCookie(baseUrl, accessToken, alternateCookieUserId);
|
||||||
|
if (fallbackTokens.length > 0) return fallbackTokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user