11
This commit is contained in:
@@ -352,6 +352,110 @@ async function newLoginPage(platform, accountId, cookies = [], startUrl) {
|
|||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开账号页:detached Chrome + connect,脚本结束后可保留窗口
|
||||||
|
* @param {string} [startUrl]
|
||||||
|
*/
|
||||||
|
async function newLoginPageKeepOpen(platform, accountId, cookies = [], startUrl) {
|
||||||
|
const key = `login_${contextKey(platform, accountId)}`;
|
||||||
|
const existing = loginBrowsers.get(key);
|
||||||
|
if (existing && existing.isConnected()) {
|
||||||
|
const pages = await existing.pages();
|
||||||
|
let page =
|
||||||
|
pages.find((p) => {
|
||||||
|
try {
|
||||||
|
const u = p.url();
|
||||||
|
return u && u !== "about:blank" && u !== "chrome://newtab/";
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}) || pages[0];
|
||||||
|
if (page) {
|
||||||
|
await bringPageToFront(page);
|
||||||
|
if (startUrl) {
|
||||||
|
try {
|
||||||
|
const cur = page.url();
|
||||||
|
if (!cur || cur === "about:blank" || !cur.includes("://")) {
|
||||||
|
await page.goto(startUrl, {
|
||||||
|
waitUntil: "domcontentloaded",
|
||||||
|
timeout: 60000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const publishKey = contextKey(platform, accountId);
|
||||||
|
const publishPort = debugPortForKey(publishKey);
|
||||||
|
const loginPort = debugPortForKey(key);
|
||||||
|
await closeLoginBrowser(platform, accountId);
|
||||||
|
await closePublishBrowser(platform, accountId);
|
||||||
|
await forceCloseChromeOnPort(loginPort);
|
||||||
|
await forceCloseChromeOnPort(publishPort);
|
||||||
|
|
||||||
|
const puppeteer = loadPuppeteer();
|
||||||
|
const dir = userDataDir(platform, accountId);
|
||||||
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
||||||
|
cleanupProfileLocks(dir);
|
||||||
|
|
||||||
|
const executablePath = getChromiumExecutablePath();
|
||||||
|
if (!executablePath) {
|
||||||
|
throw new Error(
|
||||||
|
"未找到 Chrome/Edge,请安装 Google Chrome 或 Microsoft Edge,或设置 AICLIENT_CHROMIUM_PATH",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const openUrl =
|
||||||
|
startUrl && String(startUrl).trim() ? String(startUrl).trim() : "about:blank";
|
||||||
|
|
||||||
|
globalThis.__native?.emitProgress?.("正在打开 Chrome…");
|
||||||
|
await spawnDetachedChrome(executablePath, dir, loginPort, openUrl, { force: true });
|
||||||
|
const browser = await connectPublishBrowser(puppeteer, loginPort);
|
||||||
|
browser.on("disconnected", () => loginBrowsers.delete(key));
|
||||||
|
loginBrowsers.set(key, browser);
|
||||||
|
|
||||||
|
const pages = await browser.pages();
|
||||||
|
let page =
|
||||||
|
pages.find((p) => {
|
||||||
|
try {
|
||||||
|
const u = p.url();
|
||||||
|
return u && u !== "about:blank" && u !== "chrome://newtab/";
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}) || pages[0] || null;
|
||||||
|
|
||||||
|
if (!page) {
|
||||||
|
page = await browser.newPage();
|
||||||
|
if (startUrl) {
|
||||||
|
await page.goto(startUrl, {
|
||||||
|
waitUntil: "domcontentloaded",
|
||||||
|
timeout: 60000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await page.setUserAgent(DEFAULT_USER_AGENT);
|
||||||
|
await page.evaluateOnNewDocument(STEALTH_INIT_SCRIPT);
|
||||||
|
page.setDefaultNavigationTimeout(60000);
|
||||||
|
page.setDefaultTimeout(60000);
|
||||||
|
|
||||||
|
if (Array.isArray(cookies) && cookies.length) {
|
||||||
|
try {
|
||||||
|
await page.setCookie(...cookies);
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("setCookie 失败:", e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await bringPageToFront(page);
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
async function closeLoginBrowser(platform, accountId) {
|
async function closeLoginBrowser(platform, accountId) {
|
||||||
const key = `login_${contextKey(platform, accountId)}`;
|
const key = `login_${contextKey(platform, accountId)}`;
|
||||||
const port = debugPortForKey(key);
|
const port = debugPortForKey(key);
|
||||||
@@ -381,9 +485,15 @@ async function detachLoginBrowser(platform, accountId) {
|
|||||||
if (!browser) return;
|
if (!browser) return;
|
||||||
loginBrowsers.delete(key);
|
loginBrowsers.delete(key);
|
||||||
try {
|
try {
|
||||||
|
if (!browser.isConnected()) return;
|
||||||
|
// puppeteer.connect:disconnect 后 Chrome 独立进程继续运行
|
||||||
|
if (typeof browser.disconnect === "function") {
|
||||||
|
await browser.disconnect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// puppeteer.launch:仅 unref 子进程,勿 close/disconnect
|
||||||
const proc = typeof browser.process === "function" ? browser.process() : null;
|
const proc = typeof browser.process === "function" ? browser.process() : null;
|
||||||
if (proc && typeof proc.unref === "function") proc.unref();
|
if (proc && typeof proc.unref === "function") proc.unref();
|
||||||
if (browser.isConnected()) await browser.disconnect();
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("detachLoginBrowser:", e.message);
|
console.warn("detachLoginBrowser:", e.message);
|
||||||
}
|
}
|
||||||
@@ -465,6 +575,7 @@ module.exports = {
|
|||||||
getLoginBrowser,
|
getLoginBrowser,
|
||||||
newPublishPage,
|
newPublishPage,
|
||||||
newLoginPage,
|
newLoginPage,
|
||||||
|
newLoginPageKeepOpen,
|
||||||
userDataDir,
|
userDataDir,
|
||||||
LOGIN_URLS,
|
LOGIN_URLS,
|
||||||
getChromiumExecutablePath,
|
getChromiumExecutablePath,
|
||||||
@@ -472,6 +583,7 @@ module.exports = {
|
|||||||
closeLoginBrowser,
|
closeLoginBrowser,
|
||||||
detachLoginBrowser,
|
detachLoginBrowser,
|
||||||
detachPublishBrowser,
|
detachPublishBrowser,
|
||||||
|
bringPageToFront,
|
||||||
debugPortForKey,
|
debugPortForKey,
|
||||||
contextKey,
|
contextKey,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
newLoginPage,
|
newLoginPageKeepOpen,
|
||||||
detachLoginBrowser,
|
detachLoginBrowser,
|
||||||
|
bringPageToFront,
|
||||||
LOGIN_URLS,
|
LOGIN_URLS,
|
||||||
} = require("./publish_browser.js");
|
} = require("./publish_browser.js");
|
||||||
|
|
||||||
@@ -25,11 +26,13 @@ globalThis.__nodejsMain = async function main(params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
globalThis.__native?.emitProgress?.("正在打开浏览器…");
|
globalThis.__native?.emitProgress?.("正在打开浏览器…");
|
||||||
const page = await newLoginPage(platform, accountId, cookies, targetUrl);
|
const page = await newLoginPageKeepOpen(platform, accountId, cookies, targetUrl);
|
||||||
const cur = page.url();
|
const cur = page.url();
|
||||||
if (!cur || cur === "about:blank" || !cur.includes("://")) {
|
if (!cur || cur === "about:blank" || !cur.includes("://")) {
|
||||||
await page.goto(targetUrl, { waitUntil: "domcontentloaded", timeout: 60000 });
|
await page.goto(targetUrl, { waitUntil: "domcontentloaded", timeout: 60000 });
|
||||||
}
|
}
|
||||||
|
await bringPageToFront(page);
|
||||||
|
// 断开 Puppeteer,保留 detached Chrome 窗口(Node 退出后不关浏览器)
|
||||||
await detachLoginBrowser(platform, accountId);
|
await detachLoginBrowser(platform, accountId);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user