139 lines
3.6 KiB
TypeScript
139 lines
3.6 KiB
TypeScript
import fs from "fs";
|
|
import path from "path";
|
|
import os from "os";
|
|
import { spawn } from "child_process";
|
|
import net from "net";
|
|
|
|
export interface ChromeVersionResponse {
|
|
webSocketDebuggerUrl: string;
|
|
}
|
|
|
|
const userDataDir = path.join(os.tmpdir(), "chrome-debug-profile");
|
|
|
|
export const getLocalISOString = (date = new Date()) => {
|
|
const offset = date.getTimezoneOffset();
|
|
const offsetAbs = Math.abs(offset);
|
|
const hours = Math.floor(offsetAbs / 60)
|
|
.toString()
|
|
.padStart(2, "0");
|
|
const minutes = (offsetAbs % 60).toString().padStart(2, "0");
|
|
const sign = offset > 0 ? "-" : "+";
|
|
|
|
return new Date(date.getTime() - offset * 60000)
|
|
.toISOString()
|
|
.replace("Z", `${sign}${hours}:${minutes}`);
|
|
};
|
|
|
|
function getChromePath(): string {
|
|
const platform = os.platform();
|
|
|
|
const paths: Record<NodeJS.Platform, string[]> = {
|
|
darwin: [
|
|
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
"/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary",
|
|
"/Applications/Chromium.app/Contents/MacOS/Chromium",
|
|
],
|
|
win32: [
|
|
process.env.LOCALAPPDATA + "\\Google\\Chrome\\Application\\chrome.exe",
|
|
process.env.PROGRAMFILES + "\\Google\\Chrome\\Application\\chrome.exe",
|
|
process.env["PROGRAMFILES(X86)"] +
|
|
"\\Google\\Chrome\\Application\\chrome.exe",
|
|
],
|
|
linux: [
|
|
"/usr/bin/google-chrome",
|
|
"/usr/bin/google-chrome-stable",
|
|
"/usr/bin/chromium",
|
|
"/usr/bin/chromium-browser",
|
|
],
|
|
aix: [],
|
|
freebsd: [],
|
|
openbsd: [],
|
|
sunos: [],
|
|
android: [],
|
|
haiku: [],
|
|
cygwin: [],
|
|
netbsd: [],
|
|
};
|
|
|
|
const platformPaths = paths[platform] || [];
|
|
|
|
for (const path of platformPaths) {
|
|
try {
|
|
if (fs.existsSync(path)) {
|
|
return path;
|
|
}
|
|
} catch (err) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
throw new Error("Could not find Chrome/Chromium installation");
|
|
}
|
|
|
|
export function launchChromeWithDebugging(port: number) {
|
|
try {
|
|
const chromePath = getChromePath();
|
|
const args = [
|
|
`--remote-debugging-port=${port}`,
|
|
`--user-data-dir=${userDataDir}`,
|
|
"--remote-allow-origins=*",
|
|
"--incognito",
|
|
// "--headless",
|
|
// `--proxy-server=46.3.202.240:2120`,
|
|
// `--proxy-server=http://jN8AqiMh:Pd9FEs6N@212.193.184.228:64616`,
|
|
];
|
|
|
|
console.log(`Launching Chrome at: ${chromePath}`);
|
|
|
|
const chromeProcess = spawn(chromePath, args, {
|
|
detached: true,
|
|
stdio: "ignore",
|
|
});
|
|
|
|
chromeProcess.unref();
|
|
|
|
chromeProcess.on("error", (err) => {
|
|
console.error("Failed to start Chrome:", err);
|
|
});
|
|
|
|
chromeProcess.on("exit", (code) => {
|
|
if (code !== 0) {
|
|
console.error(`Chrome process exited with code ${code}`);
|
|
}
|
|
});
|
|
|
|
console.log("Chrome launched successfully with debugging port 9222");
|
|
return chromeProcess;
|
|
} catch (error) {
|
|
console.error("Failed to launch Chrome:", error);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
export async function waitForChromeReady(port = 9222, timeout = 30000) {
|
|
const startTime = Date.now();
|
|
|
|
return new Promise((resolve, reject) => {
|
|
function check() {
|
|
const client = net.createConnection({ port }, () => {
|
|
client.end();
|
|
resolve("");
|
|
});
|
|
|
|
client.on("error", () => {
|
|
if (Date.now() - startTime > timeout) {
|
|
reject(new Error("Timeout waiting for Chrome to start"));
|
|
} else {
|
|
setTimeout(check, 500);
|
|
}
|
|
});
|
|
}
|
|
|
|
check();
|
|
});
|
|
}
|
|
|
|
export function randomDelay(min: number, max: number): Promise<void> {
|
|
const delay = Math.floor(Math.random() * (max - min) + min);
|
|
return new Promise((resolve) => setTimeout(resolve, delay));
|
|
}
|