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