aslan-h5/scripts/aslan-webview-sim.mjs
2026-07-21 14:36:20 +08:00

177 lines
5.3 KiB
JavaScript

#!/usr/bin/env node
const LOGIN_URL =
'https://api.atuchat.com/e64f27b9ba6b37881120f4584a5444a5c684d8491b703d0af953e5cc6a5f4cec'
const account = process.env.ASLAN_ACCOUNT || '6666'
const password = process.env.ASLAN_PASSWORD || '123456'
const targetUrl =
process.env.ASLAN_URL || 'https://h5.atuchat.com/#/admin-center?lang=en'
const chromePath =
process.env.CHROME_PATH || '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
const headless = process.env.ASLAN_HEADLESS === '1'
const exitAfterLoad = process.env.ASLAN_EXIT_AFTER_LOAD === '1'
async function loadPlaywright() {
try {
return await import('playwright')
} catch {
return await import(
'/Users/hy/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright/index.mjs'
)
}
}
function appHeaders(imei = 'aslan-webview-sim') {
return {
'req-lang': 'en',
'X-Forwarded-Proto': 'http',
'User-Agent': 'Dart/3.7.2 (dart:io)',
'req-imei': imei,
'req-app-intel':
'version=1.0.0;build=1;model=CodexWebView;sysVersion=1;channel=Google',
'req-client': 'Android',
'req-sys-origin': 'origin=ATYOU;originChild=ATYOU',
'Req-Atyou': 'true',
}
}
function publicUserProfile(profile = {}) {
return {
id: profile.id || profile.userId,
account: profile.account,
specialAccount: profile.ownSpecialId?.account,
userNickname: profile.userNickname,
countryName: profile.countryName,
originSys: profile.originSys || profile.sysOrigin,
sysOriginChild: profile.sysOriginChild,
}
}
async function login() {
const response = await fetch(LOGIN_URL, {
method: 'POST',
headers: {
...appHeaders('aslan-webview-sim-login'),
'content-type': 'application/json',
},
body: JSON.stringify({ account, pwd: password }),
})
const data = await response.json()
if (!response.ok || !data.status || !data.body?.token) {
const error = {
httpStatus: response.status,
status: data.status,
errorCode: data.errorCode,
errorMsg: data.errorMsg,
}
throw new Error(`Aslan login failed: ${JSON.stringify(error)}`)
}
return data.body
}
async function main() {
const auth = await login()
const profile = auth.userProfile || {}
const { chromium } = await loadPlaywright()
const browser = await chromium.launch({
headless,
executablePath: chromePath,
args: ['--no-sandbox'],
})
const context = await browser.newContext({
viewport: { width: 390, height: 844 },
isMobile: true,
hasTouch: true,
userAgent:
'Mozilla/5.0 (Linux; Android 12; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36',
})
await context.addInitScript(
({ token, profile }) => {
window.__aslanWebViewMessages = []
const postBridgeMessage = (message) => {
const text = String(message)
window.__aslanWebViewMessages.push(text)
console.info(`[AslanWebViewSim] FlutterPageControl.postMessage: ${text}`)
}
window.FlutterPageControl = {
postMessage: postBridgeMessage,
}
window.app = {
getAccessOrigin: () =>
JSON.stringify({
Authorization: `Bearer ${token}`,
'Req-Lang': 'en',
'Req-App-Intel':
'build=1;version=1.0.0;model=CodexWebView;channel=Google;Req-Imei=aslan-webview-sim',
'Req-Sys-Origin': 'origin=ATYOU;originChild=ATYOU',
}),
closePage: () => postBridgeMessage('close_page'),
back: () => history.back(),
gotoRoom: (roomId) => postBridgeMessage(`go_to_room:${roomId}`),
gotoPrivateChat: (userId) => postBridgeMessage(`private_chat:${userId}`),
openUserInfo: (userId) => postBridgeMessage(`view_user_info:${userId}`),
gotoAppPage: (pageName) => postBridgeMessage(pageName),
goToFlutterPage: (pageName) => postBridgeMessage(pageName),
uploadImgFile: () => postBridgeMessage('uploadImgFile'),
}
try {
localStorage.setItem('userProfile', JSON.stringify(profile))
} catch {}
},
{ token: auth.token, profile },
)
const page = await context.newPage()
page.on('console', (msg) => {
const text = msg.text()
if (
text.includes('[AslanWebViewSim]') ||
/error|warn|Route|Permission|APP|Failed|identity/i.test(text)
) {
console.log(`[browser:${msg.type()}] ${text}`)
}
})
page.on('pageerror', (error) => {
console.log(`[browser:pageerror] ${error.message}`)
})
console.log('Aslan WebView simulator started')
console.log(`account=${account}`)
console.log(`profile=${JSON.stringify(publicUserProfile(profile))}`)
console.log(`url=${targetUrl}`)
console.log('Close the Chrome window to stop the simulator.')
await page.goto(targetUrl, { waitUntil: 'domcontentloaded', timeout: 45_000 })
if (exitAfterLoad) {
await page.waitForTimeout(6_000)
const state = await page.evaluate(() => ({
href: location.href,
text: (document.body?.innerText || '').replace(/\s+/g, ' ').slice(0, 800),
bridgeMessages: window.__aslanWebViewMessages || [],
}))
console.log(`loaded=${JSON.stringify(state)}`)
await browser.close()
return
}
await new Promise((resolve) => {
browser.on('disconnected', resolve)
})
}
main().catch((error) => {
console.error(error.message || error)
process.exit(1)
})