177 lines
5.3 KiB
JavaScript
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)
|
|
})
|