Files
yaoyaoai/scripts/nodejs/publish_browser.js
949036910@qq.com 05f28e3a30 1
2026-05-28 15:24:23 +08:00

166 lines
4.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use strict";
/**
* 发布用 Puppeteer 浏览器(按平台/账号隔离 userDataDir
*/
const fs = require("fs");
const path = require("path");
const os = require("os");
const {
COMMON_BROWSER_ARGS,
BROWSER_IGNORE_DEFAULT_ARGS,
STEALTH_INIT_SCRIPT,
DEFAULT_USER_AGENT,
} = require("./douyin_browser_constants.js");
const browsers = new Map();
function getRuntimeDataPath(...parts) {
const base = process.env.AICLIENT_DATA_DIR || path.join(os.homedir(), ".aiclient");
return path.join(base, ...parts);
}
function getChromiumExecutablePath() {
const fromEnv =
process.env.AICLIENT_CHROMIUM_PATH || process.env.PUPPETEER_EXECUTABLE_PATH;
if (fromEnv && fs.existsSync(fromEnv)) return fromEnv;
const candidates = [];
if (process.platform === "win32") {
const pf = process.env.ProgramFiles || "C:\\Program Files";
const local = process.env.LOCALAPPDATA || "";
candidates.push(
path.join(pf, "Google", "Chrome", "Application", "chrome.exe"),
path.join(local, "Google", "Chrome", "Application", "chrome.exe"),
path.join(pf, "Microsoft", "Edge", "Application", "msedge.exe"),
);
}
return candidates.find((p) => p && fs.existsSync(p));
}
function loadPuppeteer() {
try {
return require("puppeteer-core");
} catch {
return require("puppeteer");
}
}
function contextKey(platform, accountId) {
return accountId ? `publish_${platform}_${accountId}` : `publish_${platform}`;
}
function userDataDir(platform, accountId) {
const sub = accountId ? `${platform}_${accountId}` : platform;
return getRuntimeDataPath("browser-data", "publish", sub);
}
function delay(ms) {
return new Promise((r) => setTimeout(r, ms));
}
async function getPublishBrowser(platform, accountId) {
const key = contextKey(platform, accountId);
const existing = browsers.get(key);
if (existing && existing.isConnected()) {
return existing;
}
const puppeteer = loadPuppeteer();
const dir = userDataDir(platform, accountId);
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
const executablePath = getChromiumExecutablePath();
if (!executablePath) {
throw new Error(
"未找到 Chrome/Edge请安装浏览器或设置 AICLIENT_CHROMIUM_PATH",
);
}
const browser = await puppeteer.launch({
executablePath,
headless: false,
userDataDir: dir,
args: COMMON_BROWSER_ARGS,
ignoreDefaultArgs: BROWSER_IGNORE_DEFAULT_ARGS,
defaultViewport: { width: 1280, height: 900 },
});
browser.on("disconnected", () => browsers.delete(key));
browsers.set(key, browser);
return browser;
}
async function closeBlankPages(browser, keepPage) {
try {
const pages = await browser.pages();
for (const p of pages) {
if (keepPage && p === keepPage) continue;
const u = p.url();
if (!u || u === "about:blank") {
try {
await p.close();
} catch {
/* ignore */
}
}
}
} catch {
/* ignore */
}
}
async function newPublishPage(platform, accountId, cookies) {
const browser = await getPublishBrowser(platform, accountId);
const pages = await browser.pages();
let page =
pages.find((p) => {
try {
return p.url() === "about:blank";
} catch {
return false;
}
}) || null;
if (!page) {
page = await browser.newPage();
}
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 closeBlankPages(browser, page);
return page;
}
async function closePublishBrowser(platform, accountId) {
const key = contextKey(platform, accountId);
const browser = browsers.get(key);
if (!browser) return;
browsers.delete(key);
try {
await browser.close();
} catch {
/* ignore */
}
}
const LOGIN_URLS = {
douyin: "https://creator.douyin.com/",
kuaishou: "https://cp.kuaishou.com/",
shipin: "https://channels.weixin.qq.com/",
xiaohongshu: "https://creator.xiaohongshu.com/",
};
module.exports = {
delay,
getPublishBrowser,
newPublishPage,
userDataDir,
LOGIN_URLS,
getChromiumExecutablePath,
closePublishBrowser,
};