import fs from "fs"; import path from "path"; import { Page } from "puppeteer-core"; import { env } from "../env.js"; export const getChromeExecutablePath = () => { if (env.CHROME_EXECUTABLE_PATH) { const executablePath = env.CHROME_EXECUTABLE_PATH; const normalizedPath = path.normalize(executablePath); if (!fs.existsSync(normalizedPath)) { console.warn(`Your custom chrome executable at ${normalizedPath} does not exist`); } else { return executablePath; } } if (process.platform === "win32") { const programFilesPath = `${process.env["ProgramFiles"]}\\Google\\Chrome\\Application\\chrome.exe`; const programFilesX86Path = `C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe`; if (fs.existsSync(programFilesPath)) { return programFilesPath; } else if (fs.existsSync(programFilesX86Path)) { return programFilesX86Path; } } if (process.platform === "darwin") { return "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"; } return "/usr/bin/chromium"; }; export async function installMouseHelper(page: Page, device: string) { await page.evaluateOnNewDocument((deviceType) => { // Install mouse helper only for top-level frame. if (window !== window.parent) return; window.addEventListener( "DOMContentLoaded", () => { if (deviceType === "desktop") { // Desktop mode: show regular arrow cursor const CURSOR_ID = "__cursor__"; if (document.getElementById(CURSOR_ID)) return; const cursor = document.createElement("div"); cursor.id = CURSOR_ID; Object.assign(cursor.style, { position: "fixed", top: "0px", left: "0px", width: "20px", height: "20px", backgroundImage: `url("data:image/svg+xml;utf8,")`, backgroundSize: "cover", pointerEvents: "none", zIndex: "99999", transform: "translate(-2px, -2px)", }); document.body.appendChild(cursor); document.addEventListener("mousemove", (e) => { cursor.style.top = e.clientY + "px"; cursor.style.left = e.clientX + "px"; }); } else { // Mobile mode: show circular touch indicator const box = document.createElement("puppeteer-mouse-pointer"); const styleElement = document.createElement("style"); styleElement.innerHTML = ` puppeteer-mouse-pointer { pointer-events: none; position: absolute; top: 0; z-index: 10000; left: 0; width: 20px; height: 20px; background: rgba(0,0,0,.4); border: 1px solid white; border-radius: 10px; margin: -10px 0 0 -10px; padding: 0; transition: background .2s, border-radius .2s, border-color .2s; } puppeteer-mouse-pointer.button-1 { transition: none; background: rgba(0,0,0,0.9); } puppeteer-mouse-pointer.button-2 { transition: none; border-color: rgba(0,0,255,0.9); } puppeteer-mouse-pointer.button-3 { transition: none; border-radius: 4px; } puppeteer-mouse-pointer.button-4 { transition: none; border-color: rgba(255,0,0,0.9); } puppeteer-mouse-pointer.button-5 { transition: none; border-color: rgba(0,255,0,0.9); } `; document.head.appendChild(styleElement); document.body.appendChild(box); document.addEventListener( "mousemove", (event) => { box.style.left = event.pageX + "px"; box.style.top = event.pageY + "px"; updateButtons(event.buttons); }, true, ); document.addEventListener( "mousedown", (event) => { updateButtons(event.buttons); box.classList.add("button-" + event.which); }, true, ); document.addEventListener( "mouseup", (event) => { updateButtons(event.buttons); box.classList.remove("button-" + event.which); }, true, ); function updateButtons(buttons) { for (let i = 0; i < 5; i++) // @ts-ignore box.classList.toggle("button-" + i, buttons & (1 << i)); } } }, false, ); }, device); } export function filterHeaders(headers: Record) { const headersToRemove = [ "accept-encoding", "accept", "cache-control", "pragma", "sec-fetch-dest", "sec-fetch-mode", "sec-fetch-site", "sec-fetch-user", "upgrade-insecure-requests", ]; const filteredHeaders = { ...headers }; headersToRemove.forEach((header) => { delete filteredHeaders[header]; }); return filteredHeaders; }