80 lines
1.9 KiB
JavaScript
80 lines
1.9 KiB
JavaScript
import { runtimeConfig } from '../config/runtime.js'
|
|
import { logDebug } from '../utils/logger.js'
|
|
|
|
const SESSION_DEBUG_ENABLED = Boolean(runtimeConfig.session.debug)
|
|
|
|
export function logBrowserSessionDebug(scope, detail) {
|
|
if (!SESSION_DEBUG_ENABLED) {
|
|
return
|
|
}
|
|
|
|
logDebug('[browser/session]', scope, detail)
|
|
}
|
|
|
|
export async function waitForFrame(page, predicate, timeoutMs = 15_000) {
|
|
const startedAt = Date.now()
|
|
|
|
while (Date.now() - startedAt < timeoutMs) {
|
|
const matched = page.frames().find((frame) => {
|
|
try {
|
|
return predicate(frame)
|
|
} catch {
|
|
return false
|
|
}
|
|
})
|
|
|
|
if (matched) {
|
|
return matched
|
|
}
|
|
|
|
await page.waitForTimeout(300)
|
|
}
|
|
|
|
throw new Error('未找到登录二维码 frame')
|
|
}
|
|
|
|
export async function downloadRemoteQrImage(page, qrUrl, qrImagePath, referer = '', loginType = 'unknown') {
|
|
try {
|
|
const response = await page.context().request.get(qrUrl, {
|
|
failOnStatusCode: false,
|
|
headers: {
|
|
referer,
|
|
},
|
|
})
|
|
|
|
if (!response.ok()) {
|
|
logBrowserSessionDebug(`${loginType}.capture.downloadNotOk`, {
|
|
qrUrl,
|
|
status: response.status(),
|
|
})
|
|
return false
|
|
}
|
|
|
|
const body = await response.body()
|
|
|
|
if (!body?.length) {
|
|
return false
|
|
}
|
|
|
|
return body
|
|
} catch (error) {
|
|
logBrowserSessionDebug(`${loginType}.capture.downloadError`, {
|
|
qrUrl,
|
|
message: error instanceof Error ? error.message : String(error),
|
|
})
|
|
return null
|
|
}
|
|
}
|
|
|
|
export function isRetryableQrCaptureError(error) {
|
|
const message = error instanceof Error ? error.message : String(error || '')
|
|
|
|
return (
|
|
message.includes('Frame was detached') ||
|
|
message.includes('Execution context was destroyed') ||
|
|
message.includes('Target page, context or browser has been closed') ||
|
|
message.includes('waiting for') ||
|
|
message.includes('Timeout')
|
|
)
|
|
}
|