veil-browser 0.2.0 → 0.2.1
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/dist/browser.d.ts +7 -1
- package/dist/browser.js +34 -37
- package/package.json +1 -1
package/dist/browser.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { Browser, BrowserContext, Page } from 'playwright';
|
|
2
|
+
export interface BrowserState {
|
|
3
|
+
platform: string;
|
|
4
|
+
pid: number;
|
|
5
|
+
wsEndpoint: string;
|
|
6
|
+
timestamp: number;
|
|
7
|
+
}
|
|
2
8
|
export declare function ensureBrowser(opts?: {
|
|
3
9
|
headed?: boolean;
|
|
4
10
|
platform?: string;
|
|
@@ -8,5 +14,5 @@ export declare function ensureBrowser(opts?: {
|
|
|
8
14
|
page: Page;
|
|
9
15
|
}>;
|
|
10
16
|
export declare function getPage(): Promise<Page | null>;
|
|
11
|
-
export declare function closeBrowser(
|
|
17
|
+
export declare function closeBrowser(_platform?: string): Promise<void>;
|
|
12
18
|
export declare function humanDelay(min?: number, max?: number): Promise<void>;
|
package/dist/browser.js
CHANGED
|
@@ -3,18 +3,20 @@ import { promises as fs } from 'fs';
|
|
|
3
3
|
import { homedir } from 'os';
|
|
4
4
|
import { join } from 'path';
|
|
5
5
|
import { loadSession } from './session.js';
|
|
6
|
-
const
|
|
7
|
-
|
|
6
|
+
const VEIL_DIR = join(homedir(), '.veil');
|
|
7
|
+
const STATE_FILE = join(VEIL_DIR, 'browser-state.json');
|
|
8
|
+
// In-process singletons
|
|
8
9
|
let _browser = null;
|
|
9
10
|
let _context = null;
|
|
10
11
|
let _page = null;
|
|
11
|
-
|
|
12
|
+
const STEALTH_UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36';
|
|
12
13
|
export async function ensureBrowser(opts = {}) {
|
|
13
14
|
const platform = opts.platform ?? 'default';
|
|
14
|
-
|
|
15
|
+
// Return existing if healthy
|
|
16
|
+
if (_browser?.isConnected() && _page && !_page.isClosed()) {
|
|
15
17
|
return { browser: _browser, context: _context, page: _page };
|
|
16
18
|
}
|
|
17
|
-
//
|
|
19
|
+
// Fresh browser launch
|
|
18
20
|
const browser = await chromium.launch({
|
|
19
21
|
headless: !opts.headed,
|
|
20
22
|
args: [
|
|
@@ -25,51 +27,49 @@ export async function ensureBrowser(opts = {}) {
|
|
|
25
27
|
'--disable-dev-shm-usage',
|
|
26
28
|
'--disable-accelerated-2d-canvas',
|
|
27
29
|
'--no-first-run',
|
|
28
|
-
'--no-zygote',
|
|
29
|
-
'--disable-gpu',
|
|
30
30
|
'--window-size=1280,800',
|
|
31
|
-
'--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
|
|
32
31
|
],
|
|
33
32
|
});
|
|
34
|
-
// Create context with realistic settings
|
|
35
33
|
const context = await browser.newContext({
|
|
36
34
|
viewport: { width: 1280, height: 800 },
|
|
37
|
-
userAgent:
|
|
35
|
+
userAgent: STEALTH_UA,
|
|
38
36
|
locale: 'en-US',
|
|
39
37
|
timezoneId: 'America/New_York',
|
|
40
38
|
permissions: ['notifications'],
|
|
41
|
-
extraHTTPHeaders: {
|
|
42
|
-
'Accept-Language': 'en-US,en;q=0.9',
|
|
43
|
-
},
|
|
39
|
+
extraHTTPHeaders: { 'Accept-Language': 'en-US,en;q=0.9' },
|
|
44
40
|
});
|
|
45
|
-
//
|
|
41
|
+
// Stealth: hide automation signals
|
|
46
42
|
await context.addInitScript(() => {
|
|
47
43
|
Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
|
|
48
44
|
window.chrome = { runtime: {} };
|
|
49
|
-
Object.defineProperty(navigator, 'plugins', {
|
|
50
|
-
|
|
51
|
-
});
|
|
52
|
-
Object.defineProperty(navigator, 'languages', {
|
|
53
|
-
get: () => ['en-US', 'en'],
|
|
54
|
-
});
|
|
45
|
+
Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5] });
|
|
46
|
+
Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] });
|
|
55
47
|
});
|
|
56
|
-
// Restore session cookies
|
|
57
|
-
const session = await loadSession(platform);
|
|
58
|
-
if (session?.cookies
|
|
59
|
-
await context.addCookies(session.cookies);
|
|
48
|
+
// Restore saved session cookies
|
|
49
|
+
const session = await loadSession(platform).catch(() => null);
|
|
50
|
+
if (session?.cookies?.length) {
|
|
51
|
+
await context.addCookies(session.cookies).catch(() => { });
|
|
60
52
|
}
|
|
61
53
|
const page = await context.newPage();
|
|
62
54
|
_browser = browser;
|
|
63
55
|
_context = context;
|
|
64
56
|
_page = page;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
await fs.mkdir(join(homedir(), '.veil'), { recursive: true });
|
|
57
|
+
// Persist state for reconnection
|
|
58
|
+
await fs.mkdir(VEIL_DIR, { recursive: true });
|
|
68
59
|
await fs.writeFile(STATE_FILE, JSON.stringify({
|
|
69
60
|
platform,
|
|
70
61
|
pid: process.pid,
|
|
62
|
+
wsEndpoint: '',
|
|
71
63
|
timestamp: Date.now(),
|
|
72
64
|
}), 'utf-8').catch(() => { });
|
|
65
|
+
// Cleanup state on exit
|
|
66
|
+
const cleanup = () => {
|
|
67
|
+
fs.rm(STATE_FILE).catch(() => { });
|
|
68
|
+
_browser?.close().catch(() => { });
|
|
69
|
+
};
|
|
70
|
+
process.once('exit', cleanup);
|
|
71
|
+
process.once('SIGINT', () => { cleanup(); process.exit(0); });
|
|
72
|
+
process.once('SIGTERM', () => { cleanup(); process.exit(0); });
|
|
73
73
|
return { browser, context, page };
|
|
74
74
|
}
|
|
75
75
|
export async function getPage() {
|
|
@@ -77,16 +77,13 @@ export async function getPage() {
|
|
|
77
77
|
return _page;
|
|
78
78
|
return null;
|
|
79
79
|
}
|
|
80
|
-
export async function closeBrowser(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
_page = null;
|
|
86
|
-
}
|
|
80
|
+
export async function closeBrowser(_platform) {
|
|
81
|
+
await _browser?.close().catch(() => { });
|
|
82
|
+
_browser = null;
|
|
83
|
+
_context = null;
|
|
84
|
+
_page = null;
|
|
87
85
|
await fs.rm(STATE_FILE).catch(() => { });
|
|
88
86
|
}
|
|
89
|
-
export function humanDelay(min =
|
|
90
|
-
|
|
91
|
-
return new Promise(r => setTimeout(r, delay));
|
|
87
|
+
export function humanDelay(min = 400, max = 900) {
|
|
88
|
+
return new Promise(r => setTimeout(r, Math.floor(Math.random() * (max - min) + min)));
|
|
92
89
|
}
|