You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

137 lines
3.7 KiB

const express = require("express");
const router = express.Router();
const {jsdomFromText, browser} = require("sdenv");
const {Script} = require("vm");
const fs = require("node:fs");
const path = require("node:path");
const crypto = require("crypto")
let sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
const storeCookie = new Map;
const areaJsMap = {
"yunnan": path.resolve(__dirname, '../public/yunnan/MO5zzCMcub4d.b4c45da.js'),
"hubei": path.resolve(__dirname, '../public/hubei/5PXGXoOF7eGJ.ed63b8f.js'),
}
router.post('/rsCookie', async (req, res) => {
console.time('rsCookie')
let url = req.body['url'];
let htmlStr = req.body['htmlStr'];
let jsStr = req.body['jsText'];
let areaName = req.body['areaName'];
let cookie = req.body['cookie'];
let userAgent = req.body['userAgent'];
if (url == null || url === '') {
return res.send('error url')
}
if (htmlStr == null || htmlStr === '') {
return res.send('error html')
}
try {
let jsText;
if (jsStr == null) {
let jsPath = areaJsMap[areaName];
if (jsPath == null) {
console.error('未找到js文件')
return res.send('未找到js文件')
}
jsText = fs.readFileSync(jsPath).toString('utf8');
} else {
jsText = Buffer.from(jsStr, 'base64').toString('utf-8')
}
let cookies = await handle(url,
Buffer.from(htmlStr, 'base64').toString('utf-8'),
jsText,
cookie != null ? Buffer.from(cookie, 'base64').toString('utf-8') : null,
userAgent != null ? Buffer.from(userAgent, 'base64').toString('utf-8') : null)
res.send(cookies);
} catch (e) {
console.error(e)
return res.send(e.toString())
} finally {
console.timeEnd('rsCookie')
}
})
async function handle(url, htmlStr, jsText, cookie, userAgent) {
let uuid = crypto.randomUUID()
// 获取 origin
let baseUrl = new URL(url).origin;
const [jsDom, cookieJar] = await jsdomFromText({
url: url,
referrer: url,
userAgent: userAgent,
contentType: "text/html",
runScripts: "outside-only", // runScripts: 'dangerously'/'outside-only'
})
// 设置 cookie
if (cookie != null) {
cookieJar.setCookieSync(cookie, baseUrl);
}
// 加载dom
const dom = await jsDom(htmlStr);
window = dom.window
// 加载 页面上的js
const allScript = window.document.querySelectorAll('script[r="m"]');
// let $ = cheerio.load(htmlStr);
// let nextAll = $('script[r=m]');
let js = '';
allScript.forEach(script=>{
let attr = script.textContent;
if (attr) {
js += attr
} else {
js += jsText
}
js += ";\n"
})
// allScript.each((script) => {
//
// })
// 执行完成后的钩子
window.onbeforeunload = async (url) => {
const cookies = cookieJar.getCookieStringSync(baseUrl);
// console.debug(`${url} 生成cookie:`, cookies);
storeCookie.set(uuid, cookies)
// window.close();
return cookies;
}
browser(dom.window, 'chrome');
let script = new Script(js);
let internalVMContext = dom.getInternalVMContext();
// 执行 js
script.runInContext(internalVMContext);
for (let i = 0; i < 10; i++) {
await sleep(100)
let hasCookie = storeCookie.has(uuid)
if (hasCookie) {
let newVar = storeCookie.get(uuid);
storeCookie.delete(uuid)
return newVar;
}
}
throw new Error('执行超时')
}
module.exports = router