feat: 增强浏览器特征伪装 (ref #1)

This commit is contained in:
foxhui
2025-11-26 03:27:12 +08:00
Unverified
parent 4bebdd4d3c
commit 34661cc879
5 changed files with 575 additions and 113 deletions
+20 -1
View File
@@ -4,12 +4,31 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.1.1] - 2024-11-24
## [1.2.0] - 2024-11-26
### Added
- **浏览器特征伪装**
- 在 Windows10 官方 Chrome 环境下已通过 [antibot](https://bot.sannysoft.com/) 和 [CreepJS](https://abrahamjuliot.github.io/creepjs/) 测试(无红色警示)(但在Linux下未完全通过,需要用户配合,详情和进一步伪装请查看文档常见问题部分)
- 引入 `ghost-cursor` 优化鼠标移动轨迹伪装,不再重复造轮子
### Changed
- **指定模型**
- 更改模型UUID的拦截器不再使用注入Fetch脚本和Puppeteer Interception,改用CDP拦截器,减少特征
- **浏览器特征伪装**
- 优化浏览器启动参数,减少特征
- 优化窗口大小计算方式
---
## [1.1.1] - 2024-11-25
### Fixed
- **指定模型**
- 修复因错误的UUID映射导致的 gemini-3-pro-image-preview 模型触发HTTP500的 BUG
---
## [1.1.0] - 2024-11-24
+58 -3
View File
@@ -10,12 +10,13 @@ LMArenaImagenAutomator 是一个基于 Puppeteer 的自动化图像生成工具
### ✨ 主要特性
- 🎭 **拟人操作**使用贝塞尔曲线模拟真实鼠标移动轨迹
- 💁‍♂️ **拟人操作**:模拟真实鼠标移动轨迹和抖动
- 🤖 **智能输入**:模拟人类打字速度和错误纠正行为
- 🖼️ **多图支持**:最多支持同时上传 5 张参考图片
- 🔐 **安全认证**:基于 Bearer Token 的 API 鉴权
- 📊 **队列管理**:智能任务队列,防止请求过载
- 🌐 **代理支持**:支持 HTTP 和 SOCKS5 代理配置
- 🎭 **特征伪装**:尽量伪装成真实浏览器的特征(详情参考文档结尾)
---
@@ -25,7 +26,7 @@ LMArenaImagenAutomator 是一个基于 Puppeteer 的自动化图像生成工具
- **Node.js**: 16.0 或更高版本
- **操作系统**: Windows、Linux 或 macOS
- **浏览器**: Google Chrome 或 Chromium (可选,Puppeteer 会自动下载)
- **浏览器**: Google Chrome 或 Chromium (Puppeteer 会自动下载,但是**更推荐**使用Google Chrome)
### 安装步骤
@@ -443,7 +444,7 @@ chrome:
</details>
<details>
<summary>🐧 Linux 环境下非无头模式运行</summary>
<summary>🐧 Linux 环境下非无头模式运行</summary>
**问题**: 需要在 Linux 服务器上显示浏览器界面(如手动过验证码)
@@ -475,6 +476,60 @@ chrome:
</details>
<details>
<summary>🎭 【浏览器特征伪装】</summary>
**问题**: 如何优化浏览器特征伪装,减少验证码弹出频率?
**当前状态**:
- ✅ **Windows 10 官方 Chrome**: 已通过 [antibot](https://bot.sannysoft.com/) 和 [CreepJS](https://abrahamjuliot.github.io/creepjs/) 测试(无红色警示)
- ⚠️ **Linux 环境**: 未完全通过 CreepJS 测试,但基本不影响使用
**进一步优化建议**:
> [!TIP]
> 完成后,可有效缓解验证码的弹出频率。
**1. 使用官方 Chrome(推荐)**
不推荐使用 Chromium,因为它缺少 MP4/H.264 解码器等插件,且被大量爬虫使用,会成为明显特征。
**Linux 安装官方 Chrome**:
```bash
# 从 Google 官方下载 Chrome deb 安装包
# 大陆服务器可手动下载deb安装包 https://www.google.com/chrome/?platform=linux
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo dpkg -i google-chrome-stable_current_amd64.deb
sudo apt-get install -f # 修复可能的依赖问题
```
**配置方式**:
修改 `config.yaml`,可使用`which google-chrome`指令查询路径
```yaml
chrome:
path: "/usr/bin/google-chrome"
```
使用环境变量可跳过 Puppeteer 自动下载 Chromium
```bash
export PUPPETEER_SKIP_CHROMIUM_DOWNLOAD="true"
```
**2. 优化字体指纹**
Linux 服务器通常只安装了极少量字体(甚至没有中文),这会增加指纹特征。
**安装常用字体**:
```bash
# 安装中文字体(必备,否则中文提示词将显示方框)
sudo apt install fonts-wqy-zenhei fonts-wqy-microhei
# 安装微软核心字体(减少字体指纹差异)
sudo apt install ttf-mscorefonts-installer
```
</details>
---
+107 -109
View File
@@ -1,14 +1,17 @@
import puppeteer from 'puppeteer';
import puppeteer from 'puppeteer-extra';
import StealthPlugin from 'puppeteer-extra-plugin-stealth';
import { createCursor } from 'ghost-cursor';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { anonymizeProxy, closeAnonymizedProxy } from 'proxy-chain';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const stealth = StealthPlugin();
stealth.enabledEvasions.delete('user-agent-override');
stealth.enabledEvasions.delete('iframe.contentWindow');
puppeteer.use(stealth);
// --- 配置常量 ---
const CHROME_PATH = 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe';
const USER_DATA_DIR = path.join(process.cwd(), 'data', 'chromeUserData');
const TARGET_URL = 'https://lmarena.ai/c/new?mode=direct&chat-modality=image';
const TEMP_DIR = path.join(process.cwd(), 'data', 'temp');
@@ -46,48 +49,7 @@ function getMimeType(filePath) {
return map[ext] || 'application/octet-stream';
}
// --- 核心拟人化算法 (贝塞尔曲线 + 物理模拟) ---
/**
* 三次贝塞尔曲线计算
*/
function cubicBezier(t, p0, p1, p2, p3) {
const k = 1 - t;
return k * k * k * p0 + 3 * k * k * t * p1 + 3 * k * t * t * p2 + t * t * t * p3;
}
/**
* 模拟人类鼠标移动轨迹
* @param {object} page Puppeteer 页面对象
* @param {number} startX 起始 X 坐标
* @param {number} startY 起始 Y 坐标
* @param {number} targetX 目标 X 坐标
* @param {number} targetY 目标 Y 坐标
*/
async function humanMove(page, startX, startY, targetX, targetY) {
const distance = Math.sqrt(Math.pow(targetX - startX, 2) + Math.pow(targetY - startY, 2));
const steps = Math.floor(Math.max(distance / 8, 15));
const offset = distance * 0.4;
// 生成两个随机控制点,使轨迹弯曲
const cp1X = startX + (targetX - startX) / 3 + random(-offset, offset);
const cp1Y = startY + (targetY - startY) / 3 + random(-offset, offset);
const cp2X = startX + 2 * (targetX - startX) / 3 + random(-offset, offset);
const cp2Y = startY + 2 * (targetY - startY) / 3 + random(-offset, offset);
for (let i = 0; i <= steps; i++) {
const t = i / steps;
// 缓动函数:起步快,结尾慢,模拟人类肌肉运动
const easeT = t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
let x = cubicBezier(easeT, startX, cp1X, cp2X, targetX);
let y = cubicBezier(easeT, startY, cp1Y, cp2Y, targetY);
// 添加微小的随机抖动
if (i % 3 === 0) { x += random(-1, 1); y += random(-1, 1); }
await page.mouse.move(x, y);
}
}
/**
* 安全点击元素(包含拟人化移动和点击)
@@ -98,24 +60,15 @@ async function safeClick(page, selector) {
try {
const el = await page.$(selector);
if (!el) throw new Error(`未找到: ${selector}`);
const box = await el.boundingBox();
if (!box) throw new Error(`不可见: ${selector}`);
// 先稍微移动一下当前位置 (增加真实感)
await page.mouse.move(box.x - random(50, 100), box.y - random(50, 100), { steps: 2 });
// 使用 ghost-cursor 点击
if (page.cursor) {
await page.cursor.click(el);
return;
}
// 目标点击位置在元素内部随机区域
const targetX = box.x + box.width * random(0.3, 0.7);
const targetY = box.y + box.height * random(0.3, 0.7);
// 移动鼠标到目标位置
await humanMove(page, box.x - 50, box.y - 50, targetX, targetY);
// 模拟点击过程:按下 -> 停顿 -> 抬起
await sleep(100, 300);
await page.mouse.down();
await sleep(60, 120);
await page.mouse.up();
// 降级逻辑
await el.click();
} catch (err) {
throw err;
}
@@ -242,35 +195,32 @@ function extractImage(text) {
/**
* 初始化浏览器
* @param {object} config 配置对象 (包含 chrome 配置)
* @returns {Promise<{browser: object, page: object, client: object, width: number, height: number}>}
* @returns {Promise<{browser: object, page: object, client: object}>}
*/
async function initBrowser(config) {
console.log('>>> [Browser] 开始初始化浏览器');
const chromeConfig = config?.chrome || {};
const width = Math.floor(random(900, 1100));
const height = Math.floor(random(500, 700));
// 1. 基础参数
const args = [
'--no-sandbox',
'--disable-setuid-sandbox',
`--window-size=${width},${height}`,
'--disable-blink-features=AutomationControlled',
'--disable-infobars',
'--test-type',
'--no-zygote',
'--disable-dev-shm-usage'
'--disable-dev-shm-usage',
];
// 2. Headless 模式配置
// 2. Headless 模式配置 & 窗口大小
let headlessMode = false;
if (chromeConfig.headless) {
headlessMode = 'new';
args.push('--disable-gl-drawing-for-tests');
console.log('>>> [Browser] Headless 模式: 启用');
// 无头模式锁死分辨率
args.push('--window-size=1280,690');
console.log('>>> [Browser] Headless 模式: 启用 (1280x690)');
} else {
console.log('>>> [Browser] Headless 模式: 禁用');
// 有头模式:最大化窗口以适配屏幕
args.push('--start-maximized');
console.log('>>> [Browser] Headless 模式: 禁用 (最大化窗口)');
}
// 3. GPU 配置
@@ -323,9 +273,11 @@ async function initBrowser(config) {
args: args
});
// 重用第一个标签页
const pages = await browser.pages();
const page = pages[0];
// 保留第一个标签页 (about:blank),在新标签页中打开
const page = await browser.newPage();
// 初始化 ghost-cursor
page.cursor = createCursor(page);
// 5. 代理认证 (仅当未使用 proxy-chain 桥接时)
if (chromeConfig.proxy && chromeConfig.proxy.enable && chromeConfig.proxy.user && !proxyUrlForChrome) {
@@ -336,11 +288,6 @@ async function initBrowser(config) {
console.log('>>> [Browser] 代理认证: 已设置 (HTTP Basic Auth)');
}
// 隐藏 WebDriver 特征
await page.evaluateOnNewDocument(() => {
Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
});
// 创建 CDP 会话以监听网络请求
const client = await page.target().createCDPSession();
await client.send('Network.enable');
@@ -351,12 +298,19 @@ async function initBrowser(config) {
console.log('>>> [Warmup] 正在随机浏览页面以建立信任...');
// 计算屏幕中心点
// 计算屏幕中心点 (动态获取视口大小)
let viewport = page.viewport();
// 如果是 null (有时候 headless 初始化慢),给个默认值
let width = viewport ? viewport.width : 1280;
let height = viewport ? viewport.height : 690;
const centerX = width / 2;
const centerY = height / 2;
// 第一次移动:从左上角移动到中心附近
await humanMove(page, 0, 0, centerX + random(-200, 200), centerY + random(-200, 200));
if (page.cursor) {
await page.cursor.moveTo({ x: centerX + random(-200, 200), y: centerY + random(-200, 200) });
}
await sleep(500, 1000);
// 模拟滚动行为
@@ -373,11 +327,14 @@ async function initBrowser(config) {
// 移动鼠标到输入框
const box = await (await page.$(textareaSelector)).boundingBox();
if (box) {
await humanMove(page, centerX, centerY, box.x + box.width / 2, box.y + box.height / 2);
if (page.cursor) {
await page.cursor.moveTo({ x: box.x + box.width / 2, y: box.y + box.height / 2 });
}
await sleep(500, 1000);
}
console.log('>>> [Browser] 浏览器初始化完成,系统就绪');
console.log('>>> [Browser] 当程序有任务运行时请勿随意调节窗口大小,以免鼠标轨迹错位!');
// 注册清理钩子:浏览器关闭时关闭代理服务器
if (proxyUrlForChrome) {
@@ -391,21 +348,21 @@ async function initBrowser(config) {
});
}
return { browser, page, client, width, height };
return { browser, page, client };
}
/**
* 执行生图任务
* @param {object} context 浏览器上下文 {page, client, width, height}
* @param {object} context 浏览器上下文 {page, client}
* @param {string} prompt 提示词
* @param {string[]} imgPaths 图片路径数组
* @param {string|null} modelId 模型 UUID (可选)
* @returns {Promise<{image?: string, text?: string, error?: string}>}
*/
async function generateImage(context, prompt, imgPaths, modelId) {
const { page, client, width, height } = context;
const { page, client } = context;
const textareaSelector = 'textarea';
let requestHandler = null;
let fetchPausedHandler = null;
try {
// 1. 强制开启新会话 (通过URL跳转)
@@ -428,34 +385,70 @@ async function generateImage(context, prompt, imgPaths, modelId) {
await humanType(page, textareaSelector, prompt);
await sleep(800, 1500);
// --- 注入 Fetch 拦截器 (Puppeteer Request Interception) ---
// 注入 CDP Fetch 拦截器
if (modelId) {
await page.setRequestInterception(true);
requestHandler = async (request) => {
const url = request.url();
if (url.includes('/nextjs-api/stream/') && request.method() === 'POST') {
// 1. 启用 Fetch 域拦截,仅拦截特定 URL
await client.send('Fetch.enable', {
patterns: [{
urlPattern: '*nextjs-api/stream*',
requestStage: 'Request'
}]
});
// 2. 定义拦截处理函数
fetchPausedHandler = async (event) => {
const { requestId, request } = event;
if (request.method === 'POST' && request.postData) {
try {
const postData = request.postData();
if (postData) {
const data = JSON.parse(postData);
console.log(`[Browser] 正在拦截请求。原始 modelAId: ${data.modelAId}`);
// 尝试解码可能是 base64 编码的postData
let rawBody = request.postData;
// 尝试解析 JSON
let data;
try {
data = JSON.parse(rawBody);
} catch (e) {
// 尝试 Base64 解码
try {
rawBody = Buffer.from(rawBody, 'base64').toString('utf8');
data = JSON.parse(rawBody);
} catch (e2) {
// 无法解析,跳过
}
}
if (data && data.modelAId) {
console.log(`>>> [CDP] 正在拦截请求。原始 modelAId: ${data.modelAId}`);
// 修改 modelAId
data.modelAId = modelId;
const newPostData = JSON.stringify(data);
console.log(`[Browser] 请求已修改。新 modelAId: ${data.modelAId}`);
await request.continue({ postData: newPostData });
// 重新序列化并转为 Base64 (Fetch.continueRequest 需要 base64)
const newBody = JSON.stringify(data);
const newBodyBase64 = Buffer.from(newBody).toString('base64');
console.log(`>>> [CDP] 请求已修改。新 modelAId: ${data.modelAId}`);
await client.send('Fetch.continueRequest', {
requestId,
postData: newBodyBase64
});
return;
}
} catch (e) {
console.error('[Browser] 拦截修改失败:', e);
console.error('[CDP] 拦截处理出错:', e);
}
}
await request.continue();
// 如果不匹配或出错,直接放行
try {
await client.send('Fetch.continueRequest', { requestId });
} catch (e) { }
};
page.on('request', requestHandler);
console.log(`>>> [Test] 已启用请求拦截,目标模型: ${modelId}`);
// 3. 监听拦截事件
client.on('Fetch.requestPaused', fetchPausedHandler);
console.log(`>>> [Test] 已启用 CDP Fetch 拦截,目标模型: ${modelId}`);
}
// 4. 发送
@@ -515,7 +508,12 @@ async function generateImage(context, prompt, imgPaths, modelId) {
});
// 任务结束,像人一样把鼠标移开,防止遮挡或误触
await humanMove(page, width / 2, height / 2, width - 100, height / 2);
if (page.cursor) {
const vp = page.viewport();
const w = vp ? vp.width : 1280;
const h = vp ? vp.height : 690;
await page.cursor.moveTo({ x: w - 100, y: h / 2 });
}
return result;
@@ -523,10 +521,10 @@ async function generateImage(context, prompt, imgPaths, modelId) {
console.error('>>> [Error] 生成任务失败:', err.message);
return { error: err.message };
} finally {
if (requestHandler) {
page.off('request', requestHandler);
if (fetchPausedHandler) {
client.off('Fetch.requestPaused', fetchPausedHandler);
try {
await page.setRequestInterception(false);
await client.send('Fetch.disable');
} catch (e) { }
}
}
+3
View File
@@ -11,10 +11,13 @@
"genkey": "node lib/genApiKey.js"
},
"dependencies": {
"ghost-cursor": "^1.4.1",
"got-scraping": "^4.1.2",
"js-yaml": "^4.1.1",
"proxy-chain": "^2.6.0",
"puppeteer": "^24.31.0",
"puppeteer-extra": "^3.3.6",
"puppeteer-extra-plugin-stealth": "^2.11.2",
"sharp": "^0.34.5"
}
}
+387
View File
@@ -8,6 +8,9 @@ importers:
.:
dependencies:
ghost-cursor:
specifier: ^1.4.1
version: 1.4.1
got-scraping:
specifier: ^4.1.2
version: 4.1.2
@@ -20,6 +23,12 @@ importers:
puppeteer:
specifier: ^24.31.0
version: 24.31.0
puppeteer-extra:
specifier: ^3.3.6
version: 3.3.6(puppeteer-core@24.31.0)(puppeteer@24.31.0)
puppeteer-extra-plugin-stealth:
specifier: ^2.11.2
version: 2.11.2(puppeteer-extra@3.3.6(puppeteer-core@24.31.0)(puppeteer@24.31.0))
sharp:
specifier: ^0.34.5
version: 0.34.5
@@ -216,9 +225,18 @@ packages:
'@tootallnate/quickjs-emscripten@0.23.0':
resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==}
'@types/bezier-js@4.1.3':
resolution: {integrity: sha512-FNVVCu5mx/rJCWBxLTcL7oOajmGtWtBTDjq6DSUWUI12GeePivrZZXz+UgE0D6VYsLEjvExRO03z4hVtu3pTEQ==}
'@types/debug@4.1.12':
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
'@types/http-cache-semantics@4.0.4':
resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==}
'@types/ms@2.1.0':
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
'@types/node@24.10.1':
resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==}
@@ -244,6 +262,10 @@ packages:
argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
arr-union@3.1.0:
resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==}
engines: {node: '>=0.10.0'}
ast-types@0.13.4:
resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==}
engines: {node: '>=4'}
@@ -256,6 +278,9 @@ packages:
react-native-b4a:
optional: true
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
bare-events@2.8.2:
resolution: {integrity: sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==}
peerDependencies:
@@ -302,6 +327,12 @@ packages:
resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==}
engines: {node: '>=10.0.0'}
bezier-js@6.1.4:
resolution: {integrity: sha512-PA0FW9ZpcHbojUCMu28z9Vg/fNkwTj5YhusSAjHHDfHDGLxJ6YUKrAN2vk1fP2MMOxVw4Oko16FMlRGVBGqLKg==}
brace-expansion@1.1.12:
resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
browserslist@4.28.0:
resolution: {integrity: sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
@@ -342,6 +373,10 @@ packages:
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
engines: {node: '>=12'}
clone-deep@0.2.4:
resolution: {integrity: sha512-we+NuQo2DHhSl+DP6jlUiAhyAjBQrYnpOk15rN6c6JSPScjiCLh8IbSU+VTcph6YS3o7mASE8a0+gbZ7ChLpgg==}
engines: {node: '>=0.10.0'}
color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
@@ -349,6 +384,9 @@ packages:
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
cosmiconfig@9.0.0:
resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==}
engines: {node: '>=14'}
@@ -375,6 +413,10 @@ packages:
resolution: {integrity: sha512-oj7KWToJuuxlPr7VV0vabvxEIiqNMo+q0NueIiL3XhtwC6FVOX7Hr1c0C4eD0bmf7Zr+S/dSf2xvkH3Ad6sU3Q==}
engines: {node: '>=20'}
deepmerge@4.3.1:
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
engines: {node: '>=0.10.0'}
degenerator@5.0.1:
resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==}
engines: {node: '>= 14'}
@@ -446,10 +488,29 @@ packages:
fd-slicer@1.1.0:
resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==}
for-in@0.1.8:
resolution: {integrity: sha512-F0to7vbBSHP8E3l6dCjxNOLuSFAACIxFy3UehTUlG7svlXi37HHsDkyVcHo0Pq8QwrE+pXvWSVX3ZT1T9wAZ9g==}
engines: {node: '>=0.10.0'}
for-in@1.0.2:
resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==}
engines: {node: '>=0.10.0'}
for-own@0.1.5:
resolution: {integrity: sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==}
engines: {node: '>=0.10.0'}
form-data-encoder@4.1.0:
resolution: {integrity: sha512-G6NsmEW15s0Uw9XnCg+33H3ViYRyiM0hMrMhhqQOR8NFc5GhYrI+6I3u7OTw7b91J2g8rtvMBZJDbcGb2YUniw==}
engines: {node: '>= 18'}
fs-extra@10.1.0:
resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
engines: {node: '>=12'}
fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
generative-bayesian-network@2.1.77:
resolution: {integrity: sha512-viU4CRPsmgiklR94LhvdMndaY73BkCH1pGjmOjWbLR/ZwcUd06gKF3TCcsS3npRl74o33YSInSixxm16wIukcA==}
@@ -469,6 +530,13 @@ packages:
resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==}
engines: {node: '>= 14'}
ghost-cursor@1.4.1:
resolution: {integrity: sha512-K8A8/Co/Jbdqee694qrNsGWBG51DVK5UF2gGKEoZBDx9F1WmoD2SzUoDHWoY7O+TY84s1VrWwwfkVKxI2FoV2Q==}
glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
deprecated: Glob versions prior to v9 are no longer supported
got-scraping@4.1.2:
resolution: {integrity: sha512-LtVwPM5YLnNY7HVT/AK/yDBUg/4yOZSlAjjug2ovrHQseS43QCmO1XosKKXcXrfc6OMX8OnDbAWIauFMcaJ5TQ==}
engines: {node: '>=16'}
@@ -477,6 +545,9 @@ packages:
resolution: {integrity: sha512-DjsLab39NUMf5iYlK9asVCkHMhaA2hEhrlmf+qXRhjEivuuBHWYbjmty9DA3OORUwZgENTB+6vSmY2ZW8gFHVw==}
engines: {node: '>=20'}
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
header-generator@2.1.77:
resolution: {integrity: sha512-ggSG/mfkFMu8CO7xP591G8kp1IJCBvgXu7M8oxTjC9u914JsIzE6zIfoFsXzA+pf0utWJhUsdqU0oV/DtQ4DFQ==}
engines: {node: '>=16.0.0'}
@@ -500,6 +571,13 @@ packages:
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
engines: {node: '>=6'}
inflight@1.0.6:
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
ip-address@10.1.0:
resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==}
engines: {node: '>= 12'}
@@ -507,6 +585,13 @@ packages:
is-arrayish@0.2.1:
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
is-buffer@1.1.6:
resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==}
is-extendable@0.1.1:
resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==}
engines: {node: '>=0.10.0'}
is-fullwidth-code-point@3.0.0:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
@@ -515,10 +600,18 @@ packages:
resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==}
engines: {node: '>=8'}
is-plain-object@2.0.4:
resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==}
engines: {node: '>=0.10.0'}
is-stream@4.0.1:
resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==}
engines: {node: '>=18'}
isobject@3.0.1:
resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==}
engines: {node: '>=0.10.0'}
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@@ -529,9 +622,28 @@ packages:
json-parse-even-better-errors@2.3.1:
resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
jsonfile@6.2.0:
resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==}
keyv@5.5.4:
resolution: {integrity: sha512-eohl3hKTiVyD1ilYdw9T0OiB4hnjef89e3dMYKz+mVKDzj+5IteTseASUsOB+EU9Tf6VNTCjDePcP6wkDGmLKQ==}
kind-of@2.0.1:
resolution: {integrity: sha512-0u8i1NZ/mg0b+W3MGGw5I7+6Eib2nx72S/QvXa0hYjEkjTknYmEYQJwGu3mLC0BrhtJjtQafTkyRUQ75Kx0LVg==}
engines: {node: '>=0.10.0'}
kind-of@3.2.2:
resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==}
engines: {node: '>=0.10.0'}
lazy-cache@0.2.7:
resolution: {integrity: sha512-gkX52wvU/R8DVMMt78ATVPFMJqfW8FPz1GZ1sVHBVQHmu/WvhIWE4cE1GBzhJNFicDeYhnwp6Rl35BcAIM3YOQ==}
engines: {node: '>=0.10.0'}
lazy-cache@1.0.4:
resolution: {integrity: sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==}
engines: {node: '>=0.10.0'}
lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
@@ -547,13 +659,24 @@ packages:
resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==}
engines: {node: '>=12'}
merge-deep@3.0.3:
resolution: {integrity: sha512-qtmzAS6t6grwEkNrunqTBdn0qKwFgNWvlxUbAV8es9M7Ot1EbyApytCnvE0jALPa46ZpKDUo527kKiaWplmlFA==}
engines: {node: '>=0.10.0'}
mimic-response@4.0.0:
resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
mitt@3.0.1:
resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
mixin-object@2.0.1:
resolution: {integrity: sha512-ALGF1Jt9ouehcaXaHhn6t1yGWRqGaHkPFndtFVHfZXOvkIZ/yoGaSi0AHVTafb3ZBGg4dr/bDwnaEKqCXzchMA==}
engines: {node: '>=0.10.0'}
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@@ -599,6 +722,10 @@ packages:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'}
path-is-absolute@1.0.1:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
engines: {node: '>=0.10.0'}
pend@1.2.0:
resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
@@ -627,6 +754,69 @@ packages:
resolution: {integrity: sha512-pnAohhSZipWQoFpXuGV7xCZfaGhqcBR9C4pVrU0QSrcMi7tQMH9J9lDBqBvyMAHQqe8HCARuREqFuVKRQOgTvg==}
engines: {node: '>=18'}
puppeteer-extra-plugin-stealth@2.11.2:
resolution: {integrity: sha512-bUemM5XmTj9i2ZerBzsk2AN5is0wHMNE6K0hXBzBXOzP5m5G3Wl0RHhiqKeHToe/uIH8AoZiGhc1tCkLZQPKTQ==}
engines: {node: '>=8'}
peerDependencies:
playwright-extra: '*'
puppeteer-extra: '*'
peerDependenciesMeta:
playwright-extra:
optional: true
puppeteer-extra:
optional: true
puppeteer-extra-plugin-user-data-dir@2.4.1:
resolution: {integrity: sha512-kH1GnCcqEDoBXO7epAse4TBPJh9tEpVEK/vkedKfjOVOhZAvLkHGc9swMs5ChrJbRnf8Hdpug6TJlEuimXNQ+g==}
engines: {node: '>=8'}
peerDependencies:
playwright-extra: '*'
puppeteer-extra: '*'
peerDependenciesMeta:
playwright-extra:
optional: true
puppeteer-extra:
optional: true
puppeteer-extra-plugin-user-preferences@2.4.1:
resolution: {integrity: sha512-i1oAZxRbc1bk8MZufKCruCEC3CCafO9RKMkkodZltI4OqibLFXF3tj6HZ4LZ9C5vCXZjYcDWazgtY69mnmrQ9A==}
engines: {node: '>=8'}
peerDependencies:
playwright-extra: '*'
puppeteer-extra: '*'
peerDependenciesMeta:
playwright-extra:
optional: true
puppeteer-extra:
optional: true
puppeteer-extra-plugin@3.2.3:
resolution: {integrity: sha512-6RNy0e6pH8vaS3akPIKGg28xcryKscczt4wIl0ePciZENGE2yoaQJNd17UiEbdmh5/6WW6dPcfRWT9lxBwCi2Q==}
engines: {node: '>=9.11.2'}
peerDependencies:
playwright-extra: '*'
puppeteer-extra: '*'
peerDependenciesMeta:
playwright-extra:
optional: true
puppeteer-extra:
optional: true
puppeteer-extra@3.3.6:
resolution: {integrity: sha512-rsLBE/6mMxAjlLd06LuGacrukP2bqbzKCLzV1vrhHFavqQE/taQ2UXv3H5P0Ls7nsrASa+6x3bDbXHpqMwq+7A==}
engines: {node: '>=8'}
peerDependencies:
'@types/puppeteer': '*'
puppeteer: '*'
puppeteer-core: '*'
peerDependenciesMeta:
'@types/puppeteer':
optional: true
puppeteer:
optional: true
puppeteer-core:
optional: true
puppeteer@24.31.0:
resolution: {integrity: sha512-q8y5yLxLD8xdZdzNWqdOL43NbfvUOp60SYhaLZQwHC9CdKldxQKXOyJAciOr7oUJfyAH/KgB2wKvqT2sFKoVXA==}
engines: {node: '>=18'}
@@ -655,11 +845,20 @@ packages:
resolution: {integrity: sha512-cGk8IbWEAnaCpdAt1BHzJ3Ahz5ewDJa0KseTsE3qIRMJ3C698W8psM7byCeWVpd/Ha7FUYzuRVzXoKoM6nRUbA==}
engines: {node: '>=20'}
rimraf@3.0.2:
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
deprecated: Rimraf versions prior to v4 are no longer supported
hasBin: true
semver@7.7.3:
resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==}
engines: {node: '>=10'}
hasBin: true
shallow-clone@0.1.2:
resolution: {integrity: sha512-J1zdXCky5GmNnuauESROVu31MQSnLoYvlyEn6j2Ztk6Q5EHFIhxkMhYcv6vuDzl2XEzoRr856QwzMgWM/TmZgw==}
engines: {node: '>=0.10.0'}
sharp@0.34.5:
resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -717,6 +916,10 @@ packages:
undici-types@7.16.0:
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
universalify@2.0.1:
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
engines: {node: '>= 10.0.0'}
update-browserslist-db@1.1.4:
resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==}
hasBin: true
@@ -905,8 +1108,16 @@ snapshots:
'@tootallnate/quickjs-emscripten@0.23.0': {}
'@types/bezier-js@4.1.3': {}
'@types/debug@4.1.12':
dependencies:
'@types/ms': 2.1.0
'@types/http-cache-semantics@4.0.4': {}
'@types/ms@2.1.0': {}
'@types/node@24.10.1':
dependencies:
undici-types: 7.16.0
@@ -929,12 +1140,16 @@ snapshots:
argparse@2.0.1: {}
arr-union@3.1.0: {}
ast-types@0.13.4:
dependencies:
tslib: 2.8.1
b4a@1.7.3: {}
balanced-match@1.0.2: {}
bare-events@2.8.2: {}
bare-fs@4.5.1:
@@ -976,6 +1191,13 @@ snapshots:
basic-ftp@5.0.5: {}
bezier-js@6.1.4: {}
brace-expansion@1.1.12:
dependencies:
balanced-match: 1.0.2
concat-map: 0.0.1
browserslist@4.28.0:
dependencies:
baseline-browser-mapping: 2.8.30
@@ -1018,12 +1240,22 @@ snapshots:
strip-ansi: 6.0.1
wrap-ansi: 7.0.0
clone-deep@0.2.4:
dependencies:
for-own: 0.1.5
is-plain-object: 2.0.4
kind-of: 3.2.2
lazy-cache: 1.0.4
shallow-clone: 0.1.2
color-convert@2.0.1:
dependencies:
color-name: 1.1.4
color-name@1.1.4: {}
concat-map@0.0.1: {}
cosmiconfig@9.0.0:
dependencies:
env-paths: 2.2.1
@@ -1041,6 +1273,8 @@ snapshots:
dependencies:
mimic-response: 4.0.0
deepmerge@4.3.1: {}
degenerator@5.0.1:
dependencies:
ast-types: 0.13.4
@@ -1111,8 +1345,24 @@ snapshots:
dependencies:
pend: 1.2.0
for-in@0.1.8: {}
for-in@1.0.2: {}
for-own@0.1.5:
dependencies:
for-in: 1.0.2
form-data-encoder@4.1.0: {}
fs-extra@10.1.0:
dependencies:
graceful-fs: 4.2.11
jsonfile: 6.2.0
universalify: 2.0.1
fs.realpath@1.0.0: {}
generative-bayesian-network@2.1.77:
dependencies:
adm-zip: 0.5.16
@@ -1137,6 +1387,23 @@ snapshots:
transitivePeerDependencies:
- supports-color
ghost-cursor@1.4.1:
dependencies:
'@types/bezier-js': 4.1.3
bezier-js: 6.1.4
debug: 4.4.3
transitivePeerDependencies:
- supports-color
glob@7.2.3:
dependencies:
fs.realpath: 1.0.0
inflight: 1.0.6
inherits: 2.0.4
minimatch: 3.1.2
once: 1.4.0
path-is-absolute: 1.0.1
got-scraping@4.1.2:
dependencies:
got: 14.6.4
@@ -1162,6 +1429,8 @@ snapshots:
responselike: 4.0.2
type-fest: 4.41.0
graceful-fs@4.2.11: {}
header-generator@2.1.77:
dependencies:
browserslist: 4.28.0
@@ -1195,16 +1464,33 @@ snapshots:
parent-module: 1.0.1
resolve-from: 4.0.0
inflight@1.0.6:
dependencies:
once: 1.4.0
wrappy: 1.0.2
inherits@2.0.4: {}
ip-address@10.1.0: {}
is-arrayish@0.2.1: {}
is-buffer@1.1.6: {}
is-extendable@0.1.1: {}
is-fullwidth-code-point@3.0.0: {}
is-obj@2.0.0: {}
is-plain-object@2.0.4:
dependencies:
isobject: 3.0.1
is-stream@4.0.1: {}
isobject@3.0.1: {}
js-tokens@4.0.0: {}
js-yaml@4.1.1:
@@ -1213,10 +1499,28 @@ snapshots:
json-parse-even-better-errors@2.3.1: {}
jsonfile@6.2.0:
dependencies:
universalify: 2.0.1
optionalDependencies:
graceful-fs: 4.2.11
keyv@5.5.4:
dependencies:
'@keyv/serialize': 1.1.1
kind-of@2.0.1:
dependencies:
is-buffer: 1.1.6
kind-of@3.2.2:
dependencies:
is-buffer: 1.1.6
lazy-cache@0.2.7: {}
lazy-cache@1.0.4: {}
lines-and-columns@1.2.4: {}
lodash.isequal@4.5.0: {}
@@ -1225,10 +1529,25 @@ snapshots:
lru-cache@7.18.3: {}
merge-deep@3.0.3:
dependencies:
arr-union: 3.1.0
clone-deep: 0.2.4
kind-of: 3.2.2
mimic-response@4.0.0: {}
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.12
mitt@3.0.1: {}
mixin-object@2.0.1:
dependencies:
for-in: 0.1.8
is-extendable: 0.1.1
ms@2.1.3: {}
netmask@2.0.2: {}
@@ -1288,6 +1607,8 @@ snapshots:
json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.2.4
path-is-absolute@1.0.1: {}
pend@1.2.0: {}
picocolors@1.1.1: {}
@@ -1339,6 +1660,59 @@ snapshots:
- supports-color
- utf-8-validate
puppeteer-extra-plugin-stealth@2.11.2(puppeteer-extra@3.3.6(puppeteer-core@24.31.0)(puppeteer@24.31.0)):
dependencies:
debug: 4.4.3
puppeteer-extra-plugin: 3.2.3(puppeteer-extra@3.3.6(puppeteer-core@24.31.0)(puppeteer@24.31.0))
puppeteer-extra-plugin-user-preferences: 2.4.1(puppeteer-extra@3.3.6(puppeteer-core@24.31.0)(puppeteer@24.31.0))
optionalDependencies:
puppeteer-extra: 3.3.6(puppeteer-core@24.31.0)(puppeteer@24.31.0)
transitivePeerDependencies:
- supports-color
puppeteer-extra-plugin-user-data-dir@2.4.1(puppeteer-extra@3.3.6(puppeteer-core@24.31.0)(puppeteer@24.31.0)):
dependencies:
debug: 4.4.3
fs-extra: 10.1.0
puppeteer-extra-plugin: 3.2.3(puppeteer-extra@3.3.6(puppeteer-core@24.31.0)(puppeteer@24.31.0))
rimraf: 3.0.2
optionalDependencies:
puppeteer-extra: 3.3.6(puppeteer-core@24.31.0)(puppeteer@24.31.0)
transitivePeerDependencies:
- supports-color
puppeteer-extra-plugin-user-preferences@2.4.1(puppeteer-extra@3.3.6(puppeteer-core@24.31.0)(puppeteer@24.31.0)):
dependencies:
debug: 4.4.3
deepmerge: 4.3.1
puppeteer-extra-plugin: 3.2.3(puppeteer-extra@3.3.6(puppeteer-core@24.31.0)(puppeteer@24.31.0))
puppeteer-extra-plugin-user-data-dir: 2.4.1(puppeteer-extra@3.3.6(puppeteer-core@24.31.0)(puppeteer@24.31.0))
optionalDependencies:
puppeteer-extra: 3.3.6(puppeteer-core@24.31.0)(puppeteer@24.31.0)
transitivePeerDependencies:
- supports-color
puppeteer-extra-plugin@3.2.3(puppeteer-extra@3.3.6(puppeteer-core@24.31.0)(puppeteer@24.31.0)):
dependencies:
'@types/debug': 4.1.12
debug: 4.4.3
merge-deep: 3.0.3
optionalDependencies:
puppeteer-extra: 3.3.6(puppeteer-core@24.31.0)(puppeteer@24.31.0)
transitivePeerDependencies:
- supports-color
puppeteer-extra@3.3.6(puppeteer-core@24.31.0)(puppeteer@24.31.0):
dependencies:
'@types/debug': 4.1.12
debug: 4.4.3
deepmerge: 4.3.1
optionalDependencies:
puppeteer: 24.31.0
puppeteer-core: 24.31.0
transitivePeerDependencies:
- supports-color
puppeteer@24.31.0:
dependencies:
'@puppeteer/browsers': 2.10.13
@@ -1370,8 +1744,19 @@ snapshots:
dependencies:
lowercase-keys: 3.0.0
rimraf@3.0.2:
dependencies:
glob: 7.2.3
semver@7.7.3: {}
shallow-clone@0.1.2:
dependencies:
is-extendable: 0.1.1
kind-of: 2.0.1
lazy-cache: 0.2.7
mixin-object: 2.0.1
sharp@0.34.5:
dependencies:
'@img/colour': 1.0.0
@@ -1478,6 +1863,8 @@ snapshots:
undici-types@7.16.0:
optional: true
universalify@2.0.1: {}
update-browserslist-db@1.1.4(browserslist@4.28.0):
dependencies:
browserslist: 4.28.0