arn-browser 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +43 -0
- package/bin/install.js +412 -0
- package/package.json +8 -3
- package/src/index.d.ts +16 -6
- package/src/index.js +7 -4
- package/src/utility/deleteDirectory.js +2 -2
- package/src/utility/{multilogin_token_manager.js → mlx_token.js} +32 -43
- package/src/utility/{launchBrowser.d.ts → playwright/pwLaunch.d.ts} +25 -18
- package/src/utility/{launchBrowser.js → playwright/pwLaunch.js} +221 -137
- package/src/{all_routes/routeWithSuperagent.d.ts → utility/playwright/routes/pwRoute.d.ts} +4 -4
- package/src/{all_routes/routeWithSuperagent.js → utility/playwright/routes/pwRoute.js} +2 -2
- package/src/utility/proxy-utility/proxy-chain.js +30 -3
- package/src/utility/proxy-utility/proxy-helper.js +1 -1
- package/src/utility/puppeteer/ppLaunch.d.ts +199 -0
- package/src/utility/puppeteer/ppLaunch.js +723 -0
- package/src/utility/puppeteer/routes/ppRoute.d.ts +64 -0
- package/src/utility/puppeteer/routes/ppRoute.js +326 -0
- /package/src/{human-cursor → utility/playwright/human-cursor}/HumanCursor.js +0 -0
- /package/src/{human-cursor → utility/playwright/human-cursor}/bezier.js +0 -0
- /package/src/{human-cursor → utility/playwright/human-cursor}/index.d.ts +0 -0
- /package/src/{human-cursor → utility/playwright/human-cursor}/index.js +0 -0
- /package/src/{human-cursor → utility/playwright/human-cursor}/randomizer.js +0 -0
- /package/src/{human-cursor → utility/playwright/human-cursor}/tweening.js +0 -0
- /package/src/utility/{playwright-helper.d.ts → playwright/playwright-helper.d.ts} +0 -0
- /package/src/utility/{playwright-helper.js → playwright/playwright-helper.js} +0 -0
|
@@ -5,9 +5,9 @@ import { Browser, BrowserContext, Page } from "playwright";
|
|
|
5
5
|
// ============================================================================
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Options for the
|
|
8
|
+
* Options for the pwRoute function.
|
|
9
9
|
*/
|
|
10
|
-
export interface
|
|
10
|
+
export interface PwRouteOptions {
|
|
11
11
|
/** Playwright Context (provide either context or page) */
|
|
12
12
|
context?: BrowserContext | null;
|
|
13
13
|
|
|
@@ -57,11 +57,11 @@ export interface GotRouteOptions {
|
|
|
57
57
|
/**
|
|
58
58
|
* Sets up request interception, caching, and ad-blocking on a Playwright page or context.
|
|
59
59
|
*/
|
|
60
|
-
export function
|
|
60
|
+
export function pwRoute(options: PwRouteOptions): Promise<void>;
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
63
|
* Starts logging cache statistics to the console at a set interval.
|
|
64
64
|
* @param log_cache Optional NodeCache instance (uses global by default)
|
|
65
65
|
* @param interval Interval in seconds (default: 10)
|
|
66
66
|
*/
|
|
67
|
-
export function
|
|
67
|
+
export function pwCacheLogs(log_cache?: any, interval?: number): void;
|
|
@@ -20,7 +20,7 @@ const globalCache = new NodeCache({
|
|
|
20
20
|
* @param {Object} log_cache - The cache instance to monitor
|
|
21
21
|
* @param {number} interval - The interval in seconds between log outputs
|
|
22
22
|
*/
|
|
23
|
-
export function
|
|
23
|
+
export function pwCacheLogs(log_cache = globalCache, interval = 10) {
|
|
24
24
|
if (interval > 0) {
|
|
25
25
|
setInterval(() => {
|
|
26
26
|
const stats = log_cache.stats;
|
|
@@ -109,7 +109,7 @@ async function fetchWithClient(useCache, url, requestHeaders, method, useFullUrl
|
|
|
109
109
|
* @param {Array<string>} options.allowImagePatterns - Array of strings/patterns. If a URL contains any of these, it will NOT be blocked even if blockImage is true.
|
|
110
110
|
* @param {Array<string>} options.skipGotPatterns - Array of strings/patterns. If a URL contains any of these, it will skip the custom Superagent fetch.
|
|
111
111
|
*/
|
|
112
|
-
export async function
|
|
112
|
+
export async function pwRoute({
|
|
113
113
|
context = null,
|
|
114
114
|
page = null,
|
|
115
115
|
successLogs = false,
|
|
@@ -217,9 +217,10 @@ export async function startProxyServer({
|
|
|
217
217
|
fetchProxyDetails(upstreamProxies.p2, ip2LocationKey),
|
|
218
218
|
]);
|
|
219
219
|
|
|
220
|
-
//
|
|
221
|
-
if (upstreamProxies.
|
|
222
|
-
if (upstreamProxies.
|
|
220
|
+
// Throw error if proxy was configured (URL exists) but details came back null (Connection failed)
|
|
221
|
+
if (upstreamProxies.default && !defaultDetails) throw new Error("DEFAULT_PROXY configured but unreachable.");
|
|
222
|
+
if (upstreamProxies.p1 && !p1Details) throw new Error("PROXY_1 configured but unreachable.");
|
|
223
|
+
if (upstreamProxies.p2 && !p2Details) throw new Error("PROXY_2 configured but unreachable.");
|
|
223
224
|
|
|
224
225
|
// 5. Stats
|
|
225
226
|
const stats = {
|
|
@@ -239,6 +240,9 @@ export async function startProxyServer({
|
|
|
239
240
|
const connectionMap = {}; // Maps connectionId -> { type: "..." }
|
|
240
241
|
let serverRunning = false;
|
|
241
242
|
|
|
243
|
+
// Track all open sockets so we can force-destroy them on close
|
|
244
|
+
const activeSockets = new Set();
|
|
245
|
+
|
|
242
246
|
// 6. Server
|
|
243
247
|
const server = new ProxyChain.Server({
|
|
244
248
|
port: selectedPort,
|
|
@@ -327,6 +331,23 @@ export async function startProxyServer({
|
|
|
327
331
|
try {
|
|
328
332
|
await server.listen();
|
|
329
333
|
serverRunning = true;
|
|
334
|
+
|
|
335
|
+
// Track sockets so closeServer() can destroy them all
|
|
336
|
+
server.server.on('connection', (socket) => {
|
|
337
|
+
activeSockets.add(socket);
|
|
338
|
+
socket.once('close', () => activeSockets.delete(socket));
|
|
339
|
+
|
|
340
|
+
// Intercept pipe to catch the upstream target sockets created by proxy-chain
|
|
341
|
+
const originalPipe = socket.pipe;
|
|
342
|
+
socket.pipe = function(destination, options) {
|
|
343
|
+
if (destination && typeof destination.destroy === 'function') {
|
|
344
|
+
activeSockets.add(destination);
|
|
345
|
+
destination.once('close', () => activeSockets.delete(destination));
|
|
346
|
+
}
|
|
347
|
+
return originalPipe.apply(this, arguments);
|
|
348
|
+
};
|
|
349
|
+
});
|
|
350
|
+
|
|
330
351
|
console.log(`░░ Local Proxy Started: http://127.0.0.1:${selectedPort}`);
|
|
331
352
|
} catch (err) {
|
|
332
353
|
console.error("░░ Failed to start proxy server:", err);
|
|
@@ -397,6 +418,12 @@ export async function startProxyServer({
|
|
|
397
418
|
await server.close(true);
|
|
398
419
|
serverRunning = false;
|
|
399
420
|
|
|
421
|
+
// Force-destroy any lingering sockets so Node can exit
|
|
422
|
+
for (const socket of activeSockets) {
|
|
423
|
+
socket.destroy();
|
|
424
|
+
}
|
|
425
|
+
activeSockets.clear();
|
|
426
|
+
|
|
400
427
|
// Auto console.log stats on close
|
|
401
428
|
if (proxy_stats) {
|
|
402
429
|
console.log("░░ Proxy Stats:", getProxyStatsFormatted());
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { setTimeout as sleep } from "timers/promises";
|
|
2
2
|
import randomstring from "randomstring";
|
|
3
|
-
import { getMultiloginToken } from "../
|
|
3
|
+
import { getMultiloginToken } from "../mlx_token.js";
|
|
4
4
|
import { getActiveProxyWithStartStop as fetchAwsProxy } from "./custom-proxy.js";
|
|
5
5
|
import { arn, query } from "arn-knexjs";
|
|
6
6
|
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { Browser, Page } from "puppeteer-core";
|
|
2
|
+
import type { ProxyConfig } from "../pwLaunch";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Configuration options specific to Multilogin (Puppeteer CDP).
|
|
6
|
+
*/
|
|
7
|
+
export interface PpMultiloginOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Multilogin Profile ID. If provided, launches an existing profile.
|
|
10
|
+
*/
|
|
11
|
+
profileId?: string | null;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* OS Type for Multilogin profile creation.
|
|
15
|
+
* Default: detected OS
|
|
16
|
+
*/
|
|
17
|
+
os_type?: "windows" | "macos" | "linux" | "android";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Multilogin flag: Canvas noise masking.
|
|
21
|
+
* Default: true
|
|
22
|
+
*/
|
|
23
|
+
canvas_noise?: boolean;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Multilogin flag: Media devices masking.
|
|
27
|
+
* Default: true
|
|
28
|
+
*/
|
|
29
|
+
media_masking?: boolean;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Multilogin flag: Audio masking.
|
|
33
|
+
* Default: true
|
|
34
|
+
*/
|
|
35
|
+
audio_masking?: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Options for launching a browser via Puppeteer CDP.
|
|
40
|
+
*/
|
|
41
|
+
export interface PpLaunchOptions {
|
|
42
|
+
// ========================================================================
|
|
43
|
+
// 1. BROWSER SELECTION
|
|
44
|
+
// ========================================================================
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Which browser to launch.
|
|
48
|
+
*
|
|
49
|
+
* - `"chrome"`: Chromium browser (locally installed)
|
|
50
|
+
* - `"chromium"`: Alias for Chrome
|
|
51
|
+
* - `"brave"`: Brave Browser (requires local binary)
|
|
52
|
+
* - `"multilogin"`: Multilogin anti-detect browser (via API)
|
|
53
|
+
*
|
|
54
|
+
* Default: `"chrome"`
|
|
55
|
+
*/
|
|
56
|
+
which_browser?: "chrome" | "chromium" | "brave" | "multilogin";
|
|
57
|
+
|
|
58
|
+
// ========================================================================
|
|
59
|
+
// 2. STORAGE & PROFILES
|
|
60
|
+
// ========================================================================
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Path to a persistent profile.
|
|
64
|
+
* - If absolute path: Uses that path exactly (no prefix added).
|
|
65
|
+
* - If folder name: Creates inside `~/.arn-browser/pp/persistent/` with a browser prefix (e.g., `brave_myProfile`).
|
|
66
|
+
* - If null: Creates a temporary, random profile in `~/.arn-browser/pp/temp/`.
|
|
67
|
+
*/
|
|
68
|
+
profile_path?: string | null;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Auto-cleanup profiles after X minutes since last launch.
|
|
72
|
+
*
|
|
73
|
+
* **Persistent profiles:** Cleaned after X minutes since last launch. Default: 0 (never clean).
|
|
74
|
+
* **Temp profiles:** Default: 15 minutes if not specified.
|
|
75
|
+
*
|
|
76
|
+
* Default: 0
|
|
77
|
+
*/
|
|
78
|
+
cleanupMinutes?: number;
|
|
79
|
+
|
|
80
|
+
// ========================================================================
|
|
81
|
+
// 3. NETWORK
|
|
82
|
+
// ========================================================================
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Proxy settings (URL string or config object).
|
|
86
|
+
* Passed as `--proxy-server` flag to the browser.
|
|
87
|
+
*/
|
|
88
|
+
proxy?: ProxyConfig | string | null;
|
|
89
|
+
|
|
90
|
+
// ========================================================================
|
|
91
|
+
// 4. BROWSER ARGS
|
|
92
|
+
// ========================================================================
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Additional CLI arguments to pass to the browser process.
|
|
96
|
+
* These are appended after the default args.
|
|
97
|
+
*
|
|
98
|
+
* @example ["--disable-gpu", "--window-size=1920,1080"]
|
|
99
|
+
*/
|
|
100
|
+
extraArgs?: string[];
|
|
101
|
+
|
|
102
|
+
// ========================================================================
|
|
103
|
+
// 5. ENGINE SPECIFIC
|
|
104
|
+
// ========================================================================
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Options specific to the Multilogin engine.
|
|
108
|
+
*/
|
|
109
|
+
multilogin_options?: PpMultiloginOptions;
|
|
110
|
+
|
|
111
|
+
// ========================================================================
|
|
112
|
+
// 6. FINGERPRINT SPOOFING
|
|
113
|
+
// ========================================================================
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Configuration for browser fingerprint spoofing (per-page via fingerprint-injector).
|
|
117
|
+
*
|
|
118
|
+
* - `false`: No fingerprint spoofing (default)
|
|
119
|
+
* - `true`: Spoof fingerprint with default screen dimensions
|
|
120
|
+
* - `{ minWidth?, maxWidth?, minHeight?, maxHeight? }`: Spoof fingerprint with screen constraints
|
|
121
|
+
*
|
|
122
|
+
* Default: false
|
|
123
|
+
*/
|
|
124
|
+
spoof_fingerprint?: boolean | {
|
|
125
|
+
minWidth?: number;
|
|
126
|
+
maxWidth?: number;
|
|
127
|
+
minHeight?: number;
|
|
128
|
+
maxHeight?: number;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// ========================================================================
|
|
132
|
+
// 7. LOGGING
|
|
133
|
+
// ========================================================================
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Enable launch-related console logs.
|
|
137
|
+
* Default: false
|
|
138
|
+
*/
|
|
139
|
+
launch_logs?: boolean;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Enable cleanup-related console logs.
|
|
143
|
+
* Default: false
|
|
144
|
+
*/
|
|
145
|
+
cleanup_logs?: boolean;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Successful Puppeteer browser launch result.
|
|
150
|
+
* When launchError is null, browser/context/page are guaranteed to be valid.
|
|
151
|
+
*/
|
|
152
|
+
export interface PpBrowserControllerSuccess {
|
|
153
|
+
/** The Puppeteer Browser instance. */
|
|
154
|
+
browser: Browser;
|
|
155
|
+
/** The browser instance (alias for browser in Puppeteer, since there's no separate BrowserContext). */
|
|
156
|
+
context: Browser;
|
|
157
|
+
/** The initial Page object. */
|
|
158
|
+
page: Page;
|
|
159
|
+
/** Returns true if the browser is still connected. */
|
|
160
|
+
isBrowserRunning: () => boolean;
|
|
161
|
+
/** Safely closes the browser, kills the process, and cleans up temporary directories. */
|
|
162
|
+
closeBrowser: () => Promise<boolean>;
|
|
163
|
+
/** No error occurred during launch. */
|
|
164
|
+
launchError: null;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Failed Puppeteer browser launch result.
|
|
169
|
+
* When launchError is set, browser/context/page are null.
|
|
170
|
+
*/
|
|
171
|
+
export interface PpBrowserControllerError {
|
|
172
|
+
/** Null on launch failure. */
|
|
173
|
+
browser: null;
|
|
174
|
+
/** Null on launch failure. */
|
|
175
|
+
context: null;
|
|
176
|
+
/** Null on launch failure. */
|
|
177
|
+
page: null;
|
|
178
|
+
/** Returns false since the browser failed to launch. */
|
|
179
|
+
isBrowserRunning: () => boolean;
|
|
180
|
+
/** No-op cleanup function. */
|
|
181
|
+
closeBrowser: () => Promise<boolean>;
|
|
182
|
+
/** The error that occurred during launch. */
|
|
183
|
+
launchError: Error;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* The object returned by launchPuppeteer.
|
|
188
|
+
* Check launchError to discriminate between success and failure states.
|
|
189
|
+
*/
|
|
190
|
+
export type PpBrowserController = PpBrowserControllerSuccess | PpBrowserControllerError;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Launches a browser via Puppeteer CDP based on the provided options.
|
|
194
|
+
* Spawns the browser process, connects via Chrome DevTools Protocol.
|
|
195
|
+
*
|
|
196
|
+
* Supported browsers: Chrome, Brave, Multilogin.
|
|
197
|
+
* Profile directory: ~/.arn-browser/pp/
|
|
198
|
+
*/
|
|
199
|
+
export function ppLaunch(options?: PpLaunchOptions): Promise<PpBrowserController>;
|